diff --git a/lib/decentralised_book_index/metadata/author.ex b/lib/decentralised_book_index/metadata/author.ex index b2f5134..6011aa0 100644 --- a/lib/decentralised_book_index/metadata/author.ex +++ b/lib/decentralised_book_index/metadata/author.ex @@ -3,7 +3,8 @@ defmodule DecentralisedBookIndex.Metadata.Author do otp_app: :decentralised_book_index, domain: DecentralisedBookIndex.Metadata, data_layer: AshPostgres.DataLayer, - extensions: [AshJsonApi.Resource] + extensions: [AshJsonApi.Resource], + authorizers: [Ash.Policy.Authorizer] require Ash.Query alias DecentralisedBookIndex.Metadata @@ -24,11 +25,14 @@ defmodule DecentralisedBookIndex.Metadata.Author do primary? true accept [:name, :description, :avatar_url, :author_alias_registry_id] - change fn changeset, _ -> + change fn changeset, context -> + actor = Map.get(context, :actor, nil) + registry_id = Ash.Changeset.get_attribute(changeset, :author_alias_registry_id) if registry_id == nil do - {:ok, registry} = DecentralisedBookIndex.Metadata.create_author_alias_registry() + {:ok, registry} = + DecentralisedBookIndex.Metadata.create_author_alias_registry(actor: actor) Ash.Changeset.force_change_attribute(changeset, :author_alias_registry_id, registry.id) else @@ -74,11 +78,13 @@ defmodule DecentralisedBookIndex.Metadata.Author do :dbi_server_id ] - change fn changeset, _ -> + change fn changeset, context -> + actor = Map.get(context, :actor, nil) registry_id = Ash.Changeset.get_attribute(changeset, :author_alias_registry_id) if registry_id == nil do - {:ok, registry} = DecentralisedBookIndex.Metadata.create_author_alias_registry() + {:ok, registry} = + DecentralisedBookIndex.Metadata.create_author_alias_registry(actor: actor) Ash.Changeset.force_change_attribute(changeset, :author_alias_registry_id, registry.id) else @@ -135,6 +141,7 @@ defmodule DecentralisedBookIndex.Metadata.Author do end update :sync do + description "Sync the data for an existing record." require_atomic? false accept [ @@ -171,6 +178,32 @@ defmodule DecentralisedBookIndex.Metadata.Author do end end + policies do + bypass actor_attribute_equals(:role, :admin) do + authorize_if always() + end + + policy action_type(:read) do + authorize_if always() + end + + policy action(:get_author_ids) do + authorize_if always() + end + + policy action_type(:create) do + authorize_if actor_attribute_equals(:role, :moderator) + end + + policy action_type(:update) do + authorize_if actor_attribute_equals(:role, :moderator) + end + + policy action_type(:destroy) do + authorize_if actor_attribute_equals(:role, :admin) + end + end + attributes do uuid_primary_key :id, writable?: true diff --git a/test/decentralised_book_index/metadata/author_test.exs b/test/decentralised_book_index/metadata/author_test.exs index 65a84da..d1a6f26 100644 --- a/test/decentralised_book_index/metadata/author_test.exs +++ b/test/decentralised_book_index/metadata/author_test.exs @@ -3,45 +3,50 @@ defmodule DecentralisedBookIndex.Metadata.AuthorTest do alias DecentralisedBookIndex.Metadata + setup do + user = generate(user(role: :moderator)) + %{user: user} + end + describe "authors and registries relationship" do - test "a new author get new registry by default" do - assert {:ok, author} = Metadata.create_author("Author", "An description") + test "a new author get new registry by default", %{user: user} do + assert {:ok, author} = Metadata.create_author("Author", "An description", nil, nil, actor: user) assert author.author_alias_registry_id != nil end - test "a new author belongs to a registry if specified" do - assert {:ok, registry} = Metadata.create_author_alias_registry() - assert {:ok, author} = Metadata.create_author("Author", "An description", nil, registry.id) + test "a new author belongs to a registry if specified", %{user: user} do + assert {:ok, registry} = Metadata.create_author_alias_registry(actor: user) + assert {:ok, author} = Metadata.create_author("Author", "An description", nil, registry.id, actor: user) assert author.author_alias_registry_id == registry.id end - test "a new author to a registry via a related author record" do - {:ok, related_author} = Metadata.create_author("Author", "An description") + test "a new author to a registry via a related author record", %{user: user} do + {:ok, related_author} = Metadata.create_author("Author", "An description", nil, nil, actor: user) assert {:ok, author} = - Metadata.add_author_to_related_alias_registry("Author2", "An description2", related_author.id) + Metadata.add_author_to_related_alias_registry("Author2", "An description2", related_author.id, nil, actor: user) assert related_author.author_alias_registry_id == author.author_alias_registry_id end - test "a new author to a registry via a empty related author record" do + test "a new author to a registry via a empty related author record", %{user: user} do assert {:error, _} = - Metadata.add_author_to_related_alias_registry("Author2", "An description2", nil) + Metadata.add_author_to_related_alias_registry("Author2", "An description2", nil, actor: user) end end describe "authors alternatives names" do - test "new author has no alternatives names" do - {:ok, author} = Metadata.create_author("Author", "An description") + test "new author has no alternatives names", %{user: user} do + {:ok, author} = Metadata.create_author("Author", "An description", nil, nil, actor: user) assert {:ok, alternatives_names} = Metadata.get_author_alternative_names(author) assert alternatives_names = [] end - test "author has related author so they has one alternative name" do - {:ok, related_author} = Metadata.create_author("Author", "An description") + test "author has related author so they has one alternative name", %{user: user} do + {:ok, related_author} = Metadata.create_author("Author", "An description", nil, nil, actor: user) {:ok, author} = - Metadata.add_author_to_related_alias_registry("Author2", "An description2", related_author.id) + Metadata.add_author_to_related_alias_registry("Author2", "An description2", related_author.id, nil, actor: user) assert {:ok, alternatives_names} = Metadata.get_author_alternative_names(author) assert alternatives_names = [related_author] @@ -49,19 +54,19 @@ defmodule DecentralisedBookIndex.Metadata.AuthorTest do end describe "author's ids" do - test "the list has the author's id" do - {:ok, author} = Metadata.create_author("Author", "An description") + test "the list has the author's id", %{user: user} do + {:ok, author} = Metadata.create_author("Author", "An description", nil, nil, actor: user) - assert {:ok, ids} = Metadata.get_author_ids(author) + assert {:ok, ids} = Metadata.get_author_ids(author, actor: user) assert author.id in ids end - test "the list has the aliases' ids" do - {:ok, author} = Metadata.create_author("Author", "An description") + test "the list has the aliases' ids", %{user: user} do + {:ok, author} = Metadata.create_author("Author", "An description", nil, nil, actor: user) {:ok, alias1} = - Metadata.add_author_to_related_alias_registry("Author2", "An description2", author.id) + Metadata.add_author_to_related_alias_registry("Author2", "An description2", author.id, nil, actor: user) {:ok, alias2} = - Metadata.add_author_to_related_alias_registry("Author3", "An description3", author.id) + Metadata.add_author_to_related_alias_registry("Author3", "An description3", author.id, nil, actor: user) assert {:ok, ids} = Metadata.get_author_ids(author) @@ -72,15 +77,15 @@ defmodule DecentralisedBookIndex.Metadata.AuthorTest do end describe "authors and avatar_url" do - test "a new author has no avatar by default" do - assert {:ok, author} = Metadata.create_author("Author", "An description") + test "a new author has no avatar by default", %{user: user} do + assert {:ok, author} = Metadata.create_author("Author", "An description", nil, nil, actor: user) assert author.avatar_url == nil end - test "a new author has a avatar" do + test "a new author has a avatar", %{user: user} do avatar_url = "/images/avatar.png" - assert {:ok, author} = Metadata.create_author("Author", "An description", avatar_url) + assert {:ok, author} = Metadata.create_author("Author", "An description", avatar_url, nil, actor: user) assert author.avatar_url == avatar_url end end