Ash FrameworkAF
Ash Framework7mo ago
23 replies
EAJ

Use policies to limit allowed values of Enum in create action

This is a follow-up to Accept subset of Ash.Type.Enum in action. Again, I have this Enum:
defmodule Dreng.Accounts.Role do
  use Ash.Type.Enum, values: [:superadmin, :admin, :farmer, :farmhand]
end

I realized what I really wanted to build was an invitational system, where :superadmins can invite people with any role, wheras :admins can only invite users with a role of :farmer and :farmhand. This is my invitation resource so far:
defmodule Dreng.Accounts.Invitation do
  use Ash.Resource,
    otp_app: :dreng,
    domain: Dreng.Accounts,
    data_layer: AshPostgres.DataLayer,
    authorizers: [Ash.Policy.Authorizer]

  @token_bytes_length 32

  postgres do
    table "invitations"
    repo Dreng.Repo

    references do
      reference :inviting_user, on_delete: :delete
    end
  end

  actions do
    defaults [:read, :destroy]

    create :create do
      accept [:email, :role]

      # 👇 this should only apply if the inviting user isn't a :superadmin
      validate attribute_in(:role, [:farmer, :farmhand])
    end
  end

  policies do
    policy action_type(:read) do
      authorize_if always()
    end

    policy action_type(:create) do
      authorize_if actor_attribute_equals(:role, :admin)
      authorize_if actor_attribute_equals(:role, :superadmin)
    end
  end

  attributes do
    uuid_primary_key :id
    attribute :email, :ci_string, allow_nil?: false
    attribute :role, Dreng.Accounts.Role

    attribute :token, :string do
      allow_nil? false
      sensitive? true

      default fn ->
        :crypto.strong_rand_bytes(@token_bytes_length)
        |> Base.url_encode64()
        |> binary_part(0, @token_bytes_length)
      end
    end
  end

  relationships do
    belongs_to :inviting_user, Dreng.Accounts.User
  end
end

(Continued in comments)
Solution
Give the SimpleCheck a go and let us know if it helps
Was this page helpful?