Anvil.Auth.ACL (Anvil v0.1.1)

View Source

Access Control List (ACL) management for queue memberships.

Implements queue-level access control with roles:

  • :labeler - Can request assignments and submit labels
  • :reviewer - Can view all labels, audit, and export data
  • :owner - Can manage queue membership and settings

Supports time-limited access with expiration and revocation.

Summary

Functions

Checks if a membership is currently active.

Checks if a labeler can audit/view all labels in a queue.

Checks if a labeler can export data from a queue.

Checks if a labeler can label in a queue.

Checks if a labeler can manage a queue (membership, settings).

Filters a list of memberships to only active ones.

Grants queue access to a labeler.

Revokes queue access for a labeler.

Types

error_reason()

@type error_reason() ::
  :not_member
  | :membership_revoked
  | :membership_expired
  | :insufficient_permissions
  | :tenant_mismatch

labeler()

@type labeler() :: %{id: String.t(), tenant_id: String.t()}

queue()

@type queue() :: %{id: String.t(), tenant_id: String.t()}

Functions

active?(queue_membership)

Checks if a membership is currently active.

A membership is active if:

  • It has not been revoked
  • It has not expired

Examples

iex> membership = %QueueMembership{
...>   queue_id: "q1",
...>   labeler_id: "l1",
...>   role: :labeler,
...>   tenant_id: "t1",
...>   expires_at: nil,
...>   revoked_at: nil
...> }
iex> Anvil.Auth.ACL.active?(membership)
true

can_audit?(labeler, queue, memberships)

@spec can_audit?(labeler(), queue(), [Anvil.Auth.ACL.QueueMembership.t()]) ::
  :ok | {:error, error_reason()}

Checks if a labeler can audit/view all labels in a queue.

Requires active membership with :reviewer or :owner role.

Examples

iex> membership = %QueueMembership{
...>   queue_id: "q1",
...>   labeler_id: "l1",
...>   role: :reviewer,
...>   tenant_id: "t1",
...>   expires_at: nil,
...>   revoked_at: nil
...> }
iex> labeler = %{id: "l1", tenant_id: "t1"}
iex> queue = %{id: "q1", tenant_id: "t1"}
iex> Anvil.Auth.ACL.can_audit?(labeler, queue, [membership])
:ok

can_export?(labeler, queue, memberships)

@spec can_export?(labeler(), queue(), [Anvil.Auth.ACL.QueueMembership.t()]) ::
  :ok | {:error, error_reason()}

Checks if a labeler can export data from a queue.

Requires active membership with :reviewer or :owner role.

Examples

iex> membership = %QueueMembership{
...>   queue_id: "q1",
...>   labeler_id: "l1",
...>   role: :owner,
...>   tenant_id: "t1",
...>   expires_at: nil,
...>   revoked_at: nil
...> }
iex> labeler = %{id: "l1", tenant_id: "t1"}
iex> queue = %{id: "q1", tenant_id: "t1"}
iex> Anvil.Auth.ACL.can_export?(labeler, queue, [membership])
:ok

can_label?(labeler, queue, memberships)

@spec can_label?(labeler(), queue(), [Anvil.Auth.ACL.QueueMembership.t()]) ::
  :ok | {:error, error_reason()}

Checks if a labeler can label in a queue.

Requires active membership with :labeler, :reviewer, or :owner role.

Examples

iex> membership = %QueueMembership{
...>   queue_id: "q1",
...>   labeler_id: "l1",
...>   role: :labeler,
...>   tenant_id: "t1",
...>   expires_at: nil,
...>   revoked_at: nil
...> }
iex> labeler = %{id: "l1", tenant_id: "t1"}
iex> queue = %{id: "q1", tenant_id: "t1"}
iex> Anvil.Auth.ACL.can_label?(labeler, queue, [membership])
:ok

can_manage?(labeler, queue, memberships)

@spec can_manage?(labeler(), queue(), [Anvil.Auth.ACL.QueueMembership.t()]) ::
  :ok | {:error, error_reason()}

Checks if a labeler can manage a queue (membership, settings).

Requires active membership with :owner role.

Examples

iex> membership = %QueueMembership{
...>   queue_id: "q1",
...>   labeler_id: "l1",
...>   role: :owner,
...>   tenant_id: "t1",
...>   expires_at: nil,
...>   revoked_at: nil
...> }
iex> labeler = %{id: "l1", tenant_id: "t1"}
iex> queue = %{id: "q1", tenant_id: "t1"}
iex> Anvil.Auth.ACL.can_manage?(labeler, queue, [membership])
:ok

filter_active(memberships)

Filters a list of memberships to only active ones.

Examples

iex> active = %QueueMembership{
...>   queue_id: "q1",
...>   labeler_id: "l1",
...>   role: :labeler,
...>   tenant_id: "t1",
...>   expires_at: nil,
...>   revoked_at: nil
...> }
iex> revoked = %QueueMembership{
...>   queue_id: "q2",
...>   labeler_id: "l1",
...>   role: :labeler,
...>   tenant_id: "t1",
...>   expires_at: nil,
...>   revoked_at: DateTime.utc_now()
...> }
iex> result = Anvil.Auth.ACL.filter_active([active, revoked])
iex> length(result)
1

grant_access(params)

@spec grant_access(map()) ::
  {:ok, Anvil.Auth.ACL.QueueMembership.t()} | {:error, term()}

Grants queue access to a labeler.

Examples

iex> params = %{
...>   queue_id: "q1",
...>   labeler_id: "l1",
...>   role: :labeler,
...>   tenant_id: "t1",
...>   granted_by: "admin1"
...> }
iex> {:ok, membership} = Anvil.Auth.ACL.grant_access(params)
iex> membership.role
:labeler

revoke_access(membership)

Revokes queue access for a labeler.

Examples

iex> membership = %QueueMembership{
...>   queue_id: "q1",
...>   labeler_id: "l1",
...>   role: :labeler,
...>   tenant_id: "t1",
...>   expires_at: nil,
...>   revoked_at: nil
...> }
iex> {:ok, revoked} = Anvil.Auth.ACL.revoke_access(membership)
iex> revoked.revoked_at != nil
true