import { Injectable, inject } from '@angular/core'; import { HubUsersService } from '@modules/hub-users-management/hub-users.service'; import { MerchantUsersService } from '@modules/hub-users-management/merchant-users.service'; import { BehaviorSubject, Observable, map, tap, of, catchError } from 'rxjs'; import { UserRole, UserType, AvailableRole } from '@core/models/dcb-bo-hub-user.model'; // Interfaces export interface RolePermission { canCreateUsers: boolean; canEditUsers: boolean; canDeleteUsers: boolean; canManageRoles: boolean; canViewStats: boolean; canManageMerchants: boolean; canAccessAdmin: boolean; canAccessSupport: boolean; canAccessPartner: boolean; assignableRoles: UserRole[]; } export interface AvailableRolesWithPermissions { roles: (AvailableRole & { permissions: RolePermission })[]; } interface RoleConfig { label: string; description: string; badgeClass: string; icon: string; permissions: RolePermission; } // Permissions par défaut const DEFAULT_PERMISSIONS: RolePermission = { canCreateUsers: false, canEditUsers: false, canDeleteUsers: false, canManageRoles: false, canViewStats: false, canManageMerchants: false, canAccessAdmin: false, canAccessSupport: false, canAccessPartner: false, assignableRoles: [] }; // Configuration des rôles const ROLE_CONFIG: Record = { [UserRole.DCB_ADMIN]: { label: 'Administrateur DCB', description: 'Administrateur système avec tous les accès', badgeClass: 'bg-danger', icon: 'lucideShield', permissions: { canCreateUsers: true, canEditUsers: true, canDeleteUsers: true, canManageRoles: true, canViewStats: true, canManageMerchants: true, canAccessAdmin: true, canAccessSupport: true, canAccessPartner: true, assignableRoles: Object.values(UserRole) } }, [UserRole.DCB_SUPPORT]: { label: 'Support DCB', description: 'Support technique avec accès étendus', badgeClass: 'bg-info', icon: 'lucideHeadphones', permissions: { canCreateUsers: true, canEditUsers: true, canDeleteUsers: false, canManageRoles: true, canViewStats: true, canManageMerchants: true, canAccessAdmin: false, canAccessSupport: true, canAccessPartner: true, assignableRoles: [ UserRole.DCB_SUPPORT, UserRole.DCB_PARTNER_ADMIN, UserRole.DCB_PARTNER_MANAGER, UserRole.DCB_PARTNER_SUPPORT ] } }, [UserRole.DCB_PARTNER_ADMIN]: { label: 'Admin Partenaire', description: 'Administrateur de partenaire marchand', badgeClass: 'bg-warning', icon: 'lucideShieldCheck', permissions: { canCreateUsers: true, canEditUsers: true, canDeleteUsers: true, canManageRoles: true, canViewStats: true, canManageMerchants: false, canAccessAdmin: false, canAccessSupport: false, canAccessPartner: false, assignableRoles: [UserRole.DCB_PARTNER_MANAGER, UserRole.DCB_PARTNER_SUPPORT] } }, [UserRole.DCB_PARTNER_MANAGER]: { label: 'Manager Partenaire', description: 'Manager opérationnel partenaire', badgeClass: 'bg-success', icon: 'lucideUserCog', permissions: { canCreateUsers: false, canEditUsers: false, canDeleteUsers: false, canManageRoles: false, canViewStats: true, canManageMerchants: true, canAccessAdmin: false, canAccessSupport: false, canAccessPartner: true, assignableRoles: [] } }, [UserRole.DCB_PARTNER_SUPPORT]: { label: 'Support Partenaire', description: 'Support technique partenaire', badgeClass: 'bg-secondary', icon: 'lucideHeadphones', permissions: { canCreateUsers: false, canEditUsers: false, canDeleteUsers: false, canManageRoles: false, canViewStats: true, canManageMerchants: false, canAccessAdmin: false, canAccessSupport: false, canAccessPartner: true, assignableRoles: [] } }, [UserRole.MERCHANT_CONFIG_ADMIN]: { label: 'Admin Marchand', description: 'Administrateur de configuration marchand', badgeClass: 'bg-warning', icon: 'lucideSettings', permissions: DEFAULT_PERMISSIONS }, [UserRole.MERCHANT_CONFIG_MANAGER]: { label: 'Manager Marchand', description: 'Manager de configuration marchand', badgeClass: 'bg-success', icon: 'lucideUserCog', permissions: DEFAULT_PERMISSIONS }, [UserRole.MERCHANT_CONFIG_TECHNICAL]: { label: 'Technique Marchand', description: 'Support technique configuration marchand', badgeClass: 'bg-secondary', icon: 'lucideWrench', permissions: DEFAULT_PERMISSIONS }, [UserRole.MERCHANT_CONFIG_VIEWER]: { label: 'Visualiseur Marchand', description: 'Visualiseur de configuration marchand', badgeClass: 'bg-light', icon: 'lucideEye', permissions: DEFAULT_PERMISSIONS } } as const; // Rôles Hub (pour les filtres) const HUB_ROLES = [ UserRole.DCB_ADMIN, UserRole.DCB_SUPPORT, ] as const; // Rôles Marchands (pour les filtres) const MERCHANT_ROLES = [ UserRole.DCB_PARTNER_ADMIN, UserRole.DCB_PARTNER_MANAGER, UserRole.DCB_PARTNER_SUPPORT, UserRole.MERCHANT_CONFIG_ADMIN, UserRole.MERCHANT_CONFIG_MANAGER, UserRole.MERCHANT_CONFIG_TECHNICAL, UserRole.MERCHANT_CONFIG_VIEWER ] as const; @Injectable({ providedIn: 'root' }) export class RoleManagementService { private hubUsersService = inject(HubUsersService); private merchantUsersService = inject(MerchantUsersService); private availableRoles$ = new BehaviorSubject(null); private currentUserRole$ = new BehaviorSubject(null); /** * Charge les rôles Hub disponibles */ loadAvailableHubRoles(): Observable { return this.loadRoles( () => this.hubUsersService.getAvailableHubRoles(), 'hub' ); } /** * Charge les rôles Marchands disponibles */ loadAvailableMerchantRoles(): Observable { return this.loadRoles( () => this.merchantUsersService.getAvailableMerchantRoles(), 'merchant' ); } /** * Méthode générique pour charger les rôles */ private loadRoles( fetchFn: () => Observable<{ roles: AvailableRole[] }>, type: 'hub' | 'merchant' ): Observable { return fetchFn().pipe( map(apiResponse => ({ roles: apiResponse.roles.map(role => ({ ...role, permissions: this.getPermissionsForRole(role.value) })) })), tap(roles => this.availableRoles$.next(roles)), catchError(error => { console.error(`Error loading ${type} roles:`, error); return of({ roles: [] } as AvailableRolesWithPermissions); }) ); } /** * Définit le rôle de l'utilisateur courant */ setCurrentUserRole(role: UserRole): void { this.currentUserRole$.next(role); } /** * Récupère le rôle de l'utilisateur courant */ getCurrentUserRole(): Observable { return this.currentUserRole$.asObservable(); } /** * Récupère la valeur actuelle du rôle utilisateur (synchrone) */ getCurrentUserRoleValue(): UserRole | null { return this.currentUserRole$.value; } /** * Récupère les permissions détaillées selon le rôle */ getPermissionsForRole(role: UserRole | null): RolePermission { if (!role) { return DEFAULT_PERMISSIONS; } return ROLE_CONFIG[role]?.permissions || DEFAULT_PERMISSIONS; } /** * Vérifie si un rôle peut être attribué par l'utilisateur courant */ canAssignRole(currentUserRole: UserRole | null, targetRole: UserRole): boolean { if (!currentUserRole) return false; const fullPermissionRoles = [ UserRole.DCB_ADMIN, UserRole.DCB_SUPPORT ]; if (fullPermissionRoles.includes(currentUserRole)) { return true; } const permissions = this.getPermissionsForRole(currentUserRole); return permissions.assignableRoles.includes(targetRole); } // Méthodes d'utilité pour les permissions canCreateUsers(currentUserRole: UserRole | null): boolean { return this.getPermission(currentUserRole, 'canCreateUsers'); } canEditUsers(currentUserRole: UserRole | null): boolean { return this.getPermission(currentUserRole, 'canEditUsers'); } canDeleteUsers(currentUserRole: UserRole | null): boolean { return this.getPermission(currentUserRole, 'canDeleteUsers'); } canManageRoles(currentUserRole: UserRole | null): boolean { return this.getPermission(currentUserRole, 'canManageRoles'); } canViewStats(currentUserRole: UserRole | null): boolean { return this.getPermission(currentUserRole, 'canViewStats'); } canManageMerchants(currentUserRole: UserRole | null): boolean { return this.getPermission(currentUserRole, 'canManageMerchants'); } canAccessAdmin(currentUserRole: UserRole | null): boolean { return this.getPermission(currentUserRole, 'canAccessAdmin'); } canAccessSupport(currentUserRole: UserRole | null): boolean { return this.getPermission(currentUserRole, 'canAccessSupport'); } canAccessPartner(currentUserRole: UserRole | null): boolean { return this.getPermission(currentUserRole, 'canAccessPartner'); } /** * Méthode helper générique pour les permissions */ private getPermission( role: UserRole | null, permissionKey: keyof RolePermission ): boolean { if (!role) return false; const permissions = this.getPermissionsForRole(role); return Boolean(permissions[permissionKey]); } /** * Méthodes d'utilité pour les rôles */ getRoleLabel(role: string): string { const userRole = role as UserRole; return ROLE_CONFIG[userRole]?.label || role; } getRoleDescription(role: string | UserRole): string { const userRole = role as UserRole; return ROLE_CONFIG[userRole]?.description || 'Description non disponible'; } getRoleBadgeClass(role: string): string { const userRole = role as UserRole; return ROLE_CONFIG[userRole]?.badgeClass || 'bg-secondary'; } getRoleIcon(role: string): string { const userRole = role as UserRole; return ROLE_CONFIG[userRole]?.icon || 'lucideUser'; } /** * Vérifications de type de rôle */ isAdminRole(role: UserRole): boolean { return role === UserRole.DCB_ADMIN; } isSupportRole(role: UserRole): boolean { return role === UserRole.DCB_SUPPORT; } isMerchantUserRole(role: UserRole): boolean { return role === UserRole.DCB_PARTNER_ADMIN || role === UserRole.DCB_PARTNER_MANAGER || role === UserRole.DCB_PARTNER_SUPPORT || role === UserRole.MERCHANT_CONFIG_ADMIN || role === UserRole.MERCHANT_CONFIG_MANAGER || role === UserRole.MERCHANT_CONFIG_TECHNICAL || role === UserRole.MERCHANT_CONFIG_VIEWER; } /** * Gestion des listes de rôles */ getAllRoles(): UserRole[] { return Object.values(UserRole); } getHubRoles(): UserRole[] { return [...HUB_ROLES]; } getMerchantRoles(): UserRole[] { return [...MERCHANT_ROLES]; } getAssignableRoles(currentUserRole: UserRole | null): UserRole[] { if (!currentUserRole) return []; return this.getPermissionsForRole(currentUserRole).assignableRoles; } getAssignableHubRoles(currentUserRole: UserRole | null): UserRole[] { return this.filterAssignableRoles(currentUserRole, HUB_ROLES); } getAssignableMerchantRoles(currentUserRole: UserRole | null): UserRole[] { return this.filterAssignableRoles(currentUserRole, MERCHANT_ROLES); } private filterAssignableRoles( currentUserRole: UserRole | null, roleList: readonly UserRole[] ): UserRole[] { if (!currentUserRole) return []; const permissions = this.getPermissionsForRole(currentUserRole); return roleList.filter(role => permissions.assignableRoles.includes(role)); } /** * Vérifications de rôles */ hasRole(userRole: UserRole | null, targetRole: UserRole): boolean { return userRole === targetRole; } hasAnyRole(userRole: UserRole | null, targetRoles: UserRole[]): boolean { return userRole ? targetRoles.includes(userRole) : false; } /** * Gestion du cache */ clearCache(): void { this.availableRoles$.next(null); this.currentUserRole$.next(null); } getAvailableRoles(): Observable { return this.availableRoles$.asObservable(); } }