"""Gestion des permissions et accès par rôle.""" """Gestion des permissions et accès par rôle.""" from functools import wraps from flask import abort, current_app from flask_login import current_user import os class Permission: """Définition des permissions de l'application.""" # Permissions de base VIEW_DASHBOARD = 'dashboard:view' CREATE_INTERVENTION = 'intervention:create' VIEW_INTERVENTIONS = 'intervention:view' EDIT_INTERVENTIONS = 'intervention:edit' DELETE_INTERVENTIONS = 'intervention:delete' # Permissions équipements VIEW_EQUIPMENTS = 'equipment:view' CREATE_EQUIPMENTS = 'equipment:create' EDIT_EQUIPMENTS = 'equipment:edit' DELETE_EQUIPMENTS = 'equipment:delete' # Permissions planning VIEW_PLANNING = 'planning:view' CREATE_PLANNING = 'planning:create' EDIT_PLANNING = 'planning:edit' # Permissions ENT VIEW_ENT = 'ent:view' CONFIG_ENT = 'ent:config' MANAGE_ENT_MESSAGES = 'ent:manage' # Permissions administratives VIEW_USERS = 'user:view' CREATE_USERS = 'user:create' EDIT_USERS = 'user:edit' DELETE_USERS = 'user:delete' VIEW_ADMIN = 'admin:view' # Permission de modification du code (admin seulement) EDIT_CODE = 'code:edit' # Permissions entreprises et pièces VIEW_COMPANIES = 'company:view' CREATE_COMPANIES = 'company:create' EDIT_COMPANIES = 'company:edit' DELETE_COMPANIES = 'company:delete' VIEW_PARTS = 'part:view' CREATE_PARTS = 'part:create' EDIT_PARTS = 'part:edit' DELETE_PARTS = 'part:delete' class RolePermission: """Définition des permissions par rôle.""" # Rôle administrateur (accès à tout) ADMIN = { Permission.VIEW_DASHBOARD, Permission.CREATE_INTERVENTION, Permission.VIEW_INTERVENTIONS, Permission.EDIT_INTERVENTIONS, Permission.DELETE_INTERVENTIONS, Permission.VIEW_EQUIPMENTS, Permission.CREATE_EQUIPMENTS, Permission.EDIT_EQUIPMENTS, Permission.DELETE_EQUIPMENTS, Permission.VIEW_PLANNING, Permission.CREATE_PLANNING, Permission.EDIT_PLANNING, Permission.VIEW_ENT, Permission.CONFIG_ENT, Permission.MANAGE_ENT_MESSAGES, Permission.VIEW_USERS, Permission.CREATE_USERS, Permission.EDIT_USERS, Permission.DELETE_USERS, Permission.VIEW_ADMIN, Permission.VIEW_COMPANIES, Permission.CREATE_COMPANIES, Permission.EDIT_COMPANIES, Permission.DELETE_COMPANIES, Permission.VIEW_PARTS, Permission.CREATE_PARTS, Permission.EDIT_PARTS, Permission.DELETE_PARTS, Permission.EDIT_CODE, # Permission de modification du code } # Rôle technicien (peut voir et gérer les interventions, voir les équipements) TECHNICIAN = { Permission.VIEW_DASHBOARD, Permission.CREATE_INTERVENTION, Permission.VIEW_INTERVENTIONS, Permission.EDIT_INTERVENTIONS, Permission.VIEW_EQUIPMENTS, Permission.VIEW_PLANNING, Permission.VIEW_ENT, } # Rôle chef d'établissement (peut voir et gérer les interventions, planning, voir les données) CHEF = { Permission.VIEW_DASHBOARD, Permission.CREATE_INTERVENTION, Permission.VIEW_INTERVENTIONS, Permission.EDIT_INTERVENTIONS, Permission.VIEW_EQUIPMENTS, Permission.VIEW_PLANNING, Permission.CREATE_PLANNING, Permission.VIEW_ENT, } # Rôle demandeur (peut voir le dashboard, créer des interventions, voir les équipements) DEMANDEUR = { Permission.VIEW_DASHBOARD, Permission.CREATE_INTERVENTION, Permission.VIEW_INTERVENTIONS, Permission.VIEW_EQUIPMENTS, Permission.VIEW_PLANNING, } def get_role_permissions(role): """Retourne les permissions pour un rôle donné.""" role_permissions_map = { 'admin': RolePermission.ADMIN, 'technicien': RolePermission.TECHNICIAN, 'chef': RolePermission.CHEF, 'demandeur': RolePermission.DEMANDEUR, } return role_permissions_map.get(role, set()) def permission_required(permission): """Décorateur pour vérifier une permission spécifique.""" def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): if not current_user.is_authenticated: abort(401) if current_user.role == 'admin': return f(*args, **kwargs) user_permissions = get_role_permissions(current_user.role) if permission not in user_permissions: current_app.logger.warning( f"User {current_user.username} (role: {current_user.role}) " f"tried to access {permission} which is not allowed" ) abort(403) return f(*args, **kwargs) return decorated_function return decorator def any_permission_required(*permissions): """Décorateur pour vérifier qu'au moins une permission parmi les listées est présente.""" def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): if not current_user.is_authenticated: abort(401) if current_user.role == 'admin': return f(*args, **kwargs) user_permissions = get_role_permissions(current_user.role) # Vérifier si l'utilisateur a au moins une des permissions requises has_permission = any(perm in user_permissions for perm in permissions) if not has_permission: current_app.logger.warning( f"User {current_user.username} (role: {current_user.role}) " f"tried to access {permissions} but none are allowed" ) abort(403) return f(*args, **kwargs) return decorated_function return decorator def role_required(role): """Décorateur pour vérifier le rôle exact.""" def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): if not current_user.is_authenticated: abort(401) if current_user.role != role: current_app.logger.warning( f"User {current_user.username} (role: {current_user.role}) " f"tried to access endpoint requiring {role} role" ) abort(403) return f(*args, **kwargs) return decorated_function return decorator def has_permission(permission): """Macro template pour vérifier une permission dans les templates.""" if not current_user.is_authenticated: return False if current_user.role == 'admin': return True user_permissions = get_role_permissions(current_user.role) return permission in user_permissions def get_user_permissions(user=None): """Retourne les permissions d'un utilisateur (ou de l'utilisateur courant).""" if user is None: if not current_user.is_authenticated: return set() user = current_user if user.role == 'admin': return RolePermission.ADMIN return get_role_permissions(user.role)