UNPKG

ng-secure-access

Version:

Librairie Angular pour la gestion des permissions d'accès aux routes et l'affichage conditionnel basé sur les permissions utilisateur

363 lines (282 loc) 11.6 kB
# ng-secure-access `ng-secure-access` est une librairie Angular qui permet de gérer les permissions d'accès aux routes et l'affichage des éléments en fonction des permissions d'un utilisateur. Elle permet de charger dynamiquement les permissions après l'authentification et de contrôler l'accès aux différentes parties de votre application. [![npm version](https://badge.fury.io/js/ng-secure-access.svg)](https://www.npmjs.com/package/ng-secure-access) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Angular](https://img.shields.io/badge/Angular-17%2B-red.svg)](https://angular.io/) ## 📋 Fonctionnalités - **Gestion des permissions dynamiques** : Charge un tableau de permissions pour un utilisateur après l'authentification - **Protection des routes** : Utilise un `Guard` pour vérifier les permissions avant d'accéder à une route - **Affichage conditionnel des éléments** : Affiche ou masque des éléments en fonction des permissions - **Redirection dynamique** : Redirige l'utilisateur vers des pages spécifiques s'il n'a pas les permissions requises - **Signals Angular** : Utilise les signals pour une réactivité optimale - **Standalone** : Compatible avec l'approche moderne d'Angular - **TypeScript** : Entièrement typé ## 🚀 Installation ```bash npm install ng-secure-access ``` ## 📖 Utilisation ### 1. Charger les permissions Les permissions doivent être chargées après l'authentification de l'utilisateur, par exemple dans un `LayoutComponent` : ```typescript import { Component, OnInit } from '@angular/core'; import { PermissionService } from 'ng-secure-access'; @Component({ selector: 'app-layout', templateUrl: './layout.component.html', }) export class LayoutComponent implements OnInit { constructor(private permissionService: PermissionService) {} ngOnInit() { // Charger les permissions après l'authentification de l'utilisateur this.permissionService.loadPermissions(['update', 'delete', 'create']); } } ``` #### Exemple avec une API ```typescript import { Component, OnInit } from '@angular/core'; import { PermissionService } from 'ng-secure-access'; import { AuthService } from './services/auth.service'; @Component({ selector: 'app-layout', templateUrl: './layout.component.html', }) export class LayoutComponent implements OnInit { constructor( private permissionService: PermissionService, private authService: AuthService ) {} ngOnInit() { // Charger les permissions depuis l'API this.authService.getUserPermissions().subscribe(permissions => { this.permissionService.loadPermissions(permissions); }); } } ``` ### 2. Protéger une route avec des permissions Pour protéger une route, ajoutez le `PermissionGuard` à votre route et spécifiez les permissions requises dans `data`. ```typescript import { Routes } from '@angular/router'; import { PermissionGuard } from 'ng-secure-access'; const routes: Routes = [ { path: 'create', canActivate: [PermissionGuard], data: { permissions: ['create'], // L'utilisateur doit avoir AU MOINS une de ces permissions redirectTo: '/access-denied' // Redirection en cas de permissions insuffisantes }, loadComponent: () => import('./pages/create-page/create-page.component').then(m => m.CreatePageComponent), }, { path: 'dashboard', canActivate: [PermissionGuard], data: { permissions: ['viewDashboard', 'admin'], // Au moins une de ces permissions redirectTo: '/no-access' }, loadComponent: () => import('./pages/dashboard/dashboard.component').then(m => m.DashboardComponent), } ]; ``` ### 3. Afficher des éléments conditionnellement Utilisez la directive `*hasPermission` pour afficher ou masquer des éléments en fonction des permissions d'un utilisateur. ```typescript import { Component } from '@angular/core'; import { HasPermissionDirective } from 'ng-secure-access'; @Component({ selector: 'app-menu', standalone: true, imports: [HasPermissionDirective], template: ` <!-- Afficher si l'utilisateur a AU MOINS une des permissions --> <button *hasPermission="['update', 'delete']"> Actions </button> <div *hasPermission="['admin']"> Panneau d'administration </div> <a routerLink="/dashboard" *hasPermission="['viewDashboard']"> Dashboard </a> ` }) export class MenuComponent {} ``` ### 4. Gérer les permissions dynamiquement ```typescript import { Component } from '@angular/core'; import { PermissionService } from 'ng-secure-access'; @Component({ selector: 'app-user-profile', templateUrl: './user-profile.component.html', }) export class UserProfileComponent { constructor(private permissionService: PermissionService) {} // Vérifier une permission spécifique canEdit(): boolean { return this.permissionService.hasSpecificPermission('edit'); } // Obtenir toutes les permissions getUserPermissions(): string[] { return this.permissionService.getPermissions(); } // Ajouter une permission temporaire grantTemporaryAccess(): void { this.permissionService.addPermission('temporary-access'); } // Se déconnecter et effacer les permissions logout(): void { this.permissionService.clearPermissions(); // Rediriger vers la page de connexion... } } ``` ## 📦 API ### PermissionService | Méthode | Description | |---------|-------------| | `loadPermissions(permissions: string[]): void` | Charge les permissions pour l'utilisateur actuel | | `hasPermission(permissions: string[]): boolean` | Vérifie si l'utilisateur possède **au moins une** des permissions spécifiées (logique OU) | | `hasSpecificPermission(permission: string): boolean` | Vérifie si l'utilisateur possède une permission spécifique | | `getPermissions(): string[]` | Retourne toutes les permissions de l'utilisateur | | `arePermissionsLoaded(): boolean` | Retourne `true` si les permissions sont chargées | | `clearPermissions(): void` | Efface toutes les permissions (utile lors de la déconnexion) | | `addPermission(permission: string): void` | Ajoute une permission dynamiquement | | `removePermission(permission: string): void` | Retire une permission | ### HasPermissionDirective **Sélecteur** : `*hasPermission` **Input** : `string[]` - Liste des permissions (logique OU : au moins une permission requise) ```html <button *hasPermission="['update', 'delete', 'admin']"> Actions disponibles </button> ``` ### PermissionGuard **Utilisation** : `canActivate: [PermissionGuard]` **Configuration de la route** : ```typescript { path: 'protected', canActivate: [PermissionGuard], data: { permissions: string[], // Permissions requises (au moins une) redirectTo: string // URL de redirection (optionnel, défaut: '/access-denied') } } ``` ## 📝 Exemples complets ### Menu de navigation avec permissions ```typescript import { Component } from '@angular/core'; import { RouterLink } from '@angular/router'; import { HasPermissionDirective } from 'ng-secure-access'; @Component({ selector: 'app-navbar', standalone: true, imports: [RouterLink, HasPermissionDirective], template: ` <nav> <a routerLink="/home">Accueil</a> <a routerLink="/dashboard" *hasPermission="['viewDashboard']"> Dashboard </a> <a routerLink="/users" *hasPermission="['manageUsers', 'admin']"> Utilisateurs </a> <a routerLink="/settings" *hasPermission="['admin']"> Paramètres </a> <a routerLink="/reports" *hasPermission="['viewReports']"> Rapports </a> </nav> ` }) export class NavbarComponent {} ``` ### Boutons d'action conditionnels ```html <div class="card"> <h3>Article</h3> <p>Contenu de l'article...</p> <div class="actions"> <button *hasPermission="['read']" (click)="view()"> Voir </button> <button *hasPermission="['update', 'admin']" (click)="edit()"> Modifier </button> <button *hasPermission="['delete', 'admin']" (click)="delete()"> Supprimer </button> </div> </div> ``` ### Configuration complète des routes ```typescript import { Routes } from '@angular/router'; import { PermissionGuard } from 'ng-secure-access'; export const routes: Routes = [ { path: '', redirectTo: '/home', pathMatch: 'full' }, { path: 'home', loadComponent: () => import('./pages/home/home.component').then(m => m.HomeComponent) }, { path: 'dashboard', canActivate: [PermissionGuard], data: { permissions: ['viewDashboard'], redirectTo: '/access-denied' }, loadComponent: () => import('./pages/dashboard/dashboard.component').then(m => m.DashboardComponent) }, { path: 'users', canActivate: [PermissionGuard], data: { permissions: ['manageUsers', 'admin'], redirectTo: '/access-denied' }, loadComponent: () => import('./pages/users/users.component').then(m => m.UsersComponent) }, { path: 'access-denied', loadComponent: () => import('./pages/access-denied/access-denied.component').then(m => m.AccessDeniedComponent) } ]; ``` ## 🔒 Sécurité ⚠️ **Important** : Cette librairie gère uniquement l'affichage et la navigation côté client. **Vous devez toujours valider les permissions côté serveur !** Les permissions frontend servent à : - Améliorer l'expérience utilisateur en cachant les options inaccessibles - Éviter les requêtes inutiles vers le backend - Guider l'utilisateur dans l'interface Elles **ne remplacent PAS** la sécurité backend. Toutes les actions sensibles doivent être validées par votre API. ## 📋 Prérequis - Angular 17+ (pour la syntaxe standalone et les signals) - TypeScript 5.x+ - RxJS 7.x+ ## 🤝 Contribution Les contributions sont les bienvenues ! Si vous souhaitez améliorer cette librairie ou signaler un problème, merci de : 1. Ouvrir une issue pour discuter des changements 2. Soumettre une pull request avec vos améliorations ## 📄 Licence MIT © BIBANG BEFENE Joseph Donovan ## 🔗 Liens utiles - [Documentation Angular](https://angular.dev) - [Guide des Guards](https://angular.dev/guide/routing/common-router-tasks#preventing-unauthorized-access) - [Angular Signals](https://angular.dev/guide/signals) ## ✨ Auteur Créé avec ❤️ par **BIBANG BEFENE Joseph Donovan** --- **Note** : Si vous rencontrez des problèmes ou avez des questions, n'hésitez pas à ouvrir une issue sur GitHub. ```