假设我的角度SPA应用程序中有一个菜单,现在我希望向所有用户显示基本选项,例如家庭,关于我们,承运商的机会等。
我还希望有其他一些选项,例如管理用户,管理职位等,这些选项只会显示给管理员。
我们还假设我们有一个API访问点,可以为我提供用户角色,或者更好的是,该用户角色位于从/ api / users / me检索的对象内。
封装那些管理工具以防止普通用户查看的最佳方法是什么?
视图之间是否有某种继承?就像在Django中一样,有没有办法向未经授权的用户隐藏DOM元素?(是的,我知道这是客户端)。
我真的不希望菜单使用不同的视图,因为它应该是通用组件。
我想如果我之前所有问题的答案都是“否”,那么剩下的问题就是:什么是最佳的实现方案?一个自定义指令(“ E” +“ A”)说:
<limitedAccss admin>Edit page</limitedAccess> <limitedAccss user>view page</limitedAccess>
还是仅在用户对象上使用条件的常规ng-show?
解决方法是在这个小提琴中:
http://jsfiddle.net/BmQuY/3/
var app = angular.module('myApp', []); app.service('authService', function(){ var user = {}; user.role = 'guest'; return{ getUser: function(){ return user; }, generateRoleData: function(){ /* this is resolved before the router loads the view and model. It needs to return a promise. */ /* ... */ } } }); app.directive('restrict', function(authService){ return{ restrict: 'A', priority: 100000, scope: false, compile: function(element, attr, linker){ var accessDenied = true; var user = authService.getUser(); var attributes = attr.access.split(" "); for(var i in attributes){ if(user.role == attributes[i]){ accessDenied = false; } } if(accessDenied){ element.children().remove(); element.remove(); } return function linkFn() { /* Optional */ } } } });
如果要在IE 7或8中使用此指令,则需要手动删除元素的子级,否则将引发错误:
angular.forEach(element.children(), function(elm){ try{ elm.remove(); } catch(ignore){} });
可能的用法示例:
<div data-restrict access='superuser admin moderator'><a href='#'>Administrative options</a></div>
使用噶+茉莉花单元测试: 注意: 该done回调函数仅适用于茉莉花2.0,如果您使用的1.3,你应该使用waitsFor代替。
done
describe('restrict-remove', function(){ var scope, compile, html, elem, authService, timeout; html = '<span data-restrict data-access="admin recruiter scouter"></span>'; beforeEach(function(){ module('myApp.directives'); module('myApp.services'); inject(function($compile, $rootScope, $injector){ authService = $injector.get('authService'); authService.setRole('guest'); scope = $rootScope.$new(); // compile = $compile; timeout = $injector.get('$timeout'); elem = $compile(html)(scope); elem.scope().$apply(); }); }); it('should allow basic role-based content discretion', function(done){ timeout(function(){ expect(elem).toBeUndefined(); done(); //might need a longer timeout; }, 0); }); }); describe('restrict-keep', function(){ var scope, compile, html, elem, authService, timeout; html = '<span data-restrict data-access="admin recruiter">'; beforeEach(function(){ module('myApp.directives'); module('myApp.services'); inject(function($compile, $rootScope, $injector){ authService = $injector.get('authService'); timeout = $injector.get('$timeout'); authService.setRole('admin'); scope = $rootScope.$new(); elem = $compile(html)(scope); elem.scope().$apply(); }); }); it('should allow users with sufficient priviledsges to view role-restricted content', function(done){ timeout(function(){ expect(elem).toBeDefined(); expect(elem.length).toEqual(1); done(); //might need a longer timeout; }, 0) }) });
元素的通用访问控制指令,不使用ng-if(仅自V1.2-当前是不稳定的)或ng-show,它们实际上并未从DOM中删除元素。