class

KemalIdentity::SQLite::AuthzRepository

Inherits KemalIdentity::Authz::Repository < Reference < Object

Authz::Repository over auth_tenant_memberships and auth_role_assignments.

SQLite dialect. A sibling of the PostgreSQL adapter, running the same contract spec.

#grants_for is the hot path — every authorized request runs it — so it is two statements at most, and one when the check names no tenant.

Constants

ASSIGNMENT_COLUMNS = "id, account_id, tenant_id, role, granted_at, granted_by"
MEMBERSHIP_COLUMNS = "id, account_id, tenant_id, created_at"

Constructors

Instance methods

accounts_with_role(role : String, tenant_id : String | Nil = nil) : Array(String)

Everyone holding role in tenant_id, for the access review that asks the question the other way round: not "what can this person do" but "who can do this".

Source
add_member(membership : Authz::Membership) : Bool

Adds a membership. Returns false if the account is already a member, which is not an error — a double-submitted invitation is an ordinary thing.

Source
assignments_for(account_id : String) : Array(Authz::Assignment)

Every assignment for an account, global and per-tenant, oldest first. For an access review, and for the "what would deleting this account remove" screen.

Source
grant(assignment : Authz::Assignment) : Bool

Grants a role. Returns false if the account already holds it in that scope.

It is not this method's job to check that the role exists — RoleCatalog is what knows that, it lives in the application, and a repository that validated role names would be a second, weaker copy of the same rule.

Source
grants_for(account_id : String, tenant_id : String | Nil = nil) : Authz::Grants

Everything one decision needs about account_id, optionally within tenant_id.

With a nil tenant_id the result must have member false and tenant_roles empty: no tenant was named, so neither has any meaning.

Source
member?(account_id : String, tenant_id : String) : Bool
Source
members_of(tenant_id : String, limit : Int32 = 100, offset : Int32 = 0) : Array(Authz::Membership)

Who belongs to this tenant, oldest first. Paged, because a tenant with fifty thousand members is a tenant whose administration screen must not load fifty thousand rows to show the first twenty.

Source
memberships_for(account_id : String) : Array(Authz::Membership)

Which tenants this account belongs to, oldest first.

Source
remove_account(account_id : String) : Int32

Deletes every membership and assignment for an account, returning how many rows went. What account deletion calls, and what a repository must offer so that authorization data does not outlive the account it describes.

Source
remove_member(account_id : String, tenant_id : String) : Bool

Membership and that tenant's assignments go together, in one transaction — see Authz::Repository#remove_member. Leaving the assignments would make re-inviting somebody silently restore every role they used to hold.

Source
revoke(account_id : String, role : String, tenant_id : String | Nil = nil) : Bool

IS NULL rather than = ? for the global case: a global grant and a tenant grant of the same role are different rows, and = NULL matches neither, so revoking the wrong one would silently leave the access in place.

Source