From 79f10574cfec578b2f4716dced7fdec3233a5a64 Mon Sep 17 00:00:00 2001 From: George Nash Date: Thu, 19 Oct 2023 13:51:33 +0100 Subject: [PATCH 1/2] auth guard to redirect logged out users to login page --- ui/src/app/account/account.route.ts | 2 ++ ui/src/app/account/auth.guard.ts | 34 ++++++++++++++++++++++++++ ui/src/app/app-routing.module.ts | 5 ++++ ui/src/app/app.module.ts | 4 ++- ui/src/app/home/home.component.html | 1 + ui/src/app/home/home.component.scss | 0 ui/src/app/home/home.component.spec.ts | 21 ++++++++++++++++ ui/src/app/home/home.component.ts | 10 ++++++++ ui/src/app/home/home.module.ts | 14 +++++++++++ ui/src/app/home/home.route.ts | 18 ++++++++++++++ 10 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 ui/src/app/account/auth.guard.ts create mode 100644 ui/src/app/home/home.component.html create mode 100644 ui/src/app/home/home.component.scss create mode 100644 ui/src/app/home/home.component.spec.ts create mode 100644 ui/src/app/home/home.component.ts create mode 100644 ui/src/app/home/home.module.ts create mode 100644 ui/src/app/home/home.route.ts diff --git a/ui/src/app/account/account.route.ts b/ui/src/app/account/account.route.ts index 315360708..2c8af5aeb 100644 --- a/ui/src/app/account/account.route.ts +++ b/ui/src/app/account/account.route.ts @@ -1,5 +1,7 @@ import { Routes } from "@angular/router"; import { LoginComponent } from "./login/login.component"; +import { AuthGuard } from "./auth.guard"; +import { HomeComponent } from "../home/home.component"; export const routes: Routes = [ { diff --git a/ui/src/app/account/auth.guard.ts b/ui/src/app/account/auth.guard.ts new file mode 100644 index 000000000..12f6c1275 --- /dev/null +++ b/ui/src/app/account/auth.guard.ts @@ -0,0 +1,34 @@ +import { inject } from '@angular/core'; +import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router'; + + +import { StateStorageService } from './service/state-storage.service'; +import { AccountService } from './service/account.service'; +import { Observable, map, take } from 'rxjs'; + +export const AuthGuard = (route: ActivatedRouteSnapshot, + state: RouterStateSnapshot): Observable | boolean => { + const authorities = route.data['authorities']; + + const router = inject(Router); + const accountService = inject(AccountService); + const stateStorageService = inject(StateStorageService) + + return accountService.getAccountData().pipe(take(1),map(account => { + console.log(authorities, account); + + if (account) { + const hasAnyAuthority = accountService.hasAnyAuthority(authorities); + if (hasAnyAuthority) { + return true; + } else { + router.navigate(['accessdenied']); + return false; + } + } else { + router.navigate(['/login']); + stateStorageService.storeUrl(state.url); + return false; + } + })); +} diff --git a/ui/src/app/app-routing.module.ts b/ui/src/app/app-routing.module.ts index c6ffe6c72..741325243 100644 --- a/ui/src/app/app-routing.module.ts +++ b/ui/src/app/app-routing.module.ts @@ -7,6 +7,11 @@ const routes: Routes = [ path: '', loadChildren: () => import('./account/account.module').then(m => m.AccountModule) + }, + { + path: '', + loadChildren: () => + import('./home/home.module').then(m => m.HomeModule) } ] diff --git a/ui/src/app/app.module.ts b/ui/src/app/app.module.ts index db97c9597..c9b0b18a7 100644 --- a/ui/src/app/app.module.ts +++ b/ui/src/app/app.module.ts @@ -10,13 +10,15 @@ import { FontAwesomeModule } from '@fortawesome/angular-fontawesome' import { NavbarComponent } from './layout/navbar/navbar.component' import { CommonModule } from '@angular/common' import { NgbModule } from '@ng-bootstrap/ng-bootstrap' -import { HasAnyAuthorityDirective } from './shared/directive/has-any-authority.directive' +import { HasAnyAuthorityDirective } from './shared/directive/has-any-authority.directive'; +import { HomeModule } from './home/home.module' @NgModule({ declarations: [AppComponent, NavbarComponent, HasAnyAuthorityDirective], imports: [ FontAwesomeModule, AccountModule, + HomeModule, BrowserModule, HttpClientModule, AppRoutingModule, diff --git a/ui/src/app/home/home.component.html b/ui/src/app/home/home.component.html new file mode 100644 index 000000000..5f2c53ffd --- /dev/null +++ b/ui/src/app/home/home.component.html @@ -0,0 +1 @@ +

home works!

diff --git a/ui/src/app/home/home.component.scss b/ui/src/app/home/home.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/ui/src/app/home/home.component.spec.ts b/ui/src/app/home/home.component.spec.ts new file mode 100644 index 000000000..ba1b4a35a --- /dev/null +++ b/ui/src/app/home/home.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HomeComponent } from './home.component'; + +describe('HomeComponent', () => { + let component: HomeComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [HomeComponent] + }); + fixture = TestBed.createComponent(HomeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ui/src/app/home/home.component.ts b/ui/src/app/home/home.component.ts new file mode 100644 index 000000000..820d900fa --- /dev/null +++ b/ui/src/app/home/home.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-home', + templateUrl: './home.component.html', + styleUrls: ['./home.component.scss'] +}) +export class HomeComponent { + +} diff --git a/ui/src/app/home/home.module.ts b/ui/src/app/home/home.module.ts new file mode 100644 index 000000000..1ab09a780 --- /dev/null +++ b/ui/src/app/home/home.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule } from '@angular/router'; +import { routes } from './home.route'; +import { HomeComponent } from './home.component'; + +@NgModule({ + declarations: [HomeComponent], + imports: [ + CommonModule, + RouterModule.forChild(routes) + ] +}) +export class HomeModule { } diff --git a/ui/src/app/home/home.route.ts b/ui/src/app/home/home.route.ts new file mode 100644 index 000000000..3bb148195 --- /dev/null +++ b/ui/src/app/home/home.route.ts @@ -0,0 +1,18 @@ +import { Routes } from "@angular/router"; +import { HomeComponent } from "../home/home.component"; +import { AuthGuard } from "../account/auth.guard"; + +export const routes: Routes = [ + { + + path: '', + component: HomeComponent, + data: { + authorities: ['ROLE_USER'], + pageTitle: 'home.title.string' + }, + canActivate: [AuthGuard] + + } + ]; + \ No newline at end of file From 77ec38b53a21442c057dbff231e7e72aaa85e3d8 Mon Sep 17 00:00:00 2001 From: andrej romanov <50377758+auumgn@users.noreply.github.com> Date: Thu, 19 Oct 2023 20:56:18 +0300 Subject: [PATCH 2/2] fix auth guard on refresh --- ui/src/app/account/auth.guard.ts | 4 ++-- ui/src/app/account/service/account.service.ts | 17 +++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/ui/src/app/account/auth.guard.ts b/ui/src/app/account/auth.guard.ts index 12f6c1275..af27a4c6b 100644 --- a/ui/src/app/account/auth.guard.ts +++ b/ui/src/app/account/auth.guard.ts @@ -4,7 +4,7 @@ import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/ro import { StateStorageService } from './service/state-storage.service'; import { AccountService } from './service/account.service'; -import { Observable, map, take } from 'rxjs'; +import { Observable, filter, map, take } from 'rxjs'; export const AuthGuard = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | boolean => { @@ -14,7 +14,7 @@ export const AuthGuard = (route: ActivatedRouteSnapshot, const accountService = inject(AccountService); const stateStorageService = inject(StateStorageService) - return accountService.getAccountData().pipe(take(1),map(account => { + return accountService.getAccountData().pipe(filter(account => account !== undefined),map(account => { console.log(authorities, account); if (account) { diff --git a/ui/src/app/account/service/account.service.ts b/ui/src/app/account/service/account.service.ts index 9ee2b29f5..292abc4ff 100644 --- a/ui/src/app/account/service/account.service.ts +++ b/ui/src/app/account/service/account.service.ts @@ -20,7 +20,7 @@ import { IAccount } from '../model/account.model' @Injectable({ providedIn: 'root' }) export class AccountService { - private accountData = new BehaviorSubject(undefined); + private accountData = new BehaviorSubject(undefined); private isFetchingAccountData = false; private stopFetchingAccountData = new Subject(); private authenticated = false; @@ -44,10 +44,10 @@ export class AccountService { .pipe( takeUntil(this.stopFetchingAccountData), catchError((err) => { - this.accountData.next(undefined) + this.authenticated = false + this.accountData.next(null) // TODO: uncomment when memberservice is added or change the account service so that this logic is absent from the account service //this.memberService.memberData.next(undefined); - this.authenticated = false this.authenticationState.next(this.accountData) this.isFetchingAccountData = false return EMPTY @@ -56,9 +56,10 @@ export class AccountService { this.isFetchingAccountData = false this.authenticationState.next(this.accountData) if (response && response.body) { + this.authenticated = true const account: IAccount = response.body this.accountData.next(account) - this.authenticated = true + // After retrieve the account info, the language will be changed to // the user's preferred language configured in the account setting if (this.accountData.value?.langKey) { @@ -71,7 +72,7 @@ export class AccountService { } else { // TODO: uncomment when memberservice is added or change the account service so that this logic is absent from the account service //this.memberService.memberData.next(undefined); - this.accountData.next(undefined) + this.accountData.next(null) this.authenticated = false console.error('Invalid response:', response) } @@ -121,7 +122,7 @@ export class AccountService { !this.authenticated || !this.accountData || !this.accountData.value?.authorities - ) { + ) { return false } @@ -130,7 +131,7 @@ export class AccountService { return true } } - + return false } @@ -145,7 +146,7 @@ export class AccountService { } } - getAccountData(force?: boolean): Observable { + getAccountData(force?: boolean): Observable { if (force) { // TODO: uncomment when memberservice is added or change the account service so that this logic is absent from the account service //this.memberService.stopFetchingMemberData.next();