Auth and permissions¶
Status: Placeholder — to be developed. Last reviewed: — Reference structural sibling:
guidelines/i18n/translation-rules.md(rule + workflow style).
Scope (when this guideline lands)¶
Authentication and authorisation conventions: the custom email-based User, login flow, password reset, session vs token (none currently), permission decorators / mixins (LoginRequiredMixin, PermissionRequiredMixin, custom practice-access mixin), where to declare per-view access (decorator vs mixin vs dispatch check), how API endpoints in apps/websites/ authenticate (separate from the admin / user flow).
Out of scope (cross-refs)¶
- Multi-tenant row-level isolation (which rows a user sees once they're authenticated) →
guidelines/security/multi-tenant-isolation.md(placeholder). This file covers WHICH VIEWS they can reach. - PII handling and log redaction →
guidelines/security/pii-and-logging.md(placeholder). - Admin access control (superuser-only per
website-pages-audit.md) →guidelines/backend/admin.md(placeholder). - Session middleware ordering /
LocaleMiddlewareplacement →guidelines/i18n/translation-rules.md.
Sources to mine when writing this¶
apps/accounts/— customUsermodel (email-based login), login views, permission mixins. Read all class docstrings.apps/core/permissions.py—feature_requireddecorator andFeatureRequiredMixin. Survey usage.apps/core/mixins.py— any auth-adjacent mixins.config/urls.py—login_requireddecorators and access patterns at the URL level.- Existing views — enumerate the permission patterns in use, converge on one.
apps/websites/views_cms.py— the API authentication story (likely a different mechanism — DRF auth class?).
Starter hard rules to investigate¶
LoginRequiredMixin(or equivalent) on every non-public view. Login pages, password reset, and the website-API endpoints are the only exceptions.@feature_required('feature_name')decorator (orFeatureRequiredMixin) for feature-gated views — seeapps/core/permissions.pypattern.- Permission checks live in the view class, not the template. Templates can use
{% if perms.... %}for cosmetic show/hide, but the server must enforce independently. - No
@login_requireddecorator on individual methods — use a class-level mixin so it can't be forgotten onpost()etc. - API endpoints have their own auth class (DRF) — separate from session auth used by website views.
Decision points to settle¶
- Where to declare access: decorator on URL pattern vs mixin on view class vs
dispatch()check. Codebase has all three; pick one. - Session vs token: project is session-based today. If/when an external integration needs token auth (e.g. Helios talking back), what's the policy?
- Password reset flow: built-in Django views or custom? Email content under microcopy guidelines?
- Group-based vs feature-based permissions: Django Groups map to feature sets in
apps/core/permissions.py. Document the mapping policy.
Known deviations to look for during writing¶
- Function-based views without
@login_required(silent gap). - Permission checks done only in templates (
{% if perms... %}) without a server-side mirror. - Custom auth bypass for "internal" or "debug" endpoints (security hole).
- Inconsistent feature-gate decorators across views of the same feature.
If found, file IMMEDIATELY as a backlog item — auth gaps are P0.