diff --git a/lib/kmxgit/repository_manager.ex b/lib/kmxgit/repository_manager.ex
index e7d5888..856d778 100644
--- a/lib/kmxgit/repository_manager.ex
+++ b/lib/kmxgit/repository_manager.ex
@@ -26,23 +26,25 @@ defmodule Kmxgit.RepositoryManager do
end)
end
- def change_repository(repository \\ %Repository{}) do
+ def change_repository() do
+ change_repository(%Repository{})
+ end
+ def change_repository(repository = %Repository{}) do
Repository.changeset(repository, %{})
end
-
- defp put_owner(changeset, owner) do
- case owner do
- %User{} ->
- Ecto.Changeset.put_assoc(changeset, :user, owner)
- %Organisation{} ->
- Ecto.Changeset.put_assoc(changeset, :organisation, owner)
- end
+ def change_repository(owner) do
+ change_repository(%Repository{}, owner)
+ end
+ def change_repository(repository = %Repository{}, owner = %Organisation{}) do
+ Repository.owner_changeset(repository, %{}, owner)
+ end
+ def change_repository(repository = %Repository{}, owner = %User{}) do
+ Repository.owner_changeset(repository, %{}, owner)
end
- def create_repository(owner, attrs \\ %{}) do
+ def create_repository(attrs \\ %{}, owner) do
%Repository{}
- |> Repository.changeset(attrs)
- |> put_owner(owner)
+ |> Repository.owner_changeset(attrs, owner)
|> Repo.insert()
end
@@ -65,6 +67,17 @@ defmodule Kmxgit.RepositoryManager do
get_repository(id) || raise Ecto.NoResultsError
end
+ def get_repository_by_owner_id_and_slug(org_id, nil, slug) do
+ Repo.one from r in Repository,
+ where: r.organisation_id == ^org_id and is_nil(r.user_id) and fragment("lower(?)", r.slug) == ^String.downcase(slug),
+ limit: 1
+ end
+ def get_repository_by_owner_id_and_slug(nil, user_id, slug) do
+ Repo.one from r in Repository,
+ where: is_nil(r.organisation_id) and r.user_id == ^user_id and fragment("lower(?)", r.slug) == ^String.downcase(slug),
+ limit: 1
+ end
+
def get_repository_by_owner_and_slug(owner, slug) do
downcase_owner = String.downcase(owner)
downcase_slug = String.downcase(slug)
@@ -80,7 +93,8 @@ defmodule Kmxgit.RepositoryManager do
where: (fragment("lower(?)", os.slug) == ^downcase_owner or fragment("lower(?)", us.slug) == ^downcase_owner) and fragment("lower(?)", r.slug) == ^downcase_slug,
preload: [members: :slug,
organisation: [:slug, [users: :slug]],
- user: :slug]
+ user: :slug],
+ limit: 1
end
def add_member(%Repository{} = repo, login) do
diff --git a/lib/kmxgit/repository_manager/repository.ex b/lib/kmxgit/repository_manager/repository.ex
index 4920f5d..38f3340 100644
--- a/lib/kmxgit/repository_manager/repository.ex
+++ b/lib/kmxgit/repository_manager/repository.ex
@@ -3,7 +3,10 @@ defmodule Kmxgit.RepositoryManager.Repository do
use Ecto.Schema
import Ecto.Changeset
+ alias Kmxgit.RepositoryManager
+ alias Kmxgit.OrganisationManager
alias Kmxgit.OrganisationManager.Organisation
+ alias Kmxgit.UserManager
alias Kmxgit.UserManager.User
schema "repositories" do
@@ -15,22 +18,66 @@ defmodule Kmxgit.RepositoryManager.Repository do
timestamps()
end
- def changeset(repository, attrs \\ %{}) do
+ def changeset(repository, attrs) do
repository
|> cast(attrs, [:description, :slug])
+ |> common_changeset()
+ end
+
+ def owner_changeset(repository, attrs, owner = %Organisation{}) do
+ repository
+ |> cast(attrs, [: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])
+ |> put_assoc(:organisation, nil)
+ |> put_assoc(:user, owner)
+ |> common_changeset()
+ end
+
+ defp common_changeset(changeset) do
+ changeset
|> validate_required([:slug])
|> validate_format(:slug, ~r|^[A-Za-z][-_+.@0-9A-Za-z]{0,64}(/[A-Za-z][-_+.@0-9A-Za-z]{0,64})*$|)
- |> validate_slug_uniqueness()
+ |> validate_required_owner()
+ |> validate_unique_slug()
|> Markdown.validate_markdown(:description)
end
- def validate_slug_uniqueness(changeset = %Ecto.Changeset{changes: %{slug: slug}}) do
- IO.inspect [changeset, slug]
- changeset
+ defp validate_required_owner(changeset) do
+ org = get_field(changeset, :organisation)
+ user = get_field(changeset, :user)
+ owner = org || user
+ if owner do
+ changeset
+ else
+ changeset
+ |> add_error(:organisation, "can't be blank")
+ |> add_error(:user, "can't be blank")
+ end
end
- def validate_slug_uniqueness(changeset) do
- IO.inspect changeset
+ defp validate_unique_slug(changeset = %Ecto.Changeset{valid?: true}) do
+ org = get_field(changeset, :organisation)
+ user = get_field(changeset, :user)
+ owner = org || user
+ slug = get_field(changeset, :slug)
+ if repo = RepositoryManager.get_repository_by_owner_and_slug(owner.slug.slug, slug) do
+ if repo.id != changeset.data.id do
+ changeset
+ |> add_error(:slug, "is already taken")
+ else
+ changeset
+ end
+ else
+ changeset
+ end
+ end
+ defp validate_unique_slug(changeset) do
changeset
end
diff --git a/lib/kmxgit_web/controllers/repository_controller.ex b/lib/kmxgit_web/controllers/repository_controller.ex
index e7236a1..9386022 100644
--- a/lib/kmxgit_web/controllers/repository_controller.ex
+++ b/lib/kmxgit_web/controllers/repository_controller.ex
@@ -9,13 +9,13 @@ defmodule KmxgitWeb.RepositoryController do
def new(conn, params) do
action = Routes.repository_path(conn, :create, params["owner"])
- changeset = RepositoryManager.change_repository
current_user = conn.assigns.current_user
slug = SlugManager.get_slug(params["owner"])
if !slug do
not_found(conn)
else
if slug.user && slug.user.id == current_user.id do
+ changeset = RepositoryManager.change_repository(slug.user)
conn
|> assign(:action, action)
|> assign(:changeset, changeset)
@@ -23,7 +23,8 @@ defmodule KmxgitWeb.RepositoryController do
|> render("new.html")
else
org = slug.organisation
- if org && org.users |> Enum.find(& &1.id == current_user.id) do
+ if org && Organisation.owner?(org, current_user) do
+ changeset = RepositoryManager.change_repository(org)
conn
|> assign(:action, action)
|> assign(:changeset, changeset)
@@ -45,11 +46,11 @@ defmodule KmxgitWeb.RepositoryController do
else
user = slug.user
if user && user.id == current_user.id do
- create_repo(conn, user, params["repository"])
+ create_repo(conn, params["repository"], user)
else
org = slug.organisation
if org && org.users |> Enum.find(& &1.id == current_user.id) do
- create_repo(conn, org, params["repository"])
+ create_repo(conn, params["repository"], org)
else
not_found(conn)
end
@@ -57,9 +58,9 @@ defmodule KmxgitWeb.RepositoryController do
end
end
- defp create_repo(conn, owner, params) do
+ defp create_repo(conn, params, owner) do
case Repo.transaction(fn ->
- case RepositoryManager.create_repository(owner, params) do
+ case RepositoryManager.create_repository(params, owner) do
{:ok, repo} ->
case GitManager.create(Repository.full_slug(repo)) do
{:ok, _} -> repo
diff --git a/priv/repo/migrations/20211118161213_create_repositories.exs b/priv/repo/migrations/20211118161213_create_repositories.exs
index 1243c05..31ca6ca 100644
--- a/priv/repo/migrations/20211118161213_create_repositories.exs
+++ b/priv/repo/migrations/20211118161213_create_repositories.exs
@@ -3,12 +3,11 @@ defmodule Kmxgit.Repo.Migrations.CreateRepositories do
def change do
create table(:repositories) do
- add :slug, :string, unique: true
+ add :slug, :string
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