0

Im using role guards . A user can access certain routes only if user has certain rights. The user rights are fetched from backend using a service called login service inside app root component and is stored in a set inside a configuration service. The user rights are fetched from service when required.The problem is that my role guard also needs to fetch the user rights. Since my user rights are fetched inside app component,the role guard is getting executed before the user rights service response . Im forced to call data again from backend inside the role guard.Ideally i want the data to be fetched only once.How to go about this?

Inside app.component.ts:


      loadUserOtherDetails() {
        forkJoin([this.loginService.userRights(), this.loginService.mytenant()]).subscribe(data => {
          this.onUserRightsReceived(data[0]);
          this.onTenantDataReceived(data[1]);
        });
      }


      onUserRightsReceived(userRights) {
        this.confService.updateRights(userRights["rights"]);

        }
      }

Inside configuration service(confService):

        public rights: Subject<Array<string>>;
      updateRights(rights: Array<string>) {
            this.rights.next(rights);
        }

        getRights() {
            return this.rights.asObservable();
        }

Inside role guard:

@Injectable()
export class RoleGuard implements CanActivate {
  activate = false;

  constructor(private loginService: LoginServiceService,
    private router: Router,
    private configService:ConfigurationService
  ) {
  }

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> | boolean {

    return this.confService.getRights().pipe(map((userRights) => {
      console.log("rights",userRights)
      this.configService.updateRights(userRights['rights']);
      return this.filterUserRights(userRights['rights']);
    }),
    )
  }

  filterUserRights(userRights:Array<string>){
    const requiredRights = ['create_organisation', 'create_tenant', 'create_user'];
    if (requiredRights.some((right) => userRights && userRights.includes(right))) {
      this.activate = true;
    } else {
      this.activate = false;
    }
    return this.activate;
  }

}

This works when after user logs in first time. But if i refresh the page,the rights do not get stored in confservice first.

I created resolver :

import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
import { LoginServiceService } from './login-service.service';

@Injectable()
export class RightsResolver implements Resolve<any> {
  constructor(private loginService:LoginServiceService) {}

  resolve() {
    return this.loginService.userRights();
  }
}

My routing:

const routes: Routes = [
  {
    path: "", redirectTo: "mylearning", pathMatch: "full", resolve: { rightsResolver: RightsResolver }
 },
  {
    path: "managepeople",
    component: ManagepeopleComponent,
    canActivate: [RoleGuard],
    children: [
      { path: "", redirectTo: "organisations", pathMatch: "full" },
      {
        path: "organisations",
        component: OrganisationsComponent,
        data: {
          animation: "organisations"
        }
      },

      {
        path: "organisations/create",
        component: OrganisationAddComponent,
        data: {
          breadcrumb: [
            {
              label: "Organisations ",
              url: "organisations"
            },
            {
              label: "Add",
              url: ""
            }
          ]
        }
      },
      {
        path: "organisation-edit/:id",
        component: OrganisationEditComponent,
        data: {
          breadcrumb: [
            {
              label: "Organisations ",
              url: "organisations"
            },
            {
              label: "{{orgName}} ",
              url: "organisation-detail/:id"
            },
            {
              label: "Edit",
              url: ""
            }
          ]
        }
      },
      {
        path: "organisation-detail/:id",
        component: OrganisationDetailComponent,
        data: {
          breadcrumb: [
            {
              label: "Organisations ",
              url: "organisations"
            },
            {
              label: "{{orgName}}",
              url: ""
            }
          ]
        },

        children: [
          { path: "", component: OrgMainComponent },
          {
            path: "orgunits/:id",
            component: OrganisationUnitsOfOrganisationComponent,
            data: {
              animation: "orgunitslist",
              breadcrumb: [
                {
                  label: "Organisations ",
                  url: "organisations"
                },
                {
                  label: "{{orgName}} ",
                  url: "organisation-detail/:id"
                },
                {
                  label: "Organisation Units ",
                  url: ""
                }
              ]
            }
          },

          {
            path: "orgunits/:id/add",
            component: OrganisationUnitsOfOrganisationAddComponent,
            data: {
              animation: "orgunitadd",
              breadcrumb: [
                {
                  label: "Organisations ",
                  url: "organisations"
                },
                {
                  label: "{{orgName}} ",
                  url: "organisation-detail/:id"
                },
                {
                  label: "Organisation Units ",
                  url: "organisation-detail/:id/orgunits/:id"
                },
                {
                  label: "Add ",
                  url: ""
                }
              ]
            }
          },
          {
            path: "orgunits/:id/:orgUnit/edit",
            component: OrganisationUnitsOfOrganisationEditComponent,
            data: {
              animation: "orgunitedit",
              breadcrumb: [
                {
                  label: "Organisations ",
                  url: "organisations"
                },
                {
                  label: "{{orgName}} ",
                  url: "organisation-detail/:id"
                },
                {
                  label: "Organisation Units ",
                  url: "organisation-detail/:id/orgunits/:id"
                },
                {
                  label: "Edit ",
                  url: ""
                }
              ]
            }
          },

          {
            path: "users/:id",
            component: UsersOfOrganisationComponent,
            pathMatch: "full",
            data: {
              animation: "userslist",
              breadcrumb: [
                {
                  label: "Organisations ",
                  url: "organisations"
                },
                {
                  label: "{{orgName}} ",
                  url: "organisation-detail/:id"
                },
                {
                  label: "Users ",
                  url: ""
                }
              ]
            }
          },
          {
            path: "users/:id/add",
            component: UsersOfOrganisationAddComponent,
            data: {
              animation: "usertadd",
              breadcrumb: [
                {
                  label: "Organisations ",
                  url: "organisations"
                },
                {
                  label: "{{orgName}} ",
                  url: "organisation-detail/:id"
                },
                {
                  label: "Users ",
                  url: "organisation-detail/:id/users/:id"
                },
                {
                  label: "Add ",
                  url: ""
                }
              ]
            }
          },
          {
            path: "users/:id/:user/edit",
            component: UsersOfOrganisationEditComponent,
            data: {
              animation: "useredit",
              breadcrumb: [
                {
                  label: "Organisations ",
                  url: "organisations"
                },
                {
                  label: "{{orgName}} ",
                  url: "organisation-detail/:id"
                },
                {
                  label: "Users",
                  url: "organisation-detail/:id/users/:id"
                },
                {
                  label: "Edit ",
                  url: ""
                }
              ]
            }
          },

          {
            path: "positions/:id",
            component: PositionsOfOrganisationComponent,
            data: {
              animation: "positionslist",
              breadcrumb: [
                {
                  label: "Organisations ",
                  url: "organisations"
                },
                {
                  label: "{{orgName}} ",
                  url: "organisation-detail/:id"
                },
                {
                  label: "Positions",
                  url: ""
                }
              ]
            }
          },
          {
            path: "positions/:id/add",
            component: PositionsOfOrganisationAddComponent,
            data: {
              animation: "positionadd",
              breadcrumb: [
                {
                  label: "Organisations ",
                  url: "organisations"
                },
                {
                  label: "{{orgName}} ",
                  url: "organisation-detail/:id"
                },
                {
                  label: "Positions",
                  url: "organisation-detail/:id/positions/:id"
                },
                {
                  label: "Add ",
                  url: ""
                }
              ]
            }
          },
          {
            path: "positions/:id/:position/edit",
            component: PositionsOfOrganisationEditComponent,
            data: {
              animation: "positionedit",
              breadcrumb: [
                {
                  label: "Organisations ",
                  url: "organisations"
                },
                {
                  label: "{{orgName}} ",
                  url: "organisation-detail/:id"
                },
                {
                  label: "Positions",
                  url: "organisation-detail/:id/positions/:id"
                },
                {
                  label: "Edit ",
                  url: ""
                }
              ]
            }
          },
          {
            path: "groups/:id",
            component: GroupsOfOrganisationComponent,
            data: {
              animation: "groupslist",
              breadcrumb: [
                {
                  label: "Organisations ",
                  url: "organisations"
                },
                {
                  label: "{{orgName}} ",
                  url: "organisation-detail/:id"
                },
                {
                  label: "Groups",
                  url: ""
                }
              ]
            }
          },
          {
            path: "groups/:id/add",
            component: GroupsOfOrganisationAddComponent,
            data: {
              animation: "groupadd",
              breadcrumb: [
                {
                  label: "Organisations ",
                  url: "organisations"
                },
                {
                  label: "{{orgName}} ",
                  url: "organisation-detail/:id"
                },
                {
                  label: "Groups",
                  url: "organisation-detail/:id/groups/:id"
                },
                {
                  label: "Add ",
                  url: ""
                }
              ]
            }
          },
          {
            path: "groups/:id/:group/edit",
            component: GroupsOfOrganisationEditComponent,
            data: {
              animation: "useredit",
              breadcrumb: [
                {
                  label: "Organisations ",
                  url: "organisations"
                },
                {
                  label: "{{orgName}} ",
                  url: "organisation-detail/:id"
                },
                {
                  label: "Groups",
                  url: "organisation-detail/:id/groups/:id"
                },
                {
                  label: "Edit ",
                  url: ""
                }
              ]
            }
          }
        ]
      },
      {
        path: "organisation-units",
        component: OrganisationUnitsComponent,
        data: { animation: "orgUnits" }
      },
      {
        path: "organisation-unit/create",
        component: OrganisationUnitAddComponent,
        data: {
          breadcrumb: [
            {
              label: "Organisation Units ",
              url: "organisation-units"
            },
            {
              label: "Add",
              url: ""
            }
          ]
        }
      },
      {
        path: "organisation-unit-edit/:id",
        component: OrganisationUnitEditComponent,
        data: {
          breadcrumb: [
            {
              label: "Organisation Units ",
              url: "organisation-units"
            },
            {
              label: "{{orgunitName}}",
              url: "organisation-unit-detail/:id"
            },
            {
              label: "Edit",
              url: ""
            }
          ]
        }
      },
      {
        path: "organisation-unit-detail/:id",
        component: OrgUnitsDetailComponent,
        data: {
          breadcrumb: [
            {
              label: "Organisation Units ",
              url: "organisation-units"
            },
            {
              label: "{{orgunitName}}",
              url: ""
            }
          ]
        },
        children: [
          { path: "", component: OrgUnitMainComponent },
          {
            path: "positions/:id",
            component: PositionsOfOrganisationunitComponent,
            data: {
              animation: "positionslist",
              breadcrumb: [
                {
                  label: "Organisation Units ",
                  url: "organisation-units"
                },
                {
                  label: "{{orgunitName}} ",
                  url: "organisation-unit-detail/:id"
                },
                {
                  label: "Positions",
                  url: ""
                }
              ]
            }
          },
          {
            path: "positions/:id/add",
            component: PositionsOfOrganisationunitAddComponent,
            data: {
              animation: "positionadd",
              breadcrumb: [
                {
                  label: "Organisation Units",
                  url: "organisation-units"
                },
                {
                  label: "{{orgunitName}} ",
                  url: "organisation-unit-detail/:id"
                },
                {
                  label: "Positions",
                  url: "organisation-unit-detail/:id/positions/:id"
                },
                {
                  label: "Add ",
                  url: ""
                }
              ]
            }
          },
          {
            path: "positions/:id/:position/edit",
            component: PositionsOfOrganisationunitEditComponent,
            data: {
              animation: "positionedit",
              breadcrumb: [
                {
                  label: "Organisation Units ",
                  url: "organisation-units"
                },
                {
                  label: "{{orgunitName}} ",
                  url: "organisation-unit-detail/:id"
                },
                {
                  label: "Positions",
                  url: "organisation-unit-detail/:id/positions/:id"
                },
                {
                  label: "Edit ",
                  url: ""
                }
              ]
            }
          }
        ]
      },
      {
        path: "positions",
        component: PositionsComponent,
        data: { animation: "positions" }
      },

      {
        path: "positions/add",
        component: PositionAddComponent,
        data: {
          animation: "positionsAdd",
          breadcrumb: [
            {
              label: "Positions ",
              url: "positions"
            },
            {
              label: "Add",
              url: ""
            }
          ]
        }
      },
      {
        path: "positions/edit/:id",
        component: PositionEditComponent,
        data: {
          animation: "positionEdit",
          breadcrumb: [
            {
              label: "Positions ",
              url: "positions"
            },
            {
              label: "{{positionName}} ",
              url: "position-detail/:id"
            },
            {
              label: "Edit",
              url: ""
            }
          ]
        }
      },

      {
        path: "position-detail/:id",
        component: PositionDetailComponent,
        data: {
          animation: "positionDetail",
          breadcrumb: [
            {
              label: "Positions ",
              url: "positions"
            },
            {
              label: "{{positionName}}",
              url: ""
            }
          ]
        },
        children: [{ path: "", component: PositionDetailMainComponent }]
      },

      {
        path: "position-classification",
        component: PositionClassificationComponent,
        data: { animation: "positionClassifications" }
      },
      {
        path: "position-classification/add",
        component: PositionClassificationAddComponent,
        data: {
          animation: "positionClassificationsAdd",
          breadcrumb: [
            {
              label: "Position Classifications  ",
              url: "position-classification"
            },
            {
              label: "Add",
              url: ""
            }
          ]
        }
      },
      {
        path: "position-classification-detail/:id",
        component: PositionClassificationDetailComponent,
        data: {
          animation: "postionClassificationDetail",
          breadcrumb: [
            {
              label: "Postion Classifications",
              url: "position-classification"
            },
            {
              label: "{{positionClassificationName}}",
              url: ""
            }
          ]
        },
        children: [{ path: "", component: PositionClassificationMainComponent }]
      },
      {
        path: "position-classification/edit/:id",
        component: PositionClassificationEditComponent,
        data: {
          animation: "positionClassificationEdit",
          breadcrumb: [
            {
              label: "Postion Classifications",
              url: "position-classification"
            },
            {
              label: "{{positionClassificationName}} ",
              url: "position-classification-detail/:id"
            },
            {
              label: "Edit",
              url: ""
            }
          ]
        }
      },

      {
        path: "group-types",
        component: GroupTypesComponent,
        data: { animation: "groupTypes" }
      },
      {
        path: "group-types/add",
        component: GroupTypesAddComponent,
        data: {
          animation: "groupTypesAdd",
          breadcrumb: [
            {
              label: "Group Types ",
              url: "group-types"
            },
            {
              label: "Add",
              url: ""
            }
          ]
        }
      },
      {
        path: "group-types/edit/:id",
        component: GroupTypesEditComponent,
        data: {
          animation: "groupTypesEdit",
          breadcrumb: [
            {
              label: "Group Types ",
              url: "group-types"
            },
            {
              label: "{{groupTypeName}} ",
              url: "group-type-detail/:id"
            },
            {
              label: "Edit",
              url: ""
            }
          ]
        }
      },

      {
        path: "group-type-detail/:id",
        component: GroupTypeDetailComponent,
        data: {
          animation: "groupTypeDetail",
          breadcrumb: [
            {
              label: "Group Types ",
              url: "group-types"
            },
            {
              label: "{{groupTypeName}}",
              url: ""
            }
          ]
        },
        children: [{ path: "", component: GroupTypeMainComponent }]
      },

      {
        path: "groups",
        component: GroupsComponent,
        data: { animation: "groups" }
      },
      {
        path: "groups/add",
        component: GroupAddComponent,
        data: {
          animation: "group-add",
          breadcrumb: [
            {
              label: "Groups",
              url: "groups"
            },
            {
              label: "Add",
              url: ""
            }
          ]
        }
      },
      {
        path: "group-detail/:id",
        component: GroupDetailComponent,
        data: {
          animation: "group-detail",
          breadcrumb: [
            {
              label: "Groups ",
              url: "groups"
            },
            {
              label: "{{groupName}}",
              url: ""
            }
          ]
        },
        children: [{ path: "", component: GroupMainComponent }]
      },
      {
        path: "groups/edit/:id",
        component: GroupEditComponent,
        data: {
          animation: "groupEdit",
          breadcrumb: [
            {
              label: "Groups ",
              url: "groups"
            },
            {
              label: "{{groupName}} ",
              url: "group-detail/:id"
            },
            {
              label: "Edit",
              url: ""
            }
          ]
        }
      },

      {
        path: "users",
        component: UsersComponent,
        data: { animation: "users" }
      },
      {
        path: "users/create",
        component: UsersAddComponent,
        data: {
          breadcrumb: [
            {
              label: "Users ",
              url: "users"
            },
            {
              label: "Add",
              url: ""
            }
          ]
        }
      },
      {
        path: "user-edit/:id",
        component: UserEditComponent,
        data: {
          breadcrumb: [
            {
              label: "Users ",
              url: "users"
            },
            {
              label: "{{userName}} ",
              url: "user-detail/:id"
            },
            {
              label: "Edit",
              url: ""
            }
          ]
        }
      },
      {
        path: "user-detail/:id",
        component: UsersDetailComponent,
        data: {
          breadcrumb: [
            {
              label: "Users ",
              url: "users"
            },
            {
              label: "{{userName}}",
              url: ""
            }
          ]
        }
      }
    ]
  },
Mohit Harshan
  • 1,916
  • 1
  • 18
  • 41
  • 1
    the solution to this problem pretty much depends on your routing design. you should somehow make sure that user rights are fetched in a resolver before your routes are loaded. so you must decide a particular route on your routing structure and use resolve guard for fetching user rights and populate your conf service. according to your explanation best shot would be to place the resolver on the route where you redirect just after login (however this will work if you don't need user rights before login). if you share your route configuration i can provide further ideas. – ysf Jun 19 '19 at 11:22
  • the component loaded first would always be app.component ,ie root component @ysf – Mohit Harshan Jun 19 '19 at 11:38
  • i don't get what you mean. it is obvious that app-component is the root component. i am basically saying that you must load your configuration in a resolver on the component that gets loaded just after the app-component. – ysf Jun 19 '19 at 11:52
  • yes, ok ... if i do that, itll work on first login .What if i go to another page and then refresh the browser ? will it work as intended – Mohit Harshan Jun 19 '19 at 11:57
  • is the best solution then be placing the resolver on every single route? – Mohit Harshan Jun 19 '19 at 11:59
  • if you place the resolver in a parent route that all other routes are children of it, then you don't need to place it elsewhere. and even if you refresh the page when on a child route, it will still work. as i said if you share route configuration i can show you the right direction. – ysf Jun 19 '19 at 13:00
  • ok i will update my question – Mohit Harshan Jun 20 '19 at 05:04
  • question updated @ysf – Mohit Harshan Jun 20 '19 at 08:07
  • route guards are processed before resolvers, thats the issue. My route guards requires the vdata from api – Mohit Harshan Jun 20 '19 at 08:33

0 Answers0