Pass parameter into route guard

后端 未结 3 1839
暖寄归人
暖寄归人 2020-12-02 12:28

I\'m working on an app that has a lot of roles that I need to use guards to block nav to parts of the app based on those roles. I realize I can create individual guard class

3条回答
  •  时光取名叫无心
    2020-12-02 13:19

    @AluanHaddad's solution is giving "no provider" error. Here is a fix for that (it feels dirty, but I lack the skills to make a better one).

    Conceptually, I register, as a provider, each dynamically generated class created by roleGuard.

    So for every role checked:

    canActivate: [roleGuard('foo')]
    

    you should have:

    providers: [roleGuard('foo')]
    

    However, @AluanHaddad's solution as-is will generate new class for each call to roleGuard, even if roles parameter is the same. Using lodash.memoize it looks like this:

    export var roleGuard = _.memoize(function forRole(...roles: string[]): Type {
        return class AuthGuard implements CanActivate {
            canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):
                Observable
                | Promise
                | boolean {
                console.log(`checking access for ${roles.join(', ')}.`);
                return true;
            }
        }
    });
    

    Note, each combination of roles generates a new class, so you need to register as a provider every combination of roles. I.e. if you have:

    canActivate: [roleGuard('foo')] and canActivate: [roleGuard('foo', 'bar')] you will have to register both: providers[roleGuard('foo'), roleGuard('foo', 'bar')]

    A better solution would be to register providers automatically in a global providers collection inside roleGuard, but as I said, I lack the skills to implement that.

提交回复
热议问题