diff --git a/package.json b/package.json index fa2d08b..572b917 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "scripts": { "ng": "ng", - "start": "ng serve --proxy-config proxy.conf.json", + "start": "ng serve --host 0.0.0.0 --proxy-config proxy.conf.json", "build": "ng build", "test": "ng test", "lint": "ng lint", diff --git a/src/app/modules/accounts/accounts.ts b/src/app/modules/accounts/accounts.ts index 0fcc07e..10f850b 100644 --- a/src/app/modules/accounts/accounts.ts +++ b/src/app/modules/accounts/accounts.ts @@ -48,17 +48,10 @@ export class Login extends ErrorHandlingComponent { } submit() { - this.subscribe( + this.subscribeAndNavigate( this.accountService.login(this.userIdControl.value, this.passwordControl.value), - () => {} + '/color/list' ) - // Does not use SubscribingComponent shortcut because backend doesn't return expected error type - // this.accountService.login(this.userIdControl.value, this.passwordControl.value) - // .pipe(take(1), takeUntil(this.destroy$)) - // .subscribe({ - // next: () => this.urlUtils.navigateTo('/color'), - // error: error => this.handleLoginError(error) - // }) } get controls(): { userId: FormControl, password: FormControl } { diff --git a/src/app/modules/accounts/pages/login/login.component.ts b/src/app/modules/accounts/pages/login/login.component.ts index da31ab5..919bed0 100644 --- a/src/app/modules/accounts/pages/login/login.component.ts +++ b/src/app/modules/accounts/pages/login/login.component.ts @@ -31,7 +31,7 @@ export class LoginComponent extends ErrorHandlingComponent implements OnInit { ngOnInit(): void { this.errorService.activeErrorHandler = this - if (this.accountService.isLoggedIn()) { + if (this.appState.isAuthenticated) { this.router.navigate(['/color']) } diff --git a/src/app/modules/accounts/pages/logout/logout.component.ts b/src/app/modules/accounts/pages/logout/logout.component.ts index 8b180bd..a1433c1 100644 --- a/src/app/modules/accounts/pages/logout/logout.component.ts +++ b/src/app/modules/accounts/pages/logout/logout.component.ts @@ -1,28 +1,35 @@ -import {Component, OnInit} from '@angular/core'; +import {Component} from '@angular/core'; import {AccountService} from "../../services/account.service"; -import {Router} from "@angular/router"; +import {ActivatedRoute, Router} from "@angular/router"; +import {AppState} from "../../../shared/app-state"; +import {SubscribingComponent} from "../../../shared/components/subscribing.component"; +import {ErrorService} from "../../../shared/service/error.service"; @Component({ selector: 'cre-logout', templateUrl: './logout.component.html', styleUrls: ['./logout.component.sass'] }) -export class LogoutComponent implements OnInit { +export class LogoutComponent extends SubscribingComponent { constructor( private accountService: AccountService, - private router: Router + private appState: AppState, + errorService: ErrorService, + router: Router, + activatedRoute: ActivatedRoute ) { + super(errorService, activatedRoute, router) } ngOnInit(): void { - if (!this.accountService.isLoggedIn()) { - this.router.navigate(['/account/login']) + if (!this.appState.isAuthenticated) { + this.urlUtils.navigateTo('/account/login') } - this.accountService.logout(() => { - this.router.navigate(['/account/login']) - }) + this.subscribeAndNavigate( + this.accountService.logout(), + '/account/login' + ) } - } diff --git a/src/app/modules/accounts/services/account.service.ts b/src/app/modules/accounts/services/account.service.ts index 9cee84e..066973a 100644 --- a/src/app/modules/accounts/services/account.service.ts +++ b/src/app/modules/accounts/services/account.service.ts @@ -5,7 +5,7 @@ import {AppState} from '../../shared/app-state' import {HttpClient, HttpResponse} from '@angular/common/http' import {environment} from '../../../../environments/environment' import {ApiService} from '../../shared/service/api.service' -import {Permission} from '../../shared/model/user' +import {Permission, User} from '../../shared/model/user' import {ErrorService} from '../../shared/service/error.service' import {AlertService} from '../../shared/service/alert.service' import {JwtService} from "./jwt.service"; @@ -31,28 +31,24 @@ export class AccountService implements OnDestroy { this.destroy$.complete() } - isLoggedIn(): boolean { - return this.appState.isAuthenticated - } - checkAuthenticationStatus() { - if (!this.appState.authenticatedUser) { + if (!this.appState.isAuthenticated) { // Try to get current default group user - // this.http.get(`${environment.apiUrl}/user/current`, {withCredentials: true}) - // .pipe( - // take(1), - // takeUntil(this.destroy$), - // ).subscribe( - // { - // next: user => this.appState.authenticatedUser = user, - // error: err => { - // if (err.status === 404 || err.status === 403) { - // console.warn('No default user is defined on this computer') - // } else { - // this.errorService.handleError(err) - // } - // } - // }) + this.http.get(`${environment.apiUrl}/user/group/currentuser`, {withCredentials: true}) + .pipe( + take(1), + takeUntil(this.destroy$), + ).subscribe( + { + next: user => this.appState.authenticateGroupUser(user), + error: err => { + if (err.status === 404 || err.status === 403) { + console.warn('No default user is defined on this computer') + } else { + this.errorService.handleError(err) + } + } + }) } } @@ -89,44 +85,41 @@ export class AccountService implements OnDestroy { private loginUser(response: HttpResponse) { const authorization = response.headers.get("Authorization") - const jwt = this.jwtService.parseJwt(authorization) + const user = this.jwtService.parseUser(authorization) - this.appState.authenticateUser(jwt) + this.appState.authenticateUser(user) } - logout(success: () => void) { - this.api.get('/logout', true).pipe( + logout(): Observable { + const subject = new Subject() + + this.api.get('/logout').pipe( take(1), takeUntil(this.destroy$) - ) - .subscribe({ - next: () => { - this.appState.resetAuthenticatedUser() - this.checkAuthenticationStatus() - success() - }, - error: err => this.errorService.handleError(err) - }) + ).subscribe({ + next: () => { + this.logoutUser() + + subject.next() + subject.complete() + }, + error: error => { + this.errorService.handleError(error) + + subject.next() + subject.complete() + } + }) + + return subject + } + + private logoutUser() { + this.appState.resetAuthenticatedUser() + this.checkAuthenticationStatus() } hasPermission(permission: Permission): boolean { return this.appState.authenticatedUser && this.appState.authenticatedUser.permissions.indexOf(permission) >= 0 } - - private setLoggedInUserFromApi() { - // this.api.get('/user/current', true) - // .pipe( - // take(1), - // takeUntil(this.destroy$) - // ) - // .subscribe({ - // next: user => { - // this.appState.authenticatedUser = user - // At this point the loading wheel should be visible - // globalLoadingWheel.hide() - // }, - // error: err => this.errorService.handleError(err) - // }) - console.warn("REMOVE THIS") - } } diff --git a/src/app/modules/accounts/services/jwt.service.ts b/src/app/modules/accounts/services/jwt.service.ts index 6121290..6f67366 100644 --- a/src/app/modules/accounts/services/jwt.service.ts +++ b/src/app/modules/accounts/services/jwt.service.ts @@ -1,19 +1,13 @@ import {Injectable} from "@angular/core"; import jwtDecode from "jwt-decode"; -import {parseJson} from "@angular/cli/utilities/json-file"; -import {CreJwt} from "../../shared/app-state"; +import { User } from "../../shared/model/user"; @Injectable({ providedIn: 'root' }) export class JwtService { - parseJwt(jwt: string): CreJwt { + parseUser(jwt: string): User { const decoded = jwtDecode(jwt) as any - - return { - sub: decoded.sub, - exp: decoded.exp, - user: parseJson(decoded.user) - } + return JSON.parse(decoded.user) } } diff --git a/src/app/modules/company/pages/list/list.component.html b/src/app/modules/company/pages/list/list.component.html index 1fc8be5..944d7d2 100644 --- a/src/app/modules/company/pages/list/list.component.html +++ b/src/app/modules/company/pages/list/list.component.html @@ -1,6 +1,6 @@ - Ajouter + Ajouter diff --git a/src/app/modules/material-type/pages/list/list.component.html b/src/app/modules/material-type/pages/list/list.component.html index bf32816..6555e6a 100644 --- a/src/app/modules/material-type/pages/list/list.component.html +++ b/src/app/modules/material-type/pages/list/list.component.html @@ -1,6 +1,6 @@ - Ajouter + Ajouter diff --git a/src/app/modules/recipes/recipes.ts b/src/app/modules/recipes/recipes.ts index bdc619e..e1b6410 100644 --- a/src/app/modules/recipes/recipes.ts +++ b/src/app/modules/recipes/recipes.ts @@ -46,7 +46,7 @@ export class RecipeForm extends SubscribingComponent { } ngOnInit() { - super.ngOnInit(); + super.ngOnInit() this.fetchCompanies() diff --git a/src/app/modules/shared/app-state.ts b/src/app/modules/shared/app-state.ts index 3ed0e23..5b1c93e 100644 --- a/src/app/modules/shared/app-state.ts +++ b/src/app/modules/shared/app-state.ts @@ -2,14 +2,13 @@ import {Injectable} from '@angular/core' import {User} from './model/user' import {Subject} from 'rxjs' import {Title} from '@angular/platform-browser' -import jwtDecode from "jwt-decode"; @Injectable({ providedIn: 'root' }) export class AppState { private readonly KEY_AUTHENTICATED = 'authenticated' - private readonly KEY_AUTHENTICATION_EXPIRATION = 'authentication-expiration' + private readonly KEY_DEFAULT_GROUP_USER_AUTHENTICATED = 'default-group-user-authenticated' private readonly KEY_LOGGED_IN_USER = 'logged-in-user' authenticatedUser$ = new Subject<{ authenticated: boolean, authenticatedUser: User }>() @@ -20,15 +19,19 @@ export class AppState { ) { } - authenticateUser(jwt: CreJwt) { - this.authenticatedUser = jwt.user - this.authenticationExpiration = jwt.exp + authenticateUser(user: User) { + this.authenticatedUser = user this.isAuthenticated = true } + authenticateGroupUser(user: User) { + this.authenticatedUser = user + this.isDefaultGroupUserAuthenticated = true + } + resetAuthenticatedUser() { this.isAuthenticated = false - this.authenticationExpiration = -1 + this.isDefaultGroupUserAuthenticated = false this.authenticatedUser = null } @@ -51,13 +54,16 @@ export class AppState { }) } - get authenticationExpiration(): number { - return parseInt(sessionStorage.getItem(this.KEY_AUTHENTICATION_EXPIRATION)) + get isDefaultGroupUserAuthenticated(): boolean { + return sessionStorage.getItem(this.KEY_DEFAULT_GROUP_USER_AUTHENTICATED) === 'true' } - private set authenticationExpiration(value: number) { - console.error(value) - sessionStorage.setItem(this.KEY_AUTHENTICATION_EXPIRATION, value.toString()) + private set isDefaultGroupUserAuthenticated(value: boolean) { + sessionStorage.setItem(this.KEY_DEFAULT_GROUP_USER_AUTHENTICATED, value.toString()) + } + + get hasCredentials(): boolean { + return this.isAuthenticated || this.isDefaultGroupUserAuthenticated } get authenticatedUser(): User { @@ -81,9 +87,3 @@ export class AppState { this.titleService.setTitle(`CRE: ${value}`) } } - -export interface CreJwt { - readonly sub: string - readonly exp: number, - readonly user: User -} diff --git a/src/app/modules/shared/components/header/header.component.ts b/src/app/modules/shared/components/header/header.component.ts index 6d113fd..abe4a17 100644 --- a/src/app/modules/shared/components/header/header.component.ts +++ b/src/app/modules/shared/components/header/header.component.ts @@ -58,9 +58,10 @@ export class HeaderComponent extends SubscribingComponent { } ngOnDestroy(): void { - this.accountService.logout(() => { - console.log('Successfully logged out') - }) + this.subscribe( + this.accountService.logout(), + () => console.info('Successfully logged out') + ) super.ngOnDestroy() } @@ -71,7 +72,7 @@ export class HeaderComponent extends SubscribingComponent { set activeLink(link: string) { this._activeLink = link - this.router.navigate([link]) + this.urlUtils.navigateTo(link) } get activeLink() { diff --git a/src/app/modules/shared/service/api.service.ts b/src/app/modules/shared/service/api.service.ts index 1e4c269..462531b 100644 --- a/src/app/modules/shared/service/api.service.ts +++ b/src/app/modules/shared/service/api.service.ts @@ -70,14 +70,13 @@ export class ApiService implements OnDestroy { observe: 'response' } if (needAuthentication) { - if (this.checkAuthenticated()) { + if (this.appState.hasCredentials) { if (httpOptions) { httpOptions.withCredentials = true } else { console.error('httpOptions need to be specified to use credentials in HTTP methods.') } } else { - // this.appState.resetAuthenticatedUser() this.navigateToLogin() } } @@ -89,12 +88,6 @@ export class ApiService implements OnDestroy { .pipe(takeUntil(this._destroy$), map(r => r.body), share()) } - private checkAuthenticated(): boolean { - console.log(Date.now() / 1000, this.appState.authenticationExpiration) - return (this.appState.isAuthenticated && Date.now() <= this.appState.authenticationExpiration) || - (this.appState.authenticatedUser && this.appState.authenticatedUser.group != null) - } - private navigateToLogin() { this.router.navigate(['/account/login']) } diff --git a/src/app/modules/touch-up-kit/pages/list.html b/src/app/modules/touch-up-kit/pages/list.html index 877aa6d..f5bacdf 100644 --- a/src/app/modules/touch-up-kit/pages/list.html +++ b/src/app/modules/touch-up-kit/pages/list.html @@ -1,7 +1,7 @@ - Ajouter + Ajouter