16 Commits
Author SHA1 Message Date
KKlochko 045faf59a4 Update the CI/CD configuration to build the image.
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2025-05-27 21:44:40 +03:00
KKlochko 152bee732f Update the version. 2025-05-27 21:43:51 +03:00
KKlochko 99188454e9 Update Navbar partial to show the Server menu item for moderators.
continuous-integration/drone/push Build is passing
2025-05-26 20:38:19 +03:00
KKlochko 80e99b7de8 Remove extra debug logs which used to inspect a state.
continuous-integration/drone/push Build is passing
2025-05-26 14:30:53 +03:00
KKlochko 51c584056b Fix a typo in SearchResources component that an admin is a moderator.
continuous-integration/drone/push Build is passing
2025-05-26 14:21:59 +03:00
KKlochko b70b99ba51 Update DBIServer's Index and Show to allow moderators to read. 2025-05-26 14:21:14 +03:00
KKlochko 9c7a555dae Update Show LiveViews to add information from which server. 2025-05-26 14:19:38 +03:00
KKlochko ab3d65a899 Update Oban configuration to prune jobs which older than 7 days.
continuous-integration/drone/push Build is passing
2025-05-25 21:26:22 +03:00
KKlochko 44841a53e8 Update the LiveViews permission test to fix misuse of the user values.
continuous-integration/drone/push Build is passing
2025-05-24 21:56:49 +03:00
KKlochko a25a4e24da Update to refatactor tests for syncing. 2025-05-24 21:52:22 +03:00
KKlochko 493aca0e5b Update to move get_id functions to support/helpers. 2025-05-24 21:46:02 +03:00
KKlochko 8a3b522049 Update to refactor tests for Author and Book. 2025-05-24 21:21:04 +03:00
KKlochko 89c871110c Update to refactor tests for resource forms. 2025-05-24 21:19:19 +03:00
KKlochko 64028d09f5 Fix data transformers to remove a nil value of dbi_server for syncing.
continuous-integration/drone/push Build is passing
Map.put_new don't update nil value, because the key exists.
2025-05-23 12:50:43 +03:00
KKlochko ea5ada751d Update DBIServerTransformer to fetch the dbi_server relationship. 2025-05-23 12:47:46 +03:00
KKlochko f4eb929401 Update DBIServer to make the relationship to another server public. 2025-05-23 12:42:39 +03:00
39 changed files with 394 additions and 184 deletions
+15 -1
View File
@@ -24,6 +24,20 @@ steps:
commands:
- mix test
- name: build the image
image: plugins/kaniko
settings:
username: kklochko
password:
from_secret: REGISTRY_PASSWORD
repo: git.kklochko.space/kklochko/decentralised_book_index
registry: git.kklochko.space
tags:
- latest
- ${DRONE_TAG}
when:
event: tag
volumes:
- name: mix
temp: {}
@@ -34,4 +48,4 @@ services:
environment:
POSTGRES_DB: decentralised_book_index_dev
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_PASSWORD: postgres
+2 -1
View File
@@ -12,7 +12,8 @@ config :decentralised_book_index, Oban,
repo: DecentralisedBookIndex.Repo,
queues: [default: 14],
plugins: [
Oban.Plugins.Pruner,
# A job will be pruned after 7 days.
{Oban.Plugins.Pruner, max_age: 7*24*60*60},
{Oban.Plugins.Cron,
crontab: [
{"@daily", DecentralisedBookIndex.SyncWorker},
@@ -103,7 +103,9 @@ defmodule DecentralisedBookIndex.Metadata.DBIServer do
end
relationships do
belongs_to :dbi_server, Metadata.DBIServer
belongs_to :dbi_server, Metadata.DBIServer do
public? true
end
has_many :author, Metadata.Author
has_many :author_alias_registries, Metadata.AuthorAliasRegistry
@@ -20,6 +20,10 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.AuthorTransformer do
dbi_server_id: get_in(json_body, ["attributes", "dbi_server_id"])
}
{:ok, attrs}
if is_nil(attrs[:dbi_server_id]) do
{:ok, attrs |> Map.delete(:dbi_server_id)}
else
{:ok, attrs}
end
end
end
@@ -26,6 +26,10 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.BookTransformer do
dbi_server_id: get_in(json_body, ["attributes", "dbi_server_id"])
}
{:ok, attrs}
if is_nil(attrs[:dbi_server_id]) do
{:ok, attrs |> Map.delete(:dbi_server_id)}
else
{:ok, attrs}
end
end
end
@@ -13,9 +13,15 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.DBIServerTransformer do
name: get_in(json_body, ["attributes", "name"]),
url: get_in(json_body, ["attributes", "url"]),
inserted_at: get_in(json_body, ["attributes", "inserted_at"]),
updated_at: get_in(json_body, ["attributes", "updated_at"])
updated_at: get_in(json_body, ["attributes", "updated_at"]),
# relationship
dbi_server_id: get_in(json_body, ["attributes", "dbi_server_id"])
}
{:ok, attrs}
if is_nil(attrs[:dbi_server_id]) do
{:ok, attrs |> Map.delete(:dbi_server_id)}
else
{:ok, attrs}
end
end
end
@@ -17,6 +17,10 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.PublisherTransformer do
dbi_server_id: get_in(json_body, ["attributes", "dbi_server_id"])
}
{:ok, attrs}
if is_nil(attrs[:dbi_server_id]) do
{:ok, attrs |> Map.delete(:dbi_server_id)}
else
{:ok, attrs}
end
end
end
@@ -64,7 +64,7 @@ defmodule DecentralisedBookIndexWeb.Components.MyComponents.SearchResources do
defp can_add?(current_user, role) do
case role do
:admin -> current_user != nil and Role.can_moderate?(current_user.role)
:admin -> current_user != nil and Role.can_administrate?(current_user.role)
:moderator -> current_user != nil and Role.can_moderate?(current_user.role)
_ -> false
end
@@ -20,8 +20,6 @@ defmodule DecentralisedBookIndexWeb.Components.MyComponents.SelectedAuthor do
errors =
if Phoenix.Component.used_input?(assigns.author_form), do: assigns.author_form.errors, else: []
IO.inspect("errors")
IO.inspect(errors)
assigns =
assigns
@@ -106,7 +106,7 @@ defmodule DecentralisedBookIndexWeb.Components.MyPartials.Navbar do
</a>
</li>
<% end %>
<%= if @current_user != nil and Role.can_administrate?(@current_user.role) do %>
<%= if @current_user != nil and Role.can_moderate?(@current_user.role) do %>
<li>
<a
href={~p"/servers/"}
@@ -158,9 +158,6 @@ defmodule DecentralisedBookIndexWeb.AuthorLive.FormComponent do
end
def handle_event("select-author-alias", %{"author-alias" => author_alias_id}, socket) do
IO.inspect("book_editions_registry_id")
IO.inspect(author_alias_id)
socket =
socket
|> update(:form, fn form ->
@@ -57,6 +57,25 @@ defmodule DecentralisedBookIndexWeb.AuthorLive.Show do
<p class="text-gray-300 leading-relaxed">
{@author.description}
</p>
<%= if not is_nil(@author.dbi_server) do %>
<dl>
<dt class="mt-4 mb-2 font-semibold leading-none text-gray-900 dark:text-white">
From Server
</dt>
<dd class="mb-4 font-light text-gray-500 sm:mb-5 dark:text-gray-400">
<%= if @current_user != nil and Role.can_moderate?(@current_user.role) do %>
<.link navigate={~p"/servers/#{@author.dbi_server.id}/"} class="hover:underline">
{@author.dbi_server.name}
</.link>
<% else %>
<.link navigate={@author.dbi_server.url} class="hover:underline">
{@author.dbi_server.name}
</.link>
<% end %>
</dd>
</dl>
<% end %>
</div>
</div>
@@ -74,6 +74,22 @@ defmodule DecentralisedBookIndexWeb.BookLive.Show do
<dd class="mb-4 font-light text-gray-500 sm:mb-5 dark:text-gray-400">{bid.type}: {bid.bid}</dd>
<% end %>
</dl>
<%= if not is_nil(@book.dbi_server) do %>
<dl>
<dt class="mb-2 font-semibold leading-none text-gray-900 dark:text-white">From Server</dt>
<dd class="mb-4 font-light text-gray-500 sm:mb-5 dark:text-gray-400">
<%= if @current_user != nil and Role.can_moderate?(@current_user.role) do %>
<.link navigate={~p"/servers/#{@book.dbi_server.id}/"} class="hover:underline">
{@book.dbi_server.name}
</.link>
<% else %>
<.link navigate={@book.dbi_server.url} class="hover:underline">
{@book.dbi_server.name}
</.link>
<% end %>
</dd>
</dl>
<% end %>
</div>
<%= if not Enum.empty?(@alternative_editions) do %>
@@ -61,7 +61,7 @@ defmodule DecentralisedBookIndexWeb.DbiServerLive.FormComponent do
socket =
socket
|> put_flash(:info, "Server #{socket.assigns.form.source.type}d successfully")
|> push_navigate(to: patch_url(socket.assigns.action, dbi_server.id))
|> redirect(to: patch_url(socket.assigns.action, dbi_server.id))
{:noreply, socket}
@@ -4,26 +4,30 @@ defmodule DecentralisedBookIndexWeb.DbiServerLive.Index do
alias DecentralisedBookIndex.Metadata
alias DecentralisedBookIndex.SyncTasks.SyncServerTask
alias DecentralisedBookIndex.Accounts.Role
@impl true
def render(assigns) do
~H"""
<.header>
Listing Servers
<:actions>
<div class="flex flex-row gap-2">
<%= if @current_user != nil and Role.can_administrate?(@current_user.role) do %>
<div class="flex flex-row gap-2">
<.primary_button phx-click="sync">
Sync now
</.primary_button>
</div>
<div class="flex flex-row gap-2">
<.link patch={~p"/oban"}>
<.primary_button>
Task dashboard
<div class="flex flex-row gap-2">
<.primary_button phx-click="sync">
Sync now
</.primary_button>
</.link>
</div>
<div class="flex flex-row gap-2">
<.link patch={~p"/oban"}>
<.primary_button>
Task dashboard
</.primary_button>
</.link>
</div>
</div>
</div>
<% end %>
</:actions>
</.header>
@@ -63,7 +67,9 @@ defmodule DecentralisedBookIndexWeb.DbiServerLive.Index do
<.link navigate={~p"/servers/#{dbi_server}"}>Show</.link>
</div>
<.link patch={~p"/servers/#{dbi_server}/edit"}>Edit</.link>
<%= if @current_user != nil and Role.can_administrate?(@current_user.role) do %>
<.link patch={~p"/servers/#{dbi_server}/edit"}>Edit</.link>
<% end %>
</:action>
</.table>
@@ -1,6 +1,8 @@
defmodule DecentralisedBookIndexWeb.DbiServerLive.Show do
use DecentralisedBookIndexWeb, :live_view
alias DecentralisedBookIndex.Accounts.Role
@impl true
def render(assigns) do
~H"""
@@ -8,7 +10,7 @@ defmodule DecentralisedBookIndexWeb.DbiServerLive.Show do
{@dbi_server.name}
<:actions>
<%= if is_nil(@dbi_server.dbi_server) do %>
<%= if is_nil(@dbi_server.dbi_server) and @current_user != nil and Role.can_administrate?(@current_user.role) do %>
<.link patch={~p"/servers/#{@dbi_server}/edit"} phx-click={JS.push_focus()}>
<.edit_button>
Edit
@@ -18,7 +20,6 @@ defmodule DecentralisedBookIndexWeb.DbiServerLive.Show do
</:actions>
</.header>
<div>
<dl>
<dt class="mb-2 font-semibold leading-none text-gray-900 dark:text-white">Url</dt>
@@ -28,6 +29,16 @@ defmodule DecentralisedBookIndexWeb.DbiServerLive.Show do
<dt class="mb-2 font-semibold leading-none text-gray-900 dark:text-white">Sync on?</dt>
<dd class="mb-4 font-light text-gray-500 sm:mb-5 dark:text-gray-400">{@dbi_server.sync_on?}</dd>
</dl>
<%= if not is_nil(@dbi_server.dbi_server) do %>
<dl>
<dt class="mb-2 font-semibold leading-none text-gray-900 dark:text-white">From Server</dt>
<dd class="mb-4 font-light text-gray-500 sm:mb-5 dark:text-gray-400">
<.link navigate={~p"/servers/#{@dbi_server.dbi_server.id}/"} class="hover:underline">
{@dbi_server.dbi_server.name}
</.link>
</dd>
</dl>
<% end %>
</div>
<.back navigate={~p"/servers"}>Back to servers</.back>
@@ -1,6 +1,8 @@
defmodule DecentralisedBookIndexWeb.PublisherLive.Show do
use DecentralisedBookIndexWeb, :live_view
alias DecentralisedBookIndex.Accounts.Role
@impl true
def render(assigns) do
~H"""
@@ -18,6 +20,27 @@ defmodule DecentralisedBookIndexWeb.PublisherLive.Show do
</:actions>
</.header>
<%= if not is_nil(@publisher.dbi_server) do %>
<div>
<dl>
<dt class="mt-4 mb-2 font-semibold leading-none text-gray-900 dark:text-white">
From Server
</dt>
<dd class="mb-4 font-light text-gray-500 sm:mb-5 dark:text-gray-400">
<%= if @current_user != nil and Role.can_moderate?(@current_user.role) do %>
<.link navigate={~p"/servers/#{@publisher.dbi_server.id}/"} class="hover:underline">
{@publisher.dbi_server.name}
</.link>
<% else %>
<.link navigate={@publisher.dbi_server.url} class="hover:underline">
{@publisher.dbi_server.name}
</.link>
<% end %>
</dd>
</dl>
</div>
<% end %>
<.back navigate={~p"/publishers"}>Back to publishers</.back>
"""
end
+12 -10
View File
@@ -41,6 +41,18 @@ defmodule DecentralisedBookIndexWeb.Router do
scope "/", DecentralisedBookIndexWeb do
pipe_through :browser
ash_authentication_live_session :admin_authenticated_routes,
on_mount: {DecentralisedBookIndexWeb.LiveUserAuth, :admin_required} do
live "/servers/new", DbiServerLive.Edit, :new
live "/servers/:id/edit", DbiServerLive.Edit, :edit
#live "/servers", DbiServerLive.Index, :index
#live "/servers/:id", DbiServerLive.Show, :show
live "/users", UserLive.Index, :index
live "/users/:id", UserLive.Show, :show
live "/users/:id/edit", UserLive.Edit, :edit
end
ash_authentication_live_session :moderator_authenticated_routes,
on_mount: {DecentralisedBookIndexWeb.LiveUserAuth, :moderator_required} do
live "/books/new", BookLive.Edit, :new
@@ -56,19 +68,9 @@ defmodule DecentralisedBookIndexWeb.Router do
live "/publishers/:id/edit", PublisherLive.Edit, :edit
live "/publishers/:id", PublisherLive.Show, :show
end
ash_authentication_live_session :admin_authenticated_routes,
on_mount: {DecentralisedBookIndexWeb.LiveUserAuth, :admin_required} do
live "/servers", DbiServerLive.Index, :index
live "/servers/new", DbiServerLive.Edit, :new
live "/servers/:id/edit", DbiServerLive.Edit, :edit
live "/servers/:id", DbiServerLive.Show, :show
live "/users", UserLive.Index, :index
live "/users/:id", UserLive.Show, :show
live "/users/:id/edit", UserLive.Edit, :edit
end
ash_authentication_live_session :maybe_authenticated_routes,
+1 -1
View File
@@ -4,7 +4,7 @@ defmodule DecentralisedBookIndex.MixProject do
def project do
[
app: :decentralised_book_index,
version: "0.1.0",
version: "1.0.0",
elixir: "~> 1.14",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
@@ -56,7 +56,7 @@ defmodule DecentralisedBookIndex.Metadata.AuthorTest do
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 = []
assert ^alternatives_names = []
end
test "author has related author so they has one alternative name", %{user: user} do
@@ -73,7 +73,7 @@ defmodule DecentralisedBookIndex.Metadata.AuthorTest do
)
assert {:ok, alternatives_names} = Metadata.get_author_alternative_names(author)
assert alternatives_names = [related_author]
assert get_ids(alternatives_names) == [related_author.id]
end
end
@@ -118,7 +118,8 @@ defmodule DecentralisedBookIndex.Metadata.BookTest do
bids,
author_roles,
publisher.id,
nil
nil,
actor: user
)
end
end
@@ -146,7 +147,7 @@ defmodule DecentralisedBookIndex.Metadata.BookTest do
)
assert {:ok, alternatives_names} = Metadata.get_book_alternative_editions(book)
assert alternatives_names = []
assert ^alternatives_names = []
end
test "book has related book so they has one alternative name", %{user: user} do
@@ -187,7 +188,7 @@ defmodule DecentralisedBookIndex.Metadata.BookTest do
)
assert {:ok, alternatives_names} = Metadata.get_book_alternative_editions(book)
assert alternatives_names = [related_book]
assert get_ids(alternatives_names) == [related_book.id]
end
end
@@ -201,7 +202,7 @@ defmodule DecentralisedBookIndex.Metadata.BookTest do
%{order: 1, author_id: author.id, role: ""}
]
{:ok, book} =
{:ok, _book} =
Metadata.create_book(
"Book",
"An description",
@@ -217,7 +218,7 @@ defmodule DecentralisedBookIndex.Metadata.BookTest do
actor: user
)
assert {:ok, books} = Metadata.get_author_books(author)
assert {:ok, _books} = Metadata.get_author_books(author)
end
test "get the list contains aliases' books", %{user: user} do
@@ -256,7 +257,7 @@ defmodule DecentralisedBookIndex.Metadata.BookTest do
end
describe "get a book by book id" do
test "get by bid", %{user: user} do
test "get by bid" do
expected_book = generate(book())
[%Metadata.BookId{type: type, bid: bid} | _] = expected_book.bids
@@ -12,13 +12,8 @@ defmodule DecentralisedBookIndex.Metadata.Forms.AuthorFormTest do
test "user can't submit" do
user = generate(user())
valid_params = %{
"name" => "Oleh",
"description" => "A cool author"
}
assert_raise Ash.Error.Forbidden, fn ->
form =
_form =
AshPhoenix.Form.for_create(Metadata.Author, :create,
as: "author",
actor: user
@@ -28,12 +23,7 @@ defmodule DecentralisedBookIndex.Metadata.Forms.AuthorFormTest do
end
test "moderator can submit", %{user: user} do
valid_params = %{
"name" => "Oleh",
"description" => "A cool author"
}
assert form =
assert _form =
AshPhoenix.Form.for_create(Metadata.Author, :create,
as: "author",
actor: user
@@ -55,7 +45,7 @@ defmodule DecentralisedBookIndex.Metadata.Forms.AuthorFormTest do
actor: user
)
assert {:ok, author} = AshPhoenix.Form.submit(form, params: valid_params)
assert {:ok, _author} = AshPhoenix.Form.submit(form, params: valid_params)
end
end
@@ -74,7 +64,7 @@ defmodule DecentralisedBookIndex.Metadata.Forms.AuthorFormTest do
actor: user
)
assert {:ok, author} = AshPhoenix.Form.submit(form, params: valid_params)
assert {:ok, _author} = AshPhoenix.Form.submit(form, params: valid_params)
end
end
end
@@ -4,7 +4,6 @@ defmodule DecentralisedBookIndex.Metadata.Forms.BookFormTest do
import ExUnitProperties
alias DecentralisedBookIndex.Metadata
alias DecentralisedBookIndex.Metadata.Book
setup do
user = generate(user(role: :moderator))
@@ -14,22 +13,9 @@ defmodule DecentralisedBookIndex.Metadata.Forms.BookFormTest do
describe "form submiting" do
test "user can't submit" do
user = generate(user())
bids = bids()
author_roles = author_roles()
valid_params = %{
"title" => "Book",
"description" => "A cool author",
"format" => "Paper",
"language" => "English",
"page_count" => 600,
"published" => ~D[2025-03-06],
"author_roles" => author_roles,
"bids" => bids
}
assert_raise Ash.Error.Forbidden, fn ->
form =
_form =
AshPhoenix.Form.for_create(Metadata.Book, :create,
as: "book",
actor: user
@@ -39,21 +25,7 @@ defmodule DecentralisedBookIndex.Metadata.Forms.BookFormTest do
end
test "moderator can submit", %{user: user} do
bids = bids(actor: user)
author_roles = author_roles(actor: user)
valid_params = %{
"title" => "Book",
"description" => "A cool author",
"format" => "Paper",
"language" => "English",
"page_count" => 600,
"published" => ~D[2025-03-06],
"author_roles" => author_roles,
"bids" => bids
}
assert form =
assert _form =
AshPhoenix.Form.for_create(Metadata.Book, :create,
as: "book",
actor: user
@@ -86,7 +58,7 @@ defmodule DecentralisedBookIndex.Metadata.Forms.BookFormTest do
actor: user
)
assert {:ok, user} = AshPhoenix.Form.submit(form, params: valid_params)
assert {:ok, _book} = AshPhoenix.Form.submit(form, params: valid_params)
end
end
@@ -106,7 +78,7 @@ defmodule DecentralisedBookIndex.Metadata.Forms.BookFormTest do
actor: user
)
assert {:ok, user} = AshPhoenix.Form.submit(form, params: valid_params)
assert {:ok, _book} = AshPhoenix.Form.submit(form, params: valid_params)
end
test "update bids and authors", %{user: user} do
@@ -125,7 +97,7 @@ defmodule DecentralisedBookIndex.Metadata.Forms.BookFormTest do
actor: user
)
assert {:ok, user} = AshPhoenix.Form.submit(form, params: valid_params)
assert {:ok, _book} = AshPhoenix.Form.submit(form, params: valid_params)
end
end
@@ -12,12 +12,8 @@ defmodule DecentralisedBookIndex.Metadata.Forms.PublisherFormTest do
test "user can't submit" do
user = generate(user())
valid_params = %{
"name" => "Publisher"
}
assert_raise Ash.Error.Forbidden, fn ->
form =
_form =
AshPhoenix.Form.for_create(Metadata.Publisher, :create,
as: "publisher",
actor: user
@@ -27,11 +23,7 @@ defmodule DecentralisedBookIndex.Metadata.Forms.PublisherFormTest do
end
test "moderator can submit", %{user: user} do
valid_params = %{
"name" => "Publisher"
}
assert form =
assert _form =
AshPhoenix.Form.for_create(Metadata.Publisher, :create,
as: "publisher",
actor: user
@@ -81,5 +81,40 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.AuthorTransformerTest do
updated_at: "2025-03-26T10:16:16.124581Z"
} = author
end
test "a json has dbi_server_id as nil, then author's map has not :dbi_server_id key" do
json_body = %{
"attributes" => %{
"author_alias_registry_id" => "1320a6fe-b311-45ac-bbaa-39cf29c44624",
"avatar_url" => "/images/avatar.png",
"dbi_server_id" => nil,
"description" => "Something",
"inserted_at" => "2025-03-25T19:19:15.187456Z",
"name" => "Author",
"updated_at" => "2025-03-26T10:16:16.124581Z"
},
"id" => "889a323e-d104-4b5d-b276-dad5a9b1da9d",
"links" => %{},
"meta" => %{},
"relationships" => %{
"author_alias_registry" => %{"links" => %{}, "meta" => %{}},
"dbi_server" => %{"links" => %{}, "meta" => %{}}
},
"type" => "author"
}
assert {:ok, author} = AuthorTransformer.from_json(json_body)
assert %{
id: "889a323e-d104-4b5d-b276-dad5a9b1da9d",
name: "Author",
description: "Something",
avatar_url: "/images/avatar.png",
author_alias_registry_id: "1320a6fe-b311-45ac-bbaa-39cf29c44624",
inserted_at: "2025-03-25T19:19:15.187456Z",
updated_at: "2025-03-26T10:16:16.124581Z"
} = author
refute Map.has_key?(author, :dbi_server_id)
end
end
end
@@ -138,5 +138,70 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.BookTransformerTest do
dbi_server_id: "889a323e-d104-4b5d-b276-dad5a9b1da99"
} = book
end
test "a json has dbi_server_id as nil, then book's map has not :dbi_server_id key" do
json_body = %{
"attributes" => %{
"dbi_server_id" => nil,
"cover_image_url" => "/images/book_cover.png",
"description" => "A cool book.",
"format" => "Paper",
"inserted_at" => "2025-03-20T14:44:36.162986Z",
"language" => "English",
"page_count" => 1000,
"published" => "2025-03-05",
"publisher_id" => "11349865-1b7b-454a-b999-6c4059888a78",
"title" => "Book",
"updated_at" => "2025-04-01T18:14:25.754055Z"
},
"id" => "1bbe8861-9d9d-4684-bda6-b6ec238d8d08",
"links" => %{},
"meta" => %{},
"relationships" => %{
"author_roles" => %{
"links" => %{
"related" =>
"http://localhost:4000/api/v1/json/books/1bbe8861-9d9d-4684-bda6-b6ec238d8d08/author_roles"
},
"meta" => %{}
},
"bids" => %{
"links" => %{
"related" =>
"http://localhost:4000/api/v1/json/books/1bbe8861-9d9d-4684-bda6-b6ec238d8d08/bids"
},
"meta" => %{}
},
"book_editions_registry" => %{"links" => %{}, "meta" => %{}},
"dbi_server" => %{"links" => %{}, "meta" => %{}},
"publisher" => %{
"links" => %{
"related" =>
"http://localhost:4000/api/v1/json/books/1bbe8861-9d9d-4684-bda6-b6ec238d8d08/publisher"
},
"meta" => %{}
}
},
"type" => "book"
}
assert {:ok, book} = BookTransformer.from_json(json_body)
assert %{
id: "1bbe8861-9d9d-4684-bda6-b6ec238d8d08",
cover_image_url: "/images/book_cover.png",
description: "A cool book.",
format: "Paper",
inserted_at: "2025-03-20T14:44:36.162986Z",
language: "English",
page_count: 1000,
published: "2025-03-05",
publisher_id: "11349865-1b7b-454a-b999-6c4059888a78",
title: "Book",
updated_at: "2025-04-01T18:14:25.754055Z",
} = book
refute Map.has_key?(book, :dbi_server_id)
end
end
end
@@ -8,6 +8,7 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.DBIServerTransformerTest
json_body = %{
"data" => %{
"attributes" => %{
"dbi_server_id" => "0c0647ec-07ef-4caa-b683-5847dbfbe5cc",
"inserted_at" => "2025-03-22T20:07:30.766249Z",
"name" => "Test",
"updated_at" => "2025-05-04T18:48:44.213309Z",
@@ -16,7 +17,7 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.DBIServerTransformerTest
"id" => "0c0647ec-07ef-4caa-b683-5847dbfbe5cc",
"links" => %{},
"meta" => %{},
"relationships" => %{},
"relationships" => %{"dbi_server" => %{"links" => %{}, "meta" => %{}}},
"type" => "dbi_server"
},
"jsonapi" => %{"version" => "1.0"},
@@ -34,11 +35,40 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.DBIServerTransformerTest
name: "Test",
url: "http://localhost:4001",
inserted_at: "2025-03-22T20:07:30.766249Z",
updated_at: "2025-05-04T18:48:44.213309Z"
updated_at: "2025-05-04T18:48:44.213309Z",
dbi_server_id: "0c0647ec-07ef-4caa-b683-5847dbfbe5cc"
} = server
end
test "a json doesn't contains server information \"data\" attribute" do
json_body = %{
"attributes" => %{
"dbi_server_id" => "0c0647ec-07ef-4caa-b683-5847dbfbe5cc",
"inserted_at" => "2025-03-22T20:07:30.766249Z",
"name" => "Test",
"updated_at" => "2025-05-04T18:48:44.213309Z",
"url" => "http://localhost:4001"
},
"id" => "0c0647ec-07ef-4caa-b683-5847dbfbe5cc",
"links" => %{},
"meta" => %{},
"relationships" => %{"dbi_server" => %{"links" => %{}, "meta" => %{}}},
"type" => "dbi_server"
}
assert {:ok, server} = DBIServerTransformer.from_json(json_body)
assert %{
id: "0c0647ec-07ef-4caa-b683-5847dbfbe5cc",
name: "Test",
url: "http://localhost:4001",
inserted_at: "2025-03-22T20:07:30.766249Z",
updated_at: "2025-05-04T18:48:44.213309Z",
dbi_server_id: "0c0647ec-07ef-4caa-b683-5847dbfbe5cc"
} = server
end
test "a json has dbi_server_id as nil, then server's map has not :dbi_server_id key" do
json_body = %{
"attributes" => %{
"inserted_at" => "2025-03-22T20:07:30.766249Z",
@@ -62,6 +92,8 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.DBIServerTransformerTest
inserted_at: "2025-03-22T20:07:30.766249Z",
updated_at: "2025-05-04T18:48:44.213309Z"
} = server
refute Map.has_key?(server, :dbi_server_id)
end
end
end
@@ -63,5 +63,32 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.PublisherTransformerTest
dbi_server_id: "889a323e-d104-4b5d-b276-dad5a9b1da99"
} = publisher
end
test "a json has dbi_server_id as nil, then publisher's map has not :dbi_server_id key" do
json_body = %{
"attributes" => %{
"dbi_server_id" => nil,
"inserted_at" => "2025-03-21T09:20:48.791539Z",
"name" => "Publisher",
"updated_at" => "2025-03-21T09:20:48.791539Z"
},
"id" => "11349865-1b7b-454a-b999-6c4059888a78",
"links" => %{},
"meta" => %{},
"relationships" => %{"dbi_server" => %{"links" => %{}, "meta" => %{}}},
"type" => "publisher"
}
assert {:ok, publisher} = PublisherTransformer.from_json(json_body)
assert %{
id: "11349865-1b7b-454a-b999-6c4059888a78",
name: "Publisher",
inserted_at: "2025-03-21T09:20:48.791539Z",
updated_at: "2025-03-21T09:20:48.791539Z",
} = publisher
refute Map.has_key?(publisher, :dbi_server_id)
end
end
end
@@ -26,17 +26,13 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.AuthorSyncTest do
updated_at: "2025-03-21T09:20:48.791539Z"
}
{:ok, inserted_at, 0} = DateTime.from_iso8601(author[:inserted_at])
{:ok, updated_at, 0} = DateTime.from_iso8601(author[:updated_at])
assert :ok = AuthorSync.create_update(author, server.id)
assert {:ok, saved_author} = Metadata.get_author_by_id(author.id)
author =
author
|> Map.replace(:inserted_at, inserted_at)
|> Map.replace(:updated_at, updated_at)
|> Map.delete(:author_alias_registry_id)
|> datetime_from_iso8601_for_map()
assert get_submap(saved_author, author) == author
assert nil != saved_author.author_alias_registry_id
@@ -56,16 +52,12 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.AuthorSyncTest do
updated_at: "2025-03-21T09:20:48.791539Z"
}
{:ok, inserted_at, 0} = DateTime.from_iso8601(author[:inserted_at])
{:ok, updated_at, 0} = DateTime.from_iso8601(author[:updated_at])
assert :ok = AuthorSync.create_update(author, server.id)
assert {:ok, saved_author} = Metadata.get_author_by_id(author.id)
author =
author
|> Map.replace(:inserted_at, inserted_at)
|> Map.replace(:updated_at, updated_at)
|> datetime_from_iso8601_for_map()
assert get_submap(saved_author, author) == author
assert nil != saved_author.author_alias_registry_id
@@ -88,7 +80,7 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.AuthorSyncTest do
assert :ok = AuthorSync.create_update(author_attrs, server.id)
assert {:ok, saved_author} = Metadata.get_author_by_id(author.id)
assert author = saved_author
assert get_submap(author, author_attrs) == get_submap(saved_author, author_attrs)
end
test "the local existing author wouldn't updated", %{user: user} do
@@ -32,20 +32,17 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.BookSyncTest do
updated_at: "2025-04-01T18:14:25.754055Z"
}
{:ok, inserted_at, 0} = DateTime.from_iso8601(book[:inserted_at])
{:ok, updated_at, 0} = DateTime.from_iso8601(book[:updated_at])
assert :ok = BookSync.create_update(book, server.id)
assert {:ok, saved_book} = Metadata.get_book_by_id(book.id)
book =
book
|> Map.replace(:inserted_at, inserted_at)
|> Map.replace(:updated_at, updated_at)
|> datetime_from_iso8601_for_map()
|> Map.replace(:published, Date.from_iso8601!(book[:published]))
assert nil != saved_book.book_editions_registry_id
assert server.id == saved_book.dbi_server_id
assert get_submap(saved_book, book) == book
end
test "a new book has the same editions registry" do
@@ -68,20 +65,17 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.BookSyncTest do
book_editions_registry_id: "1ed81d9e-3757-472a-aa3b-44fcdfbe770a"
}
{:ok, inserted_at, 0} = DateTime.from_iso8601(book[:inserted_at])
{:ok, updated_at, 0} = DateTime.from_iso8601(book[:updated_at])
assert :ok = BookSync.create_update(book, server.id)
assert {:ok, saved_book} = Metadata.get_book_by_id(book.id)
book =
book
|> Map.replace(:inserted_at, inserted_at)
|> Map.replace(:updated_at, updated_at)
|> datetime_from_iso8601_for_map()
|> Map.replace(:published, Date.from_iso8601!(book[:published]))
assert nil != saved_book.book_editions_registry_id
assert server.id == saved_book.dbi_server_id
assert get_submap(saved_book, book) == book
end
test "a new book with relationships will be created" do
@@ -166,10 +160,10 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.BookSyncTest do
}
assert :ok = BookSync.create_update(book_attrs, server.id)
assert {:ok, saved_book} = Metadata.get_book_by_id(book.id)
assert {:ok, _saved_book} = Metadata.get_book_by_id(book.id)
end
test "the local existing book wouldn't updated", %{user: user} do
test "the local existing book wouldn't updated" do
server = generate(dbi_server(url: @test_server_endpoint))
book = generate(book())
@@ -195,7 +189,7 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.BookSyncTest do
assert saved_book.dbi_server_id == nil
end
test "old book wouldn't be sync", %{user: user} do
test "old book wouldn't be sync" do
server = generate(dbi_server(url: @test_server_endpoint))
book = generate(book())
@@ -347,11 +341,4 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.BookSyncTest do
assert Enum.all?(old_roles, fn id -> id not in new_roles end)
end
end
defp get_ids(records) do
Enum.map(records, fn record -> get_id(record) end)
end
defp get_id(record) when is_struct(record), do: record.id
defp get_id(record) when is_map(record), do: record[:id]
end
@@ -17,11 +17,11 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.DBIServerSyncTest do
server = generate(dbi_server(url: @test_server_endpoint))
dbi_server = %{
id: "0c0647ec-07ef-4caa-b683-5847dbfbe5cc",
name: "Test",
url: "http://localhost:4001",
inserted_at: "2025-03-22T20:07:30.766249Z",
updated_at: "2025-05-04T18:48:44.213309Z"
id: "0c0647ec-07ef-4caa-b683-5847dbfbe5cc",
name: "Test",
url: "http://localhost:4001",
inserted_at: "2025-03-22T20:07:30.766249Z",
updated_at: "2025-05-04T18:48:44.213309Z"
}
{:ok, inserted_at, 0} = DateTime.from_iso8601(dbi_server[:inserted_at])
@@ -35,27 +35,30 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.DBIServerSyncTest do
|> Map.replace(:inserted_at, inserted_at)
|> Map.replace(:updated_at, updated_at)
assert dbi_server = saved_dbi_server
assert dbi_server == get_submap(saved_dbi_server, dbi_server)
assert server.id == saved_dbi_server.dbi_server_id
end
test "update an existing dbi_server", %{user: user} do
server = generate(dbi_server(url: @test_server_endpoint))
{:ok, dbi_server} = Metadata.create_dbi_server("Test", "http://localhost:4001", false, actor: user)
{:ok, dbi_server} =
Metadata.create_dbi_server("Test", "http://localhost:4001", false, actor: user)
dbi_server_attrs = %{
id: dbi_server.id,
name: "Test",
url: "http://localhost:4001",
inserted_at: "2025-03-22T20:07:30.766249Z",
updated_at: "2025-05-04T18:48:44.213309Z"
id: dbi_server.id,
name: "Test",
url: "http://localhost:4001",
inserted_at: "2025-03-22T20:07:30.766249Z",
updated_at: "2025-05-04T18:48:44.213309Z"
}
assert :ok = DBIServerSync.create_update(dbi_server_attrs, server.id)
assert {:ok, saved_dbi_server} = Metadata.get_dbi_server_by_id(dbi_server.id)
assert dbi_server_attrs = saved_dbi_server
assert datetime_from_iso8601_for_map(dbi_server_attrs) ==
get_submap(saved_dbi_server, dbi_server_attrs)
assert server.id == saved_dbi_server.dbi_server_id
end
end
@@ -23,9 +23,6 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.PublisherSyncTest do
updated_at: "2025-03-21T09:20:48.791539Z"
}
{:ok, inserted_at, 0} = DateTime.from_iso8601(publisher[:inserted_at])
{:ok, updated_at, 0} = DateTime.from_iso8601(publisher[:updated_at])
assert :ok = PublisherSync.create_update(publisher, server.id)
assert {:ok, saved_publisher} = Metadata.get_publisher_by_id(publisher.id)
@@ -16,10 +16,10 @@ defmodule DecentralisedBookIndex.SyncTasks.SyncAuthorsTaskTest do
test "sync authors", %{user: user} do
server = generate(dbi_server(url: @test_server_endpoint))
{:ok, author} = Metadata.create_author("Author", "An description", nil, nil, actor: user)
{:ok, author} = Metadata.create_author("Author2", "An description", nil, nil, actor: user)
{:ok, _author} = Metadata.create_author("Author", "An description", nil, nil, actor: user)
{:ok, _author} = Metadata.create_author("Author2", "An description", nil, nil, actor: user)
assert server = SyncAuthorsTask.sync(server)
assert ^server = SyncAuthorsTask.sync(server)
end
end
end
@@ -2,7 +2,6 @@ defmodule DecentralisedBookIndex.SyncTasks.SyncBookTaskTest do
use DecentralisedBookIndex.DataCase
alias DecentralisedBookIndex.SyncTasks.SyncBooksTask
alias DecentralisedBookIndex.Metadata
alias DecentralisedBookIndex.TestEndpoints
@test_server_endpoint TestEndpoints.test_api_endpoint()
@@ -14,7 +13,7 @@ defmodule DecentralisedBookIndex.SyncTasks.SyncBookTaskTest do
_book = generate(book())
_book = generate(book())
assert server = SyncBooksTask.sync(server)
assert ^server = SyncBooksTask.sync(server)
end
end
end
@@ -19,7 +19,7 @@ defmodule DecentralisedBookIndex.SyncTasks.SyncDBIServerTaskTest do
{:ok, _dbi_server} = Metadata.create_dbi_server("Test", "http://localhost:4001", false, actor: user)
{:ok, _dbi_server} = Metadata.create_dbi_server("Test2", "http://localhost:4001", false, actor: user)
assert server = SyncDBIServerTask.sync(server)
assert ^server = SyncDBIServerTask.sync(server)
end
end
end
@@ -19,7 +19,7 @@ defmodule DecentralisedBookIndex.SyncTasks.SyncPublishersTaskTest do
{:ok, _publisher} = Metadata.create_publisher("Publisher", actor: user)
{:ok, _publisher} = Metadata.create_publisher("Publisher2", actor: user)
assert server = SyncPublishersTask.sync(server)
assert ^server = SyncPublishersTask.sync(server)
end
end
end
@@ -3,9 +3,6 @@ defmodule DecentralisedBookIndex.SyncTasks.SyncServerTaskTest do
alias DecentralisedBookIndex.SyncTasks.SyncServerTask
alias DecentralisedBookIndex.Sync.ApiClients.FetchJson
alias DecentralisedBookIndex.Sync.AuthorSync
alias DecentralisedBookIndex.Metadata
alias DecentralisedBookIndex.TestEndpoints
@@ -18,19 +15,19 @@ defmodule DecentralisedBookIndex.SyncTasks.SyncServerTaskTest do
describe "sync all" do
test "servers", %{user: user} do
server = generate(dbi_server(url: @test_server_endpoint))
{:ok, author} = Metadata.create_author("Author", "An description", nil, nil, actor: user)
_server = generate(dbi_server(url: @test_server_endpoint))
{:ok, _author} = Metadata.create_author("Author", "An description", nil, nil, actor: user)
assert server = SyncServerTask.sync_all()
assert :ok = SyncServerTask.sync_all()
end
end
describe "sync one" do
test "server", %{user: user} do
server = generate(dbi_server(url: @test_server_endpoint))
{:ok, author} = Metadata.create_author("Author", "An description", nil, nil, actor: user)
{:ok, _author} = Metadata.create_author("Author", "An description", nil, nil, actor: user)
assert server = SyncServerTask.sync_one(server)
assert :ok = SyncServerTask.sync_one(server)
end
end
end
@@ -206,7 +206,7 @@ defmodule DecentralisedBookIndexWeb.LiveViewsPermissionsTest do
for user <- [moderator, admin] do
assert {:ok, _view, html} =
conn
|> log_in_user(moderator)
|> log_in_user(user)
|> live("/publishers")
assert html =~ "Listing Publishers"
@@ -303,12 +303,11 @@ defmodule DecentralisedBookIndexWeb.LiveViewsPermissionsTest do
end
describe "Server Index /servers" do
test "can't be accessed by regular user and moderator", %{
test "can't be accessed by regular user", %{
conn: conn,
user: user,
moderator: moderator
user: user
} do
for user <- [nil, user, moderator] do
for user <- [nil, user] do
assert {:error, {:redirect, %{flash: %{"error" => "Unauthorized!"}, to: "/"}}} =
conn
|> log_in_user(user)
@@ -316,11 +315,15 @@ defmodule DecentralisedBookIndexWeb.LiveViewsPermissionsTest do
end
end
test "can be accessed by admin", %{conn: conn, admin: admin} do
for user <- [admin] do
test "can be accessed by moderator and admin", %{
conn: conn,
moderator: moderator,
admin: admin
} do
for user <- [moderator, admin] do
assert {:ok, _view, html} =
conn
|> log_in_user(admin)
|> log_in_user(user)
|> live("/servers")
assert html =~ "Listing Servers"
@@ -333,13 +336,12 @@ defmodule DecentralisedBookIndexWeb.LiveViewsPermissionsTest do
%{server: generate(dbi_server())}
end
test "can't be accessed by non-admin user", %{
test "can't be accessed by non-moderator user", %{
conn: conn,
user: user,
moderator: moderator,
server: server
} do
for user <- [nil, user, moderator] do
for user <- [nil, user] do
assert {:error, {:redirect, %{flash: %{"error" => "Unauthorized!"}, to: "/"}}} =
conn
|> log_in_user(user)
@@ -347,8 +349,13 @@ defmodule DecentralisedBookIndexWeb.LiveViewsPermissionsTest do
end
end
test "can be accessed by admin", %{conn: conn, admin: admin, server: server} do
for user <- [admin] do
test "can be accessed by admin", %{
conn: conn,
moderator: moderator,
admin: admin,
server: server
} do
for user <- [moderator, admin] do
{:ok, _view, html} =
conn
|> log_in_user(user)
@@ -445,7 +452,7 @@ defmodule DecentralisedBookIndexWeb.LiveViewsPermissionsTest do
for user <- [admin] do
assert {:ok, _view, html} =
conn
|> log_in_user(admin)
|> log_in_user(user)
|> live("/users")
assert html =~ "Listing Users"
+7
View File
@@ -41,6 +41,13 @@ defmodule DecentralisedBookIndex.Helpers do
|> DateTime.to_iso8601()
end
def get_ids(records) do
Enum.map(records, fn record -> get_id(record) end)
end
def get_id(record) when is_struct(record), do: record.id
def get_id(record) when is_map(record), do: record[:id]
@doc """
Logs the given `user` into the `conn`.