Angular2 Route Access denied logic

4.5k views Asked by At

I'm trying to put access checks for routes and display access denied page instead of actual page. From the example below we can alert access denied on route click . I would prefer to navigate to the actual page and then show Access denied.

http://plnkr.co/edit/w1NCkGs0Tv5TjivYMdvt?p=preview

lets say url with access check is /admin/manageusers and component name is ManageUserComponent and if a user don't have access and tries the url, it should navigate to the route /admin/manageusers but should be showing Access Denied in the page.

1.One thing i can do is to use route resolve feature and get the value related to users access and in ManageUserComponent and switch the template. This approach will endup having similar code in multiple components associated with routes where i want to implement access logic.

  1. Let all component where access check needed extends another base class and validate above logic , if success then allow child component to proceed. Yet to figure out how to extend another class properly

Main goal is to preserve the accessed url with error message in the page. And the component functions should not execute.

If you can think of approaches and options to implement, please share.

If the description is not clear please let me know, i will try to make it better.

2

There are 2 answers

2
nomadev On

You can do something like this on the app-routing.module.ts

// PRIVATE ROUTES
{
    path: 'dashboard',
    component: DashboardComponent,
    canActivate: [LoggedInGuard]
},

then define this LoggedInGuard service

// logged-in.guard.ts
import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { AuthService } from './auth.service';

@Injectable()
export class LoggedInGuard implements CanActivate {
    constructor(
        private _router: Router,
        private _authService: AuthService) { }

    canActivate() {
        // return true
        if (this._authService.isLogged()) {
            // all ok, proceed navigation to routed component
            return true;
        }
        else {
            // redirect to the homepage
            this._router.navigate(['/'], { skipLocationChange: true });
            // abort current navigation
            return false;
        }
    }
}

Hope this may help you out.

0
Sergey Romanchuk On
  1. Implement CanActivate logic

  2. Implement guarded component and add route to it (for instance: 'denied').

  3. Use skipLocationChange option to navigate in router

@Injectable()
export class CanActivateRequestForm implements CanActivate {
    constructor(private authService: AuthService, private router: Router) {}
    canActivate(
        route: ActivatedRouteSnapshot,
        state: RouterStateSnapshot,
    ): Observable<boolean>|Promise<boolean>|boolean {
        let obs = this.authService.userChange.asObservable().map(({role}) => role === Role.Admin);
        obs.subscribe(v => {
            if (!v)
                this.router.navigate(['denied'], {
                    skipLocationChange: true
                });
        });
        return obs;
    }
}