diff --git a/lib/kmxgit/repository_manager.ex b/lib/kmxgit/repository_manager.ex
new file mode 100644
index 0000000..0adb30d
--- /dev/null
+++ b/lib/kmxgit/repository_manager.ex
@@ -0,0 +1,69 @@
+defmodule Kmxgit.RepositoryManager do
+
+ import Ecto.Query, warn: false
+
+ alias Kmxgit.OrganisationManager.Organisation
+ alias Kmxgit.Repo
+ alias Kmxgit.RepositoryManager.Repository
+ alias Kmxgit.SlugManager.Slug
+ alias Kmxgit.UserManager.User
+
+ def list_repositories do
+ Repo.all from org in Repository,
+ preload: [organisation: :slug],
+ preload: [user: :slug]
+ end
+
+ def change_repository(repository \\ %Repository{}) do
+ Repository.changeset(repository, %{})
+ end
+
+ def create_repository(owner), do: create_repository(owner, %{})
+
+ def create_repository(user = %User{}, attrs) do
+ %Repository{}
+ |> Repository.changeset(attrs)
+ |> Ecto.Changeset.put_assoc(:user, user)
+ |> Repo.insert()
+ end
+
+ def create_repository(org = %Organisation{}, attrs) do
+ %Repository{}
+ |> Repository.changeset(attrs)
+ |> Ecto.Changeset.put_assoc(:organisation, org)
+ |> Repo.insert()
+ end
+
+ def update_repository(repository, attrs \\ %{}) do
+ repository
+ |> Repository.changeset(attrs)
+ |> Repo.update()
+ end
+
+ def get_repository(id) do
+ Repo.one from repository in Repository,
+ where: [id: ^id],
+ preload: :slug,
+ preload: [users: :slug],
+ limit: 1
+ end
+
+ def get_repository_by_owner_and_slug(owner, slug) do
+ downcase_owner = String.downcase(owner)
+ downcase_slug = String.downcase(slug)
+ Repo.one from r in Repository,
+ join: o in Organisation,
+ on: o.id == r.organisation_id,
+ join: os in Slug,
+ on: os.organisation_id == o.id,
+ join: u in User,
+ on: u.id == r.user_id,
+ join: us in Slug,
+ on: us.user_id == u.id,
+ where: (fragment("lower(?)", os.slug) == ^downcase_owner or fragment("lower(?)", us.slug) == ^downcase_owner) and fragment("lower(?)", r.slug) == ^downcase_slug
+ end
+
+ def delete_repository(%Repository{} = repository) do
+ Repo.delete(repository)
+ end
+end
diff --git a/lib/kmxgit/repository_manager/repository.ex b/lib/kmxgit/repository_manager/repository.ex
new file mode 100644
index 0000000..7a182c6
--- /dev/null
+++ b/lib/kmxgit/repository_manager/repository.ex
@@ -0,0 +1,26 @@
+defmodule Kmxgit.RepositoryManager.Repository do
+
+ use Ecto.Schema
+ import Ecto.Changeset
+
+ alias Kmxgit.OrganisationManager.Organisation
+ alias Kmxgit.UserManager.User
+
+ schema "repositories" do
+ field :description, :string
+ belongs_to :organisation, Organisation
+ field :slug, :string, unique: true
+ belongs_to :user, User
+ timestamps()
+ end
+
+ def changeset(repository, attrs \\ %{}) do
+ repository
+ |> cast(attrs, [:description, :slug])
+ |> validate_required([:slug])
+ |> validate_format(:slug, ~r|^[A-Za-z][-_+.0-9A-Za-z]{1,64}(/[A-Za-z][-_+.0-9A-Za-z]{1,64})*$|)
+ |> unique_constraint(:_lower_slug)
+ |> Markdown.validate_markdown(:description)
+ end
+
+end
diff --git a/lib/kmxgit/slug_manager.ex b/lib/kmxgit/slug_manager.ex
index 3d8e83f..4366b87 100644
--- a/lib/kmxgit/slug_manager.ex
+++ b/lib/kmxgit/slug_manager.ex
@@ -24,9 +24,9 @@ defmodule Kmxgit.SlugManager do
def get_slug(slug) do
Repo.one from s in Slug,
- where: [slug: ^slug],
+ where: fragment("lower(slug)") == ^String.downcase(slug),
preload: [organisation: [:slug, [users: :slug]]],
- preload: [user: [:slug, [organisations: :slug]]],
+ preload: [user: [[organisations: :slug], :repositories, :slug]],
limit: 1
end
diff --git a/lib/kmxgit/slug_manager/slug.ex b/lib/kmxgit/slug_manager/slug.ex
index 55559cb..32f42d9 100644
--- a/lib/kmxgit/slug_manager/slug.ex
+++ b/lib/kmxgit/slug_manager/slug.ex
@@ -12,43 +12,11 @@ defmodule Kmxgit.SlugManager.Slug do
timestamps()
end
- def changeset(slug, attrs) do
+ def changeset(slug, attrs \\ %{}) do
slug
|> cast(attrs, [:slug])
|> validate_required([:slug])
|> validate_format(:slug, ~r/^[A-Za-z][-_+.0-9A-Za-z]{1,64}$/)
|> unique_constraint(:_lower_slug)
end
-
- def user_changeset(slug, user, attrs \\ {}) do
- slug
- |> changeset(attrs)
- |> Ecto.Changeset.put_assoc(:user, user)
- |> validate_only_user()
- end
-
- defp validate_only_user(changeset) do
- c = changeset |> validate_required(:user_id)
- if get_field(changeset, :organisation_id) do
- add_error(c, :organisation_id, "cannot be set")
- else
- c
- end
- end
-
- def organisation_changeset(slug, org, attrs \\ {}) do
- slug
- |> changeset(attrs)
- |> Ecto.Changeset.put_assoc(:organisation, org)
- |> validate_only_organisation()
- end
-
- defp validate_only_organisation(changeset) do
- c = changeset |> validate_required(:organisation_id)
- if get_field(changeset, :user_id) do
- add_error(c, :user_id, "cannot be set")
- else
- c
- end
- end
end
diff --git a/lib/kmxgit/user_manager.ex b/lib/kmxgit/user_manager.ex
index 181e688..bed1665 100644
--- a/lib/kmxgit/user_manager.ex
+++ b/lib/kmxgit/user_manager.ex
@@ -19,6 +19,7 @@ defmodule Kmxgit.UserManager do
user = Repo.one(from user in User,
where: [id: ^id],
preload: [organisations: :slug],
+ preload: :repositories,
preload: :slug
)
user || raise Ecto.NoResultsError
@@ -28,6 +29,7 @@ defmodule Kmxgit.UserManager do
Repo.one from user in User,
where: [id: ^id],
preload: [organisations: :slug],
+ preload: :repositories,
preload: :slug
end
@@ -35,34 +37,22 @@ defmodule Kmxgit.UserManager do
Repo.one from u in User,
join: s in Slug,
on: s.id == u.slug_id,
- where: s.slug == ^slug,
+ where: fragment("lower(?)", s.slug) == ^String.downcase(slug),
limit: 1
end
- def create_user(slug, attrs \\ %{}) do
- %User{slug: slug}
+ def create_user(attrs \\ %{}) do
+ %User{}
|> User.changeset(attrs)
|> Repo.insert()
end
- def admin_create_user(slug, attrs \\ %{}) do
- %User{slug: slug}
+ def admin_create_user(attrs \\ %{}) do
+ %User{}
|> User.admin_changeset(attrs)
|> Repo.insert()
end
- @doc """
- Updates a user.
-
- ## Examples
-
- iex> update_user(user, %{field: new_value})
- {:ok, %User{}}
-
- iex> update_user(user, %{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
def update_user(%User{} = user, attrs) do
user
|> User.changeset(attrs)
@@ -75,38 +65,20 @@ defmodule Kmxgit.UserManager do
|> Repo.update()
end
- @doc """
- Deletes a user.
-
- ## Examples
-
- iex> delete_user(user)
- {:ok, %User{}}
-
- iex> delete_user(user)
- {:error, %Ecto.Changeset{}}
-
- """
def delete_user(%User{} = user) do
Repo.delete(user)
end
- @doc """
- Returns an `%Ecto.Changeset{}` for tracking user changes.
-
- ## Examples
-
- iex> change_user(user)
- %Ecto.Changeset{source: %User{}}
-
- """
def change_user(%User{} = user) do
User.changeset(user, %{})
end
def authenticate_user(login, password) do
query = from u in User,
- where: fragment("lower(?)", u.login) == ^String.downcase(login) or fragment("lower(?)", u.email) == ^String.downcase(login)
+ join: s in Slug,
+ on: s.user_id == u.id,
+ where: fragment("lower(?)", s.slug) == ^String.downcase(login) or fragment("lower(?)", u.email) == ^String.downcase(login),
+ limit: 1
case Repo.one(query) do
nil ->
Bcrypt.no_user_verify()
diff --git a/lib/kmxgit/user_manager/user.ex b/lib/kmxgit/user_manager/user.ex
index a7aea10..a9e731e 100644
--- a/lib/kmxgit/user_manager/user.ex
+++ b/lib/kmxgit/user_manager/user.ex
@@ -3,8 +3,8 @@ defmodule Kmxgit.UserManager.User do
import Ecto.Changeset
alias Kmxgit.OrganisationManager.Organisation
+ alias Kmxgit.RepositoryManager.Repository
alias Kmxgit.SlugManager.Slug
- alias KmxgitWeb.Router.Helpers, as: Routes
alias BCrypt
schema "users" do
@@ -15,14 +15,15 @@ defmodule Kmxgit.UserManager.User do
field :name, :string
field :password, :string, virtual: true, redact: true
field :password_confirmation, :string, virtual: true, redact: true
+ has_many :repositories, Repository
has_one :slug, Slug, on_delete: :delete_all
field :ssh_keys, :string
- many_to_many :organisations, Organisation, join_through: "users_organisations"
+ many_to_many :organisations, Organisation, join_through: "users_organisations", on_delete: :delete_all
timestamps()
end
- defp common_changeset(user) do
- user
+ defp common_changeset(changeset) do
+ changeset
|> check_password_confirmation()
|> put_password_hash()
|> cast_assoc(:slug)
@@ -32,14 +33,12 @@ defmodule Kmxgit.UserManager.User do
|> Markdown.validate_markdown(:description)
end
- @doc false
def changeset(user, attrs \\ %{}) do
user
|> cast(attrs, [:description, :email, :name, :password, :password_confirmation, :ssh_keys])
|> common_changeset()
end
- @doc false
def admin_changeset(user, attrs \\ %{}) do
user
|> cast(attrs, [:description, :email, :is_admin, :name, :password, :password_confirmation, :ssh_keys])
@@ -84,14 +83,6 @@ defmodule Kmxgit.UserManager.User do
changeset
end
- def after_login_path(user) do
- Routes.user_path(KmxgitWeb.Endpoint, :show, user.login)
- end
-
- def after_register_path(user) do
- Routes.user_path(KmxgitWeb.Endpoint, :show, user.login)
- end
-
def display_name(user) do
user.name || user.login
end
diff --git a/lib/kmxgit_web/controllers/admin/organisation_controller.ex b/lib/kmxgit_web/controllers/admin/organisation_controller.ex
index 35cbff6..f1b1424 100644
--- a/lib/kmxgit_web/controllers/admin/organisation_controller.ex
+++ b/lib/kmxgit_web/controllers/admin/organisation_controller.ex
@@ -27,9 +27,9 @@ defmodule KmxgitWeb.Admin.OrganisationController do
case SlugManager.create_slug(org_params["slug"]["slug"]) do
{:ok, slug} ->
case OrganisationManager.create_organisation(Map.merge(org_params, %{slug: slug, user: current_user})) do
- {:ok, organisation} ->
+ {:ok, org} ->
conn
- |> redirect(to: Routes.organisation_path(conn, :show, organisation.slug))
+ |> redirect(to: Routes.admin_organisation_path(conn, :show, org))
{:error, changeset} ->
conn
|> assign(:action, Routes.admin_organisation_path(conn, :create))
diff --git a/lib/kmxgit_web/controllers/organisation_controller.ex b/lib/kmxgit_web/controllers/organisation_controller.ex
index 773412b..e7ab9c6 100644
--- a/lib/kmxgit_web/controllers/organisation_controller.ex
+++ b/lib/kmxgit_web/controllers/organisation_controller.ex
@@ -17,7 +17,7 @@ defmodule KmxgitWeb.OrganisationController do
case OrganisationManager.create_organisation(current_user, params["organisation"]) do
{:ok, organisation} ->
conn
- |> redirect(to: Routes.organisation_path(conn, :show, organisation.slug.slug))
+ |> redirect(to: Routes.slug_path(conn, :show, organisation.slug.slug))
{:error, changeset} ->
IO.inspect(changeset)
conn
@@ -66,7 +66,7 @@ defmodule KmxgitWeb.OrganisationController do
case OrganisationManager.update_organisation(organisation, params["organisation"]) do
{:ok, org} ->
conn
- |> redirect(to: Routes.organisation_path(conn, :show, org.slug.slug))
+ |> redirect(to: Routes.slug_path(conn, :show, org.slug.slug))
{:error, changeset} ->
IO.inspect(changeset)
conn
diff --git a/lib/kmxgit_web/controllers/page_controller.ex b/lib/kmxgit_web/controllers/page_controller.ex
index c2ddb3f..964a934 100644
--- a/lib/kmxgit_web/controllers/page_controller.ex
+++ b/lib/kmxgit_web/controllers/page_controller.ex
@@ -30,23 +30,12 @@ defmodule KmxgitWeb.PageController do
def new_admin_post(conn, params) do
if ! UserManager.admin_user_present? do
user_params = Map.merge(params["user"], %{"is_admin" => true})
- login = user_params["login"]
Repo.transaction fn ->
- case SlugManager.create_slug(login) do
- {:ok, slug} ->
- case UserManager.admin_create_user(slug, user_params) do
- {:ok, user} ->
- conn
- |> Guardian.Plug.sign_in(user)
- |> redirect(to: "/")
- {:error, changeset} ->
- IO.inspect(changeset)
- conn
- |> assign(:no_navbar_links, true)
- |> assign(:changeset, changeset)
- |> assign(:action, Routes.page_path(conn, :new_admin))
- |> render("new_admin.html")
- end
+ case UserManager.admin_create_user(user_params) do
+ {:ok, user} ->
+ conn
+ |> Guardian.Plug.sign_in(user)
+ |> redirect(to: "/")
{:error, changeset} ->
IO.inspect(changeset)
conn
diff --git a/lib/kmxgit_web/controllers/registration_controller.ex b/lib/kmxgit_web/controllers/registration_controller.ex
index 54178cb..82e3959 100644
--- a/lib/kmxgit_web/controllers/registration_controller.ex
+++ b/lib/kmxgit_web/controllers/registration_controller.ex
@@ -5,8 +5,10 @@ defmodule KmxgitWeb.RegistrationController do
def new(conn, _) do
changeset = UserManager.change_user(%User{})
- render(conn, "new.html", changeset: changeset,
- action: Routes.registration_path(conn, :register))
+ conn
+ |> assign(:action, Routes.registration_path(conn, :register))
+ |> assign(:changeset, changeset)
+ |> render("new.html")
end
def register(conn, params) do
@@ -14,11 +16,13 @@ defmodule KmxgitWeb.RegistrationController do
{:ok, user} ->
conn
|> Guardian.Plug.sign_in(user)
- |> redirect(to: User.after_register_path(user))
+ |> redirect(to: Routes.slug_path(conn, :show, user.slug.slug))
{:error, changeset} ->
conn
- |> render("new.html", changeset: changeset,
- action: Routes.registration_path(conn, :register))
+ |> assign(:action, Routes.registration_path(conn, :register))
+ |> assign(:changeset, changeset)
+ |> render("new.html")
+
end
end
end
diff --git a/lib/kmxgit_web/controllers/repository_controller.ex b/lib/kmxgit_web/controllers/repository_controller.ex
new file mode 100644
index 0000000..161cc2c
--- /dev/null
+++ b/lib/kmxgit_web/controllers/repository_controller.ex
@@ -0,0 +1,93 @@
+defmodule KmxgitWeb.RepositoryController do
+ use KmxgitWeb, :controller
+
+ alias Kmxgit.RepositoryManager
+
+ def new(conn, params) do
+ current_user = conn.assigns.current_user
+ # TODO: check the owner part of path
+ changeset = RepositoryManager.change_repository
+ conn
+ |> assign(:action, Routes.repository_path(conn, :create, params["owner"]))
+ |> assign(:changeset, changeset)
+ |> render("new.html")
+ end
+
+ def create(conn, params) do
+ current_user = conn.assigns.current_user
+ # TODO: handle organisations
+ owner = current_user
+ # TODO: check the owner part of path
+ case RepositoryManager.create_repository(current_user, params["repository"]) do
+ {:ok, repository} ->
+ conn
+ |> redirect(to: Routes.repository_path(conn, :show, owner.slug.slug, repository.slug))
+ {:error, changeset} ->
+ IO.inspect(changeset)
+ conn
+ |> assign(:action, Routes.repository_path(conn, :create, owner.slug))
+ |> assign(:changeset, changeset)
+ |> render("new.html")
+ end
+ end
+
+ defp not_found(conn) do
+ conn
+ |> put_status(:not_found)
+ |> put_view(ErrorView)
+ |> render(:"404")
+ end
+
+ def show(conn, params) do
+ slug = Enum.join(params["slug"], "/")
+ repo = RepositoryManager.get_repository_by_owner_and_slug(params["owner"], slug)
+ if repo do
+ org = repo.organisation
+ user = repo.user
+ conn
+ |> assign(:current_repository, repo)
+ |> assign_current_organisation(org)
+ |> assign(:owner, org || user)
+ |> render("show.html")
+ else
+ not_found(conn)
+ end
+ end
+
+ defp assign_current_organisation(conn, nil), do: conn
+ defp assign_current_organisation(conn, org) do
+ assign(conn, :current_organisation, org)
+ end
+
+ def edit(conn, params) do
+ org = RepositoryManager.get_repository_by_slug(params["slug"])
+ changeset = RepositoryManager.change_repository(org)
+ if org do
+ conn
+ |> assign(:action, Routes.repository_path(conn, :update, org.slug.slug))
+ |> assign(:changeset, changeset)
+ |> assign(:current_repository, org)
+ |> render("edit.html")
+ else
+ not_found(conn)
+ end
+ end
+
+ def update(conn, params) do
+ repository = RepositoryManager.get_repository_by_slug(params["slug"])
+ if repository do
+ case RepositoryManager.update_repository(repository, params["repository"]) do
+ {:ok, org} ->
+ conn
+ |> redirect(to: Routes.slug_path(conn, :show, org.slug.slug))
+ {:error, changeset} ->
+ IO.inspect(changeset)
+ conn
+ |> render("edit.html", changeset: changeset,
+ action: Routes.repository_path(conn, :update, repository.slug.slug))
+ end
+ else
+ not_found(conn)
+ end
+ end
+end
diff --git a/lib/kmxgit_web/controllers/session_controller.ex b/lib/kmxgit_web/controllers/session_controller.ex
index f5178ed..4651c06 100644
--- a/lib/kmxgit_web/controllers/session_controller.ex
+++ b/lib/kmxgit_web/controllers/session_controller.ex
@@ -7,7 +7,7 @@ defmodule KmxgitWeb.SessionController do
changeset = UserManager.change_user(%User{})
user = UserManager.Guardian.Plug.current_resource(conn)
if user do
- redirect(conn, to: params["redirect"] || User.after_login_path(user))
+ redirect(conn, to: params["redirect"] || Routes.user_path(KmxgitWeb.Endpoint, :show, user.slug.slug))
else
redirect = params["redirect"]
action = if redirect do
@@ -39,7 +39,7 @@ defmodule KmxgitWeb.SessionController do
defp login_reply(conn, {:ok, user}, redirect) do
conn
|> UserManager.Guardian.Plug.sign_in(user)
- |> redirect(to: redirect || User.after_login_path(user))
+ |> redirect(to: redirect || Routes.user_path(KmxgitWeb.Endpoint, :show, user.slug.slug))
end
defp login_reply(conn, {:error, reason}, _redirect) do
diff --git a/lib/kmxgit_web/controllers/user_controller.ex b/lib/kmxgit_web/controllers/user_controller.ex
index 63a8f6d..93461e3 100644
--- a/lib/kmxgit_web/controllers/user_controller.ex
+++ b/lib/kmxgit_web/controllers/user_controller.ex
@@ -48,7 +48,7 @@ defmodule KmxgitWeb.UserController do
case UserManager.update_user(current_user, params["user"]) do
{:ok, user} ->
conn
- |> redirect(to: Routes.user_path(conn, :show, user.slug.slug))
+ |> redirect(to: Routes.slug_path(conn, :show, user.slug.slug))
{:error, changeset} ->
conn
|> assign(:page_title, gettext("Edit user %{login}", login: current_user.slug.slug))
diff --git a/lib/kmxgit_web/router.ex b/lib/kmxgit_web/router.ex
index 1ca56a4..1180775 100644
--- a/lib/kmxgit_web/router.ex
+++ b/lib/kmxgit_web/router.ex
@@ -44,25 +44,27 @@ defmodule KmxgitWeb.Router do
end
get "/_register", RegistrationController, :new
- post "/", RegistrationController, :register
+ post "/_register", RegistrationController, :register
end
# definitely logged in, will redirect to login page
scope "/", KmxgitWeb do
pipe_through [:browser, :auth, :ensure_auth]
- scope "/_o" do
- get "/_new", OrganisationController, :new
- post "/", OrganisationController, :create
- get "/:slug", OrganisationController, :show
- get "/:slug/_edit", OrganisationController, :edit
- put "/:slug", OrganisationController, :update
+ scope "/_new" do
+ get "/organisation", OrganisationController, :new
+ post "/organisation", OrganisationController, :create
+ get "/:owner", RepositoryController, :new
+ post "/:owner", RepositoryController, :create
end
- scope "/_u" do
- get "/:login", UserController, :show
- get "/:login/_edit", UserController, :edit
- put "/:login", UserController, :update
+ scope "/_edit/" do
+ get "/organisation/:slug", OrganisationController, :edit
+ 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
end
scope "/admin", Admin, as: "admin" do
@@ -81,6 +83,7 @@ defmodule KmxgitWeb.Router do
pipe_through [:browser, :auth]
get "/:slug", SlugController, :show
+ get "/:owner/*slug", RepositoryController, :show
end
# Other scopes may use custom stacks.
diff --git a/lib/kmxgit_web/templates/admin/organisation/index.html.heex b/lib/kmxgit_web/templates/admin/organisation/index.html.heex
index e9adaeb..800e554 100644
--- a/lib/kmxgit_web/templates/admin/organisation/index.html.heex
+++ b/lib/kmxgit_web/templates/admin/organisation/index.html.heex
@@ -11,7 +11,7 @@
<tr>
<td><%= link org.id, to: Routes.admin_organisation_path(@conn, :show, org) %></td>
<td><%= org.name %></td>
- <td><%= link org.slug.slug, to: Routes.organisation_path(@conn, :show, org.slug.slug) %></td>
+ <td><%= link org.slug.slug, to: Routes.slug_path(@conn, :show, org.slug.slug) %></td>
</tr>
<% end %>
</table>
diff --git a/lib/kmxgit_web/templates/admin/organisation/show.html.heex b/lib/kmxgit_web/templates/admin/organisation/show.html.heex
index 5bf3e00..6efd2eb 100644
--- a/lib/kmxgit_web/templates/admin/organisation/show.html.heex
+++ b/lib/kmxgit_web/templates/admin/organisation/show.html.heex
@@ -8,11 +8,11 @@
</tr>
<tr>
<th><%= gettext "Name" %></th>
- <td><%= link @org.name, to: Routes.organisation_path(@conn, :show, @org.slug.slug) %></td>
+ <td><%= link @org.name, to: Routes.slug_path(@conn, :show, @org.slug.slug) %></td>
</tr>
<tr>
<th><%= gettext "Slug" %></th>
- <td><%= link @org.slug.slug, to: Routes.organisation_path(@conn, :show, @org.slug.slug) %></td>
+ <td><%= link @org.slug.slug, to: Routes.slug_path(@conn, :show, @org.slug.slug) %></td>
</tr>
<tr>
<th><%= gettext "Description" %></th>
diff --git a/lib/kmxgit_web/templates/admin/user/index.html.heex b/lib/kmxgit_web/templates/admin/user/index.html.heex
index a05c437..150ee82 100644
--- a/lib/kmxgit_web/templates/admin/user/index.html.heex
+++ b/lib/kmxgit_web/templates/admin/user/index.html.heex
@@ -13,7 +13,7 @@
<td><%= link user.id, to: Routes.admin_user_path(@conn, :show, user) %></td>
<td><%= user.name %></td>
<td><%= link user.email, to: "mailto:#{user.email}" %></td>
- <td><%= link user.slug.slug, to: Routes.user_path(@conn, :show, user.slug.slug) %></td>
+ <td><%= link user.slug.slug, to: Routes.slug_path(@conn, :show, user.slug.slug) %></td>
<td><%= user.is_admin %></td>
</tr>
<% end %>
diff --git a/lib/kmxgit_web/templates/admin/user/show.html.heex b/lib/kmxgit_web/templates/admin/user/show.html.heex
index 1c2d231..2003993 100644
--- a/lib/kmxgit_web/templates/admin/user/show.html.heex
+++ b/lib/kmxgit_web/templates/admin/user/show.html.heex
@@ -15,7 +15,7 @@
</tr>
<tr>
<th><%= gettext "Login" %></th>
- <td><%= link @user.slug.slug, to: Routes.user_path(@conn, :show, @user.slug.slug) %></td>
+ <td><%= link @user.slug.slug, to: Routes.slug_path(@conn, :show, @user.slug.slug) %></td>
</tr>
<tr>
<th><%= gettext "Description" %></th>
diff --git a/lib/kmxgit_web/templates/layout/nav_connected.html.heex b/lib/kmxgit_web/templates/layout/nav_connected.html.heex
index 78ad2ef..277741d 100644
--- a/lib/kmxgit_web/templates/layout/nav_connected.html.heex
+++ b/lib/kmxgit_web/templates/layout/nav_connected.html.heex
@@ -1,12 +1,12 @@
<%= if @conn.assigns[:current_organisation] do %>
<li class="nav-item">
<%= link @current_organisation.name || @current_organisation.slug.slug,
- to: Routes.organisation_path(@conn, :show, @current_organisation.slug),
+ to: Routes.slug_path(@conn, :show, @current_organisation.slug.slug),
class: "nav-link" %>
</li>
<% end %>
<li class="nav-item">
- <%= link @current_user.slug.slug, to: Routes.user_path(@conn, :show, @current_user.slug.slug), class: "nav-link" %>
+ <%= link @current_user.slug.slug, to: Routes.slug_path(@conn, :show, @current_user.slug.slug), class: "nav-link" %>
</li>
<%= if @current_user.is_admin do %>
<li class="nav-item">
diff --git a/lib/kmxgit_web/templates/organisation/show.html.heex b/lib/kmxgit_web/templates/organisation/show.html.heex
index d6ba952..04c9cf2 100644
--- a/lib/kmxgit_web/templates/organisation/show.html.heex
+++ b/lib/kmxgit_web/templates/organisation/show.html.heex
@@ -40,7 +40,7 @@
<th><%= gettext "Users" %></th>
<td>
<%= for user <- @org.users do %>
- <%= link(user.slug.slug, to: Routes.user_path(@conn, :show, user.slug.slug), class: "user") %>
+ <%= link(user.slug.slug, to: Routes.slug_path(@conn, :show, user.slug.slug), class: "user") %>
<% end %>
</td>
</tr>
diff --git a/lib/kmxgit_web/templates/page/new_admin.html.heex b/lib/kmxgit_web/templates/page/new_admin.html.heex
index 50144ba..9901753 100644
--- a/lib/kmxgit_web/templates/page/new_admin.html.heex
+++ b/lib/kmxgit_web/templates/page/new_admin.html.heex
@@ -23,11 +23,13 @@
<%= error_tag f, :email %>
</div>
- <div class="mb-3">
- <%= label f, :login, class: "form-label" %>
- <%= text_input f, :login, class: "form-control" %>
- <%= error_tag f, :login %>
- </div>
+ <%= inputs_for f, :slug, fn ff -> %>
+ <div class="mb-3">
+ <%= label ff, :slug, class: "form-label" %>
+ <%= text_input ff, :slug, class: "form-control" %>
+ <%= error_tag ff, :slug %>
+ </div>
+ <% end %>
<div class="mb-3">
<%= label f, :password, class: "form-label" %>
diff --git a/lib/kmxgit_web/templates/registration/new.html.heex b/lib/kmxgit_web/templates/registration/new.html.heex
index df1a754..a79ad95 100644
--- a/lib/kmxgit_web/templates/registration/new.html.heex
+++ b/lib/kmxgit_web/templates/registration/new.html.heex
@@ -1,7 +1,7 @@
<div class="container-fluid">
<h1><%= gettext "Register" %></h1>
- <%= form_for @changeset, @action, fn f -> %>
+ <%= form_for @changeset, @action, [as: "user"], fn f -> %>
<div class="mb-3">
<%= label f, :name, class: "form-label" %>
@@ -15,11 +15,13 @@
<%= error_tag f, :email %>
</div>
- <div class="mb-3">
- <%= label f, :login, class: "form-label" %>
- <%= text_input f, :login, class: "form-control" %>
- <%= error_tag f, :login %>
- </div>
+ <%= inputs_for f, :slug, fn ff -> %>
+ <div class="mb-3">
+ <%= label ff, :slug, gettext("Login"), class: "form-label" %>
+ <%= text_input ff, :slug, class: "form-control" %>
+ <%= error_tag ff, :slug %>
+ </div>
+ <% end %>
<div class="mb-3">
<%= label f, :password, class: "form-label" %>
diff --git a/lib/kmxgit_web/templates/repository/form.html.heex b/lib/kmxgit_web/templates/repository/form.html.heex
new file mode 100644
index 0000000..fe584fa
--- /dev/null
+++ b/lib/kmxgit_web/templates/repository/form.html.heex
@@ -0,0 +1,19 @@
+<%= form_for @changeset, @action, fn f -> %>
+
+ <div class="mb-3">
+ <%= label f, :slug, class: "form-label" %>
+ <%= text_input f, :slug, class: "form-control" %>
+ <%= error_tag f, :slug %>
+ </div>
+
+ <div class="mb-3">
+ <%= label f, :description, class: "form-label" %>
+ <%= textarea f, :description, class: "form-control" %>
+ <%= error_tag f, :description %>
+ </div>
+
+ <div class="mb-3">
+ <%= submit gettext("Submit"), class: "btn btn-primary" %>
+ </div>
+
+<% end %>
diff --git a/lib/kmxgit_web/templates/repository/new.html.heex b/lib/kmxgit_web/templates/repository/new.html.heex
new file mode 100644
index 0000000..e806943
--- /dev/null
+++ b/lib/kmxgit_web/templates/repository/new.html.heex
@@ -0,0 +1,4 @@
+<div class="container-fluid">
+ <h1>New repository</h1>
+ <%= render "form.html", assigns %>
+</div>
diff --git a/lib/kmxgit_web/templates/user/edit.html.heex b/lib/kmxgit_web/templates/user/edit.html.heex
index c0e1c5d..1d82b1b 100644
--- a/lib/kmxgit_web/templates/user/edit.html.heex
+++ b/lib/kmxgit_web/templates/user/edit.html.heex
@@ -41,7 +41,7 @@
<div class="mb-3">
<%= link gettext("Cancel"),
- to: Routes.user_path(@conn, :show, @current_user.slug.slug),
+ to: Routes.slug_path(@conn, :show, @current_user.slug.slug),
class: "btn btn-secondary" %>
<%= submit gettext("Submit"), class: "btn btn-primary" %>
diff --git a/lib/kmxgit_web/templates/user/show.html.heex b/lib/kmxgit_web/templates/user/show.html.heex
index 387eab7..dfbcd3a 100644
--- a/lib/kmxgit_web/templates/user/show.html.heex
+++ b/lib/kmxgit_web/templates/user/show.html.heex
@@ -4,6 +4,9 @@
<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" %>
@@ -14,6 +17,9 @@
<div class="col col-12 col-md-7">
<hr/>
<h2><%= gettext "Repositories" %></h2>
+ <%= for repo <- @user.repositories do %>
+ <%= link repo.slug, to: Routes.repository_path(@conn, :show, @user.slug.slug, String.split(repo.slug, "/")) %>
+ <% end %>
</div>
<div class="col col-12 col-md-4">
<hr/>
@@ -45,7 +51,7 @@
</th>
<td>
<%= for org <- @user.organisations do %>
- <%= link(org.name || org.slug.slug, to: Routes.organisation_path(@conn, :show, org.slug.slug), class: "org") %>
+ <%= 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") %>
diff --git a/lib/kmxgit_web/views/repository_view.ex b/lib/kmxgit_web/views/repository_view.ex
new file mode 100644
index 0000000..08f0b6a
--- /dev/null
+++ b/lib/kmxgit_web/views/repository_view.ex
@@ -0,0 +1,3 @@
+defmodule KmxgitWeb.RepositoryView do
+ use KmxgitWeb, :view
+end
diff --git a/priv/repo/migrations/20211118161213_create_repositories.exs b/priv/repo/migrations/20211118161213_create_repositories.exs
new file mode 100644
index 0000000..1243c05
--- /dev/null
+++ b/priv/repo/migrations/20211118161213_create_repositories.exs
@@ -0,0 +1,14 @@
+defmodule Kmxgit.Repo.Migrations.CreateRepositories do
+ use Ecto.Migration
+
+ def change do
+ create table(:repositories) do
+ add :slug, :string, unique: true
+ add :description, :string
+ add :organisation_id, references(:organisations), null: true
+ add :user_id, references(:users), null: true
+ timestamps()
+ end
+ create index(:repositories, ["(lower(slug))"], unique: true)
+ end
+end