Permissions

Part of the user manual. Related: VISIBILITY · TENANCY · NOTIFICATIONS · ROLES · PROJECTS · WORKFLOWS.

Permissions = what you're allowed to do. CRUD (Create, Retrieve, Update, Delete) on a class of records, plus a narrower per-instance gate ("you can edit X in general, but to edit THIS specific X you also need to be the owner / project admin").

This page does NOT cover which records appear in your view — that's filtering, not permissions. If you're trying to answer "why can't user X see record Y?", start at VISIBILITY. The distinction matters: a user with full CRUD permissions on workflow events can still see zero events because every visibility layer filtered them out, and a user with no edit permission can still SEE plenty of records — they just can't change them.


TL;DR

  • REBIM uses Django's per-model permission system: add_X, view_X, change_X, delete_X for every model class.
  • Permissions are usually assigned via groups, not directly to users. A handful of standard groups ship via the seed_groups management command — see Default groups.
  • On top of Django's model permissions, per-instance gates apply for most edit / delete operations (owner / project admin / role rules). Both must pass.
  • The Django admin panel is for SaaS superusers only. Tenant users never get a superuser login.
  • Tenancy itself is a visibility concept, not a permissions one — brief pointer below, full coverage in TENANCY.

Two layers — model permissions and instance gates

Every action you take in REBIM is gated by two independent checks:

  1. Model permissions (Django's per-model perms). "Can this user perform action X on records of type T at all?" Stored on auth.User directly, or — more usually — granted via group membership. The backend (REST API + views) checks them on every request.

  2. Instance gates (application-level rules). "Given the user has the model permission, is THIS specific record one they're allowed to act on?" E.g. "you have change_project, but to edit THIS project you also need to be its owner or a project admin." See the per-module gates below for the specifics.

Both must pass. Lack the model permission and the API rejects before the instance gate ever runs. Have the model permission but fail the instance gate and the API still rejects.

The frontend respects these — buttons hide when the user can't act — but it's a UX courtesy, not the enforcement. The backend is authoritative.


Users

Permissions can be assigned to individual users (Django admin → Users → Permissions). In practice this is rarely the right tool:

  • Hard to audit ("who can edit projects?" requires walking every user).
  • Easy to drift ("this user got a one-off permission last year, why?").
  • Hard to maintain ("new permission added — must update N user records").

Prefer groups for almost all real cases. Direct per-user permissions are for genuine exceptions only.


Groups

A group is a named bundle of model permissions assigned to multiple users. Standard practice across the codebase. Examples:

  • Project Manager — can create / edit / delete projects.
  • Document Controller — can create / edit / delete documents + data sources.
  • Tenant Administrator — broader edit rights across configuration models.

To assign a user to a group: Django admin → Users → (pick user) → Groups → check the group(s).

To create a new group: Django admin → Auth → Groups → Add. Pick the permissions, save. Group definitions are tenant-agnostic — a group exists across the install; visibility of records the group's permissions apply to is then filtered by tenancy per user.


Default groups (seed_groups)

The seed_groups management command creates a standard set of groups on a fresh install. Run once:

python manage.py seed_groups

Default group definitions:

  • READ PERMISSIONS — baseline group for any active user:
App Action Models
CORE VIEW Custom Field, Data History, Data Share, Data Tag, Email Template, Saved Layout, Tenant
DIRECTORY VIEW Company, Contact, Contact Type, Industry
EDMS VIEW Conversion, Conversion Request, Data Source, Document, Classification, Revision, Sequence, Status, Type
EDMS ADD Conversion Request
LIVEFEED VIEW Feed, Notification
LIVEFEED ADD / EDIT / DELETE Notification
PROJECTS VIEW Project, Role (discipline), Level, People, System
WORKFLOW VIEW Distribution Group, Event, Status, Transition, Transmittal, Transmittal Action, Transmittal Bake, Workflow
SCHEDULE VIEW Scheduled Events
  • WRITE PERMISSIONS — for users who edit data records (not configuration):
App Action Models
DIRECTORY ADD / EDIT / DELETE Company, Contact
EDMS ADD / EDIT / DELETE Document, Document Revision
PROJECTS ADD / EDIT / DELETE People
WORKFLOW ADD / EDIT / DELETE Event, Transmittal, Transmittal Bake, Status, Transition, Workflow
  • PROJECTS CRUD — for users who manage project-level setup:
App Action Models
PROJECTS ADD / EDIT / DELETE Project
EDMS ADD / EDIT / DELETE Data Source
SCHEDULE ADD / EDIT / DELETE Scheduled Events
  • TENANT ADMINISTRATOR — for users who manage tenant-wide configuration objects:
App Action Models
CORE ADD / EDIT / DELETE Custom Field
EDMS ADD / EDIT / DELETE Data Source, Classification, Sequence, Status, Document Type
PROJECTS ADD / EDIT / DELETE Role (discipline), Level, System
WORKFLOW ADD / EDIT / DELETE Distribution Group, Status, Transition, Transmittal Action, Workflow

A typical user is in READ PERMISSIONS plus one of the write-style groups depending on their job. Multiple write groups are valid (e.g. PROJECTS CRUD + TENANT ADMINISTRATOR for a power user).


Staff and the admin panel

The Django admin panel (at /admin/) is gated by Django's is_superuser flag, NOT by group permissions or tenancy. Only the SaaS administrator should have is_superuser.

Tenant users — even senior admins within a tenant — should never have a superuser login. Tenant-side administration of REBIM happens through the application's own admin surfaces (Project Admin role, Tenant Administrator group, etc.), not the Django admin panel.

Why this matters:

  • The admin panel bypasses tenancy filters. A superuser sees every record in every tenant.
  • The admin panel exposes models that the application UI deliberately hides (DataHistory, raw QueuedEmail records, etc.).
  • A compromised superuser account is far worse than a compromised tenant-admin account.

If a tenant user needs an administration action you don't have a UI for, prefer adding it to the UI over granting them admin access.


Tenants — brief

Tenancy is REBIM's multi-tenant data model. Every record belongs to zero, one, or many tenants; every user belongs to zero, one, or many tenants; visibility is the intersection.

Tenancy is not really a permissions concept — it's a visibility filter. A user with full edit permissions on documents can still see zero documents because tenancy filtered them all out. For the full treatment see TENANCY.

For permissions purposes, two things matter here:

  1. Group permissions are tenant-agnostic. A user in the Document Controller group has edit rights on documents in every tenant they can see — tenancy only narrows which documents they see, not whether they can edit the ones they do see.
  2. "No tenancy" is itself a tenancy. A user with no tenants set sees only records that also have no tenants. This is occasionally a footgun on fresh installs — see TENANCY § No-tenancy is itself a tenancy.

Per-module edit / delete gates

For each module, this lists what's needed to edit or delete a specific record beyond the model permission. Read visibility — which records appear in the user's view at all — is covered in VISIBILITY.

Projects

Create: group permission (e.g. PROJECTS CRUD). No instance gate (it's a creation, no existing instance to gate against).

Edit / Delete: group permission AND the user is either: - the project's owner (creator), OR - a project admin (their ProjectPeople row in this project has project_admin=True).

A user with the group permission but neither ownership nor project admin status on a given project cannot edit / delete that project, even though they can see it.

Contacts

Create / Edit / Delete: group permission (e.g. WRITE PERMISSIONS) AND ONE of: - the user is acting from a project where they hold project admin status (or own the project), OR - the user is the contact's owner (DirectoryContact.owner = user). Useful when you assign an owner specifically so they can edit on the frontend without being a project admin.

Note: the contact's email field, when set, overrides the linked user's email for notification delivery — see CONTACTS § The email caveat for the resolution rules and edge cases (contacts without a site_login, deactivated users, admin-CC paths that don't carry a contact).

Project People (membership)

Create / Edit / Delete: group permission AND the user is the project's owner OR a project admin OR a superuser.

Two flags on each ProjectPeople row affect what the assigned person can do, not what the editor can do:

  • project_admin — grants the assignee in-project admin rights (manage other members, edit project settings).
  • role_leader — grants the assignee broader visibility within their assigned disciplines (covered in ROLES, planned — for now see VISIBILITY § layer 4).

Disciplines (what would be called "roles" in many systems) are the M2M on ProjectPeople.disciplines. Adding / removing disciplines on a project person follows the same edit-gate rules above.

EDMS Documents

Create: group permission. Standard.

Edit: group permission AND: - the document is NOT checked out by another user (see Check-out below), AND - the document does NOT have an active workflow that locks editing (when an event references the document, edit may be restricted until the workflow completes).

Delete: group permission AND (typically) owner / project admin.

Check-out and locks

Documents can be checked out by a user, locking write actions to that user until they check it back in. While checked out:

  • Editing the document is locked to the checked-out user.
  • Editing workflow events that reference the document is locked.
  • Workflow transitions on those events are locked.
  • Tools (markup editor, etc.) open in view-only mode for other users.
  • The Explorer respects the lock (can't add / transition / edit via Explorer either).

Project admins and superusers can override check-out locks for recovery cases (departed user, abandoned check-out).

Check-out is a state-specific rule that also affects VISIBILITY layer 5 — checked-out documents are still visible but most write actions are gated.

Workflow events

Create: group permission. Standard.

Edit: group permission AND ONE of: - the user is the event's owner (creator), OR - the user is the event's assignee, OR - the user is a project admin in the event's project, OR - the user is a superuser.

Transition (advance the event through its workflow): group permission AND the user holds a discipline that the next transition requires. Role mechanics live in ROLES; for now see VISIBILITY § layer 4.

Delete: group permission AND owner / project admin / superuser.

Workflow transmittals

Create: group permission. The user becomes the transmittal owner.

Re-transmit (send again): the user is one of: - the original transmittal creator, OR - a project admin in the transmittal's project, OR - a superuser.

Discussion / chat on a transmittal: any user who can see the transmittal can participate. Read-only access does not preclude discussion (this is intentional — discussion is the consultation channel).

Schedule

Create / Edit / Delete: group permission (SCHEDULE add/change/delete) AND project admin / superuser.

Note: being a project admin alone is not sufficient — they still need the SCHEDULE CRUD group permission. The instance gate adds to the group permission, doesn't replace it.


Read visibility — pointer

Read visibility (who sees which records) is covered in detail in VISIBILITY. The summary:

Record type Read visibility filtered by
Projects Tenancy + project membership
Contacts Tenancy
Documents Tenancy + project access + data source tenancy + check-out for actions
Workflow events Tenancy + project access + role rules + state-specific rules
Workflow transmittals Tenancy + project access
Schedule events Tenancy + project access
Configuration (workflows, statuses, etc.) Tenancy

If a user says "I can't see X," the answer is almost always in VISIBILITY, not here.


For developers

This page is for users and admins. Implementation pointers:

  • Django permission classes: core.views.BimPermissions (extends DjangoModelPermissions) — applied to most viewsets.
  • Project-level instance gates: core.utils.is_user_in_project, apps.projects.models.ProjectManager.for_user.
  • Workflow event instance gates: mostly client-side in apps_workflow.js: can_user_perform_transition, is_owner_or_assignee. The backend may be more permissive than the frontend renders.
  • Check-out state: EdmsDocument.checked_out_by.
  • seed_groups management command: core/management/commands/seed_groups.py.

See devdocs/ for codebase-level material.