From e5dd5a8dde4d0ce8e20d3457032803d0baf6598f Mon Sep 17 00:00:00 2001 From: KKlochko Date: Fri, 11 Apr 2025 11:02:23 +0300 Subject: [PATCH] Add roles for users. --- lib/decentralised_book_index/accounts/role.ex | 11 +++ lib/decentralised_book_index/accounts/user.ex | 5 ++ ...20250411061857_update_user_to_add_role.exs | 21 +++++ .../repo/users/20250411061857.json | 84 +++++++++++++++++++ .../accounts/role_test.exs | 31 +++++++ 5 files changed, 152 insertions(+) create mode 100644 lib/decentralised_book_index/accounts/role.ex create mode 100644 priv/repo/migrations/20250411061857_update_user_to_add_role.exs create mode 100644 priv/resource_snapshots/repo/users/20250411061857.json create mode 100644 test/decentralised_book_index/accounts/role_test.exs diff --git a/lib/decentralised_book_index/accounts/role.ex b/lib/decentralised_book_index/accounts/role.ex new file mode 100644 index 0000000..69c8adc --- /dev/null +++ b/lib/decentralised_book_index/accounts/role.ex @@ -0,0 +1,11 @@ +defmodule DecentralisedBookIndex.Accounts.Role do + use Ash.Type.Enum, values: [:user, :moderator, :admin] + + def can_moderate?(role) when is_atom(role) do + role in [:moderator, :admin] + end + + def can_administrate?(role) when is_atom(role) do + role == :admin + end +end diff --git a/lib/decentralised_book_index/accounts/user.ex b/lib/decentralised_book_index/accounts/user.ex index 7c02611..5a38c5e 100644 --- a/lib/decentralised_book_index/accounts/user.ex +++ b/lib/decentralised_book_index/accounts/user.ex @@ -242,6 +242,11 @@ defmodule DecentralisedBookIndex.Accounts.User do allow_nil? false sensitive? true end + + attribute :role, DecentralisedBookIndex.Accounts.Role do + allow_nil? false + default :user + end end identities do diff --git a/priv/repo/migrations/20250411061857_update_user_to_add_role.exs b/priv/repo/migrations/20250411061857_update_user_to_add_role.exs new file mode 100644 index 0000000..a4172f9 --- /dev/null +++ b/priv/repo/migrations/20250411061857_update_user_to_add_role.exs @@ -0,0 +1,21 @@ +defmodule DecentralisedBookIndex.Repo.Migrations.UpdateUserToAddRole do + @moduledoc """ + Updates resources based on their most recent snapshots. + + This file was autogenerated with `mix ash_postgres.generate_migrations` + """ + + use Ecto.Migration + + def up do + alter table(:users) do + add :role, :text, null: false, default: "user" + end + end + + def down do + alter table(:users) do + remove :role + end + end +end diff --git a/priv/resource_snapshots/repo/users/20250411061857.json b/priv/resource_snapshots/repo/users/20250411061857.json new file mode 100644 index 0000000..6038707 --- /dev/null +++ b/priv/resource_snapshots/repo/users/20250411061857.json @@ -0,0 +1,84 @@ +{ + "attributes": [ + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "confirmed_at", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": false, + "default": "fragment(\"gen_random_uuid()\")", + "generated?": false, + "primary_key?": true, + "references": null, + "size": null, + "source": "id", + "type": "uuid" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "email", + "type": "citext" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "hashed_password", + "type": "text" + }, + { + "allow_nil?": false, + "default": "\"user\"", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "role", + "type": "text" + } + ], + "base_filter": null, + "check_constraints": [], + "custom_indexes": [], + "custom_statements": [], + "has_create_action": true, + "hash": "904E7EDF3D1D6FDE1A4495DA78BA722CC9053363DDAEAA68CE3174F6F134EF9C", + "identities": [ + { + "all_tenants?": false, + "base_filter": null, + "index_name": "users_unique_email_index", + "keys": [ + { + "type": "atom", + "value": "email" + } + ], + "name": "unique_email", + "nils_distinct?": true, + "where": null + } + ], + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "repo": "Elixir.DecentralisedBookIndex.Repo", + "schema": null, + "table": "users" +} \ No newline at end of file diff --git a/test/decentralised_book_index/accounts/role_test.exs b/test/decentralised_book_index/accounts/role_test.exs new file mode 100644 index 0000000..76d5a9d --- /dev/null +++ b/test/decentralised_book_index/accounts/role_test.exs @@ -0,0 +1,31 @@ +defmodule DecentralisedBookIndex.Accounts.RoleTest do + use ExUnit.Case, async: true + + alias DecentralisedBookIndex.Accounts.Role + + @user :user + @moderator :moderator + @admin :admin + + describe "can_moderate?" do + test "user can't moderate" do + refute Role.can_moderate?(@user) + end + + test "moderator and admin can moderate" do + assert Role.can_moderate?(@moderator) + assert Role.can_moderate?(@admin) + end + end + + describe "can_administrate?" do + test "user and moderator can't administrate" do + refute Role.can_administrate?(@user) + refute Role.can_administrate?(@moderator) + end + + test "admin can administrate" do + assert Role.can_administrate?(@admin) + end + end +end