From 80b4726004c65ac2337791f79c93b126c5f57c50 Mon Sep 17 00:00:00 2001 From: sanchezvem Date: Mon, 1 Jun 2026 10:41:50 +0100 Subject: [PATCH] Added conditions to check role after connexion and changed guards --- package-lock.json | 10 ++++ package.json | 1 + src/app/app.routes.ts | 4 +- .../deliverer-table/deliverer-table.html | 8 +-- .../deliverer-table/deliverer-table.ts | 4 ++ .../deliverery-note-table.html | 8 +-- .../deliverery-note-table.ts | 4 ++ src/app/components/layout/layout.html | 8 +-- src/app/components/layout/layout.ts | 12 +++-- .../purchase-order-table.html | 8 +-- .../purchase-order-table.ts | 4 ++ .../quotation-table/quotation-table.html | 8 +-- .../quotation-table/quotation-table.ts | 4 ++ .../components/setting-form/setting-form.html | 52 ++++++++++++------- .../components/setting-form/setting-form.ts | 4 ++ .../components/stock-table/stock-table.html | 8 +-- src/app/components/stock-table/stock-table.ts | 4 ++ .../supplier-table/supplier-table.html | 18 ++++--- .../supplier-table/supplier-table.ts | 4 ++ src/app/guards/auth.guard.ts | 8 ++- src/app/guards/role.guard.ts | 12 ----- src/app/services/auth.service.ts | 41 +++++---------- 22 files changed, 142 insertions(+), 92 deletions(-) delete mode 100644 src/app/guards/role.guard.ts diff --git a/package-lock.json b/package-lock.json index 751a0fa..5f7824f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "@tailwindcss/postcss": "^4.1.17", "@tailwindcss/vite": "^4.1.17", "browser-image-compression": "^2.0.2", + "jwt-decode": "^4.0.0", "ng-zorro-antd": "^20.4.0", "postcss": "^8.5.6", "rimraf": "^6.1.3", @@ -6912,6 +6913,15 @@ ], "license": "MIT" }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/less": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/less/-/less-4.4.2.tgz", diff --git a/package.json b/package.json index 29eea29..4cc1a66 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@tailwindcss/postcss": "^4.1.17", "@tailwindcss/vite": "^4.1.17", "browser-image-compression": "^2.0.2", + "jwt-decode": "^4.0.0", "ng-zorro-antd": "^20.4.0", "postcss": "^8.5.6", "rimraf": "^6.1.3", diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 5f4e052..3d610b8 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,6 +1,5 @@ import {Routes} from '@angular/router'; import {authGuard} from "./guards/auth.guard"; -import {roleGuard} from "./guards/role.guard"; export const routes: Routes = [ { @@ -60,8 +59,7 @@ export const routes: Routes = [ { path: 'user', loadComponent: () => import('./pages/user/user').then(m => m.User), - canActivate: [authGuard, roleGuard], - data: {roles: ['Admin']}, + canActivate: [authGuard], }, { path: '**', diff --git a/src/app/components/deliverer-table/deliverer-table.html b/src/app/components/deliverer-table/deliverer-table.html index 1043184..1ff9409 100644 --- a/src/app/components/deliverer-table/deliverer-table.html +++ b/src/app/components/deliverer-table/deliverer-table.html @@ -43,9 +43,11 @@
- - + @if (admin()){ + + + }
diff --git a/src/app/components/deliverer-table/deliverer-table.ts b/src/app/components/deliverer-table/deliverer-table.ts index a0c82a1..53bb557 100644 --- a/src/app/components/deliverer-table/deliverer-table.ts +++ b/src/app/components/deliverer-table/deliverer-table.ts @@ -9,6 +9,7 @@ import {DelivererForm} from "../deliverer-form/deliverer-form"; import {DeliverersService, GetDelivererDto, GetSupplierDto} from "../../services/api"; import {NzNotificationService} from "ng-zorro-antd/notification"; import {firstValueFrom} from "rxjs"; +import {AuthService} from "../../services/auth.service"; @Component({ selector: 'app-deliverer-table', @@ -28,14 +29,17 @@ import {firstValueFrom} from "rxjs"; export class DelivererTable implements OnInit { private deliverersService = inject(DeliverersService); private notificationService = inject(NzNotificationService) + private authService = inject(AuthService); deliverers = signal([]); deliverersLoading = signal(false); + admin = signal(false); modal = viewChild.required('modalNav'); async ngOnInit() { await this.fetchDeliverers(); + this.admin.set(this.authService.isAdmin()); } async fetchDeliverers() { diff --git a/src/app/components/deliverery-note-table/deliverery-note-table.html b/src/app/components/deliverery-note-table/deliverery-note-table.html index daca5a9..c7b0c4f 100644 --- a/src/app/components/deliverery-note-table/deliverery-note-table.html +++ b/src/app/components/deliverery-note-table/deliverery-note-table.html @@ -38,9 +38,11 @@ - - + @if (admin()){ + + + } diff --git a/src/app/components/deliverery-note-table/deliverery-note-table.ts b/src/app/components/deliverery-note-table/deliverery-note-table.ts index 266e222..1b31870 100644 --- a/src/app/components/deliverery-note-table/deliverery-note-table.ts +++ b/src/app/components/deliverery-note-table/deliverery-note-table.ts @@ -10,6 +10,7 @@ import {NzNotificationService} from "ng-zorro-antd/notification"; import {firstValueFrom} from "rxjs"; import {format} from "date-fns"; import {FileService} from "../../services/file.service"; +import {AuthService} from "../../services/auth.service"; @Component({ selector: 'app-deliverery-note-table', @@ -28,9 +29,11 @@ export class DelivereryNoteTable implements OnInit { private deliveryNotesService = inject(DeliverynotesService); private notificationService = inject(NzNotificationService); private fileService = inject(FileService); + private authService = inject(AuthService); deliveryNotes = signal([]); deliveryNotesLoading = signal(false); + admin = signal(false); modal = viewChild.required('modalNav'); @@ -38,6 +41,7 @@ export class DelivereryNoteTable implements OnInit { async ngOnInit() { await this.fetchDeliveryNotes(); + this.admin.set(this.authService.isAdmin()); } async fetchDeliveryNotes() { diff --git a/src/app/components/layout/layout.html b/src/app/components/layout/layout.html index 9b6c4d1..269cc2c 100644 --- a/src/app/components/layout/layout.html +++ b/src/app/components/layout/layout.html @@ -59,14 +59,14 @@ -
  • - @if (authService.hasRole(['ADMIN'])) { + @if (admin()) { +
  • Utilisateur - } -
  • + + } diff --git a/src/app/components/layout/layout.ts b/src/app/components/layout/layout.ts index 3a2181d..1a4286e 100644 --- a/src/app/components/layout/layout.ts +++ b/src/app/components/layout/layout.ts @@ -1,4 +1,4 @@ -import {Component, inject} from '@angular/core'; +import {Component, inject, OnInit, signal} from '@angular/core'; import {ModalNav} from "../modal-nav/modal-nav"; import {NzContentComponent, NzHeaderComponent, NzLayoutComponent} from "ng-zorro-antd/layout"; import {NzIconDirective} from "ng-zorro-antd/icon"; @@ -28,10 +28,16 @@ import {AuthService} from "../../services/auth.service"; templateUrl: './layout.html', styleUrl: './layout.css', }) -export class Layout { - protected authService = inject(AuthService); +export class Layout implements OnInit { + private authService = inject(AuthService); private router = inject(Router); + admin = signal(false); + + ngOnInit() { + this.admin.set(this.authService.isAdmin()); + } + async disconnect() { this.authService.logout(); await this.router.navigate(['/login']); diff --git a/src/app/components/purchase-order-table/purchase-order-table.html b/src/app/components/purchase-order-table/purchase-order-table.html index 393511a..5cb9e04 100644 --- a/src/app/components/purchase-order-table/purchase-order-table.html +++ b/src/app/components/purchase-order-table/purchase-order-table.html @@ -60,9 +60,11 @@ - - + @if (admin()) { + + + } diff --git a/src/app/components/purchase-order-table/purchase-order-table.ts b/src/app/components/purchase-order-table/purchase-order-table.ts index 1b56510..ef74075 100644 --- a/src/app/components/purchase-order-table/purchase-order-table.ts +++ b/src/app/components/purchase-order-table/purchase-order-table.ts @@ -17,6 +17,7 @@ import {firstValueFrom} from "rxjs"; import {FileService} from "../../services/file.service"; import {QuantityForm} from "../quantity-form/quantity-form"; import {DelivererChoice} from "../deliverer-choice/deliverer-choice"; +import {AuthService} from "../../services/auth.service"; @Component({ selector: 'app-purchase-order-table', @@ -38,9 +39,11 @@ export class PurchaseOrderTable implements OnInit { private notificationService = inject(NzNotificationService); private fileService = inject(FileService); private deliveryNoteService = inject(DeliverynotesService); + private authService = inject(AuthService); purchaseOrders = signal([]); purchaseOrdersLoading = signal(false); + admin = signal(false); modal = viewChild.required('modalNav'); modalQuantity = viewChild.required('modalQuantity'); @@ -48,6 +51,7 @@ export class PurchaseOrderTable implements OnInit { async ngOnInit() { await this.fetchPurchaseOrder(); + this.admin.set(this.authService.isAdmin()); } async fetchPurchaseOrder() { diff --git a/src/app/components/quotation-table/quotation-table.html b/src/app/components/quotation-table/quotation-table.html index 2adde02..9dc2cc7 100644 --- a/src/app/components/quotation-table/quotation-table.html +++ b/src/app/components/quotation-table/quotation-table.html @@ -60,9 +60,11 @@ - - + @if (admin()) { + + + } diff --git a/src/app/components/quotation-table/quotation-table.ts b/src/app/components/quotation-table/quotation-table.ts index c745387..4a3e000 100644 --- a/src/app/components/quotation-table/quotation-table.ts +++ b/src/app/components/quotation-table/quotation-table.ts @@ -14,6 +14,7 @@ import {NzNotificationService} from "ng-zorro-antd/notification"; import {firstValueFrom} from "rxjs"; import {FileService} from "../../services/file.service"; import {QuantityForm} from "../quantity-form/quantity-form"; +import {AuthService} from "../../services/auth.service"; @Component({ selector: 'app-quotation-table', @@ -34,15 +35,18 @@ export class QuotationTable implements OnInit { private quotationsService = inject(QuotationsService); private notificationService = inject(NzNotificationService); private fileService = inject(FileService); + private authService = inject(AuthService); quotations = signal([]); quotationsLoading = signal(false); + admin = signal(false); modal = viewChild.required('modalNav'); modalQuantity = viewChild.required('modalQuantity'); async ngOnInit() { await this.fetchQuotations(); + this.admin.set(this.authService.isAdmin()); } async fetchQuotations() { diff --git a/src/app/components/setting-form/setting-form.html b/src/app/components/setting-form/setting-form.html index 6cb89bd..49fe210 100644 --- a/src/app/components/setting-form/setting-form.html +++ b/src/app/components/setting-form/setting-form.html @@ -10,15 +10,23 @@ } -
    - - Logo - - - - -
    + @if (admin()){ +
    + + Logo + + + + +
    + } @else { +
    + +

    Vous ne pouvez pas modifier le logo

    +
    +
    + } @@ -31,14 +39,22 @@ } -
    - - Signature - - - - -
    + @if (admin()) { +
    + + Signature + + + + +
    + } @else { +
    + +

    Vous ne pouvez pas modifier la signature

    +
    +
    + } diff --git a/src/app/components/setting-form/setting-form.ts b/src/app/components/setting-form/setting-form.ts index 8c7af92..cf93c09 100644 --- a/src/app/components/setting-form/setting-form.ts +++ b/src/app/components/setting-form/setting-form.ts @@ -8,6 +8,7 @@ import {firstValueFrom} from "rxjs"; import {GetSettingDto, SettingsService} from "../../services/api"; import {NzNotificationService} from "ng-zorro-antd/notification"; import imageCompression from "browser-image-compression"; +import {AuthService} from "../../services/auth.service"; @Component({ selector: 'app-setting-form', @@ -27,8 +28,10 @@ import imageCompression from "browser-image-compression"; export class SettingForm implements OnInit { private settingsService = inject(SettingsService); private notificationService = inject(NzNotificationService); + private authService = inject(AuthService); settings = signal({}); + admin = signal(false); setting: SettingInfo = { logo: 'https://www.pyro-fetes.com/wp-content/themes/pcptheme/img/logo-pyro-fetes-OR-top.png', @@ -42,6 +45,7 @@ export class SettingForm implements OnInit { async ngOnInit() { await this.fetchSettings(); + this.admin.set(this.authService.isAdmin()); } async fetchSettings() { diff --git a/src/app/components/stock-table/stock-table.html b/src/app/components/stock-table/stock-table.html index 55148da..ca04789 100644 --- a/src/app/components/stock-table/stock-table.html +++ b/src/app/components/stock-table/stock-table.html @@ -46,9 +46,11 @@
    - - + @if (admin()) { + + + }
    diff --git a/src/app/components/stock-table/stock-table.ts b/src/app/components/stock-table/stock-table.ts index 7ff4c81..4da3aa3 100644 --- a/src/app/components/stock-table/stock-table.ts +++ b/src/app/components/stock-table/stock-table.ts @@ -9,6 +9,7 @@ import {GetProductDto, ProductsService, WarehouseproductsService} from "../../se import {NzNotificationService} from "ng-zorro-antd/notification"; import {first, firstValueFrom} from "rxjs"; import {NzCheckboxComponent} from "ng-zorro-antd/checkbox"; +import {AuthService} from "../../services/auth.service"; interface ProductWithQuantity extends GetProductDto { totalQuantity?: number; @@ -34,9 +35,11 @@ export class StockTable implements OnInit { private productsService = inject(ProductsService); private wareHousseProductsService = inject(WarehouseproductsService) private notificationService = inject(NzNotificationService) + private authService = inject(AuthService); products = signal([]); productsLoading = signal(false); + admin = signal(false); modal = viewChild.required('modalNav'); @@ -50,6 +53,7 @@ export class StockTable implements OnInit { async ngOnInit() { await this.fetchProducts(); + this.admin.set(this.authService.isAdmin()); } async fetchProducts() { diff --git a/src/app/components/supplier-table/supplier-table.html b/src/app/components/supplier-table/supplier-table.html index a1987e3..576e468 100644 --- a/src/app/components/supplier-table/supplier-table.html +++ b/src/app/components/supplier-table/supplier-table.html @@ -46,10 +46,12 @@ - - + @if (admin()) { + + + } @@ -62,9 +64,11 @@
    - - + @if (admin()) { + + + }
    diff --git a/src/app/components/supplier-table/supplier-table.ts b/src/app/components/supplier-table/supplier-table.ts index 0cb4e3c..3d0d181 100644 --- a/src/app/components/supplier-table/supplier-table.ts +++ b/src/app/components/supplier-table/supplier-table.ts @@ -9,6 +9,7 @@ import {GetPriceDto, GetSupplierDto, PricesService, SuppliersService} from "../. import {NzNotificationService} from "ng-zorro-antd/notification"; import {firstValueFrom} from "rxjs"; import {PriceForm} from "../price-form/price-form"; +import {AuthService} from "../../services/auth.service"; @Component({ selector: 'app-supplier-table', @@ -29,9 +30,11 @@ export class SupplierTable implements OnInit { private suppliersService = inject(SuppliersService); private pricesService = inject(PricesService); private notificationService = inject(NzNotificationService); + private authService = inject(AuthService); suppliers = signal([]); suppliersLoading = signal(false); + admin = signal(false); supplierModal = viewChild.required('supplierModal'); productModal = viewChild.required('productModal'); @@ -42,6 +45,7 @@ export class SupplierTable implements OnInit { async ngOnInit() { await this.fetchSuppliers(); + this.admin.set(this.authService.isAdmin()); } async fetchSuppliers() { diff --git a/src/app/guards/auth.guard.ts b/src/app/guards/auth.guard.ts index e909f1d..ab6317f 100644 --- a/src/app/guards/auth.guard.ts +++ b/src/app/guards/auth.guard.ts @@ -2,9 +2,13 @@ import { inject } from '@angular/core'; import { Router } from '@angular/router'; import { AuthService} from "../services/auth.service"; -export const authGuard = () => { +export const authGuard = async () => { const auth = inject(AuthService); const router = inject(Router); - return auth.isLoggedIn() ? true : router.parseUrl('/login'); + if(!auth.userAuthenticated()) { + await router.navigateByUrl('/login'); + return false; + } + return true }; \ No newline at end of file diff --git a/src/app/guards/role.guard.ts b/src/app/guards/role.guard.ts deleted file mode 100644 index 27d5488..0000000 --- a/src/app/guards/role.guard.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { inject } from '@angular/core'; -import { ActivatedRouteSnapshot, Router } from '@angular/router'; -import { AuthService} from "../services/auth.service"; - -export const roleGuard = (route: ActivatedRouteSnapshot) => { - const auth = inject(AuthService); - const router = inject(Router); - - const requiredRoles: string[] = route.data['roles']; - - return auth.hasRole(requiredRoles) ? true : router.parseUrl('/dashboard'); -}; \ No newline at end of file diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts index bffd322..fec7fab 100644 --- a/src/app/services/auth.service.ts +++ b/src/app/services/auth.service.ts @@ -2,6 +2,7 @@ import {inject, Injectable} from '@angular/core'; import {firstValueFrom} from 'rxjs'; import {NzNotificationService} from 'ng-zorro-antd/notification'; import {UsersService} from "./api"; +import { jwtDecode } from "jwt-decode" ; @Injectable({ providedIn: 'root', @@ -10,12 +11,15 @@ export class AuthService { private usersService = inject(UsersService); private notificationService = inject(NzNotificationService); + private isAuthenticated: boolean = false; + async connectUser(name: string, password: string) { try { const loginDto = {name, password}; const res = await firstValueFrom(this.usersService.connectUserEndpoint(loginDto)); localStorage.setItem('jwt', res.token); - return true; + this.isAuthenticated = true; + return this.isAuthenticated; } catch { this.notificationService.error('Erreur', 'Identifiant invalide'); return false; @@ -31,39 +35,20 @@ export class AuthService { } logout() { + this.isAuthenticated = false; localStorage.removeItem('jwt'); } - decodeToken(): { sub?: string; role?: string; exp?: number } | null { - const token = this.getToken(); - if (!token) return null; - - try { - const payload = token.split('.')[1]; - return JSON.parse(atob(payload)); - } catch { - return null; - } + userAuthenticated() { + return this.isAuthenticated } - isLoggedIn(): boolean { - const token = this.getToken(); - if (!token) return false; - - const decoded = this.decodeToken(); - if (!decoded?.exp) return true; - - return decoded.exp * 1000 > Date.now(); + getRole() { + const jwtDecoded = jwtDecode(this.getToken()); + return jwtDecoded['role']; } - getRole(): string | null { - return this.decodeToken()?.role ?? null; + isAdmin(){ + return this.getRole() === 'Admin'; } - - hasRole(requiredRoles: string[]): boolean { - const role = this.getRole(); - if (!role) return false; - return requiredRoles.includes(role); - } - }