Aqui está minha opinião sobre isso e uma possível solução para o problema do provedor ausente.
No meu caso, temos um guarda que leva uma permissão ou lista de permissões como parâmetro, mas é a mesma coisa ter uma função.
Temos uma aula para lidar com os guardas de autenticação com ou sem permissão:
@Injectable()
export class AuthGuardService implements CanActivate {
checkUserLoggedIn() { ... }
Trata-se de verificar a sessão ativa do usuário, etc.
Ele também contém um método usado para obter uma proteção de permissão personalizada, que na verdade depende do AuthGuardService
próprio
static forPermissions(permissions: string | string[]) {
@Injectable()
class AuthGuardServiceWithPermissions {
constructor(private authGuardService: AuthGuardService) { } // uses the parent class instance actually, but could in theory take any other deps
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
// checks typical activation (auth) + custom permissions
return this.authGuardService.canActivate(route, state) && this.checkPermissions();
}
checkPermissions() {
const user = ... // get the current user
// checks the given permissions with the current user
return user.hasPermissions(permissions);
}
}
AuthGuardService.guards.push(AuthGuardServiceWithPermissions);
return AuthGuardServiceWithPermissions;
}
Isso nos permite usar o método para registrar alguns guardas personalizados com base no parâmetro de permissões em nosso módulo de roteamento:
....
{ path: 'something',
component: SomeComponent,
canActivate: [ AuthGuardService.forPermissions('permission1', 'permission2') ] },
A parte interessante disso forPermission
é AuthGuardService.guards.push
- basicamente, isso garante que a qualquer momento que forPermissions
for chamado para obter uma classe de guarda personalizada, ela também a armazenará neste array. Isso também é estático na classe principal:
public static guards = [ ];
Então, podemos usar essa matriz para registrar todos os guardas - isso está ok, contanto que tenhamos certeza de que, no momento em que o módulo de app registra esses provedores, as rotas foram definidas e todas as classes de guarda foram criadas (por exemplo, verificar a ordem de importação e mantenha esses provedores o mais baixo possível na lista - ter um módulo de roteamento ajuda):
providers: [
// ...
AuthGuardService,
...AuthGuardService.guards,
]
Espero que isto ajude.