UI路由器动态状态访问级别

时间:2014-09-23 16:11:44

标签: angularjs angular-ui-router

我有这样的状态设置。这基于解决方案中的:pageSlug via pageObj从数据库提供动态页面。 我想知道是否有可能使状态本身的data.access成为动态变量,这意味着状态将从数据库中获取其访问属性。

    .state('site.home.page', {
        url: ':pageSlug',
        data: {
            access: AccessLevels.anon //make me dynamic! Can I access the resolve from here?
        },
        resolve: {
            pageObj : function($stateParams, REST, $state) {
                return REST.getOne("/page?slug="+$stateParams.pageSlug).then(function(rtnData) {
                    $state.current.data.access = rtnData.access; //this doesn't work, $state.current doesn't seem to be loaded?
                    return rtnData;
                });
            },
        },

作为参考,我使用与此http://www.frederiknakstad.com/2013/01/21/authentication-in-single-page-applications-with-angular-js/

类似的设置

非常感谢任何帮助。

编辑:原来,$ state在解析或onEnter中无法使用。可注射的$ transition $状态正在整合中。 https://github.com/angular-ui/ui-router/issues/1257

2 个答案:

答案 0 :(得分:1)

$state.current.data.access = rtnData.access;运行时,$state.current是您来自的状态,而不是。一切都解决后,$state.current才会被更改。

您可能希望在那里记录$state.current以查看它是否是您认为应该是的,而不是来自〜之前的状态(您来自)。与$stateParams相同。

根据您何时需要访问数据,您可以在$stateChangeSuccess事件中进行设置。

答案 1 :(得分:1)

首先,我认为服务器应该在访问被拒绝时返回正确的HTTP状态代码,这样您就可以安全地处理它(并防止数据通过不应该看到的线路)。

但假设这不是一个选项,如果我是你,我会创建一个服务来存储你在解析页面时从服务器收到的ACL,如下所示:

(我正在输入这个,所以请考虑更像元代码)

// Service to keep track of ACL's
.factory('aclService', [function(){
    var service = {},
        acls = {};

    service.setAcl = function(slug, acl){
        acls[slug] = acl;
    };

    service.getAcl = function(slug){
        return acls[slug] || 'access denied'; // or whatever you want to return by default
    };

    return service;
}]);

因此您可以在收到ACL时使用它来存储ACL:

.state('site.home.page', {
    url: ':pageSlug',
    data: {
        access: AccessLevels.anon //make me dynamic! Can I access the resolve from here?
    },
    resolve: {
        pageObj : function($stateParams, REST, $state, aclService) {
            return REST.getOne("/page?slug="+$stateParams.pageSlug).then(function(rtnData) {

                // Store the ACL in the service
                aclService.setAcl($stateParams.pageSlug, rtnData.access);
                });
            }
        }
    });

然后查阅ACL以决定是否要加载状态:

// Listen to the SUCCESS event
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){

    var acl = aclService.getAcl(toParams.pageSlug);

    // Do whatever check is needed to verify access
    if(toState.data.access !== acl){

        // Do whatever you like to do here when access is denied
        // The state is already loaded but you can redirect the user away
    }
});

由于您正在使用服务来存储ACL的缓存,因此您可以进一步优化并在状态转换之前添加额外的检查,例如:

// Listen to the START event here
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){

    var acl = aclService.getAcl(toParams.pageSlug);

    // Return early if no cache is found
    if(acl === undefined){
        return;
    }

    // Do whatever check is needed to verify access
    if(toState.data.access !== acl){

        // Do whatever you like to do here when access is denied
        // The state will no longer be loaded now
    }
});

如果你真的想把它发挥到极致,你可以在引导你的AngularJS应用程序时预先加载所有ACL的aclService,这样你就可以开始使用热缓存了。

希望有所帮助!

相关问题