A key feature of Ash is the ability to build security directly into your resources. We do this with policies.
Because how you write policies is *extremely* situational, this how-to guide provides a list of "considerations" as opposed to "instructions".
For more context, read the [policies guide](https://hexdocs.pm/ash/policies.html#policies).
## Writing Policies
1. Consider whether or not you want to adopt a specific style of authorization, like [ACL](https://en.wikipedia.org/wiki/Access-control_list), or [RBAC](https://en.wikipedia.org/wiki/Role-based_access_control). For standard RBAC, look into [AshRbac](https://hexdocs.pm/ash_rbac/getting_started.html), and you may not need to write any of your own policies at that point
2. Determine if there are any `bypass` policies to add (admin users, super users, etc.). Consider placing this on the domain, instead of the resource
3. Begin by making an inventory of each action on your resource, and under what conditions a given actor may be allowed to perform them. If all actions of a given type have the same criteria, we will typically use the `action_type(:type)` condition
4. Armed with this inventory, begin to write policies. Start simple, write a policy per action type, and add a description of what your policy accomplishes.
5. Find patterns, like cross-cutting checks that exist in all policies, that can be expressed as smaller, simpler policies
6. Determine if any field policies are required to prohibit access to attributes/calculations/aggregates
7. Finally, you can confirm your understanding of the authorization flow for a given resource by generating policy charts with `mix ash.generate_policy_charts` (field policies are not currently included in the generated charts)
## Example
<!-- livebook:{"disable_formatting":true} -->
```elixir
defmodule User do
use Ash.Resource,
domain: Domain,
data_layer: Ash.DataLayer.Ets
actions do
defaults [:read, create: [:admin?]]
end
attributes do
uuid_primary_key :id
attribute :admin?, :boolean do
allow_nil? false
default false
end
end
end
defmodule Tweet do
use Ash.Resource,
domain: Domain,
data_layer: Ash.DataLayer.Ets,
authorizers: [Ash.Policy.Authorizer]
attributes do
uuid_primary_key :id
attribute :text, :string do
allow_nil? false
constraints max_length: 144
public? true
end
attribute :hidden?, :boolean do
allow_nil? false
default false
public? true
end
attribute :private_note, :string do
sensitive? true
public? true
end
end
calculations do
calculate :tweet_length, :integer, expr(string_length(text)) do