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
Markdown
# 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.
[](https://www.npmjs.com/package/ng-secure-access)
[](https://opensource.org/licenses/MIT)
[](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.
```