我们假设我的角度SPA应用程序中有一个菜单,现在我希望向所有用户显示基本选项,例如家庭,关于我们,运营商机会等。
我还想提供其他几个选项,例如管理用户,管理帖子等,这些选项只会显示给管理员。
我们还假设我们有一个API访问点,它为我提供了用户角色,或者更好的是,用户角色位于从/ api / users / me检索的对象中。
将这些管理工具封装为普通用户查看的最佳方式是什么?
视图之间是否存在某种继承?像在Django?中,有没有办法隐藏未经授权的用户的DOM元素?(是的,我知道它是客户端)。
我真的不想对菜单使用不同的视图,因为它应该是一个通用组件。
我想如果我之前所有问题的答案都是否定的,那么剩下的问题是:对此最好的实施是什么?自定义指令(“E”+“A”) 说:
<limitedAccss admin>Edit page</limitedAccess>
<limitedAccss user>view page</limitedAccess>
或者只是使用带有用户对象条件的常规ng-show?。
答案 0 :(得分:38)
解决方案就是这个小提琴:
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>
使用Karma + Jasmine进行单元测试:
注意: done
回调功能仅适用于Jasmine 2.0,如果您使用的是1.3,则应使用waitsFor代替。
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开始 - 当前不稳定),或者实际上不从DOM中删除元素的ng-show。
答案 1 :(得分:3)
ng-if
绝对是我的方式!只需将审核工具放在它们所属的视图中,如果用户应该拥有它们,它们就会出现。如果您使用1.1.5之前的角度版本,ng-show
/ ng-hide
也可以。
非常重要的是确保你的后端/服务器/ api不会因为你的js打电话给主持人的行动而不尊重请求!始终让服务器在每次通话时验证其授权。
答案 2 :(得分:0)
ng-if或ng-hide可以做到这一点,
html只是一个视图,不应该负责处理安全性,安全性
拥有与用户关联的权限对象可能很有用。 当我检索用户数据时,我得到一个权限json然后在角度
date msft nok aapl ibm amzn
2018-01-01 08:00:00 107 2 161 140 1295
2018-01-01 09:00:00 112 1 143 130 1298
2018-01-01 10:00:00 109 10 185 137 1647
2018-01-01 11:00:00 98 11 146 105 1331
2018-01-01 12:00:00 83 3 214 131 1355
用户Json看起来像这样:
<div ng-if="user.permissions.restrictedArea">Very restricted area</div>