rutas redireccionar por pasar parametros example entre con componentes angular typescript angular2-routing

angular - redireccionar - Pase el parámetro a la guardia de ruta



rutas angular 5 (3)

Aquí está 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 una lista de permisos como parámetro, pero es lo mismo que tiene un papel.

Tenemos una clase para tratar con guardias de autenticación con o sin permiso:

@Injectable() export class AuthGuardService implements CanActivate { checkUserLoggedIn() { ... }

Esto trata de verificar la sesión activa del usuario, etc.

También contiene un método utilizado para obtener una protección de permisos personalizada, que en realidad depende del AuthGuardService

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; }

Esto nos permite usar el método para registrar algunas protecciones personalizadas basadas en el parámetro de permisos en nuestro módulo de enrutamiento:

.... { path: ''something'', component: SomeComponent, canActivate: [ AuthGuardService.forPermissions(''permission1'', ''permission2'') ] },

La parte interesante de forPermission es AuthGuardService.guards.push , esto básicamente se asegura de que en cualquier momento que se llame a forPermissions para obtener una clase de guardia personalizada, también la almacene en esta matriz. Esto también es estático en la clase principal:

public static guards = [ ];

Entonces podemos usar esta matriz para registrar a 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, se hayan definido las rutas y se hayan creado todas las clases de guardias (por ejemplo, verifique el orden de importación y mantenga a estos proveedores lo más bajo posible en la lista; tener un módulo de enrutamiento ayuda):

providers: [ // ... AuthGuardService, ...AuthGuardService.guards, ]

Espero que esto ayude.

Estoy trabajando en una aplicación que tiene muchas funciones que necesito para usar guardias para bloquear el acceso a partes de la aplicación en función de esas funciones. Me doy cuenta de que puedo crear clases de guardia individuales para cada rol, pero preferiría tener una clase en 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 se me ocurre una manera de hacerlo. ¿Debería simplemente morder la bala y escribir las clases de guardia individuales por rol y romper mi ilusión de elegancia al tener un solo tipo parametrizado?


La solución de @ AluanHaddad es dar un error "sin proveedor". Aquí hay una solución para eso (se siente sucio, pero me faltan las habilidades para hacer uno mejor).

Conceptualmente, registro, como proveedor, cada clase generada dinámicamente creada por roleGuard .

Entonces, para cada rol marcado:

canActivate: [roleGuard(''foo'')]

Deberías:

providers: [roleGuard(''foo'')]

Sin embargo, la solución de @ AluanHaddad como está generará una nueva clase para cada llamada a roleGuard , incluso si el parámetro roles es el mismo. Usando lodash.memoize se ve así:

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

Tenga en cuenta que cada combinación de roles genera una nueva clase, por lo que debe registrar como proveedor cada combinación de roles. Es decir, si tienes:

canActivate: [roleGuard(''foo'')] y canActivate: [roleGuard(''foo'', ''bar'')] deberá registrar ambos: providers[roleGuard(''foo''), roleGuard(''foo'', ''bar'')]

Una mejor solución sería registrar proveedores automáticamente en una colección global de proveedores dentro de roleGuard , pero como dije, no tengo las habilidades para implementar eso.


Tienes que hacer esto.

En lugar de usar forRole() , deberías usar esto:

{ path: ''super-user-stuff'', component: SuperUserStuffComponent, canActivate: RoleGuard, data: {roles: [''SuperAdmin'', ...]} }

y use esto en su RoleGuard

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) : Observable<boolean> | Promise<boolean> | boolean { let roles = route.data.roles as Array<string>; ... }