Skip to content

Commit

Permalink
Merge pull request #441 from nik0kin/bug/fix-parent-child-except-over…
Browse files Browse the repository at this point in the history
…rides

Fix: A parent state's "except" permission that is met will override the child "except" permission that is not met
  • Loading branch information
masterspambot authored Jan 20, 2018
2 parents ec48978 + 47356c0 commit 43be752
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 8 deletions.
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ When creating an issue please include:

Want to submit a Pull Request?
============================
1. Create a branch from the `ng1`/`ng2` branch accordingly to used angular version
1. Create a branch from the `development` branch
2. Implement your new feature
3. Submit a pull request to be merged in the `ng1`/`ng2` branch
3. Submit a pull request to be merged in the `development` branch

33 changes: 28 additions & 5 deletions src/permission-ui/authorization/StateAuthorization.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,18 @@ function PermStateAuthorization($q, $state, PermStatePermissionMap) {
function resolveExceptStatePermissionMap(deferred, map) {
var exceptPromises = resolveStatePermissionMap(map.except, map);

$q.all(exceptPromises)
.then(function (rejectedPermissions) {
deferred.reject(rejectedPermissions[0]);
})
.catch(function () {
// Reverse the promises, so if any "except" privileges are not met, the promise rejects
$q.all(reversePromises(exceptPromises))
.then(function () {
resolveOnlyStatePermissionMap(deferred, map);
})
.catch(function (rejectedPermissions) {

if (!angular.isArray(rejectedPermissions)) {
rejectedPermissions = [rejectedPermissions];
}

deferred.reject(rejectedPermissions[0]);
});
}

Expand Down Expand Up @@ -129,6 +135,23 @@ function PermStateAuthorization($q, $state, PermStatePermissionMap) {
});
});
}

/**
* Creates an Array of Promises that resolve when rejected, and reject when resolved
* @methodOf permission.ui.PermStateAuthorization
* @private
*
* @param promises {Array} Array of promises
*
* @returns {Array<Promise>} Promise collection
*/
function reversePromises (promises) {
return promises.map(function (promise) {
var d = $q.defer();
promise.then(d.reject, d.resolve);
return d.promise;
});
}
}

angular
Expand Down
105 changes: 104 additions & 1 deletion test/unit/permission-ui/authorization/StateAuthorization.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ describe('permission.ui', function () {
return false;
});

PermPermissionStore.definePermission('editTopic', function () {
return false;
});

PermPermissionStore.definePermission('deleteUser', function () {
return true;
});

PermRoleStore.defineRole('USER', ['editPosts']);
PermRoleStore.defineRole('ADMIN', ['editUsers']);
});
Expand All @@ -44,7 +52,6 @@ describe('permission.ui', function () {
return {path: [{data: {permissions: {except: ['editUsers']}}}]};
});


// WHEN
var map = new PermStatePermissionMap(state);
var authorizationResult = PermStateAuthorization.authorizeByPermissionMap(map);
Expand Down Expand Up @@ -117,6 +124,102 @@ describe('permission.ui', function () {
expect(authorizationResult).toBePromise();
expect(authorizationResult).toBeRejectedWith('editPosts', jasmine.any(Object));
});

it('should return resolved promise when a parent and a child state\'s "except" permissions are met', function () {
// GIVEN
var state = jasmine.createSpyObj('state', ['$$permissionState']);
state.$$permissionState.and.callFake(function () {
return {path: [
{data: {permissions: {except: ['editUsers']}}},
{data: {permissions: {except: ['editTopic']}}}
]};
});

// WHEN
var map = new PermStatePermissionMap(state);
var authorizationResult = PermStateAuthorization.authorizeByPermissionMap(map);

// THEN
expect(authorizationResult).toBePromise();
expect(authorizationResult).toBeResolved();
});

it('should return rejected promise when a parent state\'s "except" permissions are not met', function () {
// GIVEN
var state = jasmine.createSpyObj('state', ['$$permissionState']);
state.$$permissionState.and.callFake(function () {
return {path: [
{data: {permissions: {except: ['editPosts', 'editUsers']}}},
{data: {permissions: {}}}
]};
});

// WHEN
var map = new PermStatePermissionMap(state);
var authorizationResult = PermStateAuthorization.authorizeByPermissionMap(map);

// THEN
expect(authorizationResult).toBePromise();
expect(authorizationResult).toBeRejectedWith('editPosts', jasmine.any(Object));
});

it('should return rejected promise when a parent state\'s "except" permissions are met and child state\'s "except" permissions are not met', function () {
// GIVEN
var state = jasmine.createSpyObj('state', ['$$permissionState']);
state.$$permissionState.and.callFake(function () {
return {path: [
{data: {permissions: {except: ['editUsers']}}},
{data: {permissions: {except: ['editPosts']}}}
]};
});

// WHEN
var map = new PermStatePermissionMap(state);
var authorizationResult = PermStateAuthorization.authorizeByPermissionMap(map);

// THEN
expect(authorizationResult).toBePromise();
expect(authorizationResult).toBeRejectedWith('editPosts', jasmine.any(Object));
});

it('should return rejected promise when a parent state\'s "except" permissions are not met and child state\'s "except" permissions are met', function () {
// GIVEN
var state = jasmine.createSpyObj('state', ['$$permissionState']);
state.$$permissionState.and.callFake(function () {
return {path: [
{data: {permissions: {except: ['editPosts']}}},
{data: {permissions: {except: ['editUsers']}}}
]};
});

// WHEN
var map = new PermStatePermissionMap(state);
var authorizationResult = PermStateAuthorization.authorizeByPermissionMap(map);

// THEN
expect(authorizationResult).toBePromise();
expect(authorizationResult).toBeRejectedWith('editPosts', jasmine.any(Object));
});

it('should return rejected promise when a parent state\'s "except" permissions are not met and child state\'s "except" permissions are not met', function () {
// GIVEN
var state = jasmine.createSpyObj('state', ['$$permissionState']);
state.$$permissionState.and.callFake(function () {
return {path: [
{data: {permissions: {except: ['editPosts']}}},
{data: {permissions: {except: ['deleteUser']}}}
]};
});

// WHEN
var map = new PermStatePermissionMap(state);
var authorizationResult = PermStateAuthorization.authorizeByPermissionMap(map);

// THEN
expect(authorizationResult).toBePromise();
expect(authorizationResult).toBeRejectedWith('editPosts', jasmine.any(Object));
});

});
});
});
Expand Down

0 comments on commit 43be752

Please sign in to comment.