Groups and quotas
Groups, Django permissions, role templates, and GroupQuota numeric limits and feature toggles — how Fabrik decides what a user is allowed to do and how much of it.
Groups do two jobs in Fabrik: they bundle Django permissions for easy assignment, and they carry a GroupQuota that caps resource usage and toggles feature access. Most deployments configure three or four groups and never touch user-level permissions.
The group list
Settings → Administration → Groups shows every group with member count, permission count, and whether a quota is configured. Search filters by name.
Clicking a group opens three tabs:
- Members — users currently in the group, with add/remove controls.
- Permissions — Django permissions granted, grouped by app.
- Quota — numeric limits and feature toggles.
Role templates
Creating a group from scratch means picking permissions out of a list of hundreds. Templates skip that — each template is a pre-curated permission set plus a sensible quota preset.
Four templates ship built-in:
| Template | Intent | Highlights |
|---|---|---|
| Administrator | Full access | All permissions, all features on, concurrent AWX jobs capped at 10 |
| Operator | Run queries and automations | Create/edit queries and scheduled tasks, use AWX, 100 saved queries, 50 AWX requests/day |
| Editor | Build and share queries | Queries and categories only — no AWX, 50 saved queries, 10 scheduled tasks |
| Viewer | Read-only | view_* on everything, execute queries but not create, 10 saved queries, no AWX |
Templates are a starting point, not a constraint. After creating a group from a template, edit the permissions and quota freely. The template just saves you the up-front work of picking defaults.
Templates also preset the quota, not just the permissions. A Viewer group gets max_export_rows=5000 out of the box; an Operator gets 50000. Check the quota tab after creating from a template to see what was applied.
The Admin group
The Admin group is special:
- Bootstrapped on first migration — can't be deleted, can't be renamed.
- Members bypass every per-model permission check (same as a superuser).
- Members pass
IsAdminOrSuperuser, which gates all admin endpoints.
Members of Admin still need to exist as active users and still get audited like everyone else. The bypass is for permissions, not identity or accountability.
Admin membership is the closest thing Fabrik has to "root." Grant it sparingly — two or three people in a small team, a handful in a large one. Everyone else should be in Operator, Editor, or Viewer with their capabilities tuned by group quota.
Cloning a group
Clone copies all permissions from an existing group under a new name. Useful when you want a variation — "Operator-APAC" with the same permissions as Operator but a different quota, or a "Editor-External" with reduced connection limits.
The clone copies permissions only. The quota does not copy — the new group starts with no quota, which means users in it fall back to global defaults. If you want the quota copied too, set it manually after cloning.
Django permissions
Under the hood, permissions are the usual Django add_/change_/delete_/view_ tuples per model. Fabrik uses FabrikModelPermissions instead of the stock DjangoModelPermissions, with two differences:
- GET requires
view_permission (stock DRF skips permission checks for safe methods). This is the right default for a product handling sensitive infrastructure data. - Superusers and
Admingroup members bypass all checks, so the permission system doesn't get in the way of admin work.
When a regular user is denied, the response includes a descriptive message: "You do not have permission to edit APIC connections. Contact your administrator to request access." — useful context so the user knows what to ask for.
Certain Django apps are excluded from the permission picker entirely (admin, contenttypes, sessions, authtoken, token_blacklist) — they're framework machinery, not user-facing features.
Group quotas
A GroupQuota row attaches to a group and controls numeric limits and feature toggles.
Numeric limits
The rule: 0 means unlimited. Any positive integer is the hard cap.
| Field | What it caps | Default in DB |
|---|---|---|
max_saved_queries | Saved queries this user owns | 0 (unlimited) |
max_scheduled_tasks | Scheduled tasks this user owns | 0 |
max_apic_connections | APIC connections this user owns | 0 |
max_awx_requests_daily | Automation requests per day | 0 |
max_awx_concurrent | Automation jobs running at once | 5 |
max_query_results | Rows returned from a single query execution | 0 |
max_export_rows | Rows in a CSV/JSON export | 50,000 |
query_execution_daily | Background query executions per day | 0 |
ai_analysis_daily | AI builder calls per day | 0 |
The limits apply at call time: creating a saved query, starting an execution, requesting an export. If you're over the limit, the action is rejected with a message like "You have reached your limit of 50 saved queries."
Daily limits reset at midnight UTC and count rows created within the last 24 hours — the check is COUNT(*) WHERE created_at >= today_start, not a moving window.
Feature toggles
Booleans that turn whole product areas on or off for a group:
| Toggle | Gates |
|---|---|
can_create_queries | Query Builder save button |
can_execute_queries | Running any query (including saved ones) |
can_create_scheduled | Scheduled task creation |
can_use_awx | AWX Automation section entirely |
can_use_time_machine | Time Machine capture and compare |
can_export_data | CSV/JSON export endpoints |
can_share_resources | Sharing queries/tasks with other users |
can_use_ai_builder | AI-assisted query building |
Toggles stop before the numeric check. If can_use_awx=false, the user doesn't even hit max_awx_requests_daily — the AWX section is gone for them entirely.
Multi-group quota resolution
A user can belong to multiple groups. When quotas from different groups overlap, Fabrik resolves them with a single rule: most permissive wins.
- Numeric fields: if any group has
0(unlimited), the effective value is0. Otherwise, the highest value across groups wins. - Boolean toggles: if any group has
true, the effective value istrue.
Examples:
A user in Operator only:
max_saved_queries=100→ capped at 100.can_use_awx=true→ AWX allowed.max_awx_concurrent=5→ 5 concurrent jobs.
A user in Operator (100 queries, AWX on) and Viewer (10 queries, AWX off):
max_saved_queries→max(100, 10)= 100.can_use_awx→true OR false= true.
The Viewer membership adds nothing — Operator is strictly more permissive. This is fine; it doesn't hurt to be in both.
A user in Admin (everything unlimited) and Operator (100 queries):
max_saved_queries→0(unlimited) beats100= 0 (unlimited).
Unlimited wins over any finite number. This is why admins don't need to care about the quotas on other groups they're also in.
No group quota → global defaults
If a user is in no groups — or in groups that have no GroupQuota row — Fabrik falls back to DEFAULT_QUOTAS from Django settings. The defaults are mostly 0 (unlimited) for resources with a max_export_rows=50000 backstop, and all feature toggles true.
The practical read: groups with no quota configured are effectively unlimited. If you want limits, create the quota explicitly.
Superusers are always unlimited
Superusers bypass quota checks entirely. get_effective_quota returns all-unlimited for them regardless of group membership. This is intentional — the bootstrap admin should never lock themselves out of the system by accidentally landing in a restricted group.
Editing a quota
Groups → pick a group → Quota tab. The form has two sections:
- Numeric limits with a
0 = unlimitedhint under each field. - Feature toggles as a grid of switches.
Changes apply immediately to all users in the group. There is no "draft" or "preview" — if you set max_saved_queries=10 on a group whose users already have 50 queries each, they keep their existing queries but can't create new ones until they delete some.
GroupQuota is a OneToOneField to Group, so each group has at most one quota. If you see a group with no Quota tab contents, no quota is configured — click Save on the empty form to create one.
Audit trail
Group-related actions are logged under the group_permission category:
group_created,group_updated,group_deleted,group_clonedpermissions_added,permissions_removed(with the permission list in metadata)quota_updated
Quota changes don't carry a before/after diff in the current audit entry — they log that a change happened and who made it. Compare against the live settings if you need to see what changed; the audit trail is the "who and when," the current state is the "what."
Common patterns
- Three-tier setup.
Admin,Operator,Viewer. Most deployments start here. Use the three built-in templates, tune the quotas, done. - Per-team groups.
Operator-NetEng,Operator-SecOps— same permissions, different quotas. Clone the base Operator group, rename, adjust the quota. - Contractor group. Editor permissions +
can_use_awx=false+ tight daily limits. Keeps third-party access bounded. - Service accounts. Dedicated groups for non-human users (scheduled imports, monitoring integrations). Quotas typically high; feature toggles restricted to what the service actually uses.
That's access control. LDAP, covered next, plugs your corporate directory into the same group and permission system.