40

I have an AccessGuard class in my project which its work is to determine if user can access to the route or not. I used the router.url to get the current route but the url returns the route before navigation to the new route like I'm in the users route and I click on the candidates route so the url returns users instead of candidates which I want that to validate access to the route this is my route file:

const routes:Routes = [
{
    path:'',
    component:PanelComponent,
    canActivate:[AuthGuard,AccessGuard],
    canActivateChild:[AuthGuard,AccessGuard],
    children:[
        {
            path:'dashboard',
            component:DashboardComponent
        },
        {
            path:'users',
            component:UsersComponent
        },
        {
            path:'users/:id',
            component:ShowUserComponent
        },
        {
            path:'candidates',
            component:CandidatesComponent
        },
        {
            path:'permissions',
            component:PermissionsComponent
        },
        {
            path:'holidays',
            component:HolidaysComponent
        },
        {
            path:'candidate/:id',
            component:CandidateComponent
        },
        {
            path:'salary/create',
            component:InsertSalaryComponent
        },
        {
            path:'document/create',
            component:InsertDocumentComponent
        },
        {
            path:'leave/create',
            component:InsertLeaveComponent
        }
    ]
}

];

and this is my access guard:

permissions;
currentRoute;
constructor(private authService:AuthService,private router:Router){
    this.permissions = this.authService.getPermissions();
}

canActivate(){
    return this.checkHavePermission();
}

canActivateChild(){
    console.log(this.router.url);
    return this.checkHavePermission();
}

private checkHavePermission(){
    switch (this.router.url) {
        case "/panel/users":
            return this.getPermission('user.view');
        case '/panel/dashboard':
            return true;
        case '/panel/candidates':
            return this.getPermission('candidate.view');
        default:
            return true;
    }
}


getPermission(perm){
    for(var i=0;i<this.permissions.length;i++){
        if(this.permissions[i].name == perm ){
            return true;
        }
    }
    return false;
}
Hossein Ahmadi
  • 839
  • 2
  • 11
  • 24

3 Answers3

70

You need to use the method parameters to see the target route:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
  console.log(state.url);//'candidates'
}

canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot)
Guilherme Meireles
  • 7,849
  • 2
  • 21
  • 15
  • I just have question I removed the ActivatedRouteSnapshot from parameters and the state.url returned an array but if the ActivatedRouteSnapshot is in arguments it's passes the actual url why? – Hossein Ahmadi Sep 28 '16 at 12:42
  • 1
    You should not remove the ActivatedRouteSnapshot from parameters even if you just want to use the RouterStateSnapshot parameter. The parameters are defined by position. The first parameter will always be the ActivatedRouteSnapshot and its url field is an array. The second parameter will always be the RouterStateSnapshot parameter and its url field is a string. Hope it helps. – Guilherme Meireles Sep 28 '16 at 15:52
  • 4
    beware: if your url has queryparams, you might have to do this: `console.log(state.url.substring(0, state.url.indexOf("?")));` – Anand Rockzz Dec 28 '17 at 01:35
  • How I check path with param? For example: When I have /posts/:id state.url returns /posts/5 – Temo Kiknadze Nov 11 '20 at 19:53
5

this could help you:

  1. Import ActivatedRouteSnapshot and RouterStateSnapshot:

    import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';

  2. Signature in the canActivate:

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable {}

  3. Check the state:

    console.log("route-access",state);

Your Guard file would look something like this:

    import { Injectable } from '@angular/core';
    import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
    import { Observable } from 'rxjs';
    import { AutenticacionService } from 'app/services/index';
    @Injectable()
    export class AuthGuard implements CanActivate {
        constructor(private _router: Router, private auth:AutenticacionService) {}
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<boolean> {
        // console.log("route-access",state);
        let _url:string="";
        state.url.split("/").forEach(element => {
            if(_url==="")
                if(element!=="")
                    _url=element;
        });
        // console.log(_url);
        return this.auth.check(_url)
          .map((result) => {
                    if (result) {
                        return true;
                    } else {
                        this._router.navigate(['/']);
                        return false;
                    }
                });  
    }

}
eberlast
  • 160
  • 2
  • 7
2

Current URL can be returned from RouterStateSnapshot as shown below,

    import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';    

    canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot){
      console.log(state.url);  
      ...
    }
Chandan Y S
  • 968
  • 11
  • 21