diff --git a/assets/css/app.scss b/assets/css/app.scss
index f12356d..3250371 100644
--- a/assets/css/app.scss
+++ b/assets/css/app.scss
@@ -10,7 +10,8 @@ textarea#organisation_description,
textarea#repository_description {
min-height: 10em;
}
-textarea#user_ssh_keys {
+textarea#user_ssh_keys,
+textarea#repository_deploy_keys {
font-family: monospace;
min-height: 20em;
overflow-x: scroll;
diff --git a/bin/update_etc_git_auth b/bin/update_etc_git_auth
index 8676ea4..6b97be6 100755
--- a/bin/update_etc_git_auth
+++ b/bin/update_etc_git_auth
@@ -1,4 +1,4 @@
#!/bin/sh
set -e
-cd /etc/git
-ftp -o auth.conf https://git.kmx.io/_etc/git/auth.conf
+cd /etc/git/
+curl > auth.conf https://git.kmx.io/_etc/git/auth.conf
diff --git a/bin/update_git_ssh_authorized_keys b/bin/update_git_ssh_authorized_keys
new file mode 100755
index 0000000..f4c76a9
--- /dev/null
+++ b/bin/update_git_ssh_authorized_keys
@@ -0,0 +1,4 @@
+#!/bin/sh
+set -e
+cd /home/git/.ssh/
+curl > authorized_keys https://git.kmx.io/_etc/ssh/authorized_keys
diff --git a/lib/kmxgit/repository_manager/repository.ex b/lib/kmxgit/repository_manager/repository.ex
index 38f3340..1212ffa 100644
--- a/lib/kmxgit/repository_manager/repository.ex
+++ b/lib/kmxgit/repository_manager/repository.ex
@@ -10,6 +10,7 @@ defmodule Kmxgit.RepositoryManager.Repository do
alias Kmxgit.UserManager.User
schema "repositories" do
+ field :deploy_keys, :string
field :description, :string
belongs_to :organisation, Organisation
field :slug, :string
@@ -20,20 +21,20 @@ defmodule Kmxgit.RepositoryManager.Repository do
def changeset(repository, attrs) do
repository
- |> cast(attrs, [:description, :slug])
+ |> cast(attrs, [:deploy_keys, :description, :slug])
|> common_changeset()
end
def owner_changeset(repository, attrs, owner = %Organisation{}) do
repository
- |> cast(attrs, [:description, :slug])
+ |> cast(attrs, [:deploy_keys, :description, :slug])
|> put_assoc(:organisation, owner)
|> put_assoc(:user, nil)
|> common_changeset()
end
def owner_changeset(repository, attrs, owner = %User{}) do
repository
- |> cast(attrs, [:description, :slug])
+ |> cast(attrs, [:deploy_keys, :description, :slug])
|> put_assoc(:organisation, nil)
|> put_assoc(:user, owner)
|> common_changeset()
@@ -135,7 +136,8 @@ defmodule Kmxgit.RepositoryManager.Repository do
end
def auth(repo) do
- repo
+ full_slug = full_slug(repo)
+ auth = repo
|> members()
|> Enum.sort(fn a, b ->
a.slug.slug < b.slug.slug
@@ -146,7 +148,29 @@ defmodule Kmxgit.RepositoryManager.Repository do
else
"rw"
end
- "#{user.slug.slug} #{mode} \"#{full_slug(repo)}.git\"\n"
+ auth_line(user.slug.slug, mode, full_slug)
+ end)
+ auth ++ [auth_line(deploy_user(repo), "r", full_slug)]
+ end
+
+ defp auth_line(user, mode, slug) do
+ "#{user} #{mode} '#{slug}.git'\n"
+ end
+
+ def deploy_user(repo) do
+ "_deploy_#{full_slug(repo)}"
+ end
+
+ def deploy_keys_with_env(repo) do
+ (repo.deploy_keys || "")
+ |> String.split("\n")
+ |> Enum.map(fn line ->
+ if Regex.match?(~r/^[ \t]*ssh-/, line) do
+ "environment=\"GIT_AUTH_ID=#{deploy_user(repo)}\" #{line}"
+ else
+ line
+ end
end)
+ |> Enum.join("\n")
end
end
diff --git a/lib/kmxgit_web/controllers/page_controller.ex b/lib/kmxgit_web/controllers/page_controller.ex
index 8c2d3ce..966abb0 100644
--- a/lib/kmxgit_web/controllers/page_controller.ex
+++ b/lib/kmxgit_web/controllers/page_controller.ex
@@ -51,9 +51,11 @@ defmodule KmxgitWeb.PageController do
end
def keys(conn, _params) do
- k = UserManager.list_users
- |> Enum.map(fn user -> User.ssh_keys_with_env(user) end)
- |> Enum.join("\n")
+ k1 = UserManager.list_users
+ |> Enum.map(&User.ssh_keys_with_env/1)
+ k2 = RepositoryManager.list_repositories
+ |> Enum.map(&Repository.deploy_keys_with_env/1)
+ k = (k1 ++ k2) |> Enum.join("\n")
conn
|> put_resp_content_type("text/text")
|> resp(200, k)
diff --git a/lib/kmxgit_web/templates/repository/form.html.heex b/lib/kmxgit_web/templates/repository/form.html.heex
index 1535a36..b0c014a 100644
--- a/lib/kmxgit_web/templates/repository/form.html.heex
+++ b/lib/kmxgit_web/templates/repository/form.html.heex
@@ -18,6 +18,12 @@
</div>
<div class="mb-3">
+ <%= label f, :deploy_keys, class: "form-label" %>
+ <%= textarea f, :deploy_keys, class: "form-control" %>
+ <%= error_tag f, :deploy_keys %>
+ </div>
+
+ <div class="mb-3">
<%= if @conn.assigns[:current_repository] do %>
<%= link gettext("Cancel"),
to: Routes.repository_path(@conn, :show, Repository.owner_slug(@current_repository), Repository.splat(@current_repository)),