Commit 94e8a7bd83750219dbb446e1658ca73631ad652d

Thomas de Grivel 2021-11-21T20:31:49

add and remove users from organisation

diff --git a/lib/kmxgit/organisation_manager.ex b/lib/kmxgit/organisation_manager.ex
index 9d320f6..f47db9b 100644
--- a/lib/kmxgit/organisation_manager.ex
+++ b/lib/kmxgit/organisation_manager.ex
@@ -5,6 +5,7 @@ defmodule Kmxgit.OrganisationManager do
   alias Kmxgit.OrganisationManager.Organisation
   alias Kmxgit.Repo
   alias Kmxgit.SlugManager.Slug
+  alias Kmxgit.UserManager
 
   def list_organisations do
     Repo.all from org in Organisation, preload: :slug
@@ -47,6 +48,32 @@ defmodule Kmxgit.OrganisationManager do
       limit: 1
   end
 
+  def add_user(%Organisation{} = org, login) do
+    user = UserManager.get_user_by_slug(login)
+    if user do
+      users = [user | org.users]
+      org
+      |> Organisation.changeset(%{})
+      |> Ecto.Changeset.put_assoc(:users, users)
+      |> Repo.update()
+    else
+      {:error, :not_found}
+    end
+  end
+
+  def remove_user(%Organisation{} = org, login) do
+    user = UserManager.get_user_by_slug(login)
+    if user do
+      users = Enum.reject(org.users, &(&1.id == user.id))
+      org
+      |> Organisation.changeset(%{})
+      |> Ecto.Changeset.put_assoc(:users, users)
+      |> Repo.update()
+    else
+      {:error, :not_found}
+    end
+  end
+
   def delete_organisation(%Organisation{} = organisation) do
     Repo.delete(organisation)
   end
diff --git a/lib/kmxgit/organisation_manager/organisation.ex b/lib/kmxgit/organisation_manager/organisation.ex
index dfc0cb3..eb255e1 100644
--- a/lib/kmxgit/organisation_manager/organisation.ex
+++ b/lib/kmxgit/organisation_manager/organisation.ex
@@ -11,7 +11,7 @@ defmodule Kmxgit.OrganisationManager.Organisation do
     field :description, :string
     field :name, :string
     has_many :owned_repositories, Repository
-    many_to_many :users, User, join_through: "users_organisations", on_delete: :delete_all
+    many_to_many :users, User, join_through: "users_organisations", on_delete: :delete_all, on_replace: :delete
     has_one :slug, Slug, on_delete: :delete_all
     timestamps()
   end
diff --git a/lib/kmxgit_web/controllers/organisation_controller.ex b/lib/kmxgit_web/controllers/organisation_controller.ex
index e7ab9c6..494cbd3 100644
--- a/lib/kmxgit_web/controllers/organisation_controller.ex
+++ b/lib/kmxgit_web/controllers/organisation_controller.ex
@@ -77,4 +77,70 @@ defmodule KmxgitWeb.OrganisationController do
       not_found(conn)
     end
   end
+
+  def add_user(conn, params) do
+    current_user = conn.assigns.current_user
+    org = OrganisationManager.get_organisation_by_slug(params["slug"])
+    if org && Enum.find(org.users, &(&1.id == current_user.id)) do
+      conn
+      |> assign(:action, Routes.organisation_path(conn, :add_user_post, params["slug"]))
+      |> assign(:current_organisation, org)
+      |> render("add_user.html")
+    else
+      not_found(conn)
+    end
+  end
+
+  def add_user_post(conn, params) do
+    current_user = conn.assigns.current_user
+    login = params["organisation"]["login"]
+    org = OrganisationManager.get_organisation_by_slug(params["slug"])
+    if org && Enum.find(org.users, &(&1.id == current_user.id)) do
+      case OrganisationManager.add_user(org, login) do
+        {:ok, org} ->
+          conn
+          |> redirect(to: Routes.slug_path(conn, :show, org.slug.slug))
+        {:error, _} ->
+          conn
+          |> assign(:action, Routes.organisation_path(conn, :add_user_post, params["slug"]))
+          |> assign(:current_organisation, org)
+          |> render("add_user.html")
+      end
+    else
+      not_found(conn)
+    end
+  end
+
+  def remove_user(conn, params) do
+    current_user = conn.assigns.current_user
+    org = OrganisationManager.get_organisation_by_slug(params["slug"])
+    if org && Enum.find(org.users, &(&1.id == current_user.id)) do
+      conn
+      |> assign(:action, Routes.organisation_path(conn, :remove_user_post, params["slug"]))
+      |> assign(:current_organisation, org)
+      |> render("remove_user.html")
+    else
+      not_found(conn)
+    end
+  end
+
+  def remove_user_post(conn, params) do
+    current_user = conn.assigns.current_user
+    login = params["organisation"]["login"]
+    org = OrganisationManager.get_organisation_by_slug(params["slug"])
+    if org && Enum.find(org.users, &(&1.id == current_user.id)) do
+      case OrganisationManager.remove_user(org, login) do
+        {:ok, org} ->
+          conn
+          |> redirect(to: Routes.slug_path(conn, :show, org.slug.slug))
+        {:error, _} ->
+          conn
+          |> assign(:action, Routes.organisation_path(conn, :remove_user_post, params["slug"]))
+          |> assign(:current_organisation, org)
+          |> render("remove_user.html")
+      end
+    else
+      not_found(conn)
+    end
+  end
 end
diff --git a/lib/kmxgit_web/controllers/repository_controller.ex b/lib/kmxgit_web/controllers/repository_controller.ex
index 8aa674b..ea90d9b 100644
--- a/lib/kmxgit_web/controllers/repository_controller.ex
+++ b/lib/kmxgit_web/controllers/repository_controller.ex
@@ -167,10 +167,8 @@ defmodule KmxgitWeb.RepositoryController do
     if repo do
       org = repo.organisation
       if org && Enum.find(org.users, &(&1.id == current_user.id)) || repo.user_id == current_user.id do
-        changeset = RepositoryManager.change_repository(repo)
         conn
         |> assign(:action, Routes.repository_path(conn, :add_user_post, params["owner"], Repository.splat(repo)))
-        |> assign(:changeset, changeset)
         |> assign_current_organisation(org)
         |> assign(:current_repository, repo)
         |> assign(:repo, repo)
@@ -216,10 +214,8 @@ defmodule KmxgitWeb.RepositoryController do
     if repo do
       org = repo.organisation
       if org && Enum.find(org.users, &(&1.id == current_user.id)) || repo.user_id == current_user.id do
-        changeset = RepositoryManager.change_repository(repo)
         conn
         |> assign(:action, Routes.repository_path(conn, :remove_user_post, params["owner"], Repository.splat(repo)))
-        |> assign(:changeset, changeset)
         |> assign_current_organisation(org)
         |> assign(:current_repository, repo)
         |> assign(:repo, repo)
diff --git a/lib/kmxgit_web/router.ex b/lib/kmxgit_web/router.ex
index ac9c3e9..3496dab 100644
--- a/lib/kmxgit_web/router.ex
+++ b/lib/kmxgit_web/router.ex
@@ -68,11 +68,15 @@ defmodule KmxgitWeb.Router do
     end
 
     scope "/_add_user/" do
+      get  "/:slug", OrganisationController, :add_user
+      post "/:slug", OrganisationController, :add_user_post
       get  "/:owner/*slug", RepositoryController, :add_user
       post "/:owner/*slug", RepositoryController, :add_user_post
     end
 
     scope "/_remove_user/" do
+      get  "/:slug", OrganisationController, :remove_user
+      post "/:slug", OrganisationController, :remove_user_post
       get  "/:owner/*slug", RepositoryController, :remove_user
       post "/:owner/*slug", RepositoryController, :remove_user_post
     end
diff --git a/lib/kmxgit_web/templates/organisation/add_user.html.heex b/lib/kmxgit_web/templates/organisation/add_user.html.heex
new file mode 100644
index 0000000..4694f90
--- /dev/null
+++ b/lib/kmxgit_web/templates/organisation/add_user.html.heex
@@ -0,0 +1,17 @@
+<div class="container-fluid">
+
+  <h1><%= gettext "Add user to %{org}", org: @current_organisation.name || @current_organisation.slug.slug %></h1>
+
+  <%= form_for :organisation, @action, fn f -> %>
+
+    <div class="mb-3">
+      <%= label f, :login, class: "form-label" %>
+      <%= text_input f, :login, class: "form=control" %>
+    </div>
+
+    <div class="mb-3">
+      <%= submit gettext("Submit"), class: "btn btn-primary" %>
+    </div>
+
+  <% end %>
+</div>
diff --git a/lib/kmxgit_web/templates/organisation/remove_user.html.heex b/lib/kmxgit_web/templates/organisation/remove_user.html.heex
new file mode 100644
index 0000000..47e3321
--- /dev/null
+++ b/lib/kmxgit_web/templates/organisation/remove_user.html.heex
@@ -0,0 +1,17 @@
+<div class="container-fluid">
+
+  <h1><%= gettext "Remove user from %{org}", org: @current_organisation.name || @current_organisation.slug.slug %></h1>
+
+  <%= form_for :organisation, @action, fn f -> %>
+
+    <div class="mb-3">
+      <%= label f, :login, class: "form-label" %>
+      <%= text_input f, :login, class: "form=control" %>
+    </div>
+
+    <div class="mb-3">
+      <%= submit gettext("Submit"), class: "btn btn-primary" %>
+    </div>
+
+  <% end %>
+</div>
diff --git a/lib/kmxgit_web/templates/organisation/show.html.heex b/lib/kmxgit_web/templates/organisation/show.html.heex
index b9a23f0..6288719 100644
--- a/lib/kmxgit_web/templates/organisation/show.html.heex
+++ b/lib/kmxgit_web/templates/organisation/show.html.heex
@@ -48,6 +48,14 @@
             <%= for user <- @org.users do %>
               <%= link(user.slug.slug, to: Routes.slug_path(@conn, :show, user.slug.slug), class: "user") %>
             <% end %>
+            <%= if Enum.find(@org.users, &(&1.id == @current_user.id)) do %>
+              <%= link "-",
+                  to: Routes.organisation_path(@conn, :remove_user, @org.slug.slug),
+                  class: "btn btn-danger btn-sm" %>
+              <%= link "+",
+                  to: Routes.organisation_path(@conn, :add_user, @org.slug.slug),
+                  class: "btn btn-primary btn-sm" %>
+            <% end %>
           </td>
         </tr>
       </table>