mirror of
https://github.com/ash-project/ash_archival.git
synced 2024-09-19 21:13:00 +12:00
Reproduce policy error
This commit is contained in:
parent
34995130d5
commit
25d7bba700
3 changed files with 358 additions and 35 deletions
|
@ -3,7 +3,7 @@ defmodule AshArchival.Resource.Changes.ArchiveRelated do
|
|||
use Ash.Resource.Change
|
||||
require Ash.Query
|
||||
|
||||
def change(changeset, _, _) do
|
||||
def change(changeset, _, context) do
|
||||
archive_related = AshArchival.Resource.Info.archive_related(changeset.resource)
|
||||
|
||||
if Enum.empty?(archive_related) do
|
||||
|
@ -11,7 +11,8 @@ defmodule AshArchival.Resource.Changes.ArchiveRelated do
|
|||
else
|
||||
Ash.Changeset.after_action(changeset, fn changeset, result ->
|
||||
# This is not optimized. We should do this with bulk queries, not resource actions.
|
||||
loaded = changeset.api.load!(result, archive_related)
|
||||
opts = context |> Ash.context_to_opts()
|
||||
loaded = changeset.api.load!(result, archive_related, opts)
|
||||
|
||||
notifications =
|
||||
Enum.flat_map(archive_related, fn relationship ->
|
||||
|
@ -25,8 +26,8 @@ defmodule AshArchival.Resource.Changes.ArchiveRelated do
|
|||
|> List.wrap()
|
||||
|> Enum.flat_map(fn related ->
|
||||
related
|
||||
|> Ash.Changeset.for_destroy(destroy_action)
|
||||
|> (relationship.api || changeset.api).destroy!(return_notifications?: true)
|
||||
|> Ash.Changeset.for_destroy(destroy_action, opts)
|
||||
|> (relationship.api || changeset.api).destroy!(opts |> Keyword.merge(return_notifications?: true))
|
||||
end)
|
||||
end)
|
||||
|
||||
|
|
|
@ -1,6 +1,52 @@
|
|||
defmodule ArchivalTest do
|
||||
use ExUnit.Case
|
||||
|
||||
defmodule Author do
|
||||
use Ash.Resource,
|
||||
data_layer: Ash.DataLayer.Ets,
|
||||
extensions: [AshArchival.Resource]
|
||||
|
||||
ets do
|
||||
table(:authors)
|
||||
private?(true)
|
||||
end
|
||||
|
||||
archive do
|
||||
archive_related([:posts])
|
||||
end
|
||||
|
||||
actions do
|
||||
defaults([:create, :read, :update, :destroy])
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key(:id)
|
||||
end
|
||||
|
||||
relationships do
|
||||
has_many(:posts, ArchivalTest.Post)
|
||||
end
|
||||
end
|
||||
|
||||
defmodule AuthorWithArchive do
|
||||
use Ash.Resource,
|
||||
data_layer: Ash.DataLayer.Ets
|
||||
|
||||
ets do
|
||||
table(:authors)
|
||||
private?(true)
|
||||
end
|
||||
|
||||
actions do
|
||||
defaults([:create, :read, :update, :destroy])
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key(:id)
|
||||
attribute(:archived_at, :utc_datetime_usec)
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Post do
|
||||
use Ash.Resource,
|
||||
data_layer: Ash.DataLayer.Ets,
|
||||
|
@ -24,10 +70,33 @@ defmodule ArchivalTest do
|
|||
end
|
||||
|
||||
relationships do
|
||||
belongs_to :author, Author do
|
||||
attribute_writable?(true)
|
||||
end
|
||||
|
||||
has_many(:comments, ArchivalTest.Comment)
|
||||
end
|
||||
end
|
||||
|
||||
defmodule PostWithArchive do
|
||||
use Ash.Resource,
|
||||
data_layer: Ash.DataLayer.Ets
|
||||
|
||||
ets do
|
||||
table(:posts)
|
||||
private?(true)
|
||||
end
|
||||
|
||||
actions do
|
||||
defaults([:create, :read, :update, :destroy])
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key(:id)
|
||||
attribute(:archived_at, :utc_datetime_usec)
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Comment do
|
||||
use Ash.Resource,
|
||||
data_layer: Ash.DataLayer.Ets,
|
||||
|
@ -70,35 +139,14 @@ defmodule ArchivalTest do
|
|||
uuid_primary_key(:id)
|
||||
attribute(:archived_at, :utc_datetime_usec)
|
||||
end
|
||||
|
||||
relationships do
|
||||
belongs_to(:post, Post)
|
||||
end
|
||||
end
|
||||
|
||||
defmodule PostWithArchive do
|
||||
use Ash.Resource,
|
||||
data_layer: Ash.DataLayer.Ets
|
||||
|
||||
ets do
|
||||
private?(true)
|
||||
table(:posts)
|
||||
end
|
||||
|
||||
actions do
|
||||
defaults([:create, :read, :update, :destroy])
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key(:id)
|
||||
attribute(:archived_at, :utc_datetime_usec)
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Registry do
|
||||
use Ash.Registry
|
||||
|
||||
entries do
|
||||
entry(Author)
|
||||
entry(AuthorWithArchive)
|
||||
entry(Post)
|
||||
entry(PostWithArchive)
|
||||
entry(Comment)
|
||||
|
@ -120,12 +168,9 @@ defmodule ArchivalTest do
|
|||
|> Ash.Changeset.for_create(:create)
|
||||
|> Api.create!()
|
||||
|
||||
assert :ok =
|
||||
post
|
||||
|> Api.destroy!()
|
||||
assert :ok = post |> Api.destroy!()
|
||||
|
||||
[archived] = Api.read!(PostWithArchive)
|
||||
|
||||
assert archived.id == post.id
|
||||
assert archived.archived_at
|
||||
end
|
||||
|
@ -141,13 +186,37 @@ defmodule ArchivalTest do
|
|||
|> Ash.Changeset.for_create(:create, %{post_id: post.id})
|
||||
|> Api.create!()
|
||||
|
||||
assert :ok =
|
||||
post
|
||||
|> Api.destroy!()
|
||||
assert :ok = post |> Api.destroy!()
|
||||
|
||||
[archived] = Api.read!(CommentWithArchive)
|
||||
|
||||
assert archived.id == comment.id
|
||||
assert archived.archived_at
|
||||
end
|
||||
|
||||
test "destroying a record triggers a cascading archive." do
|
||||
author =
|
||||
Author
|
||||
|> Ash.Changeset.for_create(:create)
|
||||
|> Api.create!()
|
||||
|
||||
post =
|
||||
Post
|
||||
|> Ash.Changeset.for_create(:create, %{author_id: author.id})
|
||||
|> Api.create!()
|
||||
|
||||
comment =
|
||||
Comment
|
||||
|> Ash.Changeset.for_create(:create, %{post_id: post.id})
|
||||
|> Api.create!()
|
||||
|
||||
assert :ok = author |> Api.destroy!()
|
||||
|
||||
[archived_post] = Api.read!(PostWithArchive)
|
||||
assert archived_post.id == post.id
|
||||
assert archived_post.archived_at
|
||||
|
||||
[archived_comment] = Api.read!(CommentWithArchive)
|
||||
assert archived_comment.id == comment.id
|
||||
assert archived_comment.archived_at
|
||||
end
|
||||
end
|
||||
|
|
253
test/archival_with_policy_test.exs
Normal file
253
test/archival_with_policy_test.exs
Normal file
|
@ -0,0 +1,253 @@
|
|||
defmodule ArchivalWithPolicyTest do
|
||||
use ExUnit.Case
|
||||
|
||||
defmodule Author do
|
||||
use Ash.Resource,
|
||||
data_layer: Ash.DataLayer.Ets,
|
||||
extensions: [AshArchival.Resource],
|
||||
authorizers: [Ash.Policy.Authorizer]
|
||||
|
||||
ets do
|
||||
table(:authors)
|
||||
private?(true)
|
||||
end
|
||||
|
||||
archive do
|
||||
archive_related([:posts])
|
||||
end
|
||||
|
||||
actions do
|
||||
defaults([:create, :read, :update, :destroy])
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key(:id)
|
||||
end
|
||||
|
||||
relationships do
|
||||
has_many(:posts, ArchivalWithPolicyTest.Post)
|
||||
end
|
||||
|
||||
policies do
|
||||
policy always() do
|
||||
authorize_if(action_type(:create))
|
||||
authorize_if(action_type(:read))
|
||||
authorize_if(actor_attribute_equals(:admin, true))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defmodule AuthorWithArchive do
|
||||
use Ash.Resource,
|
||||
data_layer: Ash.DataLayer.Ets
|
||||
|
||||
ets do
|
||||
table(:authors)
|
||||
private?(true)
|
||||
end
|
||||
|
||||
actions do
|
||||
defaults([:create, :read, :update, :destroy])
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key(:id)
|
||||
attribute(:archived_at, :utc_datetime_usec)
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Post do
|
||||
use Ash.Resource,
|
||||
data_layer: Ash.DataLayer.Ets,
|
||||
extensions: [AshArchival.Resource],
|
||||
authorizers: [Ash.Policy.Authorizer]
|
||||
|
||||
ets do
|
||||
table(:posts)
|
||||
private?(true)
|
||||
end
|
||||
|
||||
archive do
|
||||
archive_related([:comments])
|
||||
end
|
||||
|
||||
actions do
|
||||
defaults([:create, :read, :update, :destroy])
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key(:id)
|
||||
end
|
||||
|
||||
relationships do
|
||||
belongs_to :author, Author do
|
||||
attribute_writable?(true)
|
||||
end
|
||||
|
||||
has_many(:comments, ArchivalWithPolicyTest.Comment)
|
||||
end
|
||||
|
||||
policies do
|
||||
policy always() do
|
||||
authorize_if(action_type(:create))
|
||||
authorize_if(action_type(:read))
|
||||
authorize_if(actor_attribute_equals(:admin, true))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defmodule PostWithArchive do
|
||||
use Ash.Resource,
|
||||
data_layer: Ash.DataLayer.Ets
|
||||
|
||||
ets do
|
||||
table(:posts)
|
||||
private?(true)
|
||||
end
|
||||
|
||||
actions do
|
||||
defaults([:create, :read, :update, :destroy])
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key(:id)
|
||||
attribute(:archived_at, :utc_datetime_usec)
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Comment do
|
||||
use Ash.Resource,
|
||||
data_layer: Ash.DataLayer.Ets,
|
||||
extensions: [AshArchival.Resource],
|
||||
authorizers: [Ash.Policy.Authorizer]
|
||||
|
||||
ets do
|
||||
table(:comments)
|
||||
private?(true)
|
||||
end
|
||||
|
||||
actions do
|
||||
defaults([:create, :read, :update, :destroy])
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key(:id)
|
||||
end
|
||||
|
||||
relationships do
|
||||
belongs_to :post, Post do
|
||||
attribute_writable?(true)
|
||||
end
|
||||
end
|
||||
|
||||
policies do
|
||||
policy always() do
|
||||
authorize_if(action_type(:create))
|
||||
authorize_if(action_type(:read))
|
||||
authorize_if(actor_attribute_equals(:admin, true))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defmodule CommentWithArchive do
|
||||
use Ash.Resource,
|
||||
data_layer: Ash.DataLayer.Ets
|
||||
|
||||
ets do
|
||||
table(:comments)
|
||||
private?(true)
|
||||
end
|
||||
|
||||
actions do
|
||||
defaults([:create, :read, :update, :destroy])
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key(:id)
|
||||
attribute(:archived_at, :utc_datetime_usec)
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Registry do
|
||||
use Ash.Registry
|
||||
|
||||
entries do
|
||||
entry(Author)
|
||||
entry(AuthorWithArchive)
|
||||
entry(Post)
|
||||
entry(PostWithArchive)
|
||||
entry(Comment)
|
||||
entry(CommentWithArchive)
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Api do
|
||||
use Ash.Api
|
||||
|
||||
authorization do
|
||||
authorize(:by_default)
|
||||
end
|
||||
|
||||
resources do
|
||||
registry(Registry)
|
||||
end
|
||||
end
|
||||
|
||||
test "destroying a record archives it" do
|
||||
comment =
|
||||
Comment
|
||||
|> Ash.Changeset.for_create(:create)
|
||||
|> Api.create!()
|
||||
|
||||
assert :ok = comment |> Api.destroy!(actor: %{admin: true})
|
||||
|
||||
[archived] = Api.read!(CommentWithArchive)
|
||||
assert archived.id == comment.id
|
||||
assert archived.archived_at
|
||||
end
|
||||
|
||||
test "destroying a record archives any `archive_related` it has configured" do
|
||||
post =
|
||||
Post
|
||||
|> Ash.Changeset.for_create(:create)
|
||||
|> Api.create!()
|
||||
|
||||
comment =
|
||||
Comment
|
||||
|> Ash.Changeset.for_create(:create, %{post_id: post.id})
|
||||
|> Api.create!()
|
||||
|
||||
assert :ok = post |> Api.destroy!(actor: %{admin: true})
|
||||
|
||||
[archived] = Api.read!(CommentWithArchive)
|
||||
assert archived.id == comment.id
|
||||
assert archived.archived_at
|
||||
end
|
||||
|
||||
test "destroying a record triggers a cascading archive." do
|
||||
author =
|
||||
Author
|
||||
|> Ash.Changeset.for_create(:create)
|
||||
|> Api.create!()
|
||||
|
||||
post =
|
||||
Post
|
||||
|> Ash.Changeset.for_create(:create, %{author_id: author.id})
|
||||
|> Api.create!()
|
||||
|
||||
comment =
|
||||
Comment
|
||||
|> Ash.Changeset.for_create(:create, %{post_id: post.id})
|
||||
|> Api.create!()
|
||||
|
||||
assert :ok = author |> Api.destroy!()
|
||||
|
||||
[archived_post] = Api.read!(PostWithArchive)
|
||||
assert archived_post.id == post.id
|
||||
assert archived_post.archived_at
|
||||
|
||||
[archived_comment] = Api.read!(CommentWithArchive)
|
||||
assert archived_comment.id == comment.id
|
||||
assert archived_comment.archived_at
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue