-
Notifications
You must be signed in to change notification settings - Fork 212
Controlling access in views
Make sure you are familiar with:
- Permission directive
- Basic usage
- Custom behaviour
- Async calls for permissions in initial state
- Suppressing warnings for undefined permissions
Permission module exposes directive permission
that can show/hide elements of your application based on set of permissions.
Permission directive accepts several attributes:
Attribute | Value | Description |
---|---|---|
permission-sref |
[String ] |
Reference to other state name permissions (ui-router only) |
permission-only |
[String |Array ] |
Single or multiple roles/permissions allowed to access content |
permission-except |
[String |Array ] |
Single or multiple roles/permissions denied to access content |
permission-on-authorized |
[Function ] |
Custom function invoked when authorized |
permission-on-unauthorized |
[Function ] |
Custom function invoked when unauthorized |
Directives accepts either single permission that has to be met in order to display it's content:
<div permission
permission-only="'canReadInvoice'">
<span>Congrats! You are logged in.</span>
</div>
Or set of permissions separated by 'coma':
<div permission
permission-except="['USER','ADMIN']">
<span>You are not 'ADMIN' nor 'USER'.</span>
</div>
🔥 Important
Do not use permission directive outsideui-view
/ng-view
, as they are only html elements, that content respond to router state/route changes.
Alternatively, combined together with ui-router
, you can reference other state names in order to provide view limitations instead of using permission-only
and permission-except
properties:
<div permission permission-sref="'app.adminPanel'">
<span>You must be 'ADMIN' see admin panel!</span>
</div>
By default permission directive is manipulating classes DOM elements by adding or removing ng-hide
class using hideElement
and showElement
behaviour strategies. But permission module exposes additional strategies or even custom function allowing to customize the way elements are being rendered or decorated.
Built in behaviours are stored in PermissionStrategies
value containing:
Value | Behaviour |
---|---|
enableElement |
Removes disabled attribute from element |
disableElement |
Adds disabled attribute to element |
showElement |
Removes ng-hide class showing element |
hideElement |
Adds ng-hide class hiding element |
To use different strategy pass it as value to permission-on-authorized
and permission-on-unauthorized
params:
<button
type="button"
permission
permission-only="'canEditInvoice'"
permission-on-authorized="PermissionStrategies.enableElement"
permission-on-unauthorized="PermissionStrategies.disableElement">
Edit Invoice
</button>
Or you can provide custom function defined inside controller or link function that will be invoked based on authorization results:
angular.controller('InvoiceController', function($scope){
$scope.onAuthorized = function(element){
element.prepend('<span>Great!</span>');
};
$scope.onUnauthorized = function(element){
element.prepend('<span>Sad!</span>');
};
});
And then passed in view to permission attributes:
<button
type="button"
permission
permission-only="'canEditInvoice'"
permission-on-authorized="onAuthorized"
permission-on-unauthorized="onUnauthorized">
Edit Invoice
</button>
🔥 Important
Notice that functions are being passed as reference (without brackets()
). It is required to allow later invocation. If you pass function with brackets, they simply won't work.
In some situations you may want to use different behaviour in all permission directives without the the need to add permission-on-authorized
and permission-on-unauthorized
everywhere across your code. To do that you should to use $permissionProvider
available config phase.
It exposes two methods setDefaultOnAuthorizedMethod
and setDefaultOnUnauthorizedMethod
that accepts as a string one of available methods defined in PermPermissionStrategies. Feel free to extend it and provide your own methods implementation there.
app
.config(function ($permissionProvider) {
$permissionProvider.setDefaultOnAuthorizedMethod('attachElement');
$permissionProvider.setDefaultOnUnauthorizedMethod('detachElement');
})
.run(function (PermPermissionStrategies) {
PermPermissionStrategies.attachElement = function($element){
[...]
};
PermPermissionStrategies.detachElement = function($element){
[...]
};
});
When using async calls to fetch permissions in initial states make sure that modules (or app) are waiting for permissions to be resolved before running them. To ensure that you should use deferIntercept to create delayed router start.
var app = ng.module('app', ['ui.router', 'permission', 'permission.ui']);
app
.config(function ($urlRouterProvider) {
[...]
// Prevent router from automatic state resolving
$urlRouterProvider.deferIntercept();
})
.run(function($urlRouter, $http){
// Example ajax call
$http
.get('/permissions')
.then(function(permissions){
// Use RoleStore and PermissionStore to define permissions and roles
// or even set up whole session
})
.then(function(){
// Once permissions are set-up
// kick-off router and start the application rendering
$urlRouter.sync();
// Also enable router to listen to url changes
$urlRouter.listen();
});
});
By default permission library expect you to have defined complete set of roles and permissions defined at the moment of initialization of the app. In same cases your permissions may change dynamically and you can't predict the closed list permissions. Then you wouldn't want your clients to see the warning in console right? To fix that, simply set flag suppressUndefinedPermissionWarning
to true
on your app configuration stage.
app
.config(function ($permissionProvider) {
$permissionProvider.suppressUndefinedPermissionWarning(true);
})
Next to read: 👉 Installation guide for ui-router |
---|
Next to read: 👉 Installation guide for ng-route |
---|