I use role-based authorization on both the backend and frontend. Since I use UI-Router for routing, the best resource I found (and improved for my needs) is this article:
link expired
If you are using a UI Router, definitely check it out. Basically, you need to configure route security and intercept all route changes. The article also contains a directive to hide user interface elements if the user does not have permission to access the content located behind him.
Edit: Adding code.
First, you need user permissions to be stored somewhere, for example. on the user object serialized in localStorage:
{"id":1,"name":"user","created_at":"2016-04-17 18:58:19","gender":"m","roles":["admin"]}
Then you have two important parts:
- Directive
- - determine whether the item should be visible or not based on the assigned permission.
- service - to verify authorization
Directive
(function() { 'use strict'; angular .module('app') .directive('access', access); function access(authorization) { var directive = { restrict: 'A', link: linkFunc, }; return directive; function linkFunc($scope, $element, $attrs) { var makeVisible = function () { $element.removeClass('hidden'); }; var makeHidden = function () { $element.addClass('hidden'); }; var determineVisibility = function (resetFirst) { var result; if (resetFirst) { makeVisible(); } result = authorization.authorize(true, roles, $attrs.accessPermissionType); if (result === authorization.constants.authorised) { makeVisible(); } else { makeHidden(); } }; var roles = $attrs.access.split(','); if (roles.length > 0) { determineVisibility(true); } } } })();
You need to set CSS so that elements with the hidden class are not visible.
Services:
(function() { 'use strict'; angular .module('app') .factory('authorization', authorization); function authorization($rootScope) { var service = { authorize: authorize, constants: { authorised: 0, loginRequired: 1, notAuthorised: 2 } }; return service; function authorize(loginRequired, requiredPermissions, permissionCheckType) { var result = service.constants.authorised, user = $rootScope.currentUser, loweredPermissions = [], hasPermission = true, permission; permissionCheckType = permissionCheckType || 'atLeastOne'; if (loginRequired === true && user === undefined) { result = service.constants.loginRequired; } else if ((loginRequired === true && user !== undefined) && (requiredPermissions === undefined || requiredPermissions.length === 0)) { result = service.constants.authorised; } else if (requiredPermissions) { loweredPermissions = []; angular.forEach(user.roles, function (permission) { loweredPermissions.push(permission.toLowerCase()); }); for (var i = 0; i < requiredPermissions.length; i += 1) { permission = requiredPermissions[i].toLowerCase(); if (permissionCheckType === 'combinationRequired') { hasPermission = hasPermission && loweredPermissions.indexOf(permission) > -1;
Now you can use the directive to show / hide the element:
<a ui-sref="app.administration" class="btn btn-primary pull-right" access="admin">Administration</a>
Of course, this only hides the item in the DOM, so you should also perform an authorization check on the server.
This first part is solved for showing / hiding elements in the user interface, but you can also protect application routes.
Route Definition:
(function() { 'use strict'; angular .module('app') .config(routeConfig); function routeConfig($stateProvider) { $stateProvider .state('app.dashboard', { url: '/dashboard', data: { access: { loginRequired: true } }, templateUrl: 'template_path', controller: 'DashboardController as vm' } } })();
and now just check the resolution in the $stateChangeStart event
(function() { 'use strict'; angular .module('app') .run(runBlock); function runBlock($rootScope, $state, authorization) { $rootScope.$on('$stateChangeStart', function(event, toState) {