Skip to content

angee.resources.grants

Materialize declarative grant fixtures into REBAC relationship tuples.

A kind = "grants" resource entry (entries.GRANT_KIND) carries flat {resource, relation, subject} rows in resource <- relation <- subject direction. This module resolves each row into the REBAC-owned grant tuple shape (:class:rebac.RelationshipTuple) and commits it through :func:rebac.write_relationships, which upserts by the natural tuple key — so a re-load never duplicates a grant (idempotent, caveat-free for v1).

Reference resolution composes the two owners, never re-deriving either:

  • a literal REBAC ref — a const anchor / role membership / typed wildcard — is written with a slash-form type token (<ns>/type:<id>[`relation`], e.g. angee/role:admin, products/role:products_manager#member, auth/user:*) and is parsed verbatim by :mod:rebac.types;
  • a row xref — anything else (the loader's <addon>.<xref> form, e.g. iam.alice) — resolves through the resource ledger (:func:angee.resources.widgets.resolve_xref) to the loaded row, whose own REBAC identity (:func:rebac.to_object_ref / :func:rebac.to_subject_ref) gives the tuple side — so the row owns its resource type, never a fixture prefix. On the resource side a grant honors the row's IS-A: an MTI child materializes one tuple per REBAC identity it carries — its own type plus each REBAC-registered concrete parent it IS-A (Organization IS-A Party) — so the grant reaches the row through a foreign key typed to any ancestor. An ancestor with no REBAC type is skipped; the row's own type still fails fast;
  • the bare * subject is the public wildcard (the anonymous subject).

materialize_grant_groups

python
def materialize_grant_groups(
        groups: Iterable[GrantGroup], *, ledger_model: type[models.Model],
        addon_aliases: Mapping[str, str]) -> tuple[int, int]

Write every group's grant tuples idempotently; return (created, skipped).

Rows are deduplicated by their natural tuple key before writing, so a repeat within one load — or a re-load of an unchanged fixture — is a no-op.

Released under the AGPL-3.0 License.