Skip to content

Access control

Access control decides who can do what to the records your module defines. In Victor it has two layers that work together:

  • Groups — named roles a user carries (for example, the built-in admin and user).
  • Access Rules — records of the model_access model that grant one group create / read / write / delete rights on one model.

Access is fail-closed: if no rule grants an operation on a model, that operation is denied. Superusers bypass all access checks.

This page shows the authoring surface you write against — the model_access model and its fields, how a module ships grants for its own models, and where rules are managed in the app.

Groups

A group is a named role a user carries. A user may belong to several groups at once.

Group names come from the Victor platform — membership is managed centrally, not modeled on the instance. Your module never creates or assigns groups; it simply references a group by its name (a plain string) when it grants access. When a request comes in, Victor matches the rule's group name against the groups the current user carries.

Matching is an exact, case-sensitive string comparison, so the name in a rule must match the platform's real group name character-for-character — admin is not the same as Admin. Every instance carries the built-in groups admin and user; grant to those, or to another group you have confirmed exists on the platform, rather than inventing a name.

A name that matches no group grants nothing

Access is fail-closed and there is no error for an unknown group. A rule that names a group no user carries — a typo, the wrong case, or a group that simply doesn't exist on the instance — matches no one and quietly grants nothing. If a grant seems to have no effect, check the group name first.

Superusers

A superuser bypasses every access check. Do not rely on superuser access when designing rules for regular users — always grant the groups those users actually carry.

Access Rules (the model_access model)

Per-model access rights are ordinary records of the model_access model, shipped by the built-in security module. Each row is a single grant:

one group × one model → four boolean permissions.

Field Type Meaning Default
group_name String (required) The group this rule grants rights to. Matches a group name the user carries.
model String (required) The target model these permissions apply to.
perm_read Boolean May the group read records of model? True
perm_create Boolean May the group create records? False
perm_write Boolean May the group update records? False
perm_delete Boolean May the group delete records? False

Because access is fail-closed, a group needs at least one Access Rule granting an operation on a model before it can perform that operation. No matching rule means the operation is denied.

Access is per-model, not per-record

A rule grants rights on an entire model — every record of it. There is no row-level or field-level access: you cannot grant a group only some records of a model, or hide individual fields, through Access Rules. If you're coming from a framework with per-record rules, that layer doesn't exist here.

Here is the model_access model itself — the public field surface you read and write when reasoning about rights. It is declared with the victor SDK like any other model:

from victor import fields, models


class ModelAccess(models.Model):
    name = "model_access"
    _description = 'A rule granting a role read/create/update/delete access to a model.'
    label = "Access Rule"
    display_name = fields.String(label="Name")
    group_name = fields.String(label="Group", required=True)   # matches a group the user carries
    model = fields.String(label="Model", required=True)
    perm_read = fields.Boolean(label="Read", default=True)
    perm_create = fields.Boolean(label="Create", default=False)
    perm_write = fields.Boolean(label="Write", default=False)
    perm_delete = fields.Boolean(label="Delete", default=False)

Worked example

Suppose your helpdesk app defines a ticket model and you want the built-in admin group to work with tickets fully, while every user may only read them. That is two Access Rules:

group_name model read create write delete
admin ticket
user ticket

Any user carrying neither group gets nothing on ticket — fail-closed.

Managing Access Rules in the app

Access Rules are data records, so you manage them in the running app under Settings → Access Rules — a standard list + form provided by the security module. Add a row per (group, model) grant, tick the permissions you want, and save.

How a module declares access control

You declare access control the normal module way — there is no special mechanism, and you never ship a new access model. To secure the models your module defines, you depend on the built-in security module (which provides model_access) and ship model_access records that name your model and the groups that should reach it.

The manifest

Add security to your module's requires in module.yaml (alongside base), and list the data file that carries your grants:

name: helpdesk
label: Helpdesk
author: Acme
version: 0.1.0
requires: [base, security]
models: [models]
data:
  - views/ticket.xml
  - data/access.xml

Shipping default grants as module data

Put the grants for your models in a data file so they install with the module — no manual setup on a fresh instance. Each <seed model="model_access"> row is one Access Rule; give it a stable id so re-installing updates that same record instead of creating a duplicate. This ships the two grants from the worked example above:

<victor>
  <seed model="model_access" id="acc_ticket_admin">
    <group_name>admin</group_name><model>ticket</model>
    <perm_read>true</perm_read><perm_create>true</perm_create><perm_write>true</perm_write><perm_delete>true</perm_delete>
  </seed>
  <seed model="model_access" id="acc_ticket_user">
    <group_name>user</group_name><model>ticket</model>
    <perm_read>true</perm_read>
  </seed>
</victor>

Tip

Grants are ordinary records, so shipping them as module data and adding them by hand under Settings → Access Rules are two paths to the same thing. Ship your module's baseline grants as data; use the Settings screen to adjust them per instance afterward.

Summary

  • Groups are named roles a user carries; membership is managed by the platform, and rules reference a group by its exact, case-sensitive name — the built-in groups are admin and user.
  • Access Rules (model_access records) grant a group perm_read / perm_create / perm_write / perm_delete on a whole model — read defaults on, the rest default off. There is no row-level or field-level access.
  • Access is fail-closed: no matching rule means denied (a rule naming an unknown group silently grants nothing). Superusers bypass all checks.
  • Manage rules under Settings → Access Rules, or ship them with your module as model_access data records.
  • Declaring access control is just ordinary module work: depend on security, and ship model_access grants for your models as module data.

See also: Models & fields · Views.