From d0e98482b9477965647a09d6bcfaa5eb14eb388c Mon Sep 17 00:00:00 2001 From: Cristiano Date: Fri, 29 May 2026 14:07:42 +0200 Subject: [PATCH] Added guards for auth and role --- src/app/app.routes.ts | 27 +++++++++++++++++++-------- src/app/guards/auth.guard.ts | 10 ++++++++++ src/app/guards/role.guard.ts | 12 ++++++++++++ src/app/services/auth.service.ts | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 src/app/guards/auth.guard.ts create mode 100644 src/app/guards/role.guard.ts diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 3d480f3..5f4e052 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,4 +1,6 @@ import {Routes} from '@angular/router'; +import {authGuard} from "./guards/auth.guard"; +import {roleGuard} from "./guards/role.guard"; export const routes: Routes = [ { @@ -22,35 +24,44 @@ export const routes: Routes = [ }, { path: 'dashboard', - loadComponent: () => import('./pages/dashboard/dashboard').then(m => m.Dashboard) + loadComponent: () => import('./pages/dashboard/dashboard').then(m => m.Dashboard), + canActivate: [authGuard] }, { path: 'stock', - loadComponent: () => import('./pages/stock/stock').then(m => m.Stock) + loadComponent: () => import('./pages/stock/stock').then(m => m.Stock), + canActivate: [authGuard] }, { path: 'supplier', - loadComponent: () => import('./pages/supplier/supplier').then(m => m.Supplier) + loadComponent: () => import('./pages/supplier/supplier').then(m => m.Supplier), + canActivate: [authGuard] }, { path: 'deliverer', - loadComponent: () => import('./pages/deliverer/deliverer').then(m => m.Deliverer) + loadComponent: () => import('./pages/deliverer/deliverer').then(m => m.Deliverer), + canActivate: [authGuard] }, { path: 'quotation', - loadComponent: () => import('./pages/quotation/quotation').then(m => m.Quotation) + loadComponent: () => import('./pages/quotation/quotation').then(m => m.Quotation), + canActivate: [authGuard] }, { path: 'purchase-order', - loadComponent: () => import('./pages/purchase-order/purchase-order').then(m => m.PurchaseOrder) + loadComponent: () => import('./pages/purchase-order/purchase-order').then(m => m.PurchaseOrder), + canActivate: [authGuard] }, { path: 'delivery-note', - loadComponent: () => import('./pages/delivery-note/delivery-note').then(m => m.DeliveryNote) + loadComponent: () => import('./pages/delivery-note/delivery-note').then(m => m.DeliveryNote), + canActivate: [authGuard] }, { path: 'user', - loadComponent: () => import('./pages/user/user').then(m => m.User) + loadComponent: () => import('./pages/user/user').then(m => m.User), + canActivate: [authGuard, roleGuard], + data: {roles: ['Admin']}, }, { path: '**', diff --git a/src/app/guards/auth.guard.ts b/src/app/guards/auth.guard.ts new file mode 100644 index 0000000..e909f1d --- /dev/null +++ b/src/app/guards/auth.guard.ts @@ -0,0 +1,10 @@ +import { inject } from '@angular/core'; +import { Router } from '@angular/router'; +import { AuthService} from "../services/auth.service"; + +export const authGuard = () => { + const auth = inject(AuthService); + const router = inject(Router); + + return auth.isLoggedIn() ? true : router.parseUrl('/login'); +}; \ No newline at end of file diff --git a/src/app/guards/role.guard.ts b/src/app/guards/role.guard.ts new file mode 100644 index 0000000..27d5488 --- /dev/null +++ b/src/app/guards/role.guard.ts @@ -0,0 +1,12 @@ +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 323aea2..bffd322 100644 --- a/src/app/services/auth.service.ts +++ b/src/app/services/auth.service.ts @@ -34,4 +34,36 @@ export class AuthService { 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; + } + } + + 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(): string | null { + return this.decodeToken()?.role ?? null; + } + + hasRole(requiredRoles: string[]): boolean { + const role = this.getRole(); + if (!role) return false; + return requiredRoles.includes(role); + } + }