Permissions¶
Midsummer layers several permission concepts. This page is the mental model you need before gating any view.
The layers¶
Django per-app permissions — standard
authpermissions per app (<app>.<action>_<model>).Event admin roles — six scoped roles that grant module-level admin powers within an event:
admin_event,admin_schedule,admin_staff,admin_registrar,admin_vendors,admin_shop, plusadmin_my.Tenant roles —
Membership.isTenantSuperuserand developer flags (per-tenant, on the sharedUser).Permissive department leadership — a staff member who is leadership of a department that owns a module (
ModuleOwnership) gains elevated access to that module’s department-scoped data.
The resolver: check_permission(...)¶
Views gate on check_permission(request, '<module>'), which returns a level
string — commonly something like 'none', 'staff', 'admin', 'superadmin'.
A typical guard:
if check_permission(request, 'register') not in ('admin', 'superadmin'):
return Response(..., status=403)
This helper lives in midsummer/common/permissions.py. It folds together the
event admin role, the tenant superuser flag, and the leadership model into one
answer, so most views only need a single check.
The “permissive” leadership model¶
Staff permissions are deliberately permissive: if you are leadership of a department that owns a module, you get that module’s elevated access even without an explicit event-admin role. This means membership type (staff, volunteer, deputy, leadership) and department ownership both matter.
staff__check_permissionsis a diagnostic command to see exactly what a given user can do, including a--hrsimulation that excludes deputies/staff/ volunteers from leadership-level permissions.staff__check_menusimulates what menu items a user would see.
Known pitfall: isTenantAdmin¶
Warning
The staff roster code path references a Membership.isTenantAdmin field that
does not exist on the model. It’s masked by a short-circuit today, so it
hasn’t blown up, but it is a latent bug. For any new tenant-admin gating, use
the real Membership.isTenantSuperuser field.
UI gating¶
The Python-side permission check is the source of truth. Frontend pages are
served through angular_page / angular_page_event_protected; per-module page
routes (e.g. system/audit-log/) are permission-gated in Python before the
SPA shell is served, so a hidden menu link can’t bypass the backend check.
The menu itself is built from midsummer/common/ui.py (submenus, trigger
values, menu definitions) using the same permission resolution, so what a user
sees matches what they can access.
Where to look¶
Resolver:
midsummer/common/permissions.py(check_permission)Menu/UI gating:
midsummer/common/ui.py,midsummer/common/decorators.pyStaff department model:
staff/models.py(Department,ModuleOwnership)Diagnostics:
staff/management/commands/staff__check_permissions.py,staff/management/commands/staff__check_menu.py