diff --git a/lib/kmxgit/repository_manager.ex b/lib/kmxgit/repository_manager.ex
index c1f8159..5ff2673 100644
--- a/lib/kmxgit/repository_manager.ex
+++ b/lib/kmxgit/repository_manager.ex
@@ -6,6 +6,7 @@ defmodule Kmxgit.RepositoryManager do
alias Kmxgit.Repo
alias Kmxgit.RepositoryManager.Repository
alias Kmxgit.SlugManager.Slug
+ alias Kmxgit.UserManager
alias Kmxgit.UserManager.User
def list_repositories do
@@ -66,7 +67,33 @@ defmodule Kmxgit.RepositoryManager do
user: :slug]
end
- def delete_repository(%Repository{} = repository) do
- Repo.delete(repository)
+ def add_member(%Repository{} = repo, login) do
+ user = UserManager.get_user_by_slug(login)
+ if user do
+ members = [user | repo.members]
+ repo
+ |> Repository.changeset(%{})
+ |> Ecto.Changeset.put_assoc(:members, members)
+ |> Repo.update()
+ else
+ {:error, :not_found}
+ end
+ end
+
+ def remove_member(%Repository{} = repo, login) do
+ user = UserManager.get_user_by_slug(login)
+ if user do
+ members = Enum.reject(repo.members, &(&1.id == user.id))
+ repo
+ |> Repository.changeset(%{})
+ |> Ecto.Changeset.put_assoc(:members, members)
+ |> Repo.update()
+ else
+ {:error, :not_found}
+ end
+ end
+
+ def delete_repository(%Repository{} = repo) do
+ Repo.delete(repo)
end
end
diff --git a/lib/kmxgit/repository_manager/repository.ex b/lib/kmxgit/repository_manager/repository.ex
index ded6b49..cdfa9c8 100644
--- a/lib/kmxgit/repository_manager/repository.ex
+++ b/lib/kmxgit/repository_manager/repository.ex
@@ -11,7 +11,7 @@ defmodule Kmxgit.RepositoryManager.Repository do
belongs_to :organisation, Organisation
field :slug, :string, unique: true
belongs_to :user, User
- many_to_many :members, User, join_through: "users_repositories"
+ many_to_many :members, User, join_through: "users_repositories", on_replace: :delete
timestamps()
end
diff --git a/lib/kmxgit/user_manager.ex b/lib/kmxgit/user_manager.ex
index fdc3228..ab8321a 100644
--- a/lib/kmxgit/user_manager.ex
+++ b/lib/kmxgit/user_manager.ex
@@ -36,12 +36,13 @@ defmodule Kmxgit.UserManager do
def get_user_by_slug(slug) do
Repo.one from u in User,
join: s in Slug,
- on: s.id == u.slug_id,
+ on: s.user_id == u.id,
where: fragment("lower(?)", s.slug) == ^String.downcase(slug),
limit: 1,
preload: [:slug,
organisations: :slug,
- owned_repositories: [organisation: :slug, user: :slug]]
+ owned_repositories: [organisation: :slug,
+ user: :slug]]
end
def create_user(attrs \\ %{}) do
diff --git a/lib/kmxgit_web/controllers/repository_controller.ex b/lib/kmxgit_web/controllers/repository_controller.ex
index 306405e..8aa674b 100644
--- a/lib/kmxgit_web/controllers/repository_controller.ex
+++ b/lib/kmxgit_web/controllers/repository_controller.ex
@@ -97,11 +97,13 @@ defmodule KmxgitWeb.RepositoryController do
repo = RepositoryManager.get_repository_by_owner_and_slug(params["owner"], slug)
if repo do
org = repo.organisation
+ user = repo.user
conn
|> assign_current_organisation(org)
|> assign(:current_repository, repo)
|> assign(:repo, repo)
|> assign(:members, Repository.members(repo))
+ |> assign(:owner, org || user)
|> render("show.html")
else
not_found(conn)
@@ -158,6 +160,104 @@ defmodule KmxgitWeb.RepositoryController do
end
end
+ def add_user(conn, params) do
+ current_user = conn.assigns.current_user
+ slug = Enum.join(params["slug"], "/")
+ repo = RepositoryManager.get_repository_by_owner_and_slug(params["owner"], slug)
+ 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)
+ |> render("add_user.html")
+ else
+ not_found(conn)
+ end
+ else
+ not_found(conn)
+ end
+ end
+
+ def add_user_post(conn, params) do
+ current_user = conn.assigns.current_user
+ login = params["repository"]["login"]
+ slug = Enum.join(params["slug"], "/")
+ repo = RepositoryManager.get_repository_by_owner_and_slug(params["owner"], slug)
+ if repo do
+ org = repo.organisation
+ if org && Enum.find(org.users, &(&1.id == current_user.id)) || repo.user_id == current_user.id do
+ case RepositoryManager.add_member(repo, login) do
+ {:ok, repo} ->
+ conn
+ |> redirect(to: Routes.repository_path(conn, :show, params["owner"], Repository.splat(repo)))
+ {:error, _} ->
+ conn
+ |> assign(:action, Routes.repository_path(conn, :add_user_post, params["owner"], Repository.splat(repo)))
+ |> assign_current_organisation(org)
+ |> assign(:current_repository, repo)
+ |> assign(:repo, repo)
+ |> render("add_user.html")
+ end
+ end
+ else
+ not_found(conn)
+ end
+ end
+
+ def remove_user(conn, params) do
+ current_user = conn.assigns.current_user
+ slug = Enum.join(params["slug"], "/")
+ repo = RepositoryManager.get_repository_by_owner_and_slug(params["owner"], slug)
+ 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)
+ |> render("remove_user.html")
+ else
+ not_found(conn)
+ end
+ else
+ not_found(conn)
+ end
+ end
+
+ def remove_user_post(conn, params) do
+ current_user = conn.assigns.current_user
+ login = params["repository"]["login"]
+ slug = Enum.join(params["slug"], "/")
+ repo = RepositoryManager.get_repository_by_owner_and_slug(params["owner"], slug)
+ if repo do
+ org = repo.organisation
+ if org && Enum.find(org.users, &(&1.id == current_user.id)) || repo.user_id == current_user.id do
+ case RepositoryManager.remove_member(repo, login) do
+ {:ok, repo} ->
+ conn
+ |> redirect(to: Routes.repository_path(conn, :show, params["owner"], Repository.splat(repo)))
+ {:error, _} ->
+ conn
+ |> assign(:action, Routes.repository_path(conn, :remove_user_post, params["owner"], Repository.splat(repo)))
+ |> assign_current_organisation(org)
+ |> assign(:current_repository, repo)
+ |> assign(:repo, repo)
+ |> render("remove_user.html")
+ end
+ end
+ else
+ not_found(conn)
+ end
+ end
+
def delete(conn, params) do
current_user = conn.assigns.current_user
slug = Enum.join(params["slug"], "/")
diff --git a/lib/kmxgit_web/router.ex b/lib/kmxgit_web/router.ex
index e4b0b3e..ac9c3e9 100644
--- a/lib/kmxgit_web/router.ex
+++ b/lib/kmxgit_web/router.ex
@@ -67,6 +67,16 @@ defmodule KmxgitWeb.Router do
put "/:owner/*slug", RepositoryController, :update
end
+ scope "/_add_user/" do
+ get "/:owner/*slug", RepositoryController, :add_user
+ post "/:owner/*slug", RepositoryController, :add_user_post
+ end
+
+ scope "/_remove_user/" do
+ get "/:owner/*slug", RepositoryController, :remove_user
+ post "/:owner/*slug", RepositoryController, :remove_user_post
+ end
+
scope "/admin", Admin, as: "admin" do
pipe_through :admin
get "/", DashboardController, :index
diff --git a/lib/kmxgit_web/templates/repository/add_user.html.heex b/lib/kmxgit_web/templates/repository/add_user.html.heex
new file mode 100644
index 0000000..557ea9d
--- /dev/null
+++ b/lib/kmxgit_web/templates/repository/add_user.html.heex
@@ -0,0 +1,17 @@
+<div class="container-fluid">
+
+ <h1><%= gettext "Add user to %{repo}", repo: Repository.full_slug(@repo) %></h1>
+
+ <%= form_for :repository, @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/repository/remove_user.html.heex b/lib/kmxgit_web/templates/repository/remove_user.html.heex
new file mode 100644
index 0000000..6b7a494
--- /dev/null
+++ b/lib/kmxgit_web/templates/repository/remove_user.html.heex
@@ -0,0 +1,17 @@
+<div class="container-fluid">
+
+ <h1><%= gettext "Remove user from %{repo}", repo: Repository.full_slug(@repo) %></h1>
+
+ <%= form_for :repository, @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/repository/show.html.heex b/lib/kmxgit_web/templates/repository/show.html.heex
index 5422a28..4e3f81b 100644
--- a/lib/kmxgit_web/templates/repository/show.html.heex
+++ b/lib/kmxgit_web/templates/repository/show.html.heex
@@ -33,6 +33,12 @@
<%= for user <- @members do %>
<%= link user.slug.slug, to: Routes.slug_path(@conn, :show, user.slug.slug) %>
<% end %>
+ <%= link "-",
+ to: Routes.repository_path(@conn, :remove_user, @owner.slug.slug, Repository.splat(@repo)),
+ class: "btn btn-danger btn-sm" %>
+ <%= link "+",
+ to: Routes.repository_path(@conn, :add_user, @owner.slug.slug, Repository.splat(@repo)),
+ class: "btn btn-primary btn-sm" %>
</td>
</tr>
</table>
diff --git a/lib/kmxgit_web/templates/user/show.html.heex b/lib/kmxgit_web/templates/user/show.html.heex
index 671846a..7d955ed 100644
--- a/lib/kmxgit_web/templates/user/show.html.heex
+++ b/lib/kmxgit_web/templates/user/show.html.heex
@@ -54,7 +54,7 @@
<%= link(org.name || org.slug.slug, to: Routes.slug_path(@conn, :show, org.slug.slug), class: "org") %>
<% end %>
<%= if @user == @current_user do %>
- <%= link("+", to: Routes.organisation_path(@conn, :new), class: "btn btn-primary") %>
+ <%= link("+", to: Routes.organisation_path(@conn, :new), class: "btn btn-primary btn-sm") %>
<% end %>
</td>
</tr>