feature/30-group-authentication #9

Merged
william merged 6 commits from feature/30-group-authentication into develop 2022-08-03 08:07:11 -04:00
32 changed files with 126 additions and 101 deletions
Showing only changes of commit 24349ae051 - Show all commits

View File

@ -47,9 +47,9 @@ export class Login extends ErrorHandlingComponent {
}
submit() {
this.subscribeAndNavigate(
this.subscribe(
this.accountService.login(this.userIdControl.value, this.passwordControl.value),
'/color/list'
next => {}
)
}

View File

@ -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, User} from '../../shared/model/user'
import {Permission, AccountModel, LoginDto} from '../../shared/model/account.model'
import {ErrorService} from '../../shared/service/error.service'
import {AlertService} from '../../shared/service/alert.service'
import {JwtService} from "./jwt.service";
@ -31,57 +31,74 @@ export class AccountService implements OnDestroy {
this.destroy$.complete()
}
login(userId: number, password: string): Observable<LoginDto> {
const login$ = this.http.post<LoginDto>(
`${environment.apiUrl}/account/login`,
{id: userId, password},
{withCredentials: true})
.pipe(take(1), takeUntil(this.destroy$))
login$.subscribe({
next: result => {
console.log(result)
},
error: err => this.errorService.handleError(err)
})
return login$
}
checkAuthenticationStatus() {
if (!this.appState.isAuthenticated) {
// Try to get current default group user
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)
}
}
})
// this.http.get<AccountModel>(`${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)
// }
// }
// })
}
}
login(userId: number, password: string): Observable<any> {
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)
subject.next()
subject.complete()
},
error: error => {
if (error.status === 403) {
this.alertService.pushError('Les identifiants entrés sont invalides')
} else {
this.errorService.handleError(error)
}
subject.next()
subject.complete()
}
})
return subject
}
// login(userId: number, password: string): Observable<any> {
// 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)
//
// subject.next()
// subject.complete()
// },
// error: error => {
// if (error.status === 403) {
// this.alertService.pushError('Les identifiants entrés sont invalides')
// } else {
// this.errorService.handleError(error)
// }
//
// subject.next()
// subject.complete()
// }
// })
//
// return subject
// }
private loginUser(response: HttpResponse<void>) {
const authorization = response.headers.get("Authorization")

View File

@ -1,12 +1,12 @@
import {Injectable} from "@angular/core";
import jwtDecode from "jwt-decode";
import { User } from "../../shared/model/user";
import { AccountModel } from "../../shared/model/account.model";
@Injectable({
providedIn: 'root'
})
export class JwtService {
parseUser(jwt: string): User {
parseUser(jwt: string): AccountModel {
const decoded = jwtDecode(jwt) as any
return JSON.parse(decoded.user)
}

View File

@ -1,7 +1,7 @@
import {Component} from '@angular/core'
import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component'
import {CompanyService} from '../../service/company.service'
import {Permission} from '../../../shared/model/user'
import {Permission} from '../../../shared/model/account.model'
import {ActivatedRoute, Router} from '@angular/router'
import {ErrorService} from '../../../shared/service/error.service'
import {AppState} from '../../../shared/app-state'

View File

@ -1,6 +1,6 @@
import {Component, ViewChild} from '@angular/core'
import {ActivatedRoute, Router} from '@angular/router'
import {Group} from '../../../shared/model/user'
import {Group} from '../../../shared/model/account.model'
import {GroupService} from '../../services/group.service'
import {Validators} from '@angular/forms'
import {currentPermissionsFieldComponent} from '../../../shared/components/permissions-field/permissions-field.component'

View File

@ -1,6 +1,6 @@
import {Component} from '@angular/core'
import {GroupService} from '../../services/group.service'
import {Group, Permission} from '../../../shared/model/user'
import {Group, Permission} from '../../../shared/model/account.model'
import {AccountService} from '../../../accounts/services/account.service'
import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component'
import {ActivatedRoute, Router} from '@angular/router'

View File

@ -1,7 +1,7 @@
import {Injectable} from '@angular/core'
import {ApiService} from '../../shared/service/api.service'
import {Observable} from 'rxjs'
import {User, Group, Permission} from '../../shared/model/user'
import {AccountModel, Group, Permission} from '../../shared/model/account.model'
import {tap} from 'rxjs/operators'
@Injectable({
@ -38,15 +38,15 @@ export class GroupService {
return this.api.post<void>(`/user/group/default/${value.id}`, {})
}
getUsersForGroup(id: number): Observable<User[]> {
return this.api.get<User[]>(`/user/group/${id}/users`)
getUsersForGroup(id: number): Observable<AccountModel[]> {
return this.api.get<AccountModel[]>(`/user/group/${id}/users`)
}
addUserToGroup(id: number, user: User): Observable<void> {
addUserToGroup(id: number, user: AccountModel): Observable<void> {
return this.api.put<void>(`/user/group/${id}/${user.id}`)
}
removeUserFromGroup(user: User): Observable<void> {
removeUserFromGroup(user: AccountModel): Observable<void> {
return this.api.delete<void>(`/user/group/${user.group.id}/${user.id}`)
}

View File

@ -1,7 +1,7 @@
import {Component} from '@angular/core'
import {MaterialTypeService} from '../../service/material-type.service'
import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component'
import {Permission} from '../../../shared/model/user'
import {Permission} from '../../../shared/model/account.model'
import {ActivatedRoute, Router} from '@angular/router'
import {ErrorService} from '../../../shared/service/error.service'
import {AppState} from '../../../shared/app-state'

View File

@ -1,7 +1,7 @@
import {Component, ViewChild} from '@angular/core'
import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component'
import {MaterialService} from '../../service/material.service'
import {Permission} from '../../../shared/model/user'
import {Permission} from '../../../shared/model/account.model'
import {ActivatedRoute, Router} from '@angular/router'
import {ErrorService} from '../../../shared/service/error.service'
import {Material, materialFilterFieldSeparator, materialMatchesFilter, openSimdut} from '../../../shared/model/material.model'

View File

@ -15,7 +15,7 @@ import {ConfirmBoxComponent} from '../../../shared/components/confirm-box/confir
import {ErrorService} from '../../../shared/service/error.service'
import {AlertService} from '../../../shared/service/alert.service'
import {MaterialService} from '../../../material/service/material.service'
import {Permission} from '../../../shared/model/user'
import {Permission} from '../../../shared/model/account.model'
import {AccountService} from '../../../accounts/services/account.service'
import {Material, openSimdut} from '../../../shared/model/material.model'

View File

@ -2,7 +2,7 @@ import {Component, Input} from '@angular/core'
import {Recipe, RecipeStep, recipeStepsForGroupId, sortRecipeSteps} from '../../../shared/model/recipe.model'
import {MatTable} from '@angular/material/table'
import {Observable} from 'rxjs'
import {Group} from '../../../shared/model/user'
import {Group} from '../../../shared/model/account.model'
@Component({
selector: 'cre-step-table',

View File

@ -18,7 +18,7 @@ import {ConfirmBoxComponent} from '../shared/components/confirm-box/confirm-box.
import {GroupService} from '../groups/services/group.service'
import {AppState} from '../shared/app-state'
import {AccountService} from '../accounts/services/account.service'
import {Permission} from '../shared/model/user'
import {Permission} from '../shared/model/account.model'
import {FormControl} from '@angular/forms';
import {map} from 'rxjs/operators';
import {CreInputEntry} from '../shared/components/inputs/inputs';

View File

@ -10,7 +10,7 @@ import {AppState} from '../shared/app-state'
import {ErrorService} from '../shared/service/error.service'
import {ActivatedRoute, Router} from '@angular/router'
import {Config} from '../shared/model/config.model'
import {Permission} from '../shared/model/user'
import {Permission} from '../shared/model/account.model'
import {FormControl} from '@angular/forms'
@Component({

View File

@ -16,7 +16,7 @@ import {FormControl, Validators} from '@angular/forms'
import {takeUntil} from 'rxjs/operators'
import {CreComboBoxComponent, CreInputEntry} from '../../shared/components/inputs/inputs'
import {AccountService} from '../../accounts/services/account.service'
import {Permission} from '../../shared/model/user'
import {Permission} from '../../shared/model/account.model'
import {UNIT_MILLILITER} from '../../shared/units'
@Component({

View File

@ -11,7 +11,7 @@ import {FormControl, Validators} from '@angular/forms';
import {Component, EventEmitter, Input, Output, ViewChild, ViewEncapsulation} from '@angular/core';
import {Recipe, recipeMixCount, RecipeStep, recipeStepCount} from '../shared/model/recipe.model';
import {AccountService} from '../accounts/services/account.service';
import {Permission} from '../shared/model/user';
import {Permission} from '../shared/model/account.model';
import {AlertService} from '../shared/service/alert.service';
import {GroupService} from '../groups/services/group.service';
import {StepTableComponent} from './components/step-table/step-table.component';

View File

@ -1,5 +1,5 @@
import {Injectable} from '@angular/core'
import {User} from './model/user'
import {AccountModel, LoginDto} from './model/account.model'
import {Subject} from 'rxjs'
import {Title} from '@angular/platform-browser'
@ -11,7 +11,7 @@ export class AppState {
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 }>()
authenticatedUser$ = new Subject<{ authenticated: boolean, authenticatedUser: LoginDto }>()
serverOnline$ = new Subject<boolean>()
constructor(
@ -19,12 +19,12 @@ export class AppState {
) {
}
authenticateUser(user: User) {
authenticateUser(user: LoginDto) {
this.authenticatedUser = user
this.isAuthenticated = true
}
authenticateGroupUser(user: User) {
authenticateGroupUser(user: LoginDto) {
this.authenticatedUser = user
this.isDefaultGroupUserAuthenticated = true
}
@ -66,12 +66,12 @@ export class AppState {
return this.isAuthenticated || this.isDefaultGroupUserAuthenticated
}
get authenticatedUser(): User {
get authenticatedUser(): LoginDto {
const userString = sessionStorage.getItem(this.KEY_LOGGED_IN_USER)
return userString ? JSON.parse(userString) : null
}
private set authenticatedUser(value: User) {
private set authenticatedUser(value: LoginDto) {
if (value === null) {
// sessionStorage.removeItem(this.KEY_LOGGED_IN_USER)
} else {

View File

@ -1,7 +1,7 @@
import {Component, Input} from '@angular/core'
import {Observable} from 'rxjs'
import {AccountService} from '../../../accounts/services/account.service'
import {Permission} from '../../model/user'
import {Permission} from '../../model/account.model'
import {animate, state, style, transition, trigger} from '@angular/animations'
@Component({

View File

@ -1,7 +1,7 @@
import {Component} from '@angular/core'
import {ActivatedRoute, ResolveEnd, Router} from '@angular/router'
import {AppState} from '../../app-state'
import {Permission} from '../../model/user'
import {Permission} from '../../model/account.model'
import {AccountService} from '../../../accounts/services/account.service'
import {SubscribingComponent} from '../subscribing.component'
import {ErrorService} from '../../service/error.service'

View File

@ -1,5 +1,5 @@
import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import {User, Permission} from "../../model/user";
import {AccountModel, Permission} from "../../model/account.model";
import {AccountService} from "../../../accounts/services/account.service";
import {ActivatedRoute, Router} from "@angular/router";
import {takeUntil} from "rxjs/operators";
@ -54,7 +54,7 @@ export class NavComponent implements OnInit, OnDestroy {
return this._activeLink
}
private updateEnabledLinks(user: User) {
private updateEnabledLinks(user: AccountModel) {
this.links.forEach(l => {
if (l.permission) {
l.enabled = user && user.permissions.indexOf(l.permission) >= 0;

View File

@ -1,5 +1,5 @@
import {Component, Input, OnInit, ViewChild} from '@angular/core';
import {Permission, mapped_permissions} from "../../model/user";
import {Permission, mapped_permissions} from "../../model/account.model";
import {FormControl} from "@angular/forms";
import {AccountService} from "../../../accounts/services/account.service";

View File

@ -1,5 +1,5 @@
import {Component, Input, OnInit} from '@angular/core'
import {User, Group, Permission, mapped_permissions} from '../../model/user'
import {AccountModel, Group, Permission, mapped_permissions} from '../../model/account.model'
@Component({
selector: 'cre-permissions-list',
@ -7,7 +7,7 @@ import {User, Group, Permission, mapped_permissions} from '../../model/user'
styleUrls: ['./permissions-list.component.sass']
})
export class PermissionsListComponent {
@Input() user: User
@Input() user: AccountModel
@Input() group: Group
// @ts-ignore

View File

@ -1,6 +1,6 @@
import {Component, OnDestroy, OnInit} from '@angular/core'
import {AppState} from '../../app-state'
import {User} from '../../model/user'
import {AccountModel} from '../../model/account.model'
import {Subject} from 'rxjs'
import {takeUntil} from 'rxjs/operators'
import {UrlUtils} from '../../utils/url.utils'
@ -13,7 +13,7 @@ import {ActivatedRoute, Router} from '@angular/router'
})
export class UserMenuComponent implements OnInit, OnDestroy {
authenticated = false
user: User = null
user: AccountModel = null
userInGroup = false
menuEnabled = false
@ -52,7 +52,7 @@ export class UserMenuComponent implements OnInit, OnDestroy {
this.menuEnabled = false
}
private authenticationState(authenticated: boolean, user: User) {
private authenticationState(authenticated: boolean, user: AccountModel) {
this.authenticated = authenticated
this.user = user
if (this.user != null) {

View File

@ -1,4 +1,12 @@
export class User {
export interface LoginDto {
id: string,
fullName: string,
permissions: string[],
groupId?: number,
groupName?: string
}
export class AccountModel {
constructor(
public id: number,
public firstName: string,

View File

@ -1,6 +1,6 @@
import {Material} from './material.model'
import {Company} from './company.model'
import {Group} from './user'
import {Group} from './account.model'
import {UNIT_MILLILITER} from "../units";
import {MaterialType} from "./materialtype.model";

View File

@ -6,7 +6,7 @@ import {TouchUpKitService} from '../service/touch-up-kit.service'
import {AccountService} from '../../accounts/services/account.service'
import {ErrorService} from '../../shared/service/error.service'
import {ActivatedRoute, Router} from '@angular/router'
import {Permission} from '../../shared/model/user'
import {Permission} from '../../shared/model/account.model'
import {RecipeService} from '../../recipes/services/recipe.service'
import {AppState} from '../../shared/app-state'
import {map} from 'rxjs/operators'

View File

@ -3,7 +3,7 @@ import {currentPermissionsFieldComponent} from '../../../shared/components/permi
import {UserService} from '../../services/user.service'
import {GroupService} from '../../../groups/services/group.service'
import {ActivatedRoute, Router} from '@angular/router'
import {User} from '../../../shared/model/user'
import {AccountModel} from '../../../shared/model/account.model'
import {AccountService} from '../../../accounts/services/account.service'
import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component'
import {ErrorHandler, ErrorService} from '../../../shared/service/error.service'
@ -19,7 +19,7 @@ import {AppState} from '../../../shared/app-state'
export class EditComponent extends ErrorHandlingComponent {
@ViewChild('permissionsTemplateRef', {static: true}) permissionsTemplateRef
user: User | null
user: AccountModel | null
formFields: FormField[] = [{
name: 'id',
label: 'Numéro d\'utilisateur',

View File

@ -1,7 +1,7 @@
import {Component} from '@angular/core'
import {Observable} from 'rxjs'
import {UserService} from '../../services/user.service'
import {User, Permission} from '../../../shared/model/user'
import {AccountModel, Permission} from '../../../shared/model/account.model'
import {takeUntil} from 'rxjs/operators'
import {AccountService} from '../../../accounts/services/account.service'
import {animate, state, style, transition, trigger} from '@angular/animations'
@ -23,7 +23,7 @@ import {AppState} from '../../../shared/app-state'
]
})
export class ListComponent extends ErrorHandlingComponent {
users$: Observable<User[]>
users$: Observable<AccountModel[]>
columns = [
{def: 'id', title: 'Numéro d\'utilisateur', valueFn: e => e.id},
{def: 'name', title: 'Nom', valueFn: e => `${e.firstName} ${e.lastName}`},

View File

@ -1,7 +1,7 @@
import {Component} from '@angular/core'
import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component'
import {UserService} from '../../services/user.service'
import {User} from '../../../shared/model/user'
import {AccountModel} from '../../../shared/model/account.model'
import {ActivatedRoute, Router} from '@angular/router'
import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms'
import {ErrorHandler, ErrorService} from '../../../shared/service/error.service'
@ -12,7 +12,7 @@ import {ErrorHandler, ErrorService} from '../../../shared/service/error.service'
styleUrls: ['./password-edit.component.sass']
})
export class PasswordEditComponent extends ErrorHandlingComponent {
user: User | null
user: AccountModel | null
form: FormGroup
passwordControl = new FormControl(null, Validators.compose([Validators.required, Validators.minLength(8)]))

View File

@ -1,6 +1,6 @@
import {Injectable} from '@angular/core';
import {ApiService} from "../../shared/service/api.service";
import {User, Permission} from "../../shared/model/user";
import {AccountModel, Permission} from "../../shared/model/account.model";
import {Observable} from "rxjs";
@Injectable({
@ -12,17 +12,17 @@ export class UserService {
) {
}
get all(): Observable<User[]> {
return this.api.get<User[]>('/user')
get all(): Observable<AccountModel[]> {
return this.api.get<AccountModel[]>('/user')
}
getById(id: number): Observable<User> {
return this.api.get<User>(`/user/${id}`)
getById(id: number): Observable<AccountModel> {
return this.api.get<AccountModel>(`/user/${id}`)
}
save(id: number, firstName: string, lastName: string, password: string, group: number, permissions: Permission[]): Observable<User> {
save(id: number, firstName: string, lastName: string, password: string, group: number, permissions: Permission[]): Observable<AccountModel> {
const user = {id, firstName, lastName, password, groupId: group >= 0 ? group : null, permissions}
return this.api.post<User>('/user', user)
return this.api.post<AccountModel>('/user', user)
}
update(id: number, firstName: string, lastName: string, group: number, permissions: Permission[]): Observable<void> {

View File

@ -1,7 +1,7 @@
import {Component} from '@angular/core'
import {SubMenuComponent} from '../../modules/shared/components/sub-menu/sub-menu.component'
import {NavLink} from '../../modules/shared/components/nav/nav.component'
import {Permission} from '../../modules/shared/model/user'
import {Permission} from '../../modules/shared/model/account.model'
@Component({
selector: 'cre-administration',

View File

@ -1,6 +1,6 @@
import {Component} from '@angular/core'
import {NavLink} from '../../modules/shared/components/nav/nav.component'
import {Permission} from '../../modules/shared/model/user'
import {Permission} from '../../modules/shared/model/account.model'
import {SubMenuComponent} from '../../modules/shared/components/sub-menu/sub-menu.component'
@Component({

View File

@ -1,7 +1,7 @@
import {Component} from '@angular/core'
import {SubMenuComponent} from '../../modules/shared/components/sub-menu/sub-menu.component'
import {NavLink} from '../../modules/shared/components/nav/nav.component'
import {Permission} from '../../modules/shared/model/user'
import {Permission} from '../../modules/shared/model/account.model'
@Component({
selector: 'cre-others',