Skip to content

Instantly share code, notes, and snippets.

@zachdaniel
Created January 3, 2020 05:17
Show Gist options
  • Save zachdaniel/dfe20cf1c987515235cfd9a056960e25 to your computer and use it in GitHub Desktop.
Save zachdaniel/dfe20cf1c987515235cfd9a056960e25 to your computer and use it in GitHub Desktop.

An example of a resource with authorization rules declared.

  defmodule Author do
    use Ash.Resource, name: "authors", type: "author"
    use Ash.DataLayer.Ets, private?: true

    actions do
      read :default, authorization_steps: [authorize_if: always()]

      create :default,
        authorization_steps: [
          authorize_if: user_attribute(:admin, true),
          authorize_if: user_attribute(:manager, true)
        ]
    end

    attributes do
      attribute :name, :string, authorization_steps: false

      attribute :state, :string,
        authorization_steps: [
          authorize_if: user_attribute(:admin, true),
          forbid_if: setting(to: "closed"),
          authorize_if: always()
        ]

      attribute :bio_locked, :boolean,
        default: {:constant, false},
        authorization_steps: false

      attribute :self_manager, :boolean, authorization_steps: false

      attribute :fired, :boolean, authorization_steps: false
    end

    relationships do
      many_to_many :posts, Ash.Test.Authorization.CreateAuthorizationTest.Post,
        through: Ash.Test.Authorization.CreateAuthorizationTest.AuthorPost

      has_one :bio, Ash.Test.Authorization.CreateAuthorizationTest.Bio,
        authorization_steps: [
          forbid_if: attribute_equals(:bio_locked, true),
          authorize_if: always()
        ]
    end
  end

An example of error output that is generated from a system like the above.

17:04:39.736 [info]  forbidden:
  Facts Gathered
    Global facts:
      ✓ setting state to "closed" ⭑
      ✓ always true ⭑
      ✗ user.admin == true ⭑
      ✗ user.admin == true ⭑
      ✓ user.manager == true ⭑
  Authorization run with `strict_access?: true`. This is the only safe way to authorize requests for lists of filtered data.
  Some checks may still fetch data from the database, like filters on related data when their primary key was given.
  Authorization Steps:
    create - `default`:
      ↓ | authorize_if: user.admin == true ✗
      ✓ | authorize_if: user.manager == true ✓
    ------
    change on `state`:
      ↓ | authorize_if: user.admin == true ✗
      ✗ | forbid_if: setting state to "closed" ✓
      ✓ | authorize_if: always true ✓
  Scenarios:
    No scenarios found. Under construction.
    Eventually, scenarios will explain what data you could change to make the request possible.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment