Failure to execute the guard condition

Currently, I am tackling a new project that involves Angular along with Firebase for Authentication and Firestore as the database. However, while implementing an Admin Guard to check user privileges, I encountered a perplexing issue where the guard condition does not seem to execute.

The function responsible for fetching user data from the database is as follows:

get(uid: string): AngularFirestoreDocument<User> {
  return this.afs.doc(`users/${uid}`)
}

Within the Auth Service, the method to retrieve the user details is defined as:

get dbUser$(): Observable<any> {
  return this.user$.pipe(
    switchMap(user => {
      if(user && user.uid) {
        return this.dbService.get(user.uid).valueChanges();
      } else {
        return of(null);
      }
    }),
  )
}

Furthermore, in the AdminAuthGuard class, the logic to determine admin access rights is implemented as described below:

export class AdminAuthGuard {

  constructor(
    private authService: AuthService, 
    private dbService: DatabaseService,
    private router: Router
  ) {}

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    return this.authService.dbUser$
    .pipe(
      map((userData: any) => {
        console.log('Admin Auth Guard returns true');
        if(userData && userData.isAdmin) {
          return true;
        } else {
          console.log('Admin Auth Guard returns false');
          return false;
        }
      })
    );
  }
}

Despite having debug statements placed strategically, the expected output is not being generated during runtime. The scenario becomes more puzzling when the expected 'isAdmin' property of the user object seems to appear after multiple iterations.

The routing configuration intended for paths requiring admin authentication are shown below:

  {path: 'admin/products', component: AdminProductsComponent, canActivate: [AdminAuthGuard]},
  {path: 'admin/orders', component: AdminOrdersComponent, canActivate: [AdminAuthGuard]},

In an attempt to troubleshoot, I created an Admin Guard for two separate routes but was unable to elicit any response from the functions invoked.

Answer №1

Here are some steps to try:

Authentication Service

user$: Observable<AppUserModel | null | undefined>;

  constructor(
    private afs: AngularFirestore,
    public afAuth: AngularFireAuth,
  ) {
    super(afs);

    this.user$ = afAuth.authState.pipe(
      switchMap(user => {
        if (user) {
          return this.afs.doc<AppUserModel>(`${entityName}/${user.uid}`)
            .snapshotChanges()
            .pipe(map(snap => {
              if (snap) {
                return this.convertSnap<AppUserModel>(snap);
              } else {
                return null;
              }
            }));
        } else {
          return of(null);
        }
      }));
  }

Admin Guard

export class AuthGuard  {
  constructor(
    private router: Router,
    private auth: AuthService
  ) { }

  canActivate(_route: any, state: RouterStateSnapshot): Observable<boolean> {
    return this.auth.user$.pipe(map(user => {
      if (!user) {
        this.router.navigate(['/'], { queryParams: { returnUrl: state.url } });
        return false;
      } else {
        return true
      }
    }));
  }
}

I utilize the convert snap method to extract the user UID

  convertSnap<T>(snap: Action<DocumentSnapshot<T>>) {
    if (snap.payload.exists === false) {
      return null;
    } else {
      return <T>{
        uid: snap.payload.id,
        ...snap.payload.data()
      }
    }
  }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Definition in Typescript: The term "value is" refers to a function that takes in any number of arguments of

export function isFunction(value: any): value is (...args: any[]) => any { return typeof value === 'function'; } What is the reason behind using value is (...args: any[]) => any instead of boolean ? ...

Steps for creating an observable array using a Firestore DocumentReference array field

I am in the process of organizing a firestore database specifically for e-commerce functions. At the moment, I have a main collection for products and another for users. The users collection includes an array field named cart where I store DocumentReferenc ...

Error in Angular Material Snackbar issue

Within my Angular 4 project, I have successfully implemented MatSnackbar to display useful messages to the user. However, there is one instance where a particular snackbar displays an error. The issue arises when a user attempts to access the application ...

Troubleshooting Typescript & Express Routing Issue

I am currently following a tutorial on how to set up a simple express-typescript application. However, I am encountering some difficulties with my routes not working as expected. Despite searching for similar problems and solutions, I haven't found an ...

The ng-bootstrap modal fails to appear when incorporating [formGroup]="FormName" or formControlName="elementName"

Utilizing ng-bootstrap to create a popup modal has been a challenge for me. When I import FormsModule and ReactiveFormsModule in src/app/modal-basic.module.ts, the code inside it looks like this: import { NgModule } from '@angular/core'; import { ...

Caution: Updating a component is not possible during the rendering of another component. ReactJS

I am encountering an error in my ReactHooks/Typescript application with a Navigation component that renders a PatientInfo component. The PatientInfo component is conditionally rendered based on the props it receives, determined by a searchbox in another ch ...

Angular encountering difficulty in setting checkbox to checked state

Greetings! I am currently working on an AngularJS application where I have a list of checkboxes being displayed. Below is the code snippet: <div class="checkbox" id="checkboxes" style="display:block" *ngFor="let rolename of roles; let i = index"> ...

Utilizing Pick to define a type that is a combination of multiple types

I am currently working on simplifying an existing interface by creating a new type. The original type is derived from @mui/x-data-grid and is as follows: export declare type GridEnrichedColDef<R extends GridValidRowModel = any, V = any, F = V> = Grid ...

Submitting sizable tiff documents using nodejs

I'm currently working on a web application with MEAN Stack and Angular 6. My challenge is uploading tiff files (maps) with large file sizes, up to 1.4 GB. I've tried using 'ng2fileUpload' and 'multer', but they are not compati ...

Updating validation patterns dynamically in Angular during runtime

I currently have a template-driven form with pattern validation that is functioning correctly: <input type="text" [(ngModel)]="model.defaultVal" name="defaultVal" pattern="[a-zA-Z ]*" /> <div *ngIf="defaultVal.touched || !defaultVal.prist ...

WebStorm is unable to detect tsconfig paths

Currently, we are facing an issue with WebStorm identifying some of our named paths as problematic. Despite this, everything compiles correctly with webpack. Here is how our project is structured: apps app1 tsconfig.e2e.json src tests ...

Unable to locate the TypeScript template file

Can someone help me with calling an HTML file into a TS file? I keep getting a "file not found" error. https://i.sstatic.net/fY1xc.png @Component({ selector: 'app/jsonData.ts', templateUrl: 'src/app/jsonData.html', }) export class ...

Incorrect order in Angular2 NgFor within tree model when elements are removed and then added back

Currently experimenting with Angular 2 alpha version 44. Working with a tree model that utilizes recursion for display purposes. Each group contains 'Criterions', 'Segments', and other 'Groups'. Elements can be added or delet ...

What are the effective solutions to troubleshoot UnhandledPromiseWarning?

In my Post method that utilizes Busboy, the events are triggered correctly and the data returned is accurate. However, there is an issue with the catch block generating an 'UnhandledPromiseRejectionWarning'. Here is the code snippet: route.post( ...

Facing issues with the template URL not functioning properly during the migration from Angular 1.5 to Angular 6

I am currently in the process of migrating an Angular 1.5 project to Angular 6, but I've encountered an issue with the templateUrl not working in the Angular 1.5 component. The packages I am using are: Angular CLI 6.0.8 TypeScript 2.7.2 Angular 6.0.7 ...

The system encountered an issue: unable to determine the property 'endsWith' of an undefined value

As I delve into writing my initial unit tests for the components, certain issues have arisen: TypeError: Cannot read property 'endsWith' of undefined. How can I define the data.iconPath in my test to resolve this error? Presenting my component ...

Updating a specific field in a Firestore document: A step-by-step guide

Is there a way to retrieve and edit a particular field in Angular Firestore? https://i.sstatic.net/fiElK.png ...

Angular's reactive forms retrieve the current validation rules directly from the AbstractControl

My goal is to automatically display an asterisk on an input field when a specific control has the validation rule 'required'. In my component ts file: this.form = this.fb.group({ name: ['', [Validators.required]] }); In my compon ...

Unusual Outcome from Observable.interval() Combined with flatMap()

When attempting to chain Observable.interval() with .flatMap(), I encountered what seems to be unexpected behavior. Below is the code snippet I am using (with Angular 2): Observable.interval(1500) .scan((numArr:any[], curr:any, i:number) => { nu ...

Tips for working with Typescript: utilizing the default value for a non-existent computed property

When utilizing Computed Property in javascript, I can structure my code as follows const default_values = {a:"debug",b:"info",c:"warning"}; function execute(y) { let x = default_values[y] || default_values.a /* if y is no ...