Protocol for converting values to AshGrant.PermissionInput structs.
This protocol enables AshGrant to accept permissions from various sources
without requiring manual conversion in your PermissionResolver.
Why Use This Protocol?
- Zero boilerplate: Return your existing structs directly from the resolver
- Separation of concerns: Conversion logic lives near your struct definition
- Extensible: Implement for any struct, including third-party ones
- Backward compatible: Plain strings continue to work without changes
Default Implementations
AshGrant provides implementations for:
BitString(plain strings) - Converts toPermissionInputwith just the stringAshGrant.PermissionInput- Pass-through, returns as-isAshGrant.Permission- Converts parsed permission back to input format
Implementing for Custom Structs
If you have your own permission struct, implement the protocol:
defmodule MyApp.RolePermission do
defstruct [:permission_string, :label, :role_name]
end
defimpl AshGrant.Permissionable, for: MyApp.RolePermission do
def to_permission_input(%MyApp.RolePermission{} = rp) do
%AshGrant.PermissionInput{
string: rp.permission_string,
description: rp.label,
source: "role:#{rp.role_name}"
}
end
endThen your resolver can simply return these structs:
defmodule MyApp.PermissionResolver do
@behaviour AshGrant.PermissionResolver
@impl true
def resolve(actor, _context) do
# Just return your structs - AshGrant handles conversion
MyApp.Accounts.get_role_permissions(actor)
end
endUsage Examples
Plain strings (backward compatible)
def resolve(actor, _context) do
["post:*:read:always", "post:*:update:own"]
endMixed strings and PermissionInput
def resolve(actor, _context) do
[
"post:*:read:always",
%AshGrant.PermissionInput{
string: "post:*:update:own",
description: "Edit own posts",
source: "editor_role"
}
]
endCustom structs via Protocol
def resolve(actor, _context) do
# Returns [%MyApp.RolePermission{}, ...]
# Protocol handles conversion automatically
MyApp.Accounts.get_role_permissions(actor)
end
Summary
Functions
Converts a value to AshGrant.PermissionInput struct.
Types
@type t() :: term()
All the types that implement this protocol.
Functions
@spec to_permission_input(t()) :: AshGrant.PermissionInput.t()
Converts a value to AshGrant.PermissionInput struct.
Examples
iex> AshGrant.Permissionable.to_permission_input("post:*:read:always")
%AshGrant.PermissionInput{string: "post:*:read:always"}
iex> input = %AshGrant.PermissionInput{string: "post:*:read:always", description: "Read posts"}
iex> AshGrant.Permissionable.to_permission_input(input)
%AshGrant.PermissionInput{string: "post:*:read:always", description: "Read posts"}