1

I am creating one angular2 app.

export const routes: Route[] = [
{path: '',redirectTo: "login",pathMatch: "full" }, 
{path: 'login', component: LoginComponent }, 
{path: 'dashboard', component: DashboardComponent,canActivate:[AuthGuard], children:
    [
        { path: '', redirectTo: 'dashboard', pathMatch: 'full' },
        { path: 'A', component: AComponent },
        { path: 'B', component: BComponent },

        { path: 'C', component: CComponent },
        { path: 'D', component: DComponent },
    ]
}];

When i login to my app using LoginComponent it will go to DashboardComponent which have four child components

  1. -A
  2. -B
  3. -C
  4. -D

Now i have by default set redirectTo to my dashboard component. but in place of this redirect i want to redirect to route A,B,C,D on the basis of type of login like wherether he is admin, superadmin, student or teacher.

Suppose

If Login User is "Admin" he should be redirectTo - > dashboard/A

If Login User is "Teacher" then he should be redirectTo - >dashboard/B

i have create authGuard like this

@Injectable()
export class AuthGuard implements CanActivate {

    constructor(public router: Router){ }

    canActivate(){
        if(localStorage.getItem('userData')){
            return true;
        }

        // this.router.navigateByUrl('/');
        return false;
    }
}

export class activateEmployee implements CanActivate {

    constructor(){ }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot){
        console.log(localStorage.getItem('userData'), "employee");
        if(localStorage.getItem('userData') == 'superadmin'){
            return true;
        }

        // this.router.navigateByUrl('/');
        return false;
    }
}

export class activateSuperAdmin implements CanActivate {

    constructor(public router: Router){ }

    canActivate(){
        console.log(localStorage.getItem('userData'), "Superadmin");
        if(localStorage.getItem('userData') == 'superadmin'){
            return true;
        }

        return false;
    }
}

export class activateAdmin implements CanActivate {

    constructor(public router: Router){ }

    canActivate(){
        console.log(localStorage.getItem('userData'),"Admin");
        if(localStorage.getItem('userData') == 'admin'){
            return true;
        }

        return false;
    }
}

PS: my main goal is to protect route that if someone knows the URL of protected route even than he is not able to go to there. or we can say i want something like multiple authGuard in a single service.

Update

Now i have created different classes for routing, but i am getting this error dont know why ? error is

 Can't resolve all parameters for activateAdmin: (?).
Community
  • 1
  • 1
Pardeep Jain
  • 84,110
  • 37
  • 165
  • 215
  • so do you want to redirect inside the guard? somehting like [this](https://stackoverflow.com/a/39002528/2545680)? – Max Koretskyi Jul 20 '17 at 06:29
  • no , i can redirect simply but i want to protect routes like if login role is admin than no can access routes of teacher role or student – Pardeep Jain Jul 20 '17 at 06:32
  • so why redirecting doesn't help? – Max Koretskyi Jul 20 '17 at 06:34
  • but if we just redirect than anyone can acecess protected route as well by just entering URL in browser which is not right way for routing – Pardeep Jain Jul 20 '17 at 06:37
  • when you enter the URL in a browser, Angular and the router still runs and the guards run as well. It's no different then navigating inside the app with the link – Max Koretskyi Jul 20 '17 at 06:45
  • You're mixing 2 requirements A and B in one question, and describe requirement A (re-direct after login) when wanting to do requirement B (role-based guards). For requirement B, you'd need to specify special guards for each child route (e.g. `{ path: 'A', component: AComponent, canActivate:[AdminAuthGuard] }, { path: 'B', component: BComponent, canActivate:[TeacherAuthGuard] }`) – Harry Ninh Jul 20 '17 at 06:45
  • I think the link provided by @Maximus would satisfy your problem. Even if someone know the url of your protected route, they'll not be able to access it – brijmcq Jul 20 '17 at 06:48
  • @brijmcq i completly agree link provided will work fine , but not in mine use case becasue in my case i not want only to protect dashboard instead i want to protect different 4 modules – Pardeep Jain Jul 20 '17 at 06:50
  • @HarryNinh yes exactly what i want, even i am trying the same but getting some error like this `Can't resolve all parameters for activateAdmin: (?).` – Pardeep Jain Jul 20 '17 at 06:51
  • @PardeepJain I understand, you can do what Harry Ninh commented but you will just end up with 4 different route guards that do the same thing. You can just simplify it using one guard with just an if/else or switch statements. – brijmcq Jul 20 '17 at 06:54
  • Can you show how you get the roles of your user so that I can post an answer – brijmcq Jul 20 '17 at 06:55
  • yups even i thought like this, but problem is if we use if else in same class than how can you set `canActivate` method in routing file for diff. conditions ? l – Pardeep Jain Jul 20 '17 at 06:56
  • @brijmcq i got the solution, please check my answer. – Pardeep Jain Jul 20 '17 at 07:06
  • error is because i am missing `@injectable()` on every service – Pardeep Jain Jul 20 '17 at 07:20

2 Answers2

3

Instead of creating 4 different route guards, you can refactor it using just one by using switch/if-else in your route guard like this

canActivate(){
  let theRole = localStorage.getItem('userData');
  switch(theRole){
   case "admin": { 
       this.router.navigate(['/dashboard/a']);
      return true;
   } 
   case "teacher": { 
     this.router.navigate(['/dashboard/b']);
      return true;       
   } 
   case "superadmin": {
     this.router.navigate(['/dashboard/c']);
     return true;    
   } 
   case "student": { 
  this.router.navigate(['/dashboard/d']);
    return true;
   }  
   default: { 
    this.router.navigate(['/login'])
     return false;           
   } 
  }

If having 4 different route guards suits you, you don't need to follow the code. At the end, it still boils down to personal preference or practices of your team

brijmcq
  • 3,354
  • 2
  • 17
  • 34
  • haha thanku mate for your answer, your answer is correct but problem with your answer is that your `authGuard` will always return true if case value is either `admin` , `superadmin` or `student` , than how will you put condition in the routing file becuase there you just set `canActivate:[authGuard]` for all cases which is false , that is why i have to create 4 guards for diff. role, i hope you get my point – Pardeep Jain Jul 21 '17 at 08:00
  • Yes I get your point :) You are correct that it will return true whenever you have roles but they will be redirected to their own dashboard. Let's say my role is student, I will not be able to go to the admin dashboard. Thank you for your reply though – brijmcq Jul 21 '17 at 08:36
  • @PardeepJain one more question because I just want to deepen my knowledge, what's your problem if it always return true if the role is admin, role etc. if it will still be redirected to their proper dashboards? Even if I only use a one route guard for the pages. I'm just curious. Though I understand you may want to separate your code in files to have their own responsibility. – brijmcq Jul 21 '17 at 10:54
0

Got the solution (hint from from here)

I just have to create different classes by implementing CanActivate for conditions so that you can apply that guard into your routing like this

{path: 'dashboard', component: DashboardComponent,canActivate:[AuthGuard], children:
    [
        { path: '', redirectTo: 'dashboard', pathMatch: 'full' },
        { path: 'A', component: AComponent , canActivate: [activateA]},
        { path: 'B', component: BComponent , canActivate: [activateB]},
        .....
Pardeep Jain
  • 84,110
  • 37
  • 165
  • 215