Search code examples
.netangulartypescriptfrontendngrx-store

Angular getCurrentUser different roles with different models


I have a logic issue and I’m not sure how to proceed. I have an auth method that sends email and password, and my API responds with a JWT token. Then, I need a getCurrentUser method, but I have multiple roles, each with its own model—for example, I have admin, moderator, and user, and each has its own model. How should I approach this?

I’ve thought about having 3 methods: LoadCurrentUser, LoadCurrentModo, and LoadCurrentAdmin, each receiving its own model. I’m not sure if it’s a good approach and how I could determine which method to call after the user has authenticated. Then, I asked ChatGPT if it has any idea.

export type UserType = Admin | Modo | User;

getCurrentUser(): Observable<UserType> {
  return this.http.get<UserType>(`/api/user/current`).pipe(
    map((data: any) => {
      switch (data.role) {
        case 'admin':
          return data as Admin;
        case 'modo':
          return data as Modo;
        default:
          return data as User;
      }
    })
  );
}

My current method with Ngrx Signal Store :

      getCurrentUser: rxMethod<void>(
        pipe(
          tap(() => patchState(store, { isLoading: true })),
          concatMap((input) => {
            return infra.loadCurrentUser().pipe(
              tapResponse({
                next: (user) => {
                  patchState(store, {
                    isLoading: false,
                    user: user,
                  });
                },
                error: () => {
                  patchState(store, { isLoading: false });
                },
              })
            );
          })
        )
      ),

Do you have an idea?


Solution

  • As Admin and Modo extend from User, your getCurrentUser() function should return an Observable of type User.

    getCurrentUser(): Observable<User> {
      return this.http.get<User>(`/api/user/current`);
    }
    

    Now you can offer functions to check if a user is an admin or modo, using the is keyword:

    isAdminUser(user: User): user is Admin {
      return 'role' in user && user.role === 'admin';
    }
    
    isModoUser(user: User): user is Modo {
      return 'role' in user && user.role === 'modo';
    }
    

    And use those functions like the following:

    service.getCurrentUser().subscribe(user => {
      if (service.isAdminUser(user)) {
        // user now has type `Admin` in this block
        // you can safely use properties which only exist in the `Admin` type
      }
    });