""" Shared role / access helpers for DigiServer blueprints. Import these instead of duplicating decorators in every blueprint. """ from functools import wraps from flask import abort, flash, redirect, url_for from flask_login import current_user # ── Role-gate decorators ────────────────────────────────────────────────────── def editor_required(f): """Allow admin and editor roles; redirect viewers with a flash message.""" @wraps(f) def decorated(*args, **kwargs): if not current_user.is_authenticated: return redirect(url_for('auth.login')) if current_user.role not in ('admin', 'editor'): flash('You need editor or admin privileges to perform this action.', 'danger') return redirect(url_for('main.dashboard')) return f(*args, **kwargs) return decorated def admin_required(f): """Allow admin role only.""" @wraps(f) def decorated(*args, **kwargs): if not current_user.is_authenticated: return redirect(url_for('auth.login')) if current_user.role != 'admin': flash('Administrator access required.', 'danger') return redirect(url_for('main.dashboard')) return f(*args, **kwargs) return decorated # ── Playlist permission check ───────────────────────────────────────────────── def can_edit_playlist(user, playlist_id: int) -> bool: """ Return True if *user* is allowed to edit the given playlist. - admin / editor → always True - viewer → True only when a PlaylistPermission row exists """ if user.role in ('admin', 'editor'): return True from app.models.playlist_permission import PlaylistPermission return PlaylistPermission.query.filter_by( user_id=user.id, playlist_id=playlist_id ).first() is not None def get_editable_playlist_ids(user) -> set: """Return the set of playlist IDs the user may edit (used in list views).""" if user.role in ('admin', 'editor'): # Import here to avoid circular imports at module load time from app.models.playlist import Playlist return {p.id for p in Playlist.query.with_entities(Playlist.id).all()} from app.models.playlist_permission import PlaylistPermission rows = PlaylistPermission.query.filter_by(user_id=user.id).all() return {r.playlist_id for r in rows}