637 lines
22 KiB
Python
637 lines
22 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Erweiterte Berechtigungsverwaltung für MYP Platform
|
|
Granulare Rollen und Permissions für feingranulare Zugriffskontrolle
|
|
"""
|
|
|
|
from enum import Enum
|
|
from functools import wraps
|
|
from typing import List, Dict, Set, Optional
|
|
from flask import request, jsonify, abort
|
|
from flask_login import login_required, current_user
|
|
from sqlalchemy import Column, Integer, String, Boolean, ForeignKey, Table, DateTime, MetaData
|
|
from sqlalchemy.orm import relationship
|
|
from datetime import datetime, timedelta
|
|
from utils.logging_config import get_logger
|
|
|
|
logger = get_logger("permissions")
|
|
|
|
# ===== PERMISSION DEFINITIONS =====
|
|
|
|
class Permission(Enum):
|
|
"""Alle verfügbaren Berechtigungen im System"""
|
|
|
|
# Basis-Berechtigungen
|
|
LOGIN = "login"
|
|
VIEW_DASHBOARD = "view_dashboard"
|
|
|
|
# Drucker-Berechtigungen
|
|
VIEW_PRINTERS = "view_printers"
|
|
CREATE_PRINTER = "create_printer"
|
|
EDIT_PRINTER = "edit_printer"
|
|
DELETE_PRINTER = "delete_printer"
|
|
CONTROL_PRINTER = "control_printer" # Ein-/Ausschalten
|
|
VIEW_PRINTER_DETAILS = "view_printer_details"
|
|
|
|
# Job-Berechtigungen
|
|
VIEW_JOBS = "view_jobs"
|
|
CREATE_JOB = "create_job"
|
|
EDIT_OWN_JOB = "edit_own_job"
|
|
EDIT_ALL_JOBS = "edit_all_jobs"
|
|
DELETE_OWN_JOB = "delete_own_job"
|
|
DELETE_ALL_JOBS = "delete_all_jobs"
|
|
EXTEND_JOB = "extend_job"
|
|
CANCEL_JOB = "cancel_job"
|
|
VIEW_JOB_HISTORY = "view_job_history"
|
|
APPROVE_JOBS = "approve_jobs" # Berechtigung zum Genehmigen und Verwalten von Jobs
|
|
|
|
# Benutzer-Berechtigungen
|
|
VIEW_USERS = "view_users"
|
|
CREATE_USER = "create_user"
|
|
EDIT_USER = "edit_user"
|
|
DELETE_USER = "delete_user"
|
|
MANAGE_ROLES = "manage_roles"
|
|
VIEW_USER_DETAILS = "view_user_details"
|
|
|
|
# Admin-Berechtigungen
|
|
VIEW_ADMIN_PANEL = "view_admin_panel"
|
|
MANAGE_SYSTEM = "manage_system"
|
|
VIEW_LOGS = "view_logs"
|
|
EXPORT_DATA = "export_data"
|
|
BACKUP_DATABASE = "backup_database"
|
|
MANAGE_SETTINGS = "manage_settings"
|
|
ADMIN = "admin" # Allgemeine Admin-Berechtigung für administrative Funktionen
|
|
|
|
# Gast-Berechtigungen
|
|
VIEW_GUEST_REQUESTS = "view_guest_requests"
|
|
CREATE_GUEST_REQUEST = "create_guest_request"
|
|
APPROVE_GUEST_REQUEST = "approve_guest_request"
|
|
DENY_GUEST_REQUEST = "deny_guest_request"
|
|
MANAGE_GUEST_REQUESTS = "manage_guest_requests"
|
|
|
|
# Statistik-Berechtigungen
|
|
VIEW_STATS = "view_stats"
|
|
VIEW_DETAILED_STATS = "view_detailed_stats"
|
|
EXPORT_STATS = "export_stats"
|
|
|
|
# Kalender-Berechtigungen
|
|
VIEW_CALENDAR = "view_calendar"
|
|
EDIT_CALENDAR = "edit_calendar"
|
|
MANAGE_SHIFTS = "manage_shifts"
|
|
|
|
# Wartung-Berechtigungen
|
|
SCHEDULE_MAINTENANCE = "schedule_maintenance"
|
|
VIEW_MAINTENANCE = "view_maintenance"
|
|
PERFORM_MAINTENANCE = "perform_maintenance"
|
|
|
|
class Role(Enum):
|
|
"""Vordefinierte Rollen mit Standard-Berechtigungen"""
|
|
|
|
GUEST = "guest"
|
|
USER = "user"
|
|
POWER_USER = "power_user"
|
|
TECHNICIAN = "technician"
|
|
SUPERVISOR = "supervisor"
|
|
ADMIN = "admin"
|
|
SUPER_ADMIN = "super_admin"
|
|
|
|
# ===== ROLE PERMISSIONS MAPPING =====
|
|
|
|
ROLE_PERMISSIONS = {
|
|
Role.GUEST: {
|
|
Permission.LOGIN,
|
|
Permission.VIEW_PRINTERS,
|
|
Permission.CREATE_GUEST_REQUEST,
|
|
Permission.VIEW_CALENDAR,
|
|
},
|
|
|
|
Role.USER: {
|
|
Permission.LOGIN,
|
|
Permission.VIEW_DASHBOARD,
|
|
Permission.VIEW_PRINTERS,
|
|
Permission.VIEW_JOBS,
|
|
Permission.CREATE_JOB,
|
|
Permission.EDIT_OWN_JOB,
|
|
Permission.DELETE_OWN_JOB,
|
|
Permission.EXTEND_JOB,
|
|
Permission.CANCEL_JOB,
|
|
Permission.VIEW_STATS,
|
|
Permission.VIEW_CALENDAR,
|
|
Permission.CREATE_GUEST_REQUEST,
|
|
},
|
|
}
|
|
|
|
# Power User erweitert User-Permissions
|
|
ROLE_PERMISSIONS[Role.POWER_USER] = ROLE_PERMISSIONS[Role.USER] | {
|
|
Permission.VIEW_PRINTER_DETAILS,
|
|
Permission.VIEW_JOB_HISTORY,
|
|
Permission.VIEW_DETAILED_STATS,
|
|
Permission.EXPORT_STATS,
|
|
Permission.VIEW_GUEST_REQUESTS,
|
|
}
|
|
|
|
# Technician erweitert Power User-Permissions
|
|
ROLE_PERMISSIONS[Role.TECHNICIAN] = ROLE_PERMISSIONS[Role.POWER_USER] | {
|
|
Permission.CONTROL_PRINTER,
|
|
Permission.EDIT_PRINTER,
|
|
Permission.SCHEDULE_MAINTENANCE,
|
|
Permission.VIEW_MAINTENANCE,
|
|
Permission.PERFORM_MAINTENANCE,
|
|
Permission.EDIT_CALENDAR,
|
|
}
|
|
|
|
# Supervisor erweitert Technician-Permissions
|
|
ROLE_PERMISSIONS[Role.SUPERVISOR] = ROLE_PERMISSIONS[Role.TECHNICIAN] | {
|
|
Permission.CREATE_PRINTER,
|
|
Permission.EDIT_ALL_JOBS,
|
|
Permission.DELETE_ALL_JOBS,
|
|
Permission.VIEW_USERS,
|
|
Permission.APPROVE_GUEST_REQUEST,
|
|
Permission.DENY_GUEST_REQUEST,
|
|
Permission.MANAGE_GUEST_REQUESTS,
|
|
Permission.MANAGE_SHIFTS,
|
|
Permission.VIEW_USER_DETAILS,
|
|
Permission.APPROVE_JOBS, # Jobs genehmigen und verwalten
|
|
}
|
|
|
|
# Admin erweitert Supervisor-Permissions
|
|
ROLE_PERMISSIONS[Role.ADMIN] = ROLE_PERMISSIONS[Role.SUPERVISOR] | {
|
|
Permission.DELETE_PRINTER,
|
|
Permission.VIEW_ADMIN_PANEL,
|
|
Permission.CREATE_USER,
|
|
Permission.EDIT_USER,
|
|
Permission.DELETE_USER,
|
|
Permission.EXPORT_DATA,
|
|
Permission.VIEW_LOGS,
|
|
Permission.MANAGE_SETTINGS,
|
|
Permission.ADMIN, # Allgemeine Admin-Berechtigung hinzufügen
|
|
}
|
|
|
|
# Super Admin hat alle Berechtigungen
|
|
ROLE_PERMISSIONS[Role.SUPER_ADMIN] = {perm for perm in Permission}
|
|
|
|
# ===== DATABASE MODELS EXTENSIONS =====
|
|
|
|
# Metadata für die Tabellen erstellen
|
|
metadata = MetaData()
|
|
|
|
# Many-to-Many Tabelle für User-Permissions
|
|
user_permissions = Table('user_permissions', metadata,
|
|
Column('user_id', Integer, ForeignKey('users.id'), primary_key=True),
|
|
Column('permission_id', Integer, ForeignKey('permissions.id'), primary_key=True)
|
|
)
|
|
|
|
# Many-to-Many Tabelle für User-Roles
|
|
user_roles = Table('user_roles', metadata,
|
|
Column('user_id', Integer, ForeignKey('users.id'), primary_key=True),
|
|
Column('role_id', Integer, ForeignKey('roles.id'), primary_key=True)
|
|
)
|
|
|
|
class PermissionModel:
|
|
"""Datenbank-Model für Berechtigungen"""
|
|
|
|
__tablename__ = 'permissions'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(100), unique=True, nullable=False)
|
|
description = Column(String(255))
|
|
category = Column(String(50)) # Gruppierung von Berechtigungen
|
|
created_at = Column(DateTime, default=datetime.now)
|
|
|
|
class RoleModel:
|
|
"""Datenbank-Model für Rollen"""
|
|
|
|
__tablename__ = 'roles'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(50), unique=True, nullable=False)
|
|
display_name = Column(String(100))
|
|
description = Column(String(255))
|
|
is_system_role = Column(Boolean, default=False) # System-Rollen können nicht gelöscht werden
|
|
created_at = Column(DateTime, default=datetime.now)
|
|
|
|
# Relationships
|
|
permissions = relationship("PermissionModel", secondary="role_permissions", back_populates="roles")
|
|
|
|
class UserPermissionOverride:
|
|
"""Temporäre oder spezielle Berechtigungsüberschreibungen"""
|
|
|
|
__tablename__ = 'user_permission_overrides'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
|
|
permission = Column(String(100), nullable=False)
|
|
granted = Column(Boolean, nullable=False) # True = gewährt, False = verweigert
|
|
reason = Column(String(255))
|
|
granted_by = Column(Integer, ForeignKey('users.id'))
|
|
expires_at = Column(DateTime, nullable=True) # NULL = permanent
|
|
created_at = Column(DateTime, default=datetime.now)
|
|
|
|
# ===== PERMISSION CHECKER CLASS =====
|
|
|
|
class PermissionChecker:
|
|
"""Hauptklasse für Berechtigungsprüfungen"""
|
|
|
|
def __init__(self, user=None):
|
|
self.user = user or current_user
|
|
self._permission_cache = {}
|
|
self._cache_timeout = timedelta(minutes=5)
|
|
self._cache_timestamp = None
|
|
|
|
def has_permission(self, permission: Permission) -> bool:
|
|
"""
|
|
Prüft ob der Benutzer eine bestimmte Berechtigung hat
|
|
|
|
Args:
|
|
permission: Die zu prüfende Berechtigung
|
|
|
|
Returns:
|
|
bool: True wenn Berechtigung vorhanden
|
|
"""
|
|
if not self.user or not self.user.is_authenticated:
|
|
return False
|
|
|
|
# Cache prüfen
|
|
if self._is_cache_valid() and permission.value in self._permission_cache:
|
|
return self._permission_cache[permission.value]
|
|
|
|
# Berechtigungen neu berechnen
|
|
has_perm = self._calculate_permission(permission)
|
|
|
|
# Cache aktualisieren
|
|
self._update_cache(permission.value, has_perm)
|
|
|
|
return has_perm
|
|
|
|
def _calculate_permission(self, permission: Permission) -> bool:
|
|
"""Berechnet ob eine Berechtigung vorhanden ist"""
|
|
|
|
# Super Admin hat alle Rechte
|
|
if hasattr(self.user, 'is_super_admin') and self.user.is_super_admin:
|
|
return True
|
|
|
|
# Explizite Überschreibungen prüfen
|
|
override = self._check_permission_override(permission)
|
|
if override is not None:
|
|
return override
|
|
|
|
# Rollen-basierte Berechtigungen prüfen
|
|
user_roles = self._get_user_roles()
|
|
for role in user_roles:
|
|
if permission in ROLE_PERMISSIONS.get(role, set()):
|
|
return True
|
|
|
|
# Direkte Benutzer-Berechtigungen prüfen
|
|
if hasattr(self.user, 'permissions'):
|
|
user_permissions = [Permission(p.name) for p in self.user.permissions if hasattr(Permission, p.name.upper())]
|
|
if permission in user_permissions:
|
|
return True
|
|
|
|
return False
|
|
|
|
def _check_permission_override(self, permission: Permission) -> Optional[bool]:
|
|
"""Prüft ob es eine Berechtigungsüberschreibung gibt"""
|
|
if not hasattr(self.user, 'permission_overrides'):
|
|
return None
|
|
|
|
now = datetime.now()
|
|
for override in self.user.permission_overrides:
|
|
if (override.permission == permission.value and
|
|
(override.expires_at is None or override.expires_at > now)):
|
|
logger.info(f"Permission override angewendet: {permission.value} = {override.granted} für User {self.user.id}")
|
|
return override.granted
|
|
|
|
return None
|
|
|
|
def _get_user_roles(self) -> List[Role]:
|
|
"""Holt die Rollen des Benutzers"""
|
|
roles = []
|
|
|
|
# Legacy Admin-Check
|
|
if hasattr(self.user, 'is_admin') and self.user.is_admin:
|
|
roles.append(Role.ADMIN)
|
|
|
|
# Neue Rollen-System
|
|
if hasattr(self.user, 'roles'):
|
|
for role_model in self.user.roles:
|
|
try:
|
|
role = Role(role_model.name)
|
|
roles.append(role)
|
|
except ValueError:
|
|
logger.warning(f"Unbekannte Rolle: {role_model.name}")
|
|
|
|
# Standard-Rolle wenn keine andere definiert
|
|
if not roles:
|
|
roles.append(Role.USER)
|
|
|
|
return roles
|
|
|
|
def _is_cache_valid(self) -> bool:
|
|
"""Prüft ob der Permission-Cache noch gültig ist"""
|
|
if self._cache_timestamp is None:
|
|
return False
|
|
|
|
return datetime.now() - self._cache_timestamp < self._cache_timeout
|
|
|
|
def _update_cache(self, permission: str, has_permission: bool):
|
|
"""Aktualisiert den Permission-Cache"""
|
|
if self._cache_timestamp is None or not self._is_cache_valid():
|
|
self._permission_cache = {}
|
|
self._cache_timestamp = datetime.now()
|
|
|
|
self._permission_cache[permission] = has_permission
|
|
|
|
def get_all_permissions(self) -> Set[Permission]:
|
|
"""Gibt alle Berechtigungen des Benutzers zurück"""
|
|
permissions = set()
|
|
|
|
for permission in Permission:
|
|
if self.has_permission(permission):
|
|
permissions.add(permission)
|
|
|
|
return permissions
|
|
|
|
def can_access_resource(self, resource_type: str, resource_id: int = None, action: str = "view") -> bool:
|
|
"""
|
|
Prüft Zugriff auf spezifische Ressourcen
|
|
|
|
Args:
|
|
resource_type: Art der Ressource (job, printer, user, etc.)
|
|
resource_id: ID der Ressource (optional)
|
|
action: Aktion (view, edit, delete, etc.)
|
|
|
|
Returns:
|
|
bool: True wenn Zugriff erlaubt
|
|
"""
|
|
# Resource-spezifische Logik
|
|
if resource_type == "job":
|
|
return self._check_job_access(resource_id, action)
|
|
elif resource_type == "printer":
|
|
return self._check_printer_access(resource_id, action)
|
|
elif resource_type == "user":
|
|
return self._check_user_access(resource_id, action)
|
|
|
|
return False
|
|
|
|
def _check_job_access(self, job_id: int, action: str) -> bool:
|
|
"""Prüft Job-spezifische Zugriffsrechte"""
|
|
if action == "view":
|
|
if self.has_permission(Permission.VIEW_JOBS):
|
|
return True
|
|
elif action == "edit":
|
|
if self.has_permission(Permission.EDIT_ALL_JOBS):
|
|
return True
|
|
if self.has_permission(Permission.EDIT_OWN_JOB) and job_id:
|
|
# Prüfen ob eigener Job (vereinfacht)
|
|
return self._is_own_job(job_id)
|
|
elif action == "delete":
|
|
if self.has_permission(Permission.DELETE_ALL_JOBS):
|
|
return True
|
|
if self.has_permission(Permission.DELETE_OWN_JOB) and job_id:
|
|
return self._is_own_job(job_id)
|
|
|
|
return False
|
|
|
|
def _check_printer_access(self, printer_id: int, action: str) -> bool:
|
|
"""Prüft Drucker-spezifische Zugriffsrechte"""
|
|
if action == "view":
|
|
return self.has_permission(Permission.VIEW_PRINTERS)
|
|
elif action == "edit":
|
|
return self.has_permission(Permission.EDIT_PRINTER)
|
|
elif action == "delete":
|
|
return self.has_permission(Permission.DELETE_PRINTER)
|
|
elif action == "control":
|
|
return self.has_permission(Permission.CONTROL_PRINTER)
|
|
|
|
return False
|
|
|
|
def _check_user_access(self, user_id: int, action: str) -> bool:
|
|
"""Prüft Benutzer-spezifische Zugriffsrechte"""
|
|
if action == "view":
|
|
if self.has_permission(Permission.VIEW_USERS):
|
|
return True
|
|
# Eigenes Profil ansehen
|
|
if user_id == self.user.id:
|
|
return True
|
|
elif action == "edit":
|
|
if self.has_permission(Permission.EDIT_USER):
|
|
return True
|
|
# Eigenes Profil bearbeiten (begrenzt)
|
|
if user_id == self.user.id:
|
|
return True
|
|
elif action == "delete":
|
|
if self.has_permission(Permission.DELETE_USER) and user_id != self.user.id:
|
|
return True
|
|
|
|
return False
|
|
|
|
def _is_own_job(self, job_id: int) -> bool:
|
|
"""Hilfsfunktion um zu prüfen ob Job dem Benutzer gehört"""
|
|
# Vereinfachte Implementierung - sollte mit DB-Query implementiert werden
|
|
try:
|
|
from models import Job, get_db_session
|
|
db_session = get_db_session()
|
|
job = db_session.query(Job).filter(Job.id == job_id).first()
|
|
db_session.close()
|
|
|
|
return job and (job.user_id == self.user.id or job.owner_id == self.user.id)
|
|
except Exception as e:
|
|
logger.error(f"Fehler bei Job-Ownership-Check: {e}")
|
|
return False
|
|
|
|
# ===== DECORATORS =====
|
|
|
|
def require_permission(permission: Permission):
|
|
"""
|
|
Decorator der eine bestimmte Berechtigung erfordert
|
|
|
|
Args:
|
|
permission: Die erforderliche Berechtigung
|
|
"""
|
|
def decorator(f):
|
|
@wraps(f)
|
|
@login_required
|
|
def wrapper(*args, **kwargs):
|
|
checker = PermissionChecker()
|
|
|
|
if not checker.has_permission(permission):
|
|
logger.warning(f"Zugriff verweigert: User {current_user.id} hat keine Berechtigung {permission.value}")
|
|
|
|
if request.path.startswith('/api/'):
|
|
return jsonify({
|
|
'error': 'Insufficient permissions',
|
|
'message': f'Berechtigung "{permission.value}" erforderlich',
|
|
'required_permission': permission.value
|
|
}), 403
|
|
else:
|
|
abort(403)
|
|
|
|
return f(*args, **kwargs)
|
|
|
|
return wrapper
|
|
return decorator
|
|
|
|
def require_role(role: Role):
|
|
"""
|
|
Decorator der eine bestimmte Rolle erfordert
|
|
|
|
Args:
|
|
role: Die erforderliche Rolle
|
|
"""
|
|
def decorator(f):
|
|
@wraps(f)
|
|
@login_required
|
|
def wrapper(*args, **kwargs):
|
|
checker = PermissionChecker()
|
|
user_roles = checker._get_user_roles()
|
|
|
|
if role not in user_roles:
|
|
logger.warning(f"Zugriff verweigert: User {current_user.id} hat nicht die Rolle {role.value}")
|
|
|
|
if request.path.startswith('/api/'):
|
|
return jsonify({
|
|
'error': 'Insufficient role',
|
|
'message': f'Rolle "{role.value}" erforderlich',
|
|
'required_role': role.value
|
|
}), 403
|
|
else:
|
|
abort(403)
|
|
|
|
return f(*args, **kwargs)
|
|
|
|
return wrapper
|
|
return decorator
|
|
|
|
def require_resource_access(resource_type: str, action: str = "view"):
|
|
"""
|
|
Decorator für ressourcen-spezifische Berechtigungsprüfung
|
|
|
|
Args:
|
|
resource_type: Art der Ressource
|
|
action: Erforderliche Aktion
|
|
"""
|
|
def decorator(f):
|
|
@wraps(f)
|
|
@login_required
|
|
def wrapper(*args, **kwargs):
|
|
# Resource ID aus URL-Parametern extrahieren
|
|
resource_id = kwargs.get('id') or kwargs.get(f'{resource_type}_id')
|
|
|
|
checker = PermissionChecker()
|
|
|
|
if not checker.can_access_resource(resource_type, resource_id, action):
|
|
logger.warning(f"Ressourcen-Zugriff verweigert: User {current_user.id}, {resource_type}:{resource_id}, Action: {action}")
|
|
|
|
if request.path.startswith('/api/'):
|
|
return jsonify({
|
|
'error': 'Resource access denied',
|
|
'message': f'Zugriff auf {resource_type} nicht erlaubt',
|
|
'resource_type': resource_type,
|
|
'action': action
|
|
}), 403
|
|
else:
|
|
abort(403)
|
|
|
|
return f(*args, **kwargs)
|
|
|
|
return wrapper
|
|
return decorator
|
|
|
|
# ===== UTILITY FUNCTIONS =====
|
|
|
|
def check_permission(permission: Permission, user=None) -> bool:
|
|
"""
|
|
Standalone-Funktion zur Berechtigungsprüfung
|
|
|
|
Args:
|
|
permission: Die zu prüfende Berechtigung
|
|
user: Benutzer (optional, default: current_user)
|
|
|
|
Returns:
|
|
bool: True wenn Berechtigung vorhanden
|
|
"""
|
|
checker = PermissionChecker(user)
|
|
return checker.has_permission(permission)
|
|
|
|
def get_user_permissions(user=None) -> Set[Permission]:
|
|
"""
|
|
Gibt alle Berechtigungen eines Benutzers zurück
|
|
|
|
Args:
|
|
user: Benutzer (optional, default: current_user)
|
|
|
|
Returns:
|
|
Set[Permission]: Alle Berechtigungen des Benutzers
|
|
"""
|
|
checker = PermissionChecker(user)
|
|
return checker.get_all_permissions()
|
|
|
|
def grant_temporary_permission(user_id: int, permission: Permission, duration_hours: int = 24, reason: str = "", granted_by_id: int = None):
|
|
"""
|
|
Gewährt temporäre Berechtigung
|
|
|
|
Args:
|
|
user_id: ID des Benutzers
|
|
permission: Die zu gewährende Berechtigung
|
|
duration_hours: Dauer in Stunden
|
|
reason: Begründung
|
|
granted_by_id: ID des gewährenden Benutzers
|
|
"""
|
|
try:
|
|
from models import get_db_session
|
|
db_session = get_db_session()
|
|
|
|
override = UserPermissionOverride(
|
|
user_id=user_id,
|
|
permission=permission.value,
|
|
granted=True,
|
|
reason=reason,
|
|
granted_by=granted_by_id or (current_user.id if current_user.is_authenticated else None),
|
|
expires_at=datetime.now() + timedelta(hours=duration_hours)
|
|
)
|
|
|
|
db_session.add(override)
|
|
db_session.commit()
|
|
db_session.close()
|
|
|
|
logger.info(f"Temporäre Berechtigung gewährt: {permission.value} für User {user_id} ({duration_hours}h)")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Fehler beim Gewähren temporärer Berechtigung: {e}")
|
|
|
|
# ===== TEMPLATE HELPERS =====
|
|
|
|
def init_permission_helpers(app):
|
|
"""
|
|
Registriert Template-Helper für Berechtigungen
|
|
|
|
Args:
|
|
app: Flask-App-Instanz
|
|
"""
|
|
|
|
@app.template_global()
|
|
def has_permission(permission_name: str) -> bool:
|
|
"""Template Helper für Berechtigungsprüfung"""
|
|
try:
|
|
permission = Permission(permission_name)
|
|
return check_permission(permission)
|
|
except ValueError:
|
|
return False
|
|
|
|
@app.template_global()
|
|
def has_role(role_name: str) -> bool:
|
|
"""Template Helper für Rollenprüfung"""
|
|
try:
|
|
role = Role(role_name)
|
|
checker = PermissionChecker()
|
|
return role in checker._get_user_roles()
|
|
except ValueError:
|
|
return False
|
|
|
|
@app.template_global()
|
|
def can_access(resource_type: str, resource_id: int = None, action: str = "view") -> bool:
|
|
"""Template Helper für Ressourcen-Zugriff"""
|
|
checker = PermissionChecker()
|
|
return checker.can_access_resource(resource_type, resource_id, action)
|
|
|
|
logger.info("🔐 Permission Template Helpers registriert") |