Skip to content

Ownership Functions

Functions for managing tenant and group ownership. Owners have elevated privileges: they can manage other owners and perform certain actions without explicit permissions. The ownership model supports both tenant-level ownership (where user_group_id is null) and group-level ownership (where user_group_id identifies the owned group).

Source: 027_functions_auth_owner.sql


Ownership Checks

auth.has_owner

Checks whether a given tenant or group currently has at least one owner assigned.

Parameter Type Default Description
_user_group_id integer null Group ID to check; null checks for tenant-level owners
_tenant_id integer 1 Tenant ID to check within

Returns: boolean -- true if at least one owner exists for the specified tenant/group combination, false otherwise. Permission required: None Source: 027_functions_auth_owner.sql:13


auth.is_owner

Checks whether a specific user is an owner of a tenant or group. When _user_group_id is null, checks for tenant-level ownership across all groups.

Parameter Type Default Description
_user_id bigint -- ID of the user to check
_correlation_id text -- Correlation ID for audit trail
_user_group_id integer null Group ID to check ownership of; null matches any group or tenant-level ownership
_tenant_id integer 1 Tenant ID to check within

Returns: boolean -- true if the user is an owner, false otherwise. Permission required: None Source: 027_functions_auth_owner.sql:27


Ownership Management

auth.create_owner

Assigns a user as an owner of a tenant or group. The acting user must either already be an owner themselves or hold the appropriate permission (tenants.assign_owner for tenant-level ownership, tenants.assign_group_owner for group-level ownership). Logs a journal entry with event code 11010 (tenant_user_added) on success.

Parameter Type Default Description
_created_by text -- Identifier of the user performing the action
_user_id bigint -- ID of the acting user (for permission/ownership check)
_correlation_id text -- Correlation ID for audit trail
_target_user_id bigint -- ID of the user to make an owner
_user_group_id integer null Group ID to assign ownership of; null for tenant-level ownership
_tenant_id integer 1 Tenant within which ownership is assigned

Returns: table(__owner_id bigint) -- the newly created owner record ID. Permission required: The acting user must be an existing owner of the same scope, or hold tenants.assign_owner (for tenant-level) / tenants.assign_group_owner (for group-level). Source: 027_functions_auth_owner.sql:45


auth.delete_owner

Removes a user's ownership of a tenant or group. The acting user must either be an owner themselves or hold the appropriate permission. Logs a journal entry with event code 11011 (tenant_user_removed) on success.

Parameter Type Default Description
_deleted_by text -- Identifier of the user performing the deletion
_user_id bigint -- ID of the acting user (for permission/ownership check)
_correlation_id text -- Correlation ID for audit trail
_target_user_id bigint -- ID of the user whose ownership is being removed
_user_group_id integer -- Group ID to remove ownership of (required, not optional)
_tenant_id integer 1 Tenant within which ownership is removed

Returns: void Permission required: The acting user must be an existing owner of the same scope, or hold tenants.assign_owner (for tenant-level) / tenants.assign_group_owner (for group-level). Source: 027_functions_auth_owner.sql:70


Authorization Model

Both auth.create_owner and auth.delete_owner delegate authorization to the internal function unsecure.verify_owner_or_permission, which implements an "owner-or-permission" check:

  1. Owner check first -- If the acting user is already an owner of the target group, they are authorized.
  2. Tenant-level owner fallback -- If the acting user is a tenant-level owner (i.e., owner with user_group_id = null), they are also authorized.
  3. Permission fallback -- If neither owner check passes, the function requires an explicit permission:
    • tenants.assign_group_owner when _user_group_id is not null
    • tenants.assign_owner when _user_group_id is null

This means tenant-level owners can always manage both tenant and group ownership, while group-level owners can only manage ownership within their own group.

Underlying Table

All ownership records are stored in auth.owner:

Column Type Description
owner_id bigint Auto-generated primary key
created_at timestamptz Creation timestamp (defaults to now())
created_by text Identifier of the creator
tenant_id integer Tenant this ownership belongs to (FK to auth.tenant)
user_group_id integer Group this ownership applies to; null for tenant-level ownership (FK to auth.user_group)
user_id bigint The user who is an owner (FK to auth.user_info)