12-user-info-jwt #4

Merged
william merged 5 commits from 12-user-info-jwt into develop 2021-12-15 00:24:15 -05:00
5 changed files with 101 additions and 53 deletions
Showing only changes of commit 07b410d053 - Show all commits

View File

@ -10,6 +10,9 @@
"e2e": "ng e2e"
},
"private": true,
"browser": {
"fs": false
},
"dependencies": {
"@angular/animations": "~12.2.14",
"@angular/cdk": "^12.2.13",
@ -21,10 +24,11 @@
"@angular/platform-browser": "~12.2.14",
"@angular/platform-browser-dynamic": "~12.2.14",
"@angular/router": "~12.2.14",
"@js-joda/core": "^4.3.1",
"@mdi/angular-material": "^6.5.95",
"bootstrap": "^4.5.2",
"copy-webpack-plugin": "^10.0.0",
"@js-joda/core": "^4.3.1",
"jwt-decode": "^3.1.2",
"material-design-icons": "^3.0.1",
"ngx-material-file-input": "^2.1.1",
"rxjs": "^7.4.0",

View File

@ -48,18 +48,17 @@ export class Login extends ErrorHandlingComponent {
}
submit() {
this.subscribeAndNavigate(
this.accountService.login(this.userIdControl.value, this.passwordControl.value),
'/color'
)
// 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({
error: error => this.handleLoginError(error)
})
}
private handleLoginError(error) {
if (error.status === 403) {
this.alertService.pushError('Les identifiants entrés sont invalides')
}
// 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 } {

View File

@ -1,14 +1,15 @@
import {Injectable, OnDestroy} from '@angular/core'
import {Observable, Subject} from 'rxjs'
import {take, takeUntil, tap} from 'rxjs/operators'
import {take, takeUntil} from 'rxjs/operators'
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 {User, Permission} from '../../shared/model/user'
import {Permission} from '../../shared/model/user'
import {ErrorService} from '../../shared/service/error.service'
import {globalLoadingWheel} from '../../shared/components/loading-wheel/loading-wheel.component'
import {AlertService} from '../../shared/service/alert.service'
import {JwtService} from "./jwt.service";
@Injectable({
providedIn: 'root'
@ -20,6 +21,7 @@ export class AccountService implements OnDestroy {
private http: HttpClient,
private api: ApiService,
private appState: AppState,
private jwtService: JwtService,
private errorService: ErrorService,
private alertService: AlertService
) {
@ -37,47 +39,61 @@ export class AccountService implements OnDestroy {
checkAuthenticationStatus() {
if (!this.appState.authenticatedUser) {
// 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/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)
// }
// }
// })
}
}
login(userId: number, password: string): Observable<any> {
globalLoadingWheel.show()
const request$ = this.http.post<any>(`${environment.apiUrl}/login`, {id: userId, password}, {
const subject = new Subject<void>()
this.http.post<any>(`${environment.apiUrl}/login`, {id: userId, password}, {
withCredentials: true,
observe: 'response' as 'body'
}).pipe(
take(1),
takeUntil(this.destroy$)
)
).subscribe({
next: (response: HttpResponse<void>) => {
this.loginUser(response)
request$.subscribe({
next: (response: HttpResponse<any>) => {
globalLoadingWheel.hide()
// TODO: Login user
subject.next()
subject.complete()
},
error: error => {
globalLoadingWheel.hide()
this.errorService.handleError(error)
if (error.status === 403) {
this.alertService.pushError('Les identifiants entrés sont invalides')
} else {
this.errorService.handleError(error)
}
subject.next()
subject.complete()
}
})
return request$
return subject
}
private loginUser(response: HttpResponse<void>) {
const authorization = response.headers.get("Authorization")
const jwt = this.jwtService.parseJwt(authorization)
this.appState.authenticatedUser = jwt.user
this.appState.authenticationExpiration = jwt.exp
}
loginOld(id: number, password: string, success: () => void) {
@ -129,18 +145,19 @@ export class AccountService implements OnDestroy {
}
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)
})
// 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")
}
}

View File

@ -0,0 +1,25 @@
import {Injectable} from "@angular/core";
import {User} from "../../shared/model/user";
import jwtDecode from "jwt-decode";
import {parseJson} from "@angular/cli/utilities/json-file";
@Injectable({
providedIn: 'root'
})
export class JwtService {
parseJwt(jwt: string): CreJwt {
const decoded = jwtDecode(jwt) as any
return {
sub: decoded.sub,
exp: decoded.exp,
user: parseJson(decoded.user)
}
}
}
interface CreJwt {
readonly sub: string
readonly exp: number,
readonly user: User
}

View File

@ -2,6 +2,7 @@ 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'
@ -59,8 +60,10 @@ export class AppState {
set authenticatedUser(value: User) {
if (value === null) {
console.log(1)
sessionStorage.removeItem(this.KEY_LOGGED_IN_USER)
} else {
console.log(2)
sessionStorage.setItem(this.KEY_LOGGED_IN_USER, JSON.stringify(value))
}
this.authenticatedUser$.next({