Estoy trabajando en una aplicación que tiene muchos roles que necesito para usar guardias para bloquear la navegación a partes de la aplicación según esos roles. Me doy cuenta de que puedo crear clases de guardia individuales para cada rol, pero prefiero tener una clase a la que de alguna manera podría pasar un parámetro. En otras palabras, me gustaría poder hacer algo similar a esto:
{
path: 'super-user-stuff',
component: SuperUserStuffComponent,
canActivate: [RoleGuard.forRole('superUser')]
}
Pero como todo lo que pasa es el nombre del tipo de su guardia, no puedo pensar en una forma de hacerlo. ¿Debería simplemente tomarme la bala y escribir las clases de guardias individuales por rol y romper mi ilusión de elegancia al tener un solo tipo parametrizado en su lugar?
angular
typescript
angular2-routing
Brian Noyes
fuente
fuente
roles
objeto y la protección de ruta están vinculados sin saber cómo funciona el código de antemano. Apesta que Angular no admita una forma de hacer esto de una manera más declarativa. (Para que quede claro, me estoy lamentando de que Angular no sea esta solución perfectamente razonable.)Esta es mi opinión sobre esto y una posible solución para el problema del proveedor que falta.
En mi caso, tenemos un guardia que toma un permiso o lista de permisos como parámetro, pero es lo mismo que tiene un rol.
Tenemos una clase para tratar con los guardias de autenticación con o sin permiso:
Se trata de comprobar la sesión activa del usuario, etc.
También contiene un método que se utiliza para obtener un protector de permisos personalizado, que en realidad depende del
AuthGuardService
propioEsto nos permite usar el método para registrar algunos guardias personalizados basados en el parámetro de permisos en nuestro módulo de enrutamiento:
La parte interesante de
forPermission
esAuthGuardService.guards.push
- esto básicamente se asegura de que cada vez queforPermissions
se llama para obtener una clase de protección a medida que también lo almacenará en esta matriz. Esto también es estático en la clase principal:Luego, podemos usar esta matriz para registrar todos los guardias; esto está bien siempre y cuando nos aseguremos de que para cuando el módulo de la aplicación registre a estos proveedores, las rutas se hayan definido y todas las clases de guardias se hayan creado (por ejemplo, verificar el orden de importación y mantenga estos proveedores lo más bajo posible en la lista; tener un módulo de enrutamiento ayuda):
Espero que esto ayude.
fuente
ERROR in Error during template compile of 'RoutingModule' Function calls are not supported in decorators but 'PermGuardService' was called.
La solución de @ AluanHaddad está dando el error "sin proveedor". Aquí hay una solución para eso (se siente sucio, pero no tengo las habilidades para hacer uno mejor).
Conceptualmente, registro, como proveedor, cada clase generada dinámicamente creada por
roleGuard
.Entonces, para cada rol verificado:
Deberías:
Sin embargo, la solución de @ AluanHaddad tal como está generará una nueva clase para cada llamada a
roleGuard
, incluso si elroles
parámetro es el mismo. Usarlolodash.memoize
se ve así:Tenga en cuenta que cada combinación de roles genera una nueva clase, por lo que debe registrarse como proveedor en cada combinación de roles. Es decir, si tienes:
canActivate: [roleGuard('foo')]
ycanActivate: [roleGuard('foo', 'bar')]
tendrás que registrar ambos:providers[roleGuard('foo'), roleGuard('foo', 'bar')]
Una mejor solución sería registrar proveedores automáticamente en una colección de proveedores globales dentro
roleGuard
, pero como dije, carezco de las habilidades para implementar eso.fuente