1

I'm working with Nested Module Structure and having some difficulty to implement guard.

Right Now I have to use canActivate on parent module route and canActivateChild on every child module route.
I want a solution where I will just put guard on Parent module route and that guard will also be activated on all the child module routes...

Following is the module structure

app-routing.module.ts

{
    path: 'pages',
    loadChildren: () => PagesModule,
  },

pages-routing.module.ts canActivate on AdminModule route.

{
    path: 'admin',
    loadChildren: () => AdminModule,
    canActivate: [AuthGuard],
  },

admin-routing.module.ts canActivateChild on every child module of admin

{
    path: 'dashboard',
    loadChildren: () => DashboardModule,
    canActivateChild: [AuthGuard],
  },
  {
    path: 'allusers',
    loadChildren: () => AllUsersModule,
    canActivateChild: [AuthGuard],
  },

dashboard-routing.module.ts

const routes: Routes = [{ path: '', component: DashboardComponent }];

allusers-routing.module.ts

const routes: Routes = [{ path: '', component: AllUsersComponent }];

AuthGaurd

export class AuthGuard implements CanActivate, CanActivateChild {
  constructor(
    private readonly authService: AuthService,
    private readonly route: Router,
  ) {}

  async canActivate() {
    if (this.authService.isLoggedOut()) {
      localStorage.clear();
      this.route.navigate(['/login']);
      alert('Access Denied Token Not Found');
      return false;
    } else {
      return true;
    }
  }

  canActivateChild(
    childRoute: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ):
    | boolean
    | UrlTree
    | Observable<boolean | UrlTree>
    | Promise<boolean | UrlTree> {
    return this.canActivate();
  }
}
M Nouman
  • 437
  • 1
  • 5
  • 22

1 Answers1

0

Your question doesn't state this explicitly, but I'm going to assume that you want AuthGuard to execute on every child route of admin/ (in your example, these will be pages/admin/dashboard and pages/admin/allusers).

In this case, it seems that you confused canActivate with canActivateChild.

If you define pages-routing.module.ts like so:

  {
    path: 'admin',
    loadChildren: () => AdminModule,
    canActivate: [AuthGuard],      // fire for pages/admin page itself
    canActivateChild: [AuthGuard], // fire for every descendant
  },

then all routes that are descendants of pages/admin/ URL will fire AuthGuard on entry, every time navigation occurs into or within pages/admin/ URL tree. You don't need to add any canActivate or canActivateChild anywhere else in the routing configuration. Note that going to pages itself will not trigger AuthGuard.

Edit: added canActivate entry, too, since you wrote you want to guard pages/admin itself as well.

More generally, canActivateChild, when defined on route X/, will fire every time navigation occurs whose target is a descendant of route X/, but not route X itself.

Dzinx
  • 55,586
  • 10
  • 60
  • 78
  • I'm sorry If I didn't post an understandable question. But I don't want for every child of `pages`. I want for every child of `admin` – M Nouman Dec 21 '22 at 12:37
  • Including admin itself? – Dzinx Dec 21 '22 at 12:38
  • yes including `admin`. Although `pages` is parent. But I'm keeping `admin page` as parent in this particular case. – M Nouman Dec 21 '22 at 12:40
  • OK, I adjusted my answer. – Dzinx Dec 21 '22 at 12:42
  • `4200/admin` works. But `4200/dashboard` and `4200/allusers` are visible. guard is not working on them – M Nouman Dec 21 '22 at 12:44
  • Wait, what's your routing structure? It isn't hierarchical? How are the three routing modules connected? – Dzinx Dec 21 '22 at 12:46
  • The routing structure is in my question. Below the `Following is the module structure`. – M Nouman Dec 21 '22 at 12:47
  • `Pages Module` is imported in `App Module`. There are multiple pages including `admin` in `Pages Module`, and all those modules are `imported` in `Pages Module`. Then `Admin Module` is imported in `Pages Module`. And `Dashboard Module` and `Allusers Module` are imported in `Admin Module.` – M Nouman Dec 21 '22 at 12:53
  • `Dashboard and Allusers` are childeren of `Admin`. Admin is child of `Pages`. And Pages is imported in `App`. – M Nouman Dec 21 '22 at 12:56
  • If dashboard and allusers are children of admin, which is a child of pages, wouldn't that mean that the URL for allusers is actually 4200/pages/admin/allusers? – Dzinx Jan 02 '23 at 09:55
  • Yes you are right. But I have multiple child modules in pages. And I don't want to activate that guard on every child module. Instead I want to activate that guard for `Admin Module` and `Admin's Child Modules`. Let's say I have 5 modules in `pages module`. If I put guard on `pages` it will be activated on all those 5 `child modules of pages module`. And I don't want that. I want only `Admin and Admin's child` under `guard`, not other `Admin Siblings` as well. – M Nouman Jan 02 '23 at 19:03