Files
MyPOS/app/admin/utils.py
T
2026-05-07 11:22:13 -04:00

71 lines
2.0 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 JSON-serialisable dict of the named fields from an ORM object.
Converts datetime -> ISO-8601 string, Decimal -> float, all others pass through.
Safe to use directly as AuditLog before_json / after_json values.
"""
import datetime
from decimal import Decimal
result = {}
for f in fields:
val = getattr(obj, f, None)
if isinstance(val, (datetime.datetime, datetime.date)):
result[f] = val.isoformat()
elif isinstance(val, Decimal):
result[f] = float(val)
else:
result[f] = val
return result