From 2632f859fe538f3c0fc4936a5dcdaa2f4813df8e Mon Sep 17 00:00:00 2001 From: Chneemann Date: Sun, 13 Apr 2025 12:46:58 +0200 Subject: [PATCH] fix: clear currentUserCache on logout to ensure correct state --- src/app/guards/authenticated.guard.ts | 13 +++++++++++++ src/app/services/user.service.ts | 19 +++++++++++++++++++ .../header/navbar/navbar.component.ts | 5 +++-- .../components/sidebar/sidebar.component.ts | 10 +++++++++- 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/app/guards/authenticated.guard.ts b/src/app/guards/authenticated.guard.ts index 7c89bd8..ec6b2fd 100644 --- a/src/app/guards/authenticated.guard.ts +++ b/src/app/guards/authenticated.guard.ts @@ -4,24 +4,37 @@ import { map, Observable } from 'rxjs'; import { AuthService } from '../services/auth.service'; import { TokenService } from '../services/token.service'; import { ToastNotificationService } from '../services/toast-notification.service'; +import { UserService } from '../services/user.service'; @Injectable({ providedIn: 'root', }) export class AuthenticatedGuard implements CanActivate { constructor( + private userService: UserService, private authService: AuthService, private tokenService: TokenService, private toastNotificationService: ToastNotificationService, private router: Router ) {} + /** + * Determines whether the route can be activated based on the user's authentication status. + * + * This method checks if the user's token and user ID are available. If either is unavailable, + * it navigates to the login page, resets the user cache, and displays a session expired toast. + * If both are available, it checks the user's authentication status and returns it. + * + * @returns {Observable | Promise | boolean} An observable, promise, or boolean + * indicating whether the route can be activated. + */ canActivate(): Observable | Promise | boolean { if ( !this.tokenService.isTokenAvailable() || !this.tokenService.isUserIdAvailable() ) { this.router.navigate(['/login']); + this.userService.resetUserCache(); this.toastNotificationService.showSessionExpiredToast(); return false; } diff --git a/src/app/services/user.service.ts b/src/app/services/user.service.ts index f006f9c..60f6f9f 100644 --- a/src/app/services/user.service.ts +++ b/src/app/services/user.service.ts @@ -64,10 +64,29 @@ export class UserService { ); } + /** + * Resets the current user cache and emits a null value to the current user Observable. + */ + resetUserCache(): void { + this.currentUserCache = null; + this.currentUserSubject.next(null); + } + + /** + * Retrieves the list of all users from the API. + * + * @returns An Observable resolving to the list of all users. + */ getUsers(): Observable { return this.apiService.getUsers(); } + /** + * Retrieves a user by its ID from the API. + * + * @param userId The ID of the user to be retrieved. + * @returns An Observable resolving to the user with the given ID, or an empty Observable if the user does not exist. + */ getUserById(userId: string): Observable { return this.apiService.getUserById(userId); } diff --git a/src/app/shared/components/header/navbar/navbar.component.ts b/src/app/shared/components/header/navbar/navbar.component.ts index 4a6095e..a535c53 100644 --- a/src/app/shared/components/header/navbar/navbar.component.ts +++ b/src/app/shared/components/header/navbar/navbar.component.ts @@ -4,6 +4,7 @@ import { LanguageService } from '../../../../services/language.service'; import { CommonModule } from '@angular/common'; import { TranslateModule } from '@ngx-translate/core'; import { AuthService } from '../../../../services/auth.service'; +import { UserService } from '../../../../services/user.service'; @Component({ selector: 'app-navbar', @@ -21,12 +22,11 @@ export class NavbarComponent { constructor( public langService: LanguageService, private router: Router, + private userService: UserService, private authService: AuthService ) {} /** - * Lifecycle hook that is called after the component has been initialized. - * * Sets the currentRoute property to the current route's url. */ ngOnInit() { @@ -40,6 +40,7 @@ export class NavbarComponent { * data, and navigate the user to the logout page. */ logout() { + this.userService.resetUserCache(); this.authService.logout(); } } diff --git a/src/app/shared/components/sidebar/sidebar.component.ts b/src/app/shared/components/sidebar/sidebar.component.ts index e403bf2..9f8f246 100644 --- a/src/app/shared/components/sidebar/sidebar.component.ts +++ b/src/app/shared/components/sidebar/sidebar.component.ts @@ -5,6 +5,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { LanguageService } from '../../../services/language.service'; import { AuthService } from '../../../services/auth.service'; import { Subject, takeUntil } from 'rxjs'; +import { UserService } from '../../../services/user.service'; @Component({ selector: 'app-sidebar', @@ -20,17 +21,23 @@ export class SidebarComponent implements OnInit, OnDestroy { constructor( private router: Router, + private userService: UserService, public languageService: LanguageService, private authService: AuthService ) {} /** - * Calls the getCurrentPath method to set the currentPath property to the current route's url. + * Calls the getCurrentPath method to set the currentPath property to the + * current route's url. */ ngOnInit(): void { this.getCurrentPath(); } + /** + * Emits a value to the `destroy$` subject and completes it to clean up + * any subscriptions and prevent memory leaks. + */ ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); @@ -56,6 +63,7 @@ export class SidebarComponent implements OnInit, OnDestroy { * data, and navigate the user to the logout page. */ logout() { + this.userService.resetUserCache(); this.authService.logout(); } }