Skip to main content

Authorization

:::info Status Implemented. Source: fastapi-backend/core/security.py, fastapi-backend/api/v1/endpoints/{mosques,memberships,invites,join,users}.py. :::

This page covers person-level authorization — what an authenticated user is allowed to do. It is a different model from Device Authorization, which governs what a physical transmitter or stream player may do over MQTT — the two are not interchangeable and this system never conflates them.

Two independent axes

Azan360 checks two separate things on almost every mosque-scoped write:

  1. JWT rolesuperadmin or not. Carried directly on the token (core/security.py:require_role(["superadmin"])), checked with no database lookup.
  2. Per-mosque admin standing — whether this user has a row in the mosque-admins relationship for this specific mosque (db.is_mosque_admin(mosque_id, user_id)), checked with security.require_mosque_admin(mosque_id, user). A superadmin short-circuits this check and passes for every mosque without a row.

There is no global "mosque admin" role on the JWT — admin standing is always evaluated per mosque, per request.

Mosque-admin flags

A mosque-admin row carries its own sub-permissions, not just membership in the relationship:

FlagMeaning
is_ownerThe original/primary admin for the mosque
can_triggerMay start broadcasts/triggers for this mosque
can_manageMay manage mosque settings/admins/devices

security.require_can_trigger(mosque_id, user) checks can_trigger specifically (superadmin still short-circuits) — a mosque admin added without that flag can manage the mosque but not push the trigger button. security.require_mosque_admin is the coarser check used by most mosque-scoped endpoints (mosque CRUD, admins list, memberships list, activity feed).

Membership status

A user's relationship to a mosque as a member (not an admin) is tracked separately in memberships, with a status state machine: pending → approved, plus rejected and banned. Full lifecycle: Membership module.

Membership status gates:

  • Playback entitlement — only an approved membership contributes to who receives azaan push notifications and (per Playback Entitlement) device-level streaming rights.
  • What a member may edit on their own membership — only notification toggles (notify_azaan, notify_jummah, notify_waaz, notify_announcement); status changes are admin/superadmin-only. This split is deliberate: without it, a banned member could PATCH their own membership back to approved and keep receiving azaan triggers.

Superadmin-only endpoints

Gated with dependencies=[Depends(security.require_role(["superadmin"]))] at the route level (not inside the handler) — e.g. all of users.py's list/ create/update/delete-by-id endpoints. This is a stricter, all-or-nothing gate than the per-mosque admin check above.

Self-service vs. admin-initiated membership

PathWho initiatesApproval
POST /mosques/{id}/join, POST /join (join code)The user themselfpending, unless the mosque has auto_approve_members set
POST /mosques/{id}/membershipsA mosque admin/superadmin, enrolling a specific user directlyAlways approved immediately — there is no admin-initiated pending state
POST /invitesA mosque admin, by email/WhatsApp contact (creates the user account if needed)approved if auto_approve requested, else pending

See Membership module for the full request/response shapes and edge cases (e.g. inviting an already-approved member as a mosque admin).