Narzerus/angular-permission — pull request #15 by ankri (2014-11-09 20:51:02+00:00)
Title: Check all

In reference to Narzerus/angular-permission#12

**tl;dr**: Needed it myself. Implemented it. Pushed it to a new branch for review.

Hmm. I thought I could propose a new branch. Sorry I don't know how to do it, so sadly I will crate this pull request for the development branch.

Short preface
------------------
I have to confess, that I always thought that the only permission was 'allOfThese' instead the 'oneOfThese' permission. Partly because I only had one role. 'isLoggedIn'. As soon as I needed a second role, I needed this functionality myself. Today I had too much time on my hands and implemented such a functionality.

The added API
-------------------

```javascript
$stateProvider.state('restricted', {
data: {
permissions: {
all: ['roleA', 'roleB'],
redirectTo: 'redirectToThisState'
}
}
});
```

Just like expected. The state only changes if both `roleA` and `roleB` are resolved, otherwise the user will be redirected to `redirectToThisState`.

As soon as I added this feature I felt the need that you could provide separate `redirectTo`s for the different roles:

```javascript
$stateProvider.state('restricted', {
data: {
permissions: {
all: {
'roleA': {},
'roleB': {
redirectTo: 'stateB'
}
},
redirectTo: 'stateC'
}
}
});
```

Along with the array notation it is possible for the `all` property to receive an object. This one is a bit more complicated:
The state will successfully change to `restricted` if both roles are resolved. But if `roleB` is rejected the state will change to `stateB` instead. If `roleA` or another role, that doesn't explicitly have a `redirectTo` state, rejects then the default `redirectTo` will take place and the state will change to `stateC`.

I also have an alternative approach:
You can directly specify the route that the user shall be redirected to in the rejection function of the role. An example:

The role:
```javascript
Permission.defineRole('roleC', function () {
var deferred = $q.defer();
deferred.reject({redirectTo: 'stateA'});
return deferred.promise;
});
```
The state:
```javascript
$stateProvider.state('restricted', {
data: {
permissions: {
all: ['roleC'],
redirectTo: 'stateB'
}
}
});
```

The roles can be provided via the array or the object notation. If `roleC` rejects the state will be redirected to `stateA` as stated in the role and not to `stateB` as written in the state object.

Currently I have implemented both versions into one.

The role:
```javascript
Permission.defineRole('roleC', function () {
var deferred = $q.defer();
deferred.reject({redirectTo: 'stateA'});
return deferred.promise;
});
```
The state:
```javascript
$stateProvider.state('restricted', {
data: {
permissions: {
all: {
roleA: {},
roleC: {
redirectTo: 'stateY'
}
},
redirectTo: 'stateB'
}
}
});
```

The if `roleC` rejects the state would be redirected to `stateA` as the role says. So the order is:
`redirectTo` in rejection > `redirectTo` as property of role in the state > `redirectTo` as property of the state.

What do you guys think of the approaches. Please feel free to post your opinion.

PS: I'm currently in Antwerp for the [devoxx](http://www.devoxx.be) if anyone is attending, too and up for a chat, shoot me a message.