Fix login and group user login. Hides add buttons when the user doesn't have the required permission.
continuous-integration/drone/pr Build was killed
Details
continuous-integration/drone/pr Build was killed
Details
This commit is contained in:
parent
cb7f38b46b
commit
be592a22f5
|
@ -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",
|
||||
|
|
|
@ -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 } {
|
||||
|
|
|
@ -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'])
|
||||
}
|
||||
|
||||
|
|
|
@ -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'
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<User>(`${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<User>(`${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<void>) {
|
||||
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<void>('/logout', true).pipe(
|
||||
logout(): Observable<void> {
|
||||
const subject = new Subject<void>()
|
||||
|
||||
this.api.get<void>('/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>('/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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<cre-action-bar [reverse]="true">
|
||||
<cre-action-group>
|
||||
<cre-accent-button routerLink="/catalog/company/add">Ajouter</cre-accent-button>
|
||||
<cre-accent-button *ngIf="hasEditPermission" routerLink="/catalog/company/add">Ajouter</cre-accent-button>
|
||||
</cre-action-group>
|
||||
</cre-action-bar>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<cre-action-bar [reverse]="true">
|
||||
<cre-action-group>
|
||||
<cre-accent-button routerLink="/catalog/materialtype/add">Ajouter</cre-accent-button>
|
||||
<cre-accent-button *ngIf="hasEditPermission" routerLink="/catalog/materialtype/add">Ajouter</cre-accent-button>
|
||||
</cre-action-group>
|
||||
</cre-action-bar>
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ export class RecipeForm extends SubscribingComponent {
|
|||
}
|
||||
|
||||
ngOnInit() {
|
||||
super.ngOnInit();
|
||||
super.ngOnInit()
|
||||
|
||||
this.fetchCompanies()
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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'])
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<cre-action-bar>
|
||||
<cre-action-group></cre-action-group>
|
||||
<cre-action-group>
|
||||
<cre-accent-button routerLink="/misc/touch-up-kit/add">Ajouter</cre-accent-button>
|
||||
<cre-accent-button *ngIf="canEditTouchUpKits" routerLink="/misc/touch-up-kit/add">Ajouter</cre-accent-button>
|
||||
</cre-action-group>
|
||||
</cre-action-bar>
|
||||
|
||||
|
|
Loading…
Reference in New Issue