0

I have implemented Routing and Guard Service in my application. When navigate by clicking by anchor tag button it is working fine. But, when I try to navigate by hitting url it is returning empty page.

app-routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { PageForbiddenComponent } from './error/page-forbidden/page-forbidden.component';
import { PageNotfoundComponent } from './error/page-notfound/page-notfound.component';
import { HomeComponent } from './home/home.component';
import { LayoutComponent } from './layout/layout.component';
import { LoginComponent } from './login/login.component';
import { ProfileComponent } from './profile/profile.component';
import { AuthGuardService } from './service/auth-guard.service';
import { TaskComponent } from './task/task.component';

const routes: Routes = [
  { path: '', component: LoginComponent },
  {
    path: 'layout',
    component: LayoutComponent,
    canActivateChild: [AuthGuardService],
    children: [
      { path: '', component: HomeComponent },
      {
        path: 'profile',
        component: ProfileComponent,
      },
      {
        path: 'task',
        component: TaskComponent,
      },
    ],
  },
  { path: '403', component: PageForbiddenComponent },
  { path: '404', component: PageNotfoundComponent },
  { path: '**', redirectTo: '404' },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

auth-guard.service.ts

import { Injectable } from '@angular/core';
import {
  ActivatedRouteSnapshot,
  CanActivate,
  CanActivateChild,
  Route,
  Router,
  RouterStateSnapshot,
  UrlTree,
} from '@angular/router';
import { Observable } from 'rxjs';
import { IChildMenuEntity } from '../model/login/IChildMenuEntity';
import { IUserDetailsEntity } from '../model/login/IUserDetailsEntity';
import { AppSettingsService } from './app-settings.service';
import { LoginService } from './login.service';

@Injectable({
  providedIn: 'root',
})
export class AuthGuardService implements CanActivate, CanActivateChild {
  userDetails!: IUserDetailsEntity;
  childMenuItems!: IChildMenuEntity[];
  token: string;
  defaultPage = '/layout';

  constructor(
    private _router: Router,
    private _loginService: LoginService,
    private _appSettings: AppSettingsService
  ) {}
  canActivateChild(
    childRoute: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ):
    | boolean
    | UrlTree
    | Observable<boolean | UrlTree>
    | Promise<boolean | UrlTree> {
    this.token = localStorage.getItem(
      this._appSettings.appConstants.tokenHeader
    );
    this.userDetails = this._loginService.userDetails;
    if (this.token) {
      if (this.userDetails == null || this.userDetails == undefined) {
        this._loginService.GetCurrentUserDetails().subscribe((data) => {
          this._loginService.userDetails = data;
          this.userDetails = this._loginService.userDetails;
          return this.AuthorizeRoute(state, this.userDetails);
        });
      } else {
        return this.AuthorizeRoute(state, this.userDetails);
      }
    } else {
      this._router.navigateByUrl('/');
      return false;
    }
  }
  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ):
    | boolean
    | UrlTree
    | Observable<boolean | UrlTree>
    | Promise<boolean | UrlTree> {
    this.token = localStorage.getItem(
      this._appSettings.appConstants.tokenHeader
    );
    this.userDetails = this._loginService.userDetails;
    if (this.token) {
      if (this.userDetails == null || this.userDetails == undefined) {
        this._loginService.GetCurrentUserDetails().subscribe((data) => {
          this._loginService.userDetails = data;
          this.userDetails = this._loginService.userDetails;
          // return this.AuthorizeRoute(state, this.userDetails);
          this._router.navigateByUrl(this.defaultPage);
        });
      } else {
        // return this.AuthorizeRoute(state, this.userDetails);
        this._router.navigateByUrl(this.defaultPage);
      }
    } else {
      this._router.navigateByUrl('/');
      return false;
    }
  }

  GetConfiguredRoutes = (): Route[] => {
    return this._router.config[1].children;
  };

  AuthorizeRoute = (
    state: RouterStateSnapshot,
    userDetails: IUserDetailsEntity
  ): any => {
    console.log(state.url);

    if (userDetails != null) {
      let configuredRoutes = this.GetConfiguredRoutes();
      let sideMenus = [];
      userDetails.sideMenu.forEach((x) => {
        x.childMenuEntities.forEach((y) => {
          sideMenus.push(y.routeURL);
        });
      });

      console.log(sideMenus);

      if (this.defaultPage.toLowerCase() === state.url.toLowerCase()) {
        if (configuredRoutes.find((x) => x.path == '')) {
          return true;
        } else {
          this._router.navigateByUrl('/404');
          return false;
        }
      } else {
        console.log('other than home');

        if (
          configuredRoutes.find(
            (x) => `${this.defaultPage}/${x.path.toLowerCase()}` == state.url
          )
        ) {
          console.log('Route Configured');

          if (sideMenus.find((x) => x.toLowerCase() === state.url)) {
            console.log('valid route');
            return true;
          } else {
            this._router.navigateByUrl('/403');
            return false;
          }
        } else {
          this._router.navigateByUrl('/404');
          return false;
        }
      }
    }
  };
}

This are the configuration i have done in the guard and routing. So when i try to navigate using side menu it is working fine. But when i enter url in the browser search it is not working as expected i.e it is navigating to the URL:localhost:4200/ not to the eg-URL:localhost:4200/layout/profile.

Please help me!!!! Thanks in advance!!!

pjpscriv
  • 866
  • 11
  • 20
prakash s
  • 33
  • 4
  • 1
    Why not try and debug and see if you are getting a token from local storage when you enter the URL on the browser. – Frank Fajardo Mar 08 '22 at 04:10
  • I haven't seen the problem, but just a side note, you shouldn't redirect the user directly in the guard, instead return a UrlTree to the 404 page (or promise/observable). In the same spirit, don't subscribe in the Guard, instead return an Observable thus you won't have to unsubscribe + I'm pretty sure the return you made in subs won't work as you expect those to work. – Jean-Xavier Raynaud Mar 16 '22 at 14:13

0 Answers0