56 lines
1.6 KiB
Python
56 lines
1.6 KiB
Python
"""
|
|
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}
|