-
-
Notifications
You must be signed in to change notification settings - Fork 181
/
changing_attributes.ex
69 lines (59 loc) · 2.01 KB
/
changing_attributes.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
defmodule Ash.Policy.Check.ChangingAttributes do
@moduledoc "This check is true when attribute changes correspond to the provided options."
use Ash.Policy.FilterCheck
@impl true
def describe(opts) do
message =
Enum.map_join(opts[:changing], " and ", fn
{key, further} ->
field_message =
Enum.map_join(further, ", ", fn
{:to, to_value} ->
"to #{inspect(to_value)}"
{:from, from_value} ->
"from #{inspect(from_value)}"
end)
"#{key} #{field_message}"
key ->
"#{key}"
end)
"changing #{message}"
end
@impl true
def filter(_actor, %{changeset: %Ash.Changeset{} = changeset}, options) do
Enum.reduce_while(options[:changing], true, fn {attribute, opts}, expr ->
if Keyword.has_key?(opts, :from) && changeset.action_type == :create do
{:halt, false}
else
if Ash.Changeset.changing_attribute?(changeset, attribute) do
case {Keyword.fetch(opts, :from), Keyword.fetch(opts, :to)} do
{:error, :error} ->
{:cont, expr}
{{:ok, from}, {:ok, to}} ->
if expr == true do
{:cont, expr(^ref(attribute) == ^from and ^atomic_ref(attribute) == ^to)}
else
{:cont,
expr(^expr and ^ref(attribute) == ^from and ^atomic_ref(attribute) == ^to)}
end
{{:ok, from}, :error} ->
if expr == true do
{:cont, expr(^ref(attribute) == ^from)}
else
{:cont, expr(^expr and ^ref(attribute) == ^from)}
end
{:error, {:ok, to}} ->
if expr == true do
{:cont, expr(^atomic_ref(attribute) == ^to)}
else
{:cont, expr(^expr and ^atomic_ref(attribute) == ^to)}
end
end
else
{:halt, false}
end
end
end)
end
def filter(_, _, _), do: false
end