diff --git a/assets/css/app.scss b/assets/css/app.scss
index 17afdec..f12356d 100644
--- a/assets/css/app.scss
+++ b/assets/css/app.scss
@@ -35,6 +35,10 @@ pre.ssh_keys {
color: blue;
}
}
+.file-content {
+ border: solid 1px #ccc;
+ padding: 1.5em;
+}
.invalid-feedback {
display: inherit;
diff --git a/lib/kmxgit/git_manager.ex b/lib/kmxgit/git_manager.ex
index af97ce7..57e1923 100644
--- a/lib/kmxgit/git_manager.ex
+++ b/lib/kmxgit/git_manager.ex
@@ -6,18 +6,9 @@ defmodule Kmxgit.GitManager do
"#{@git_root}/#{repo}.git"
end
- def status(repo) do
- dir = git_dir(repo)
- {out, status} = System.cmd("git", ["-C", dir, "status"], stderr_to_stdout: true)
- case status do
- 0 -> {:ok, out}
- _ -> {:error, out}
- end
- end
-
def branches(repo) do
dir = git_dir(repo)
- {out, status} = System.cmd("git", ["branch", "--list"], stderr_to_stdout: true)
+ {out, status} = System.cmd("git", ["-C", dir, "branch", "--list"], stderr_to_stdout: true)
case status do
0 ->
b = out
@@ -90,12 +81,30 @@ defmodule Kmxgit.GitManager do
def rename(from, to) do
dir_from = git_dir(from)
dir_to = git_dir(to)
- dir = Path.dirname(dir_to)
- :ok = File.mkdir_p(dir)
- {out, status} = System.cmd("mv", [dir_from, dir_to], stderr_to_stdout: true)
- case status do
- 0 -> {:ok, out}
- _ -> {:error, out}
+ if File.exists?(dir_to) do
+ {:error, "file exists"}
+ else
+ dir = Path.dirname(dir_to)
+ :ok = File.mkdir_p(dir)
+ {out, status} = System.cmd("mv", [dir_from, dir_to], stderr_to_stdout: true)
+ case status do
+ 0 -> :ok
+ _ -> {:error, out}
+ end
+ end
+ end
+
+ def rename_dir(from, to) do
+ dir_from = "#{@git_root}/#{from}/"
+ dir_to = "#{@git_root}/#{to}/"
+ if File.exists?(dir_to) do
+ {:error, "file exists"}
+ else
+ {out, status} = System.cmd("mv", [dir_from, dir_to], stderr_to_stdout: true)
+ case status do
+ 0 -> :ok
+ _ -> {:error, out}
+ end
end
end
@@ -110,11 +119,19 @@ defmodule Kmxgit.GitManager do
end
end
- def delete(repo) do
- dir = git_dir(repo)
+ defp rm_rf(dir) do
case System.cmd("rm", ["-rf", dir], stderr_to_stdout: true) do
{"", 0} -> :ok
{err, _} -> {:error, err}
end
end
+
+ def delete(repo) do
+ repo |> git_dir() |> rm_rf()
+ end
+
+ def delete_dir(dir) do
+ "#{@git_root}/#{dir}/"
+ |> rm_rf()
+ end
end
diff --git a/lib/kmxgit/organisation_manager.ex b/lib/kmxgit/organisation_manager.ex
index c896ffe..a19bcf8 100644
--- a/lib/kmxgit/organisation_manager.ex
+++ b/lib/kmxgit/organisation_manager.ex
@@ -86,6 +86,8 @@ defmodule Kmxgit.OrganisationManager do
end
def delete_organisation(%Organisation{} = organisation) do
- Repo.delete(organisation)
+ organisation
+ |> Organisation.changeset(%{})
+ |> Repo.delete()
end
end
diff --git a/lib/kmxgit/organisation_manager/organisation.ex b/lib/kmxgit/organisation_manager/organisation.ex
index 91acb68..e531c0c 100644
--- a/lib/kmxgit/organisation_manager/organisation.ex
+++ b/lib/kmxgit/organisation_manager/organisation.ex
@@ -23,6 +23,13 @@ defmodule Kmxgit.OrganisationManager.Organisation do
|> cast_assoc(:slug)
|> validate_required([:slug])
|> Markdown.validate_markdown(:description)
+ |> foreign_key_constraint(:owned_repositories, name: :repositories_organisation_id_fkey)
end
+ def owner?(org, user) do
+ org.users
+ |> Enum.find(fn u ->
+ u.id == user.id
+ end)
+ end
end
diff --git a/lib/kmxgit/repository_manager.ex b/lib/kmxgit/repository_manager.ex
index 3eaed38..e7d5888 100644
--- a/lib/kmxgit/repository_manager.ex
+++ b/lib/kmxgit/repository_manager.ex
@@ -14,7 +14,16 @@ defmodule Kmxgit.RepositoryManager do
preload: [members: :slug,
organisation: [:slug, users: :slug],
user: :slug])
- |> Enum.sort_by(fn x -> Repository.full_slug(x) end)
+ |> Enum.sort_by(&Repository.full_slug/1)
+ end
+
+ def list_contributor_repositories(user) do
+ list_repositories()
+ |> Enum.filter(fn repo ->
+ (!repo.user || repo.user.id != user.id) &&
+ (Repository.members(repo)
+ |> Enum.find(fn u -> u.id == user.id end))
+ end)
end
def change_repository(repository \\ %Repository{}) do
diff --git a/lib/kmxgit/repository_manager/repository.ex b/lib/kmxgit/repository_manager/repository.ex
index 0381e85..322d2ba 100644
--- a/lib/kmxgit/repository_manager/repository.ex
+++ b/lib/kmxgit/repository_manager/repository.ex
@@ -48,17 +48,35 @@ defmodule Kmxgit.RepositoryManager.Repository do
String.split(repo.slug, "/")
end
- def members(repo) do
+ def owners(repo) do
if repo.user do
- Enum.concat [repo.user], repo.members
+ [repo.user]
else
if repo.organisation do
- Enum.concat repo.organisation.users, repo.members
+ repo.organisation.users
end
end
+ end
+
+ def owner?(repo, user) do
+ repo
+ |> owners()
+ |> Enum.find(fn u -> u.id == user.id end)
+ end
+
+ def members(repo) do
+ repo
+ |> owners()
+ |> Enum.concat(repo.members)
|> Enum.uniq
end
+ def member?(repo, user) do
+ repo
+ |> members()
+ |> Enum.find(fn u -> u.id == user.id end)
+ end
+
def auth(repo) do
repo
|> members()
diff --git a/lib/kmxgit/user_manager/user.ex b/lib/kmxgit/user_manager/user.ex
index 1fdff72..d463098 100644
--- a/lib/kmxgit/user_manager/user.ex
+++ b/lib/kmxgit/user_manager/user.ex
@@ -31,8 +31,8 @@ defmodule Kmxgit.UserManager.User do
|> cast_assoc(:slug)
|> validate_required([:deploy_only, :email, :encrypted_password, :is_admin, :slug])
|> validate_format(:email, ~r/^[-_+.0-9A-Za-z]+@([-_0-9A-Za-z]+[.])+[A-Za-z]+$/)
- |> unique_constraint(:email, name: "users__lower_email_index")
|> Markdown.validate_markdown(:description)
+ |> unique_constraint(:email, name: "users__lower_email_index")
end
def changeset(user, attrs \\ %{}) do
diff --git a/lib/kmxgit_web/controllers/organisation_controller.ex b/lib/kmxgit_web/controllers/organisation_controller.ex
index 373fc9c..c7e0777 100644
--- a/lib/kmxgit_web/controllers/organisation_controller.ex
+++ b/lib/kmxgit_web/controllers/organisation_controller.ex
@@ -1,7 +1,10 @@
defmodule KmxgitWeb.OrganisationController do
use KmxgitWeb, :controller
+ alias Kmxgit.GitManager
alias Kmxgit.OrganisationManager
+ alias Kmxgit.OrganisationManager.Organisation
+ alias Kmxgit.Repo
def new(conn, _params) do
_ = conn.assigns.current_user
@@ -33,22 +36,11 @@ defmodule KmxgitWeb.OrganisationController do
|> render(:"404")
end
- def show(conn, params) do
- org = OrganisationManager.get_organisation_by_slug(params["slug"])
- if org do
- conn
- |> assign(:current_organisation, org)
- |> assign(:org, org)
- |> render("show.html")
- else
- not_found(conn)
- end
- end
-
def edit(conn, params) do
+ current_user = conn.assigns.current_user
org = OrganisationManager.get_organisation_by_slug(params["slug"])
changeset = OrganisationManager.change_organisation(org)
- if org do
+ if org && Organisation.owner?(org, current_user) do
conn
|> assign(:action, Routes.organisation_path(conn, :update, org.slug.slug))
|> assign(:changeset, changeset)
@@ -60,16 +52,31 @@ defmodule KmxgitWeb.OrganisationController do
end
def update(conn, params) do
- organisation = OrganisationManager.get_organisation_by_slug(params["slug"])
- if organisation do
- case OrganisationManager.update_organisation(organisation, params["organisation"]) do
- {:ok, org} ->
+ current_user = conn.assigns.current_user
+ org = OrganisationManager.get_organisation_by_slug(params["slug"])
+ if org && Organisation.owner?(org, current_user) do
+ case Repo.transaction(fn ->
+ case OrganisationManager.update_organisation(org, params["organisation"]) do
+ {:ok, org1} ->
+ if org.slug.slug != org1.slug.slug do
+ case GitManager.rename_dir(org.slug.slug, org1.slug.slug) do
+ :ok -> org1
+ {:error, err} -> Repo.rollback(err)
+ end
+ else
+ org1
+ end
+ {:error, changeset} -> Repo.rollback(changeset)
+ end
+ end) do
+ {:ok, org1} ->
conn
- |> redirect(to: Routes.slug_path(conn, :show, org.slug.slug))
+ |> redirect(to: Routes.slug_path(conn, :show, org1.slug.slug))
{:error, changeset} ->
conn
- |> render("edit.html", changeset: changeset,
- action: Routes.organisation_path(conn, :update, organisation.slug.slug))
+ |> assign(:action, Routes.organisation_path(conn, :update, org.slug.slug))
+ |> assign(:changeset, changeset)
+ |> render("edit.html")
end
else
not_found(conn)
@@ -79,7 +86,7 @@ defmodule KmxgitWeb.OrganisationController do
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
+ if org && Organisation.owner?(org, current_user) do
conn
|> assign(:action, Routes.organisation_path(conn, :add_user_post, params["slug"]))
|> assign(:current_organisation, org)
@@ -93,12 +100,12 @@ defmodule KmxgitWeb.OrganisationController 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
+ if org && Organisation.owner?(org, current_user) do
case OrganisationManager.add_user(org, login) do
{:ok, org} ->
conn
|> redirect(to: Routes.slug_path(conn, :show, org.slug.slug))
- {:error, e} ->
+ {:error, _e} ->
conn
|> assign(:action, Routes.organisation_path(conn, :add_user_post, params["slug"]))
|> assign(:current_organisation, org)
@@ -112,7 +119,7 @@ defmodule KmxgitWeb.OrganisationController do
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
+ if org && Organisation.owner?(org, current_user) do
conn
|> assign(:action, Routes.organisation_path(conn, :remove_user_post, params["slug"]))
|> assign(:current_organisation, org)
@@ -126,7 +133,7 @@ defmodule KmxgitWeb.OrganisationController 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
+ if org && Organisation.owner?(org, current_user) do
case OrganisationManager.remove_user(org, login) do
{:ok, org} ->
conn
@@ -141,4 +148,30 @@ defmodule KmxgitWeb.OrganisationController do
not_found(conn)
end
end
+
+ def delete(conn, params) do
+ current_user = conn.assigns.current_user
+ org = OrganisationManager.get_organisation_by_slug(params["slug"])
+ if org && Organisation.owner?(org, current_user) do
+ case Repo.transaction(fn ->
+ case OrganisationManager.delete_organisation(org) do
+ {:ok, _} ->
+ case GitManager.delete_dir(org.slug.slug) do
+ :ok -> :ok
+ {:error, out} -> Repo.rollback(status: out)
+ end
+ {:error, e} -> Repo.rollback(e)
+ end
+ end) do
+ {:ok, _} ->
+ conn
+ |> redirect(to: Routes.slug_path(conn, :show, current_user.slug.slug))
+ {:error, _} ->
+ conn
+ |> redirect(to: Routes.organisation_path(conn, :edit, org.slug.slug))
+ end
+ else
+ not_found(conn)
+ end
+ end
end
diff --git a/lib/kmxgit_web/controllers/page_controller.ex b/lib/kmxgit_web/controllers/page_controller.ex
index 5ad99e9..8c2d3ce 100644
--- a/lib/kmxgit_web/controllers/page_controller.ex
+++ b/lib/kmxgit_web/controllers/page_controller.ex
@@ -50,7 +50,7 @@ defmodule KmxgitWeb.PageController do
end
end
- def keys(conn, params) do
+ def keys(conn, _params) do
k = UserManager.list_users
|> Enum.map(fn user -> User.ssh_keys_with_env(user) end)
|> Enum.join("\n")
@@ -59,7 +59,7 @@ defmodule KmxgitWeb.PageController do
|> resp(200, k)
end
- def auth(conn, params) do
+ def auth(conn, _params) do
a = RepositoryManager.list_repositories
|> Enum.sort(fn a, b ->
Repository.full_slug(a) < Repository.full_slug(b)
diff --git a/lib/kmxgit_web/controllers/repository_controller.ex b/lib/kmxgit_web/controllers/repository_controller.ex
index 7a315c6..32d88c2 100644
--- a/lib/kmxgit_web/controllers/repository_controller.ex
+++ b/lib/kmxgit_web/controllers/repository_controller.ex
@@ -15,20 +15,15 @@ defmodule KmxgitWeb.RepositoryController do
if !slug do
not_found(conn)
else
- user = slug.user
- if user do
- if user != current_user do
- not_found(conn)
- else
- conn
- |> assign(:action, action)
- |> assign(:changeset, changeset)
- |> assign(:owner, user)
- |> render("new.html")
- end
+ if slug.user && slug.user.id == current_user.id do
+ conn
+ |> assign(:action, action)
+ |> assign(:changeset, changeset)
+ |> assign(:owner, slug.user)
+ |> render("new.html")
else
org = slug.organisation
- if org do
+ if org && org.users |> Enum.find(& &1.id == current_user.id) do
conn
|> assign(:action, action)
|> assign(:changeset, changeset)
@@ -49,15 +44,11 @@ defmodule KmxgitWeb.RepositoryController do
not_found(conn)
else
user = slug.user
- if user do
- if user != current_user do
- not_found(conn)
- else
- create_repo(conn, user, params["repository"])
- end
+ if user && user.id == current_user.id do
+ create_repo(conn, user, params["repository"])
else
org = slug.organisation
- if org do
+ if org && org.users |> Enum.find(& &1.id == current_user.id) do
create_repo(conn, org, params["repository"])
else
not_found(conn)
@@ -102,70 +93,33 @@ defmodule KmxgitWeb.RepositoryController do
|> render(:"404")
end
- def chunk_path(path) do
- chunk_path(path, [[]])
- end
-
- def chunk_path([], acc) do
- acc
- |> Enum.reverse()
- |> Enum.map(&Enum.reverse/1)
- end
- def chunk_path([first | rest], acc = [acc_first | acc_rest]) do
- if Regex.match?(~r/^_/, first) do
- chunk_path(rest, [[first] | acc])
- else
- chunk_path(rest, [[first | acc_first] | acc_rest])
- end
- end
-
def show(conn, params) do
- path = params["slug"] |> chunk_path()
- slug = path |> Enum.at(0) |> Enum.join("/")
- {branch, path1} = if (path1 = path |> Enum.at(1)) && (path1 |> Enum.at(0)) == "_branch" do
- {_, rest} = path |> Enum.split(2)
- rest1 = rest |> Enum.map(fn x ->
- Enum.join(x, "/")
- end)
- {_, path2} = path1 |> Enum.split(2)
- {path1 |> Enum.at(1),
- path2 ++ rest1 |> Enum.reject(&(!&1 || &1 == "")) |> Enum.join("/")}
- else
- {nil, ""}
- end
- IO.inspect([path: path, slug: slug, branch: branch, path1: path1])
+ current_user = conn.assigns.current_user
+ chunks = params["slug"] |> chunk_path()
+ slug = chunks |> Enum.at(0) |> Enum.join("/")
+ {branch, path} = get_branch_and_path(chunks)
repo = RepositoryManager.get_repository_by_owner_and_slug(params["owner"], slug)
- if repo do
- branch = branch || "master"
+ if repo && Enum.find(Repository.members(repo), fn u -> u.id == current_user.id end) do
org = repo.organisation
user = repo.user
- git = %{branches: [],
- content: nil,
- files: [],
- readme: [],
- status: "",
- valid: true}
- |> git_put_branches(repo, conn)
- |> git_put_files(repo, branch, path1, conn)
- |> git_put_content(repo)
- |> git_put_readme(repo)
- IO.inspect(git)
- if !branch do
- {b, _} = Enum.at(git.branches, 0)
+ git = setup_git(repo, branch || "master", path, conn)
+ first_branch = Enum.at(git.branches, 0)
+ if !branch && first_branch do
+ {b, _} = first_branch
conn
|> redirect(to: Routes.repository_path(conn, :show, Repository.owner_slug(repo), Repository.splat(repo) ++ ["_branch", b]))
else
if git.valid do
conn
|> assign(:branch, branch)
- |> assign(:branch_url, branch_url(git.branches, branch))
+ |> assign(:branch_url, if git.branches != [] do branch_url(git.branches, branch) end)
|> assign_current_organisation(org)
|> assign(:current_repository, repo)
|> assign(:git, git)
|> assign(:repo, repo)
|> assign(:members, Repository.members(repo))
|> assign(:owner, org || user)
- |> assign(:path, path1)
+ |> assign(:path, path)
|> render("show.html")
else
not_found(conn)
@@ -176,6 +130,50 @@ defmodule KmxgitWeb.RepositoryController do
end
end
+ def chunk_path(path) do
+ chunk_path(path, [[]])
+ end
+
+ def chunk_path([], acc) do
+ acc
+ |> Enum.reverse()
+ |> Enum.map(&Enum.reverse/1)
+ end
+ def chunk_path([first | rest], acc = [acc_first | acc_rest]) do
+ if Regex.match?(~r/^_/, first) do
+ chunk_path(rest, [[first] | acc])
+ else
+ chunk_path(rest, [[first | acc_first] | acc_rest])
+ end
+ end
+
+ defp get_branch_and_path(chunks) do
+ if (path = chunks |> Enum.at(1)) && (path |> Enum.at(0)) == "_branch" do
+ {_, rest} = chunks |> Enum.split(2)
+ rest1 = rest |> Enum.map(fn x ->
+ Enum.join(x, "/")
+ end)
+ {["_branch", branch], path1} = path |> Enum.split(2)
+ {branch,
+ path1 ++ rest1 |> Enum.reject(&(!&1 || &1 == "")) |> Enum.join("/")}
+ else
+ {nil, ""}
+ end
+ end
+
+ defp setup_git(repo, branch, path, conn) do
+ %{branches: [],
+ content: nil,
+ files: [],
+ readme: [],
+ status: "",
+ valid: true}
+ |> git_put_branches(repo, conn)
+ |> git_put_files(repo, branch, path, conn)
+ |> git_put_content(repo)
+ |> git_put_readme(repo)
+ end
+
defp branch_url([{b, url} | rest], branch) do
if b == branch do
url
@@ -200,17 +198,6 @@ defmodule KmxgitWeb.RepositoryController do
git
end
- defp git_put_status(git = %{content: nil, valid: true}, repo) do
- case GitManager.status(Repository.full_slug(repo)) do
- {:ok, status} -> %{git | status: status}
- {:error, status} -> %{git | status: status, valid: false}
- end
- end
-
- defp git_put_status(git, _) do
- git
- end
-
defp git_put_files(git = %{valid: true}, repo, branch, subdir, conn) do
case GitManager.files(Repository.full_slug(repo), branch, subdir) do
{:ok, []} -> git
@@ -227,8 +214,7 @@ defmodule KmxgitWeb.RepositoryController do
git
end
- defp git_put_content(git = %{files: [%{name: name, type: _type, sha1: sha1}], valid: true}, repo) do
- IO.inspect(git)
+ defp git_put_content(git = %{files: [%{type: "blob", sha1: sha1}], valid: true}, repo) do
case GitManager.content(Repository.full_slug(repo), sha1) do
{:ok, content} -> %{git | content: content}
{:error, error} -> %{git | status: error}
@@ -258,7 +244,7 @@ defmodule KmxgitWeb.RepositoryController do
|> Enum.filter(& &1)
%{git | readme: readme}
end
- defp git_put_readme(git) do
+ defp git_put_readme(git, _) do
git
end
@@ -266,20 +252,16 @@ defmodule KmxgitWeb.RepositoryController 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
+ if repo && Repository.owner?(repo, current_user) 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, :update, params["owner"], Repository.splat(repo)))
- |> assign(:changeset, changeset)
- |> assign_current_organisation(org)
- |> assign(:current_repository, repo)
- |> assign(:repo, repo)
- |> render("edit.html")
- else
- not_found(conn)
- end
+ changeset = RepositoryManager.change_repository(repo)
+ conn
+ |> assign(:action, Routes.repository_path(conn, :update, params["owner"], Repository.splat(repo)))
+ |> assign(:changeset, changeset)
+ |> assign_current_organisation(org)
+ |> assign(:current_repository, repo)
+ |> assign(:repo, repo)
+ |> render("edit.html")
else
not_found(conn)
end
@@ -289,33 +271,35 @@ defmodule KmxgitWeb.RepositoryController 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
+ if repo && Repository.owner?(repo, current_user) do
org = repo.organisation
- if org && Enum.find(org.users, &(&1.id == current_user.id)) || repo.user_id == current_user.id do
- case Repo.transaction(fn ->
- case RepositoryManager.update_repository(repo, params["repository"]) do
- {:ok, repo1} ->
- s = Repository.full_slug(repo)
- s1 = Repository.full_slug(repo1)
- if s != s1 do
- GitManager.rename(s, s1)
+ case Repo.transaction(fn ->
+ case RepositoryManager.update_repository(repo, params["repository"]) do
+ {:ok, repo1} ->
+ s = Repository.full_slug(repo)
+ s1 = Repository.full_slug(repo1)
+ if s != s1 do
+ case GitManager.rename(s, s1) do
+ :ok -> repo1
+ {:error, err} -> Repo.rollback(err)
end
+ else
repo1
- {:error, changeset} -> Repo.rollback(changeset)
- end
- end) do
- {:ok, repo} ->
- conn
- |> redirect(to: Routes.repository_path(conn, :show, params["owner"], Repository.splat(repo)))
- {:error, changeset} ->
- conn
- |> assign(:action, Routes.repository_path(conn, :update, params["owner"], Repository.splat(repo)))
- |> assign(:changeset, changeset)
- |> assign_current_organisation(org)
- |> assign(:current_repository, repo)
- |> assign(:repo, repo)
- |> render("edit.html")
- end
+ end
+ {:error, changeset} -> Repo.rollback(changeset)
+ end
+ end) do
+ {:ok, repo} ->
+ conn
+ |> redirect(to: Routes.repository_path(conn, :show, params["owner"], Repository.splat(repo)))
+ {:error, changeset} ->
+ conn
+ |> assign(:action, Routes.repository_path(conn, :update, params["owner"], Repository.splat(repo)))
+ |> assign(:changeset, changeset)
+ |> assign_current_organisation(org)
+ |> assign(:current_repository, repo)
+ |> assign(:repo, repo)
+ |> render("edit.html")
end
else
not_found(conn)
@@ -326,18 +310,14 @@ defmodule KmxgitWeb.RepositoryController 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
+ if repo && Repository.owner?(repo, current_user) do
org = repo.organisation
- if org && Enum.find(org.users, &(&1.id == current_user.id)) || repo.user_id == current_user.id do
- 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")
- else
- not_found(conn)
- end
+ 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")
else
not_found(conn)
end
@@ -348,21 +328,19 @@ defmodule KmxgitWeb.RepositoryController do
login = params["repository"]["login"]
slug = Enum.join(params["slug"], "/")
repo = RepositoryManager.get_repository_by_owner_and_slug(params["owner"], slug)
- if repo do
+ if repo && Repository.owner?(repo, current_user) 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
+ 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
else
not_found(conn)
@@ -373,18 +351,14 @@ defmodule KmxgitWeb.RepositoryController 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
+ if repo && Repository.owner?(repo, current_user) do
org = repo.organisation
- if org && Enum.find(org.users, &(&1.id == current_user.id)) || repo.user_id == current_user.id do
- 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")
- else
- not_found(conn)
- end
+ 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")
else
not_found(conn)
end
@@ -395,21 +369,19 @@ defmodule KmxgitWeb.RepositoryController do
login = params["repository"]["login"]
slug = Enum.join(params["slug"], "/")
repo = RepositoryManager.get_repository_by_owner_and_slug(params["owner"], slug)
- if repo do
+ if repo && Repository.owner?(repo, current_user) 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
+ 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
else
not_found(conn)
@@ -420,24 +392,19 @@ defmodule KmxgitWeb.RepositoryController 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
- case Repo.transaction(fn ->
- case RepositoryManager.delete_repository(repo) do
- {:ok, _} -> :ok
- {:error, changeset} -> Repo.rollback changeset
- end
- end) do
- {:ok, _} ->
- conn
- |> redirect(to: Routes.slug_path(conn, :show, params["owner"]))
- {:error, changeset} ->
- conn
- |> redirect(to: Routes.slug_path(conn, :edit, params["owner"]))
- end
- else
- not_found(conn)
+ if repo && Repository.owner?(repo, current_user) do
+ case Repo.transaction(fn ->
+ case RepositoryManager.delete_repository(repo) do
+ {:ok, _} -> :ok = GitManager.delete(Repository.full_slug(repo))
+ {:error, changeset} -> Repo.rollback changeset
+ end
+ end) do
+ {:ok, _} ->
+ conn
+ |> redirect(to: Routes.slug_path(conn, :show, params["owner"]))
+ {:error, _changeset} ->
+ conn
+ |> redirect(to: Routes.slug_path(conn, :edit, params["owner"]))
end
else
not_found(conn)
diff --git a/lib/kmxgit_web/controllers/slug_controller.ex b/lib/kmxgit_web/controllers/slug_controller.ex
index 60428e3..d149111 100644
--- a/lib/kmxgit_web/controllers/slug_controller.ex
+++ b/lib/kmxgit_web/controllers/slug_controller.ex
@@ -1,7 +1,8 @@
defmodule KmxgitWeb.SlugController do
use KmxgitWeb, :controller
- alias Kmxgit.OrganisationManager
+ alias Kmxgit.RepositoryManager
+ alias Kmxgit.RepositoryManager.Repository
alias Kmxgit.SlugManager
alias KmxgitWeb.ErrorView
alias KmxgitWeb.OrganisationView
@@ -22,6 +23,8 @@ defmodule KmxgitWeb.SlugController do
user = slug.user
if user do
conn
+ |> assign(:contributor_repos, RepositoryManager.list_contributor_repositories(user))
+ |> assign(:owned_repos, user.owned_repositories |> Enum.sort_by(&Repository.full_slug/1))
|> assign(:page_title, gettext("User %{login}", login: user.slug.slug))
|> assign(:user, user)
|> put_view(UserView)
@@ -41,21 +44,4 @@ defmodule KmxgitWeb.SlugController do
end
end
end
-
- def delete(conn, params) do
- current_user = conn.assigns.current_user
- slug = SlugManager.get_slug(params["slug"])
- if slug do
- org = slug.organisation
- if org && Enum.find(org.users, &(&1.id == current_user.id)) do
- {:ok, _} = OrganisationManager.delete_organisation(org)
- conn
- |> redirect(to: Routes.slug_path(conn, :show, current_user.slug.slug))
- else
- not_found(conn)
- end
- else
- not_found(conn)
- end
- end
end
diff --git a/lib/kmxgit_web/controllers/user_controller.ex b/lib/kmxgit_web/controllers/user_controller.ex
index df689a6..49f4ad2 100644
--- a/lib/kmxgit_web/controllers/user_controller.ex
+++ b/lib/kmxgit_web/controllers/user_controller.ex
@@ -1,28 +1,12 @@
defmodule KmxgitWeb.UserController do
use KmxgitWeb, :controller
+ alias Kmxgit.GitManager
+ alias Kmxgit.Repo
alias Kmxgit.UserManager
alias Kmxgit.UserManager.User
alias KmxgitWeb.ErrorView
- def show(conn, params) do
- #current_user = conn.assigns[:current_user]
- #user = if current_user && params["login"] == current_user.slug.slug do
- # current_user
- #else
- user = UserManager.get_user_by_slug(params["login"])
- #end
- if user do
- conn
- |> assign(:page_title, gettext("User %{login}", login: user.slug.slug))
- |> assign(:user, user)
- |> render("show.html")
- else
- conn
- |> not_found()
- end
- end
-
defp not_found(conn) do
conn
|> put_status(:not_found)
@@ -31,7 +15,7 @@ defmodule KmxgitWeb.UserController do
end
def edit(conn, params) do
- current_user = conn.assigns[:current_user]
+ current_user = conn.assigns.current_user
if params["login"] == current_user.slug.slug do
changeset = User.changeset(current_user)
conn
@@ -43,9 +27,22 @@ defmodule KmxgitWeb.UserController do
end
def update(conn, params) do
- current_user = conn.assigns[:current_user]
+ current_user = conn.assigns.current_user
if params["login"] == current_user.slug.slug do
- case UserManager.update_user(current_user, params["user"]) do
+ case Repo.transaction(fn ->
+ case UserManager.update_user(current_user, params["user"]) do
+ {:ok, user} ->
+ if user.slug.slug != current_user.slug.slug do
+ case GitManager.rename_dir(current_user.slug.slug, user.slug.slug) do
+ :ok -> user
+ {:error, err} -> Repo.rollback(err)
+ end
+ else
+ user
+ end
+ {:error, changeset} -> Repo.rollback(changeset)
+ end
+ end) do
{:ok, user} ->
conn
|> redirect(to: Routes.slug_path(conn, :show, user.slug.slug))
@@ -59,4 +56,29 @@ defmodule KmxgitWeb.UserController do
not_found(conn)
end
end
+
+ def delete(conn, params) do
+ current_user = conn.assigns.current_user
+ if params["login"] == current_user.slug.slug do
+ case Repo.transaction(fn ->
+ case UserManager.delete_user(current_user) do
+ {:ok, _} ->
+ case GitManager.delete_dir(current_user.slug.slug) do
+ :ok -> :ok
+ {:error, out} -> Repo.rollback(status: out)
+ end
+ {:error, e} -> Repo.rollback(e)
+ end
+ end) do
+ {:ok, _} ->
+ conn
+ |> redirect(to: "/")
+ {:error, _} ->
+ conn
+ |> redirect(to: Routes.user_path(conn, :edit, current_user.slug.slug))
+ end
+ else
+ not_found(conn)
+ end
+ end
end
diff --git a/lib/kmxgit_web/router.ex b/lib/kmxgit_web/router.ex
index 852e183..d91cff6 100644
--- a/lib/kmxgit_web/router.ex
+++ b/lib/kmxgit_web/router.ex
@@ -56,8 +56,8 @@ defmodule KmxgitWeb.Router do
scope "/_new" do
get "/organisation", OrganisationController, :new
post "/organisation", OrganisationController, :create
- get "/:owner", RepositoryController, :new
- post "/:owner", RepositoryController, :create
+ get "/repository/:owner", RepositoryController, :new
+ post "/repository/:owner", RepositoryController, :create
end
scope "/_edit/" do
@@ -65,8 +65,8 @@ defmodule KmxgitWeb.Router do
put "/organisation/:slug", OrganisationController, :update
get "/user/:login", UserController, :edit
put "/user/:login", UserController, :update
- get "/:owner/*slug", RepositoryController, :edit
- put "/:owner/*slug", RepositoryController, :update
+ get "/repository/:owner/*slug", RepositoryController, :edit
+ put "/repository/:owner/*slug", RepositoryController, :update
end
scope "/_add_user/" do
@@ -83,7 +83,13 @@ defmodule KmxgitWeb.Router do
post "/:owner/*slug", RepositoryController, :remove_user_post
end
- scope "/admin", Admin, as: "admin" do
+ scope "/_delete/" do
+ delete "/organisation/:slug", OrganisationController, :delete
+ delete "/user/:login", UserController, :delete
+ delete "/repository/:owner/*slug", RepositoryController, :delete
+ end
+
+ scope "/_admin", Admin, as: "admin" do
pipe_through :admin
get "/", DashboardController, :index
resources "/organisations", OrganisationController do
@@ -103,16 +109,9 @@ defmodule KmxgitWeb.Router do
import Phoenix.LiveDashboard.Router
live_dashboard "/dashboard", metrics: KmxgitWeb.Telemetry
end
- end
-
- # maybe logged in
- scope "/", KmxgitWeb do
- pipe_through [:browser, :auth]
- get "/:slug", SlugController, :show
- delete "/:slug", SlugController, :delete
- get "/:owner/*slug", RepositoryController, :show
- delete "/:owner/*slug", RepositoryController, :delete
+ get "/:slug", SlugController, :show
+ get "/:owner/*slug", RepositoryController, :show
end
# Other scopes may use custom stacks.
diff --git a/lib/kmxgit_web/templates/organisation/form.html.heex b/lib/kmxgit_web/templates/organisation/form.html.heex
index 4c401c9..0f316af 100644
--- a/lib/kmxgit_web/templates/organisation/form.html.heex
+++ b/lib/kmxgit_web/templates/organisation/form.html.heex
@@ -22,8 +22,11 @@
<div class="mb-3">
<%= if @conn.assigns[:current_organisation] do %>
+ <%= link gettext("Cancel"),
+ to: Routes.slug_path(@conn, :show, @current_organisation.slug.slug),
+ class: "btn btn-secondary" %>
<%= link gettext("Delete organisation"),
- to: Routes.slug_path(@conn, :delete, @current_organisation.slug.slug),
+ to: Routes.organisation_path(@conn, :delete, @current_organisation.slug.slug),
method: :delete,
class: "btn btn-danger",
data: [confirm: gettext("Are you sure you want to delete the organisation %{org} ?", org: @current_organisation.name || @current_organisation.slug.slug)] %>
diff --git a/lib/kmxgit_web/templates/organisation/show.html.heex b/lib/kmxgit_web/templates/organisation/show.html.heex
index 0124ded..78b7609 100644
--- a/lib/kmxgit_web/templates/organisation/show.html.heex
+++ b/lib/kmxgit_web/templates/organisation/show.html.heex
@@ -4,12 +4,14 @@
<h1><%= @org.name || @org.slug.slug %></h1>
</div>
<div class="col col-12 col-sm-4">
- <%= link gettext("New repository"),
- to: Routes.repository_path(@conn, :new, @org.slug.slug),
- class: "btn btn-primary" %>
- <%= link gettext("Edit"),
- to: Routes.organisation_path(@conn, :edit, @org.slug.slug),
- class: "btn btn-primary" %>
+ <%= if Organisation.owner?(@org, @current_user) do %>
+ <%= link gettext("New repository"),
+ to: Routes.repository_path(@conn, :new, @org.slug.slug),
+ class: "btn btn-primary" %>
+ <%= link gettext("Edit"),
+ to: Routes.organisation_path(@conn, :edit, @org.slug.slug),
+ class: "btn btn-primary" %>
+ <% end %>
</div>
</div>
@@ -49,7 +51,7 @@
<tr>
<th>
<%= gettext "Users" %><br/>
- <%= if Enum.find(@org.users, &(&1.id == @current_user.id)) do %>
+ <%= if Organisation.owner?(@org, @current_user) do %>
<%= link "-",
to: Routes.organisation_path(@conn, :remove_user, @org.slug.slug),
class: "btn btn-danger btn-sm" %>
diff --git a/lib/kmxgit_web/templates/repository/show.html.heex b/lib/kmxgit_web/templates/repository/show.html.heex
index 28a85b7..05d712a 100644
--- a/lib/kmxgit_web/templates/repository/show.html.heex
+++ b/lib/kmxgit_web/templates/repository/show.html.heex
@@ -5,9 +5,11 @@
<h1 id="repo_title"><%= link Repository.owner_slug(@repo), to: Routes.slug_path(@conn, :show, Repository.owner_slug(@repo)) %>/<%= link @repo.slug, to: Routes.repository_path(@conn, :show, Repository.owner_slug(@repo), String.split(@repo.slug, "/")) %></h1>
</div>
<div class="col col-12 col-sm-4">
- <%= link gettext("Edit"),
- to: Routes.repository_path(@conn, :edit, Repository.owner_slug(@repo), String.split(@repo.slug, "/")),
- class: "btn btn-primary" %>
+ <%= if Repository.owner?(@repo, @current_user) do %>
+ <%= link gettext("Edit"),
+ to: Routes.repository_path(@conn, :edit, Repository.owner_slug(@repo), String.split(@repo.slug, "/")),
+ class: "btn btn-primary" %>
+ <% end %>
</div>
</div>
@@ -42,11 +44,13 @@
<%= Enum.map @git.readme, fn readme -> %>
<hr/>
<h2><%= readme.name %></h2>
- <%= if readme.html do %>
- <%= raw readme.html %>
- <% else %>
- <pre><%= readme.txt %></pre>
- <% end %>
+ <div class="container-fluid file-content">
+ <%= if readme.html do %>
+ <%= raw readme.html %>
+ <% else %>
+ <pre><%= readme.txt %></pre>
+ <% end %>
+ </div>
<% end %>
</div>
<div class="col col-12 col-md-4">
@@ -68,12 +72,14 @@
<tr>
<th>
<%= gettext "Users" %><br/>
- <%= 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" %>
+ <%= if Repository.owner?(@repo, @current_user) do %>
+ <%= 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" %>
+ <% end %>
</th>
<td>
<ul>
diff --git a/lib/kmxgit_web/templates/user/edit.html.heex b/lib/kmxgit_web/templates/user/edit.html.heex
index 7ddb7d5..8cc2342 100644
--- a/lib/kmxgit_web/templates/user/edit.html.heex
+++ b/lib/kmxgit_web/templates/user/edit.html.heex
@@ -56,7 +56,11 @@
<%= link gettext("Cancel"),
to: Routes.slug_path(@conn, :show, @current_user.slug.slug),
class: "btn btn-secondary" %>
-
+ <%= link gettext("Delete user"),
+ to: Routes.user_path(@conn, :delete, @current_user.slug.slug),
+ method: :delete,
+ class: "btn btn-danger",
+ data: [confirm: gettext("Are you sure you want to delete the user %{user} ?", user: @current_user.slug.slug)] %>
<%= submit gettext("Submit"), class: "btn btn-primary" %>
</div>
diff --git a/lib/kmxgit_web/templates/user/show.html.heex b/lib/kmxgit_web/templates/user/show.html.heex
index 65bb7a8..7a96ba5 100644
--- a/lib/kmxgit_web/templates/user/show.html.heex
+++ b/lib/kmxgit_web/templates/user/show.html.heex
@@ -4,12 +4,14 @@
<h1><%= @user.slug.slug %></h1>
</div>
<div class="col col-12 col-sm-4">
- <%= link gettext("New repository"),
- to: Routes.repository_path(@conn, :new, @user.slug.slug),
- class: "btn btn-primary" %>
- <%= link gettext("Edit"),
- to: Routes.user_path(@conn, :edit, @user.slug.slug),
- class: "btn btn-primary" %>
+ <%= if @user.id == @current_user.id do %>
+ <%= link gettext("New repository"),
+ to: Routes.repository_path(@conn, :new, @user.slug.slug),
+ class: "btn btn-primary" %>
+ <%= link gettext("Edit"),
+ to: Routes.user_path(@conn, :edit, @user.slug.slug),
+ class: "btn btn-primary" %>
+ <% end %>
</div>
</div>
@@ -18,9 +20,14 @@
<hr/>
<h2><%= gettext "Repositories" %></h2>
<ul>
- <%= for repo <- Enum.sort_by(@user.owned_repositories, &Repository.full_slug/1) do %>
+ <%= for repo <- @owned_repos do %>
<li>
- <%= link Repository.full_slug(repo), to: Routes.repository_path(@conn, :show, @user.slug.slug, Repository.splat(repo)) %>
+ <%= link Repository.full_slug(repo), to: Routes.repository_path(@conn, :show, Repository.owner_slug(repo), Repository.splat(repo)) %>
+ </li>
+ <% end %>
+ <%= for repo <- @contributor_repos do %>
+ <li>
+ <%= link Repository.full_slug(repo), to: Routes.repository_path(@conn, :show, Repository.owner_slug(repo), Repository.splat(repo)) %>
</li>
<% end %>
</ul>
@@ -56,7 +63,7 @@
<tr>
<th>
<%= gettext "Organisations" %><br/>
- <%= if @user == @current_user do %>
+ <%= if @user.id == @current_user.id do %>
<%= link("+", to: Routes.organisation_path(@conn, :new), class: "btn btn-primary btn-sm") %>
<% end %>
</th>
diff --git a/lib/kmxgit_web/views/organisation_view.ex b/lib/kmxgit_web/views/organisation_view.ex
index 1e9b731..c0241e5 100644
--- a/lib/kmxgit_web/views/organisation_view.ex
+++ b/lib/kmxgit_web/views/organisation_view.ex
@@ -1,5 +1,6 @@
defmodule KmxgitWeb.OrganisationView do
use KmxgitWeb, :view
+ alias Kmxgit.OrganisationManager.Organisation
alias Kmxgit.RepositoryManager.Repository
end