Runique Admin

Roles and permissions

Overview

The admin permission system has three levels:

LevelControlEffect
is_staffUser fieldGrants access to the admin login page only
Groupseihwaz_groupes + eihwaz_groupes_droits tablesGranular CRUD permissions per resource
is_superuserUser fieldBypasses all checks

Access control fields

FieldTypeRole
is_staffboolAllows login at /admin/login
is_superuserboolFull access, bypasses all permission checks
is_activeboolBlocks inactive accounts

Granular permissions per group

Permissions are carried by groups, not directly by users. A user inherits permissions from all their groups (aggregated with logical OR).

Each group has one entry per resource in eihwaz_groupes_droits:

FieldEffect
can_readSee the resource in the nav + access the list
can_createCreate a record
can_updateEdit any record
can_deleteDelete any record
can_update_ownEdit only their own records
can_delete_ownDelete only their own records

Configuration via the panel

  1. Go to Admin → Groups → create a group
  2. Configure that group's permissions per resource
  3. Go to Admin → Users → assign the group to the user

A user with no group sees no resources in the nav (except superuser).

Immediate revocation

Rights, and the account's state (active, staff, superuser), are read from the database on every admin request: the session only keeps who the user is. Removing a right or a group, deactivating an account or taking away its staff status therefore applies to its next request, whatever made the change (admin, CLI, SQL, another instance). An account that is deactivated or no longer has admin access gets its session closed.


`groupes` and `groupes_droits` resources

These two resources get no special treatment: they follow the exact same generic logic as any other resource (can_read/can_create/can_update/can_delete via eihwaz_groupes_droits). A superuser can therefore deliberately grant can_update on "groupes" to an "Admin" group, which can then manage other groups' permissions (for example, to delegate to moderators) — this is a legitimate use, not a bypass.

What this means in practice: granting rights on groupes/groupes_droits to a non-superuser group gives it real control over permissions — potentially including its own, if its user also belongs to that group. There's no framework safeguard against self-elevation in that specific case: it's up to whoever configures groups not to grant these rights to a role that shouldn't have them. Only is_superuser remains a total, non-delegatable bypass (a bit on the user, never granted through a group).


Access logic

authenticated?
  └─ no  → redirect to /admin/login
  └─ yes → is_staff OR is_superuser?
               └─ neither → redirect to /admin/login
               └─ is_superuser → GRANTED (full access, all resources)
               └─ is_staff → can_read on the resource?
                                └─ no  → resource absent from the nav
                                └─ yes → list visible
                                         can_create / can_update / can_delete
                                         for the corresponding operations
                                         can_update_own / can_delete_own
                                         for their own records only

Notes

  • The admin! macro no longer declares permissions: — configuration is entirely in the database.
  • Permissions are aggregated with logical OR across all of the user's groups.
  • A user can have can_read without can_create — they see the list but cannot create.