diff --git a/.vscode/settings.json b/.vscode/settings.json index fc7c09216..3a2504441 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,5 +7,5 @@ }, "editor.defaultFormatter": "esbenp.prettier-vscode", "scss.lint.unknownAtRules": "ignore", - "eslint.validate": ["json"] + "eslint.validate": ["json", "javascript", "typescript", "html"] } diff --git a/src/app/core/components/header/header.component.ts b/src/app/core/components/header/header.component.ts index f6603542c..a599fcefd 100644 --- a/src/app/core/components/header/header.component.ts +++ b/src/app/core/components/header/header.component.ts @@ -10,7 +10,6 @@ import { Router } from '@angular/router'; import { AuthService } from '@osf/core/services'; import { UserSelectors } from '@osf/core/store/user'; -import { LoaderService } from '@osf/shared/services'; import { BreadcrumbComponent } from '../breadcrumb/breadcrumb.component'; @@ -25,7 +24,6 @@ export class HeaderComponent { currentUser = select(UserSelectors.getCurrentUser); private readonly router = inject(Router); - private readonly loaderService = inject(LoaderService); private readonly authService = inject(AuthService); items = [ @@ -37,7 +35,6 @@ export class HeaderComponent { { label: 'navigation.logOut', command: () => { - this.loaderService.show(); this.authService.logout(); }, }, diff --git a/src/app/core/components/nav-menu/nav-menu.component.ts b/src/app/core/components/nav-menu/nav-menu.component.ts index e730b3a40..00859c4e5 100644 --- a/src/app/core/components/nav-menu/nav-menu.component.ts +++ b/src/app/core/components/nav-menu/nav-menu.component.ts @@ -14,6 +14,7 @@ import { ActivatedRoute, NavigationEnd, Router, RouterLink, RouterLinkActive } f import { MENU_ITEMS } from '@core/constants'; import { filterMenuItems, updateMenuItems } from '@osf/core/helpers'; import { RouteContext } from '@osf/core/models'; +import { AuthService } from '@osf/core/services'; import { UserSelectors } from '@osf/core/store/user'; import { IconComponent } from '@osf/shared/components'; import { WrapFnPipe } from '@osf/shared/pipes'; @@ -29,6 +30,7 @@ export class NavMenuComponent { private readonly router = inject(Router); private readonly route = inject(ActivatedRoute); + private readonly authService = inject(AuthService); private readonly isAuthenticated = select(UserSelectors.isAuthenticated); @@ -87,6 +89,16 @@ export class NavMenuComponent { } goToLink(item: MenuItem) { + if (item.id === 'sign-in') { + this.authService.navigateToSignIn(); + return; + } + + if (item.id === 'log-out') { + this.authService.logout(); + return; + } + if (!item.items) { this.closeMenu.emit(); } diff --git a/src/app/core/constants/nav-items.constant.ts b/src/app/core/constants/nav-items.constant.ts index 3ed62c7c9..0d650c15a 100644 --- a/src/app/core/constants/nav-items.constant.ts +++ b/src/app/core/constants/nav-items.constant.ts @@ -370,4 +370,18 @@ export const MENU_ITEMS: MenuItem[] = [ }, ], }, + { + id: 'sign-in', + label: 'navigation.signIn', + visible: false, + routerLink: null, + styleClass: 'mt-5', + }, + { + id: 'log-out', + label: 'navigation.logOut', + visible: false, + routerLink: null, + styleClass: 'mt-5', + }, ]; diff --git a/src/app/core/guards/auth.guard.ts b/src/app/core/guards/auth.guard.ts index a0c567f8a..c1d8dd62e 100644 --- a/src/app/core/guards/auth.guard.ts +++ b/src/app/core/guards/auth.guard.ts @@ -1,26 +1,35 @@ import { Store } from '@ngxs/store'; -import { filter, map, take } from 'rxjs'; +import { map, switchMap, take } from 'rxjs'; import { inject } from '@angular/core'; import { CanActivateFn, Router } from '@angular/router'; -import { UserSelectors } from '@osf/core/store/user'; +import { GetCurrentUser, UserSelectors } from '@osf/core/store/user'; export const authGuard: CanActivateFn = () => { const store = inject(Store); const router = inject(Router); - return store.select(UserSelectors.getCurrentUserLoading).pipe( - filter((loading) => !loading), - take(1), - map(() => { - const user = store.selectSnapshot(UserSelectors.getCurrentUser); - if (!user) { - router.navigate(['/']); - return false; - } - return true; + const isAuthenticated = store.selectSnapshot(UserSelectors.isAuthenticated); + + if (isAuthenticated) { + return true; + } + + return store.dispatch(GetCurrentUser).pipe( + switchMap(() => { + return store.select(UserSelectors.isAuthenticated).pipe( + take(1), + map((isAuthenticated) => { + if (!isAuthenticated) { + router.navigate(['/']); + return false; + } + + return true; + }) + ); }) ); }; diff --git a/src/app/core/guards/redirect-if-logged-in.guard.ts b/src/app/core/guards/redirect-if-logged-in.guard.ts index e39e216a2..b89bcb1eb 100644 --- a/src/app/core/guards/redirect-if-logged-in.guard.ts +++ b/src/app/core/guards/redirect-if-logged-in.guard.ts @@ -1,18 +1,35 @@ -import { select } from '@ngxs/store'; +import { Store } from '@ngxs/store'; + +import { map, switchMap, take } from 'rxjs'; import { inject } from '@angular/core'; import { CanActivateFn, Router } from '@angular/router'; -import { UserSelectors } from '@osf/core/store/user'; +import { GetCurrentUser, UserSelectors } from '@osf/core/store/user'; export const redirectIfLoggedInGuard: CanActivateFn = () => { + const store = inject(Store); const router = inject(Router); - const isAuthenticated = select(UserSelectors.isAuthenticated); + const isAuthenticated = store.selectSnapshot(UserSelectors.isAuthenticated); - if (isAuthenticated()) { - return router.navigate(['/dashboard']); + if (isAuthenticated) { + router.navigate(['/dashboard']); + return false; } - return true; + return store.dispatch(GetCurrentUser).pipe( + switchMap(() => { + return store.select(UserSelectors.isAuthenticated).pipe( + take(1), + map((isAuthenticated) => { + if (isAuthenticated) { + router.navigate(['/dashboard']); + return false; + } + return true; + }) + ); + }) + ); }; diff --git a/src/app/core/helpers/nav-menu.helper.ts b/src/app/core/helpers/nav-menu.helper.ts index 613ccab3d..924e6616a 100644 --- a/src/app/core/helpers/nav-menu.helper.ts +++ b/src/app/core/helpers/nav-menu.helper.ts @@ -22,6 +22,14 @@ export function filterMenuItems(items: MenuItem[], isAuthenticated: boolean): Me }; } + if (item.id === 'sign-in') { + updatedItem = { ...updatedItem, visible: !isAuthenticated }; + } + + if (item.id === 'log-out') { + updatedItem = { ...updatedItem, visible: isAuthenticated }; + } + if (item.items) { updatedItem.items = filterMenuItems(item.items, isAuthenticated); } diff --git a/src/app/core/services/auth.service.ts b/src/app/core/services/auth.service.ts index 6770ffca5..aab97bf40 100644 --- a/src/app/core/services/auth.service.ts +++ b/src/app/core/services/auth.service.ts @@ -6,7 +6,7 @@ import { inject, Injectable } from '@angular/core'; import { ClearCurrentUser } from '@osf/core/store/user'; import { urlParam } from '@osf/shared/helpers'; -import { JsonApiService } from '@osf/shared/services'; +import { JsonApiService, LoaderService } from '@osf/shared/services'; import { SignUpModel } from '../models'; @@ -18,9 +18,11 @@ import { environment } from 'src/environments/environment'; export class AuthService { private readonly jsonApiService = inject(JsonApiService); private readonly cookieService = inject(CookieService); + private readonly loaderService = inject(LoaderService); private readonly actions = createDispatchMap({ clearCurrentUser: ClearCurrentUser }); navigateToSignIn(): void { + this.loaderService.show(); const loginUrl = `${environment.casUrl}/login?${urlParam({ service: `${environment.webUrl}/login` })}`; window.location.href = loginUrl; } @@ -42,6 +44,7 @@ export class AuthService { } logout(): void { + this.loaderService.show(); this.cookieService.deleteAll(); this.actions.clearCurrentUser(); window.location.href = `${environment.webUrl}/logout/?next=${encodeURIComponent('/')}`;