""" app/admin/utils.py Shared helpers used across all admin portal blueprints. """ import logging from functools import wraps from flask import abort, request from flask_login import current_user logger = logging.getLogger(__name__) def superadmin_required(f): """ Decorator: ensures the current user is an authenticated superadmin. Aborts 401 if unauthenticated, 403 if wrong role. Use on every admin blueprint route. """ @wraps(f) def decorated(*args, **kwargs): if not current_user.is_authenticated: abort(401) if current_user.role != "superadmin": logger.warning( "superadmin_required: denied user id=%s role=%s endpoint=%s", current_user.id, current_user.role, request.endpoint, ) abort(403) return f(*args, **kwargs) return decorated def log_admin_action(action, target_type=None, target_id=None, before=None, after=None): """ Convenience wrapper — creates an AuditLog entry and adds it to the current db session. Caller must commit. """ from app.models.platform import AuditLog AuditLog.log( actor_id=current_user.id, actor_type="system_user", action=action, target_type=target_type, target_id=target_id, before=before, after=after, ip_address=request.remote_addr, ) def model_to_dict(obj, fields): """Return a plain dict of the named fields from an ORM object (for audit before/after).""" return {f: getattr(obj, f, None) for f in fields}