"""Access control for views: signed in, Publisher, Admin (FR-1, FR-2, FR-25).""" from __future__ import annotations from functools import wraps from urllib.parse import urlencode from django.shortcuts import redirect, render from django.urls import reverse def login_required(view): @wraps(view) def wrapper(request, *args, **kwargs): if getattr(request, "portal_user", None) is None: target = reverse("login") if request.method in ("GET", "HEAD"): target += "?" + urlencode({"next": request.get_full_path()}) return redirect(target) return view(request, *args, **kwargs) return wrapper def _role_required(attribute: str): def decorator(view): @wraps(view) def wrapper(request, *args, **kwargs): if not getattr(request.portal_user, attribute): return render(request, "accounts/forbidden.html", status=403) return view(request, *args, **kwargs) return login_required(wrapper) return decorator publisher_required = _role_required("is_publisher") admin_required = _role_required("is_admin")