445 lines
12 KiB
TypeScript
445 lines
12 KiB
TypeScript
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, RoleConfig> = {
|
|
[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<AvailableRolesWithPermissions | null>(null);
|
|
private currentUserRole$ = new BehaviorSubject<UserRole | null>(null);
|
|
|
|
/**
|
|
* Charge les rôles Hub disponibles
|
|
*/
|
|
loadAvailableHubRoles(): Observable<AvailableRolesWithPermissions> {
|
|
return this.loadRoles(
|
|
() => this.hubUsersService.getAvailableHubRoles(),
|
|
'hub'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Charge les rôles Marchands disponibles
|
|
*/
|
|
loadAvailableMerchantRoles(): Observable<AvailableRolesWithPermissions> {
|
|
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<AvailableRolesWithPermissions> {
|
|
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<UserRole | null> {
|
|
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<AvailableRolesWithPermissions | null> {
|
|
return this.availableRoles$.asObservable();
|
|
}
|
|
} |