From 5147d191d5941da7219c1eca6910c6f908df87bb Mon Sep 17 00:00:00 2001 From: Jannik Streek Date: Mon, 18 Nov 2024 15:23:44 +0100 Subject: [PATCH 1/3] started change for admin users --- assets/js/app.js | 2 +- lib/mindwendel/accounts.ex | 42 +++++++++++++++++-- lib/mindwendel/brainstormings.ex | 7 ---- .../brainstormings/brainstorming.ex | 2 +- .../brainstorming_moderating_user.ex | 23 ---------- lib/mindwendel_web/channels/user_socket.ex | 35 ---------------- lib/mindwendel_web/endpoint.ex | 6 +-- .../live/brainstorming_live/show.ex | 9 ++-- lib/mindwendel_web/live/live_helpers.ex | 1 + test/mindwendel/accounts_test.exs | 33 +++++++++++++++ test/mindwendel/brainstormings_test.exs | 34 +-------------- .../show_idea_comment_test.exs | 2 +- .../show_idea_delete_test.exs | 2 +- .../show_idea_edit_test.exs | 8 ++-- .../show_sort_by_label_test.exs | 2 +- .../live/brainstorming_live_test.exs | 10 ++--- 16 files changed, 97 insertions(+), 121 deletions(-) delete mode 100644 lib/mindwendel/brainstormings/brainstorming_moderating_user.ex delete mode 100644 lib/mindwendel_web/channels/user_socket.ex diff --git a/assets/js/app.js b/assets/js/app.js index bf4af30f..5d976101 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -139,7 +139,7 @@ Hooks.SetIdeaLabelBackgroundColor = { }; let liveSocket = new LiveSocket("/live", Socket, { - hooks: Hooks, params: { _csrf_token: csrfToken } + hooks: Hooks, params: { _csrf_token: csrfToken, adminSecret: location.hash.substring(1) } }) // Show progress bar on live navigation and form submits diff --git a/lib/mindwendel/accounts.ex b/lib/mindwendel/accounts.ex index 6a28459f..cfb56977 100644 --- a/lib/mindwendel/accounts.ex +++ b/lib/mindwendel/accounts.ex @@ -2,7 +2,9 @@ defmodule Mindwendel.Accounts do import Ecto.Query, warn: false alias Mindwendel.Repo alias Mindwendel.Accounts.User + alias Mindwendel.Brainstormings alias Mindwendel.Brainstormings.Brainstorming + alias Mindwendel.Accounts.BrainstormingModeratingUser require Logger @@ -70,6 +72,43 @@ defmodule Mindwendel.Accounts do |> Repo.update() end + @doc """ + Adds a user as moderating user to a brainstorming. + + ## Examples + + iex> add_moderating_user(brainstorming, user) + %Brainstorming{} + + """ + def add_moderating_user(%Brainstorming{} = brainstorming, %User{} = user) do + unless user.id in Enum.map(brainstorming.users, fn e -> e.id end) do + moderating_user_result = + %BrainstormingModeratingUser{brainstorming_id: brainstorming.id, user_id: user.id} + |> BrainstormingModeratingUser.changeset() + |> Repo.insert() + + case moderating_user_result do + # reload brainstorming + {:ok, _} -> Brainstormings.get_brainstorming!(brainstorming.id) + {:error, _} -> brainstorming + end + else + brainstorming + end + end + + def add_moderating_user(%Brainstorming{} = brainstorming, user_id) when is_binary(user_id) do + case Ecto.UUID.dump(user_id) do + :error -> brainstorming + {:ok, _} -> add_moderating_user(brainstorming, get_or_create_user(user_id)) + end + end + + def add_moderating_user(%Brainstorming{} = brainstorming, user_id) when is_nil(user_id) do + brainstorming + end + @doc """ Connects user to a brainstorm. @@ -80,9 +119,6 @@ defmodule Mindwendel.Accounts do iex> merge_brainstorming_user(brainstorming, user) %Brainstorming{} - iex> update_user(user, %{field: bad_value}) - {:error, %Ecto.Changeset{}} - """ def merge_brainstorming_user(%Brainstorming{} = brainstorming, %User{} = user) do # credo:disable-for-next-line diff --git a/lib/mindwendel/brainstormings.ex b/lib/mindwendel/brainstormings.ex index 642778e8..2e818caf 100644 --- a/lib/mindwendel/brainstormings.ex +++ b/lib/mindwendel/brainstormings.ex @@ -13,7 +13,6 @@ defmodule Mindwendel.Brainstormings do alias Mindwendel.Lanes alias Mindwendel.Ideas alias Mindwendel.Brainstormings.Brainstorming - alias Mindwendel.Brainstormings.BrainstormingModeratingUser require Logger @@ -36,12 +35,6 @@ defmodule Mindwendel.Brainstormings do ) end - def add_moderating_user(%Brainstorming{} = brainstorming, %User{} = user) do - %BrainstormingModeratingUser{brainstorming_id: brainstorming.id, user_id: user.id} - |> BrainstormingModeratingUser.changeset() - |> Repo.insert() - end - @doc """ Returns the list of brainstormings. diff --git a/lib/mindwendel/brainstormings/brainstorming.ex b/lib/mindwendel/brainstormings/brainstorming.ex index 80ee5152..97a41e5e 100644 --- a/lib/mindwendel/brainstormings/brainstorming.ex +++ b/lib/mindwendel/brainstormings/brainstorming.ex @@ -6,7 +6,7 @@ defmodule Mindwendel.Brainstormings.Brainstorming do alias Mindwendel.Brainstormings.Idea alias Mindwendel.Brainstormings.IdeaLabel alias Mindwendel.Brainstormings.Lane - alias Mindwendel.Brainstormings.BrainstormingModeratingUser + alias Mindwendel.Accounts.BrainstormingModeratingUser alias Mindwendel.Accounts.User alias Mindwendel.Accounts.BrainstormingUser diff --git a/lib/mindwendel/brainstormings/brainstorming_moderating_user.ex b/lib/mindwendel/brainstormings/brainstorming_moderating_user.ex deleted file mode 100644 index c36f204f..00000000 --- a/lib/mindwendel/brainstormings/brainstorming_moderating_user.ex +++ /dev/null @@ -1,23 +0,0 @@ -defmodule Mindwendel.Brainstormings.BrainstormingModeratingUser do - # Not using Mindwendel.Schema as the `@derive` in there clashes here - use Ecto.Schema - alias Mindwendel.Brainstormings.Brainstorming - alias Mindwendel.Accounts.User - - @primary_key false - schema "brainstorming_moderating_users" do - belongs_to :brainstorming, Brainstorming, type: :binary_id - belongs_to :user, User, type: :binary_id - - timestamps() - end - - def changeset(%__MODULE__{} = brainstorming_moderating_user) do - brainstorming_moderating_user - |> Ecto.Changeset.cast(%{}, [:brainstorming_id, :user_id]) - |> Ecto.Changeset.validate_required([:brainstorming_id, :user_id]) - |> Ecto.Changeset.unique_constraint([:brainstorming_id, :user_id], - name: :brainstorming_moderating_users_pkey - ) - end -end diff --git a/lib/mindwendel_web/channels/user_socket.ex b/lib/mindwendel_web/channels/user_socket.ex deleted file mode 100644 index 22ec171d..00000000 --- a/lib/mindwendel_web/channels/user_socket.ex +++ /dev/null @@ -1,35 +0,0 @@ -defmodule MindwendelWeb.UserSocket do - use Phoenix.Socket - - ## Channels - # channel "room:*", MindwendelWeb.RoomChannel - - # Socket params are passed from the client and can - # be used to verify and authenticate a user. After - # verification, you can put default assigns into - # the socket that will be set for all channels, ie - # - # {:ok, assign(socket, :user_id, verified_user_id)} - # - # To deny connection, return `:error`. - # - # See `Phoenix.Token` documentation for examples in - # performing token verification on connect. - @impl true - def connect(_params, socket, _connect_info) do - {:ok, socket} - end - - # Socket id's are topics that allow you to identify all sockets for a given user: - # - # def id(socket), do: "user_socket:#{socket.assigns.user_id}" - # - # Would allow you to broadcast a "disconnect" event and terminate - # all active sockets and channels for a given user: - # - # MindwendelWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{}) - # - # Returning `nil` makes this socket anonymous. - @impl true - def id(_socket), do: nil -end diff --git a/lib/mindwendel_web/endpoint.ex b/lib/mindwendel_web/endpoint.ex index 0dae0719..6755245a 100644 --- a/lib/mindwendel_web/endpoint.ex +++ b/lib/mindwendel_web/endpoint.ex @@ -10,9 +10,9 @@ defmodule MindwendelWeb.Endpoint do signing_salt: "Kxo5qCGx" ] - socket "/socket", MindwendelWeb.UserSocket, - websocket: true, - longpoll: false + # socket "/socket", MindwendelWeb.UserSocket, + # websocket: true, + # longpoll: false socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]] diff --git a/lib/mindwendel_web/live/brainstorming_live/show.ex b/lib/mindwendel_web/live/brainstorming_live/show.ex index 778b133d..b5ff9964 100644 --- a/lib/mindwendel_web/live/brainstorming_live/show.ex +++ b/lib/mindwendel_web/live/brainstorming_live/show.ex @@ -13,10 +13,13 @@ defmodule MindwendelWeb.BrainstormingLive.Show do if connected?(socket), do: Brainstormings.subscribe(id) current_user_id = Mindwendel.Services.SessionService.get_current_user_id(session) + brainstorming = Brainstormings.get_brainstorming!(id) - brainstorming = - Brainstormings.get_brainstorming!(id) - |> Accounts.merge_brainstorming_user(current_user_id) + case get_connect_params(socket)["adminSecret"] == "" do + # TODO Check the secret if valid + false -> Accounts.add_moderating_user(brainstorming, current_user_id) + true -> Accounts.merge_brainstorming_user(brainstorming, current_user_id) + end lanes = Lanes.get_lanes_for_brainstorming_with_labels_filtered(id) current_user = Mindwendel.Accounts.get_user(current_user_id) diff --git a/lib/mindwendel_web/live/live_helpers.ex b/lib/mindwendel_web/live/live_helpers.ex index 84e98c03..ff214e0b 100644 --- a/lib/mindwendel_web/live/live_helpers.ex +++ b/lib/mindwendel_web/live/live_helpers.ex @@ -9,6 +9,7 @@ defmodule MindwendelWeb.LiveHelpers do end def has_moderating_permission(brainstorming, current_user) do + IO.inspect Enum.member?(brainstorming.moderating_users |> Enum.map(& &1.id), current_user.id) Enum.member?(brainstorming.moderating_users |> Enum.map(& &1.id), current_user.id) end diff --git a/test/mindwendel/accounts_test.exs b/test/mindwendel/accounts_test.exs index a227edd4..e9a41586 100644 --- a/test/mindwendel/accounts_test.exs +++ b/test/mindwendel/accounts_test.exs @@ -4,6 +4,7 @@ defmodule Mindwendel.AccountsTest do alias Mindwendel.Accounts alias Mindwendel.Accounts.User alias Mindwendel.Accounts.BrainstormingUser + alias Mindwendel.Accounts.BrainstormingModeratingUser alias Mindwendel.Brainstormings.Brainstorming import ExUnit.CaptureLog @@ -12,6 +13,38 @@ defmodule Mindwendel.AccountsTest do %{user: Factory.insert!(:user)} end + describe "#add_moderating_user" do + test "adds a moderating user to the brainstorming", %{ + brainstorming: brainstorming, + user: %User{id: user_id} = user + } do + Accounts.add_moderating_user(brainstorming, user) + + assert 1 = Repo.one(from(bmu in BrainstormingModeratingUser, select: count(bmu.user_id))) + assert brainstorming_moderatoring_user = Repo.one(BrainstormingModeratingUser) + assert brainstorming_moderatoring_user.user_id == user.id + assert brainstorming_moderatoring_user.brainstorming_id == brainstorming.id + + brainstorming = Repo.preload(brainstorming, :moderating_users) + assert [%User{id: ^user_id}] = brainstorming.moderating_users + end + + test "responds with an error when brainstorming already contains the moderating user", %{ + brainstorming: brainstorming, + user: user + } do + Accounts.add_moderating_user(brainstorming, user) + + assert {:error, + %Ecto.Changeset{ + valid?: false, + errors: [ + brainstorming_id: {_, [{:constraint, :unique}, _]} + ] + }} = Accounts.add_moderating_user(brainstorming, user) + end + end + describe "get_or_create_user" do test "get existing user", %{user: existing_user} do user = Accounts.get_or_create_user(existing_user.id) diff --git a/test/mindwendel/brainstormings_test.exs b/test/mindwendel/brainstormings_test.exs index 18cbd413..caecf1ec 100644 --- a/test/mindwendel/brainstormings_test.exs +++ b/test/mindwendel/brainstormings_test.exs @@ -1,7 +1,7 @@ defmodule Mindwendel.BrainstormingsTest do alias Mindwendel.Brainstormings.IdeaIdeaLabel use Mindwendel.DataCase, async: true - alias Mindwendel.Brainstormings.BrainstormingModeratingUser + alias Mindwendel.Accounts.BrainstormingModeratingUser alias Mindwendel.Factory alias Mindwendel.Brainstormings @@ -56,38 +56,6 @@ defmodule Mindwendel.BrainstormingsTest do end end - describe "#add_moderating_user" do - test "adds a moderating user to the brainstorming", %{ - brainstorming: brainstorming, - user: %User{id: user_id} = user - } do - Brainstormings.add_moderating_user(brainstorming, user) - - assert 1 = Repo.one(from(bmu in BrainstormingModeratingUser, select: count(bmu.user_id))) - assert brainstorming_moderatoring_user = Repo.one(BrainstormingModeratingUser) - assert brainstorming_moderatoring_user.user_id == user.id - assert brainstorming_moderatoring_user.brainstorming_id == brainstorming.id - - brainstorming = Repo.preload(brainstorming, :moderating_users) - assert [%User{id: ^user_id}] = brainstorming.moderating_users - end - - test "responds with an error when brainstorming already contains the moderating user", %{ - brainstorming: brainstorming, - user: user - } do - Brainstormings.add_moderating_user(brainstorming, user) - - assert {:error, - %Ecto.Changeset{ - valid?: false, - errors: [ - brainstorming_id: {_, [{:constraint, :unique}, _]} - ] - }} = Brainstormings.add_moderating_user(brainstorming, user) - end - end - describe "change brainstorming" do test "shortens the brainstorming name if it is too long", %{brainstorming: brainstorming} do result = diff --git a/test/mindwendel_web/live/brainstorming_live/show_idea_comment_test.exs b/test/mindwendel_web/live/brainstorming_live/show_idea_comment_test.exs index e6051df4..9a8f5506 100644 --- a/test/mindwendel_web/live/brainstorming_live/show_idea_comment_test.exs +++ b/test/mindwendel_web/live/brainstorming_live/show_idea_comment_test.exs @@ -26,7 +26,7 @@ defmodule MindwendelWeb.BrainstormingLive.ShowIdeaCommentTest do }) moderating_user = Factory.insert!(:user) - Brainstormings.add_moderating_user(brainstorming, moderating_user) + Accounts.add_moderating_user(brainstorming, moderating_user) new_user = Factory.insert!(:user) diff --git a/test/mindwendel_web/live/brainstorming_live/show_idea_delete_test.exs b/test/mindwendel_web/live/brainstorming_live/show_idea_delete_test.exs index 17b2f763..5ae9b41c 100644 --- a/test/mindwendel_web/live/brainstorming_live/show_idea_delete_test.exs +++ b/test/mindwendel_web/live/brainstorming_live/show_idea_delete_test.exs @@ -32,7 +32,7 @@ defmodule MindwendelWeb.BrainstormingLive.ShowIdeaDeleteTest do brainstorming: brainstorming } do moderating_user = Factory.insert!(:user) - Brainstormings.add_moderating_user(brainstorming, moderating_user) + Accounts.add_moderating_user(brainstorming, moderating_user) {:ok, show_live_view, _html} = conn diff --git a/test/mindwendel_web/live/brainstorming_live/show_idea_edit_test.exs b/test/mindwendel_web/live/brainstorming_live/show_idea_edit_test.exs index 317f6b22..7780efc5 100644 --- a/test/mindwendel_web/live/brainstorming_live/show_idea_edit_test.exs +++ b/test/mindwendel_web/live/brainstorming_live/show_idea_edit_test.exs @@ -34,7 +34,7 @@ defmodule MindwendelWeb.BrainstormingLive.ShowIdeaEditTest do brainstorming: brainstorming, user: user } do - Brainstormings.add_moderating_user(brainstorming, user) + Accounts.add_moderating_user(brainstorming, user) {:ok, show_live_view, _html} = live(conn, ~p"/brainstormings/#{brainstorming.id}") assert show_live_view @@ -75,7 +75,7 @@ defmodule MindwendelWeb.BrainstormingLive.ShowIdeaEditTest do idea: idea, user: user } do - Brainstormings.add_moderating_user(brainstorming, user) + Accounts.add_moderating_user(brainstorming, user) {:ok, show_live_view, _html} = live(conn, ~p"/brainstormings/#{brainstorming.id}") @@ -114,7 +114,7 @@ defmodule MindwendelWeb.BrainstormingLive.ShowIdeaEditTest do idea: idea } do moderatoring_user = Factory.insert!(:user) - Brainstormings.add_moderating_user(brainstorming, moderatoring_user) + Accounts.add_moderating_user(brainstorming, moderatoring_user) {:ok, show_live_view, _html} = conn @@ -141,7 +141,7 @@ defmodule MindwendelWeb.BrainstormingLive.ShowIdeaEditTest do user: %User{id: user_id} } do moderator_user = Factory.insert!(:user) - Brainstormings.add_moderating_user(brainstorming, moderator_user) + Accounts.add_moderating_user(brainstorming, moderator_user) {:ok, show_live_view, _html} = conn diff --git a/test/mindwendel_web/live/brainstorming_live/show_sort_by_label_test.exs b/test/mindwendel_web/live/brainstorming_live/show_sort_by_label_test.exs index 5c95dad0..531771b6 100644 --- a/test/mindwendel_web/live/brainstorming_live/show_sort_by_label_test.exs +++ b/test/mindwendel_web/live/brainstorming_live/show_sort_by_label_test.exs @@ -8,7 +8,7 @@ defmodule MindwendelWeb.BrainstormingLive.ShowSortByLabelTest do setup do moderating_user = Factory.insert!(:user) brainstorming = Factory.insert!(:brainstorming) - Brainstormings.add_moderating_user(brainstorming, moderating_user) + Accounts.add_moderating_user(brainstorming, moderating_user) %{brainstorming: brainstorming, moderating_user: moderating_user} end diff --git a/test/mindwendel_web/live/brainstorming_live_test.exs b/test/mindwendel_web/live/brainstorming_live_test.exs index f41ee26d..3de44a7b 100644 --- a/test/mindwendel_web/live/brainstorming_live_test.exs +++ b/test/mindwendel_web/live/brainstorming_live_test.exs @@ -149,7 +149,7 @@ defmodule MindwendelWeb.BrainstormingLiveTest do test "enables dragging for admin", %{conn: conn, brainstorming: brainstorming, lane: lane} do moderating_user = List.first(brainstorming.users) - Brainstormings.add_moderating_user(brainstorming, moderating_user) + Accounts.add_moderating_user(brainstorming, moderating_user) {:ok, view, _html} = conn @@ -191,7 +191,7 @@ defmodule MindwendelWeb.BrainstormingLiveTest do brainstorming: brainstorming } do moderating_user = List.first(brainstorming.users) - Brainstormings.add_moderating_user(brainstorming, moderating_user) + Accounts.add_moderating_user(brainstorming, moderating_user) {:ok, view, _html} = conn @@ -241,7 +241,7 @@ defmodule MindwendelWeb.BrainstormingLiveTest do brainstorming: brainstorming } do moderating_user = List.first(brainstorming.users) - Brainstormings.add_moderating_user(brainstorming, moderating_user) + Accounts.add_moderating_user(brainstorming, moderating_user) {:ok, view, _html} = conn @@ -257,7 +257,7 @@ defmodule MindwendelWeb.BrainstormingLiveTest do lane: lane } do moderating_user = List.first(brainstorming.users) - Brainstormings.add_moderating_user(brainstorming, moderating_user) + Accounts.add_moderating_user(brainstorming, moderating_user) {:ok, view, _html} = conn @@ -289,7 +289,7 @@ defmodule MindwendelWeb.BrainstormingLiveTest do test "sets a label filter as admin", %{conn: conn, brainstorming: brainstorming} do moderating_user = List.first(brainstorming.users) - Brainstormings.add_moderating_user(brainstorming, moderating_user) + Accounts.add_moderating_user(brainstorming, moderating_user) selected_ideal_label = Enum.at(brainstorming.labels, 0) {:ok, view, _html} = From d97b0d81127246782b7dd522dc347e2d29fb8abb Mon Sep 17 00:00:00 2001 From: Jannik Streek Date: Mon, 18 Nov 2024 16:48:40 +0100 Subject: [PATCH 2/3] fix tests --- assets/js/app.js | 2 +- lib/mindwendel/accounts.ex | 18 +++------------ .../accounts/brainstorming_moderating_user.ex | 23 +++++++++++++++++++ lib/mindwendel/accounts/user.ex | 2 +- lib/mindwendel/brainstormings.ex | 4 ++++ .../live/brainstorming_live/show.ex | 11 +++++---- lib/mindwendel_web/live/live_helpers.ex | 1 - test/mindwendel/accounts_test.exs | 19 +++++++++++---- .../create_brainstorming_test.exs | 2 +- test/mindwendel/brainstormings_test.exs | 1 - .../show_idea_comment_test.exs | 2 +- .../show_idea_delete_test.exs | 3 ++- .../show_idea_edit_test.exs | 2 +- .../show_sort_by_label_test.exs | 2 +- .../live/brainstorming_live_test.exs | 1 + test/support/factory.ex | 3 ++- 16 files changed, 62 insertions(+), 34 deletions(-) create mode 100644 lib/mindwendel/accounts/brainstorming_moderating_user.ex diff --git a/assets/js/app.js b/assets/js/app.js index 5d976101..c16cca52 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -139,7 +139,7 @@ Hooks.SetIdeaLabelBackgroundColor = { }; let liveSocket = new LiveSocket("/live", Socket, { - hooks: Hooks, params: { _csrf_token: csrfToken, adminSecret: location.hash.substring(1) } + hooks: Hooks, params: { _csrf_token: csrfToken, adminSecret: window.location.hash.substring(1) } }) // Show progress bar on live navigation and form submits diff --git a/lib/mindwendel/accounts.ex b/lib/mindwendel/accounts.ex index cfb56977..57681d98 100644 --- a/lib/mindwendel/accounts.ex +++ b/lib/mindwendel/accounts.ex @@ -2,7 +2,6 @@ defmodule Mindwendel.Accounts do import Ecto.Query, warn: false alias Mindwendel.Repo alias Mindwendel.Accounts.User - alias Mindwendel.Brainstormings alias Mindwendel.Brainstormings.Brainstorming alias Mindwendel.Accounts.BrainstormingModeratingUser @@ -82,20 +81,9 @@ defmodule Mindwendel.Accounts do """ def add_moderating_user(%Brainstorming{} = brainstorming, %User{} = user) do - unless user.id in Enum.map(brainstorming.users, fn e -> e.id end) do - moderating_user_result = - %BrainstormingModeratingUser{brainstorming_id: brainstorming.id, user_id: user.id} - |> BrainstormingModeratingUser.changeset() - |> Repo.insert() - - case moderating_user_result do - # reload brainstorming - {:ok, _} -> Brainstormings.get_brainstorming!(brainstorming.id) - {:error, _} -> brainstorming - end - else - brainstorming - end + %BrainstormingModeratingUser{brainstorming_id: brainstorming.id, user_id: user.id} + |> BrainstormingModeratingUser.changeset() + |> Repo.insert() end def add_moderating_user(%Brainstorming{} = brainstorming, user_id) when is_binary(user_id) do diff --git a/lib/mindwendel/accounts/brainstorming_moderating_user.ex b/lib/mindwendel/accounts/brainstorming_moderating_user.ex new file mode 100644 index 00000000..1c37db36 --- /dev/null +++ b/lib/mindwendel/accounts/brainstorming_moderating_user.ex @@ -0,0 +1,23 @@ +defmodule Mindwendel.Accounts.BrainstormingModeratingUser do + # Not using Mindwendel.Schema as the `@derive` in there clashes here + use Ecto.Schema + alias Mindwendel.Brainstormings.Brainstorming + alias Mindwendel.Accounts.User + + @primary_key false + schema "brainstorming_moderating_users" do + belongs_to :brainstorming, Brainstorming, type: :binary_id + belongs_to :user, User, type: :binary_id + + timestamps() + end + + def changeset(%__MODULE__{} = brainstorming_moderating_user) do + brainstorming_moderating_user + |> Ecto.Changeset.cast(%{}, [:brainstorming_id, :user_id]) + |> Ecto.Changeset.validate_required([:brainstorming_id, :user_id]) + |> Ecto.Changeset.unique_constraint([:brainstorming_id, :user_id], + name: :brainstorming_moderating_users_pkey + ) + end +end diff --git a/lib/mindwendel/accounts/user.ex b/lib/mindwendel/accounts/user.ex index ea4168d4..a40ccb96 100644 --- a/lib/mindwendel/accounts/user.ex +++ b/lib/mindwendel/accounts/user.ex @@ -5,7 +5,7 @@ defmodule Mindwendel.Accounts.User do alias Mindwendel.Brainstormings.Brainstorming alias Mindwendel.Brainstormings.Idea - alias Mindwendel.Brainstormings.BrainstormingModeratingUser + alias Mindwendel.Accounts.BrainstormingModeratingUser alias Mindwendel.Accounts.BrainstormingUser schema "users" do diff --git a/lib/mindwendel/brainstormings.ex b/lib/mindwendel/brainstormings.ex index 2e818caf..db840431 100644 --- a/lib/mindwendel/brainstormings.ex +++ b/lib/mindwendel/brainstormings.ex @@ -230,6 +230,10 @@ defmodule Mindwendel.Brainstormings do brainstorming end + def validate_admin_secret(brainstorming, admin_secret_id) do + brainstorming.admin_url_id == admin_secret_id + end + @doc """ Returns a subscibe result. diff --git a/lib/mindwendel_web/live/brainstorming_live/show.ex b/lib/mindwendel_web/live/brainstorming_live/show.ex index b5ff9964..6d32e8ee 100644 --- a/lib/mindwendel_web/live/brainstorming_live/show.ex +++ b/lib/mindwendel_web/live/brainstorming_live/show.ex @@ -12,16 +12,19 @@ defmodule MindwendelWeb.BrainstormingLive.Show do def mount(%{"id" => id}, session, socket) do if connected?(socket), do: Brainstormings.subscribe(id) + # If the admin secret in the URL after the hash (only available inside the client session) is given, add the user as moderating user to the brainstorming. + # If not, add the user as normal user. current_user_id = Mindwendel.Services.SessionService.get_current_user_id(session) brainstorming = Brainstormings.get_brainstorming!(id) + admin_secret = get_connect_params(socket)["adminSecret"] - case get_connect_params(socket)["adminSecret"] == "" do - # TODO Check the secret if valid - false -> Accounts.add_moderating_user(brainstorming, current_user_id) - true -> Accounts.merge_brainstorming_user(brainstorming, current_user_id) + case Brainstormings.validate_admin_secret(brainstorming, admin_secret) do + true -> Accounts.add_moderating_user(brainstorming, current_user_id) + _ -> Accounts.merge_brainstorming_user(brainstorming, current_user_id) end lanes = Lanes.get_lanes_for_brainstorming_with_labels_filtered(id) + # load the user, also for permissions of brainstormings current_user = Mindwendel.Accounts.get_user(current_user_id) { diff --git a/lib/mindwendel_web/live/live_helpers.ex b/lib/mindwendel_web/live/live_helpers.ex index ff214e0b..84e98c03 100644 --- a/lib/mindwendel_web/live/live_helpers.ex +++ b/lib/mindwendel_web/live/live_helpers.ex @@ -9,7 +9,6 @@ defmodule MindwendelWeb.LiveHelpers do end def has_moderating_permission(brainstorming, current_user) do - IO.inspect Enum.member?(brainstorming.moderating_users |> Enum.map(& &1.id), current_user.id) Enum.member?(brainstorming.moderating_users |> Enum.map(& &1.id), current_user.id) end diff --git a/test/mindwendel/accounts_test.exs b/test/mindwendel/accounts_test.exs index e9a41586..ae0b3f52 100644 --- a/test/mindwendel/accounts_test.exs +++ b/test/mindwendel/accounts_test.exs @@ -2,6 +2,7 @@ defmodule Mindwendel.AccountsTest do use Mindwendel.DataCase, async: true alias Mindwendel.Factory alias Mindwendel.Accounts + alias Mindwendel.Brainstormings alias Mindwendel.Accounts.User alias Mindwendel.Accounts.BrainstormingUser alias Mindwendel.Accounts.BrainstormingModeratingUser @@ -10,7 +11,13 @@ defmodule Mindwendel.AccountsTest do import ExUnit.CaptureLog setup do - %{user: Factory.insert!(:user)} + user = Factory.insert!(:user) + brainstorming = Factory.insert!(:brainstorming) + + %{ + brainstorming: brainstorming, + user: user + } end describe "#add_moderating_user" do @@ -25,8 +32,8 @@ defmodule Mindwendel.AccountsTest do assert brainstorming_moderatoring_user.user_id == user.id assert brainstorming_moderatoring_user.brainstorming_id == brainstorming.id - brainstorming = Repo.preload(brainstorming, :moderating_users) - assert [%User{id: ^user_id}] = brainstorming.moderating_users + assert [%User{id: ^user_id}] = + Brainstormings.get_brainstorming!(brainstorming.id).moderating_users end test "responds with an error when brainstorming already contains the moderating user", %{ @@ -87,11 +94,13 @@ defmodule Mindwendel.AccountsTest do |> Repo.preload(:users) old_user = Factory.insert!(:user, updated_at: ~N[2021-01-01 10:00:00]) - Accounts.merge_brainstorming_user(old_brainstorming, old_user.id) + + updated_old_brainstorming = + Accounts.merge_brainstorming_user(old_brainstorming, old_user.id) %{ old_user: old_user, - old_brainstorming: old_brainstorming + old_brainstorming: updated_old_brainstorming } end diff --git a/test/mindwendel/brainstormings/create_brainstorming_test.exs b/test/mindwendel/brainstormings/create_brainstorming_test.exs index ef01512f..a1dc7c5e 100644 --- a/test/mindwendel/brainstormings/create_brainstorming_test.exs +++ b/test/mindwendel/brainstormings/create_brainstorming_test.exs @@ -1,6 +1,6 @@ defmodule Mindwendel.Brainstormings.CreateBrainstormingTest do use Mindwendel.DataCase, async: true - alias Mindwendel.Brainstormings.BrainstormingModeratingUser + alias Mindwendel.Accounts.BrainstormingModeratingUser alias Mindwendel.Accounts.BrainstormingUser alias Mindwendel.Factory diff --git a/test/mindwendel/brainstormings_test.exs b/test/mindwendel/brainstormings_test.exs index caecf1ec..8b015ab1 100644 --- a/test/mindwendel/brainstormings_test.exs +++ b/test/mindwendel/brainstormings_test.exs @@ -1,7 +1,6 @@ defmodule Mindwendel.BrainstormingsTest do alias Mindwendel.Brainstormings.IdeaIdeaLabel use Mindwendel.DataCase, async: true - alias Mindwendel.Accounts.BrainstormingModeratingUser alias Mindwendel.Factory alias Mindwendel.Brainstormings diff --git a/test/mindwendel_web/live/brainstorming_live/show_idea_comment_test.exs b/test/mindwendel_web/live/brainstorming_live/show_idea_comment_test.exs index 9a8f5506..39edee39 100644 --- a/test/mindwendel_web/live/brainstorming_live/show_idea_comment_test.exs +++ b/test/mindwendel_web/live/brainstorming_live/show_idea_comment_test.exs @@ -1,7 +1,7 @@ defmodule MindwendelWeb.BrainstormingLive.ShowIdeaCommentTest do use MindwendelWeb.ConnCase, async: true import Phoenix.LiveViewTest - alias Mindwendel.Brainstormings + alias Mindwendel.Accounts alias Mindwendel.Factory diff --git a/test/mindwendel_web/live/brainstorming_live/show_idea_delete_test.exs b/test/mindwendel_web/live/brainstorming_live/show_idea_delete_test.exs index 5ae9b41c..62c4fde1 100644 --- a/test/mindwendel_web/live/brainstorming_live/show_idea_delete_test.exs +++ b/test/mindwendel_web/live/brainstorming_live/show_idea_delete_test.exs @@ -1,7 +1,8 @@ defmodule MindwendelWeb.BrainstormingLive.ShowIdeaDeleteTest do use MindwendelWeb.ConnCase, async: true + import Phoenix.LiveViewTest - alias Mindwendel.Brainstormings + alias Mindwendel.Accounts alias Mindwendel.Factory diff --git a/test/mindwendel_web/live/brainstorming_live/show_idea_edit_test.exs b/test/mindwendel_web/live/brainstorming_live/show_idea_edit_test.exs index 7780efc5..4dffffab 100644 --- a/test/mindwendel_web/live/brainstorming_live/show_idea_edit_test.exs +++ b/test/mindwendel_web/live/brainstorming_live/show_idea_edit_test.exs @@ -1,7 +1,7 @@ defmodule MindwendelWeb.BrainstormingLive.ShowIdeaEditTest do use MindwendelWeb.ConnCase, async: true import Phoenix.LiveViewTest - alias Mindwendel.Brainstormings + alias Mindwendel.Accounts alias Mindwendel.Accounts.User alias Mindwendel.Factory diff --git a/test/mindwendel_web/live/brainstorming_live/show_sort_by_label_test.exs b/test/mindwendel_web/live/brainstorming_live/show_sort_by_label_test.exs index 531771b6..20f7f337 100644 --- a/test/mindwendel_web/live/brainstorming_live/show_sort_by_label_test.exs +++ b/test/mindwendel_web/live/brainstorming_live/show_sort_by_label_test.exs @@ -1,7 +1,7 @@ defmodule MindwendelWeb.BrainstormingLive.ShowSortByLabelTest do use MindwendelWeb.ConnCase, async: true import Phoenix.LiveViewTest - alias Mindwendel.Brainstormings + alias Mindwendel.Accounts alias Mindwendel.Factory diff --git a/test/mindwendel_web/live/brainstorming_live_test.exs b/test/mindwendel_web/live/brainstorming_live_test.exs index 3de44a7b..6d560c52 100644 --- a/test/mindwendel_web/live/brainstorming_live_test.exs +++ b/test/mindwendel_web/live/brainstorming_live_test.exs @@ -2,6 +2,7 @@ defmodule MindwendelWeb.BrainstormingLiveTest do use MindwendelWeb.ConnCase, async: true import Phoenix.LiveViewTest + alias Mindwendel.Accounts alias Mindwendel.Brainstormings alias Mindwendel.Factory alias Mindwendel.Brainstormings.Brainstorming diff --git a/test/support/factory.ex b/test/support/factory.ex index 1b42926e..50c53451 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -18,7 +18,8 @@ defmodule Mindwendel.Factory do # This can be removed as soon the todo is solved in lib/mindwendel/brainstormings/brainstorming.ex:12 admin_url_id: Ecto.UUID.generate(), labels: Brainstorming.idea_label_factory(), - lanes: [build(:lane)] + lanes: [build(:lane)], + moderating_users: [] } end From 0a5d97e457ff4be587b13b084fb74a16667321d5 Mon Sep 17 00:00:00 2001 From: Jannik Streek Date: Mon, 18 Nov 2024 17:17:57 +0100 Subject: [PATCH 3/3] fix tests and cleanup --- lib/mindwendel/accounts.ex | 2 +- lib/mindwendel_web/live/idea_live/card_component.ex | 2 +- .../live/label_live/captions_component.ex | 3 +-- lib/mindwendel_web/live/live_helpers.ex | 2 +- priv/gettext/de/LC_MESSAGES/default.po | 6 +++--- priv/gettext/default.pot | 6 +++--- priv/gettext/en/LC_MESSAGES/default.po | 6 +++--- test/mindwendel/accounts_test.exs | 2 +- .../mindwendel_web/live/label_live/captions_test.exs | 12 +++++++----- 9 files changed, 21 insertions(+), 20 deletions(-) diff --git a/lib/mindwendel/accounts.ex b/lib/mindwendel/accounts.ex index 57681d98..eadc29ba 100644 --- a/lib/mindwendel/accounts.ex +++ b/lib/mindwendel/accounts.ex @@ -48,7 +48,7 @@ defmodule Mindwendel.Accounts do end def get_user(id) do - Repo.get(User, id) |> Repo.preload(:brainstormings) + Repo.get(User, id) |> Repo.preload([:brainstormings, :moderated_brainstormings]) rescue Ecto.Query.CastError -> nil end diff --git a/lib/mindwendel_web/live/idea_live/card_component.ex b/lib/mindwendel_web/live/idea_live/card_component.ex index 19fc768b..36b468e5 100644 --- a/lib/mindwendel_web/live/idea_live/card_component.ex +++ b/lib/mindwendel_web/live/idea_live/card_component.ex @@ -10,7 +10,7 @@ defmodule MindwendelWeb.IdeaLive.CardComponent do %{current_user: current_user, brainstorming: brainstorming} = socket.assigns - if current_user.id in [idea.user_id | brainstorming.moderating_users |> Enum.map(& &1.id)] do + if has_moderating_or_ownership_permission(brainstorming, idea, current_user) do {:ok, _} = Ideas.delete_idea(idea) end diff --git a/lib/mindwendel_web/live/label_live/captions_component.ex b/lib/mindwendel_web/live/label_live/captions_component.ex index 82108e9d..ba471259 100644 --- a/lib/mindwendel_web/live/label_live/captions_component.ex +++ b/lib/mindwendel_web/live/label_live/captions_component.ex @@ -4,8 +4,7 @@ defmodule MindwendelWeb.LabelLive.CaptionsComponent do alias Mindwendel.Brainstormings def handle_event("set_filter_idea_label", %{"id" => idea_label_id}, socket) do - brainstorming = socket.assigns.brainstorming - current_user = socket.assigns.current_user + %{current_user: current_user, brainstorming: brainstorming} = socket.assigns if has_moderating_permission(brainstorming, current_user) do # If the filter is already present, remove it as its toggled. If not, add it. diff --git a/lib/mindwendel_web/live/live_helpers.ex b/lib/mindwendel_web/live/live_helpers.ex index 84e98c03..1983f1ce 100644 --- a/lib/mindwendel_web/live/live_helpers.ex +++ b/lib/mindwendel_web/live/live_helpers.ex @@ -9,7 +9,7 @@ defmodule MindwendelWeb.LiveHelpers do end def has_moderating_permission(brainstorming, current_user) do - Enum.member?(brainstorming.moderating_users |> Enum.map(& &1.id), current_user.id) + Enum.member?(current_user.moderated_brainstormings |> Enum.map(& &1.id), brainstorming.id) end def has_ownership(record, current_user) do diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po index 6fd797a0..315a3272 100644 --- a/priv/gettext/de/LC_MESSAGES/default.po +++ b/priv/gettext/de/LC_MESSAGES/default.po @@ -26,12 +26,12 @@ msgstr "Wie können wir ..." msgid "Ready?" msgstr "Fertig?" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:168 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:174 #, elixir-autogen, elixir-format msgid "%{name} - Edit" msgstr "%{name} - Editieren" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:145 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:151 #, elixir-autogen, elixir-format msgid "%{name} - New Idea" msgstr "%{name} - Neue Idee" @@ -403,7 +403,7 @@ msgstr "Löschen" msgid "Type the label name" msgstr "Gebe dem Label einen Namen" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:155 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:161 #, elixir-autogen, elixir-format, fuzzy msgid "%{name} - New Lane" msgstr "%{name} - Neue Idee" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index ce5580c0..5cfa5827 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -25,12 +25,12 @@ msgstr "" msgid "Ready?" msgstr "" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:168 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:174 #, elixir-autogen, elixir-format msgid "%{name} - Edit" msgstr "" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:145 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:151 #, elixir-autogen, elixir-format msgid "%{name} - New Idea" msgstr "" @@ -402,7 +402,7 @@ msgstr "" msgid "Type the label name" msgstr "" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:155 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:161 #, elixir-autogen, elixir-format msgid "%{name} - New Lane" msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index a490ebf3..9bab3f64 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -26,12 +26,12 @@ msgstr "" msgid "Ready?" msgstr "" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:168 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:174 #, elixir-autogen, elixir-format msgid "%{name} - Edit" msgstr "" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:145 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:151 #, elixir-autogen, elixir-format msgid "%{name} - New Idea" msgstr "" @@ -403,7 +403,7 @@ msgstr "" msgid "Type the label name" msgstr "" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:155 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:161 #, elixir-autogen, elixir-format, fuzzy msgid "%{name} - New Lane" msgstr "" diff --git a/test/mindwendel/accounts_test.exs b/test/mindwendel/accounts_test.exs index ae0b3f52..d8e067ef 100644 --- a/test/mindwendel/accounts_test.exs +++ b/test/mindwendel/accounts_test.exs @@ -71,7 +71,7 @@ defmodule Mindwendel.AccountsTest do describe "get_user" do test "returns user when it exists", %{user: existing_user} do - assert existing_user |> Repo.preload(:brainstormings) == + assert existing_user |> Repo.preload([:brainstormings, :moderated_brainstormings]) == Accounts.get_user(existing_user.id) end diff --git a/test/mindwendel_web/live/label_live/captions_test.exs b/test/mindwendel_web/live/label_live/captions_test.exs index 0a205195..21c6e5d3 100644 --- a/test/mindwendel_web/live/label_live/captions_test.exs +++ b/test/mindwendel_web/live/label_live/captions_test.exs @@ -3,6 +3,7 @@ defmodule MindwendelWeb.LabelLive.CaptionsTest do import Phoenix.LiveViewTest + alias Mindwendel.Accounts alias Mindwendel.Brainstormings alias Mindwendel.Factory @@ -16,20 +17,21 @@ defmodule MindwendelWeb.LabelLive.CaptionsTest do brainstorming: brainstorming, user: user } do - preloaded_braisntorming = Brainstormings.get_brainstorming!(brainstorming.id) + preloaded_brainstorming = Brainstormings.get_brainstorming!(brainstorming.id) + preloaded_user = Accounts.get_user(user.id) captions_component = render_component(CaptionsComponent, id: "captions", - brainstorming: preloaded_braisntorming, - current_user: user + brainstorming: preloaded_brainstorming, + current_user: preloaded_user ) # make sure that there is at least one label in the list: - assert length(preloaded_braisntorming.labels) > 0 + assert length(preloaded_brainstorming.labels) > 0 - Enum.each(brainstorming.labels, fn label -> + Enum.each(preloaded_brainstorming.labels, fn label -> assert captions_component =~ label.name end) end