Commit 8667cd1508c4222389e3a8ff76f11ffbe1d5c321

Thomas de Grivel 2021-11-19T14:03:43

new organisation repo, edit repo

diff --git a/lib/kmxgit/organisation_manager.ex b/lib/kmxgit/organisation_manager.ex
index 9d7ad57..31beec7 100644
--- a/lib/kmxgit/organisation_manager.ex
+++ b/lib/kmxgit/organisation_manager.ex
@@ -39,9 +39,12 @@ defmodule Kmxgit.OrganisationManager do
     Repo.one from o in Organisation,
       join: s in Slug,
       on: s.organisation_id == o.id,
-      where: s.slug == ^slug,
-      preload: :slug,
-      preload: [users: :slug]
+      where: fragment("lower(?)", s.slug) == ^String.downcase(slug),
+      preload: [:slug,
+                repositories: [organisation: :slug,
+                               user: :slug],
+                users: :slug],
+      limit: 1
   end
 
   def delete_organisation(%Organisation{} = organisation) do
diff --git a/lib/kmxgit/organisation_manager/organisation.ex b/lib/kmxgit/organisation_manager/organisation.ex
index 2e63dd9..553d148 100644
--- a/lib/kmxgit/organisation_manager/organisation.ex
+++ b/lib/kmxgit/organisation_manager/organisation.ex
@@ -3,12 +3,14 @@ defmodule Kmxgit.OrganisationManager.Organisation do
   use Ecto.Schema
   import Ecto.Changeset
 
+  alias Kmxgit.RepositoryManager.Repository
   alias Kmxgit.SlugManager.Slug
   alias Kmxgit.UserManager.User
 
   schema "organisations" do
     field :description, :string
     field :name, :string
+    has_many :repositories, Repository
     many_to_many :users, User, join_through: "users_organisations", on_delete: :delete_all
     has_one :slug, Slug, on_delete: :delete_all
     timestamps()
diff --git a/lib/kmxgit/repository_manager.ex b/lib/kmxgit/repository_manager.ex
index d596007..9bd0a8d 100644
--- a/lib/kmxgit/repository_manager.ex
+++ b/lib/kmxgit/repository_manager.ex
@@ -61,7 +61,7 @@ defmodule Kmxgit.RepositoryManager do
       full_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,
-      preload: [organisation: :slug],
+      preload: [organisation: [:slug, :users]],
       preload: [user: :slug]
   end
 
diff --git a/lib/kmxgit/repository_manager/repository.ex b/lib/kmxgit/repository_manager/repository.ex
index ca96d00..d9e1fff 100644
--- a/lib/kmxgit/repository_manager/repository.ex
+++ b/lib/kmxgit/repository_manager/repository.ex
@@ -23,10 +23,10 @@ defmodule Kmxgit.RepositoryManager.Repository do
     |> Markdown.validate_markdown(:description)
   end
 
-  def owner(repo = %__MODULE__{organisation: org = %Organisation{}}) do
+  def owner(%__MODULE__{organisation: org = %Organisation{}}) do
     org
   end
-  def owner(repo = %__MODULE__{user: user = %User{}}) do
+  def owner(%__MODULE__{user: user = %User{}}) do
     user
   end
 
diff --git a/lib/kmxgit/slug_manager.ex b/lib/kmxgit/slug_manager.ex
index f71a06a..f159104 100644
--- a/lib/kmxgit/slug_manager.ex
+++ b/lib/kmxgit/slug_manager.ex
@@ -24,8 +24,10 @@ defmodule Kmxgit.SlugManager do
 
   def get_slug(slug) do
     Repo.one from s in Slug,
-      where: fragment("lower(slug)") == ^String.downcase(slug),
+      where: fragment("lower(?)", s.slug) == ^String.downcase(slug),
       preload: [organisation: [:slug,
+                               repositories: [organisation: :slug,
+                                              user: :slug],
                                users: :slug],
                 user: [:slug,
                        organisations: :slug,
diff --git a/lib/kmxgit_web/controllers/page_controller.ex b/lib/kmxgit_web/controllers/page_controller.ex
index 964a934..123c3b8 100644
--- a/lib/kmxgit_web/controllers/page_controller.ex
+++ b/lib/kmxgit_web/controllers/page_controller.ex
@@ -2,7 +2,6 @@ defmodule KmxgitWeb.PageController do
   use KmxgitWeb, :controller
 
   alias Kmxgit.Repo
-  alias Kmxgit.SlugManager
   alias Kmxgit.UserManager
   alias Kmxgit.UserManager.{Guardian, User}
 
diff --git a/lib/kmxgit_web/controllers/repository_controller.ex b/lib/kmxgit_web/controllers/repository_controller.ex
index 038c2b7..ba1880e 100644
--- a/lib/kmxgit_web/controllers/repository_controller.ex
+++ b/lib/kmxgit_web/controllers/repository_controller.ex
@@ -2,26 +2,72 @@ defmodule KmxgitWeb.RepositoryController do
   use KmxgitWeb, :controller
 
   alias Kmxgit.RepositoryManager
+  alias Kmxgit.RepositoryManager.Repository
+  alias Kmxgit.SlugManager
 
   def new(conn, params) do
-    current_user = conn.assigns.current_user
-    # TODO: check the owner part of path
+    action = Routes.repository_path(conn, :create, params["owner"])
     changeset = RepositoryManager.change_repository
-    conn
-    |> assign(:action, Routes.repository_path(conn, :create, params["owner"]))
-    |> assign(:changeset, changeset)
-    |> render("new.html")
+    current_user = conn.assigns.current_user
+    slug = SlugManager.get_slug(params["owner"])
+    if !slug do
+      not_found(conn)
+    else
+      user = slug.user
+      if user do
+        if user != current_user && !current_user.is_admin do
+          not_found(conn)
+        else
+          conn
+          |> assign(:action, action)
+          |> assign(:changeset, changeset)
+          |> render("new.html")
+        end
+      else
+        org = slug.organisation
+        if org do
+          conn
+          |> assign(:action, action)
+          |> assign(:changeset, changeset)
+          |> assign(:current_organisation, org)
+          |> render("new.html")
+        else
+          not_found(conn)
+        end
+      end
+    end
   end
 
   def create(conn, params) do
     current_user = conn.assigns.current_user
-    # TODO: handle organisations
-    owner = current_user
+    slug = SlugManager.get_slug(params["owner"])
+    if !slug do
+      not_found(conn)
+    else
+      user = slug.user
+      if user do
+        if user != current_user && !current_user.is_admin do
+          not_found(conn)
+        else
+          create_repo(conn, user, params["repository"])
+        end
+      else
+        org = slug.organisation
+        if org do
+          create_repo(conn, org, params["repository"])
+        else
+          not_found(conn)
+        end
+      end
+    end
+  end
     # TODO: check the owner part of path
-    case RepositoryManager.create_repository(current_user, params["repository"]) do
-      {:ok, repository} ->
+
+  defp create_repo(conn, owner, params) do
+    case RepositoryManager.create_repository(owner, params) do
+      {:ok, repo} ->
         conn
-        |> redirect(to: Routes.repository_path(conn, :show, owner.slug.slug, repository.slug))
+        |> redirect(to: Routes.repository_path(conn, :show, owner.slug.slug, Repository.splat(repo)))
       {:error, changeset} ->
         IO.inspect(changeset)
         conn
@@ -40,10 +86,9 @@ defmodule KmxgitWeb.RepositoryController do
 
   def show(conn, params) do
     slug = Enum.join(params["slug"], "/")
-    repo =  RepositoryManager.get_repository_by_owner_and_slug(params["owner"], slug)
+    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)
@@ -55,36 +100,49 @@ defmodule KmxgitWeb.RepositoryController do
   end
 
   def edit(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)
-    changeset = RepositoryManager.change_repository(repo)
+    repo = RepositoryManager.get_repository_by_owner_and_slug(params["owner"], slug)
     if repo do
       org = repo.organisation
-      user = repo.user
-      conn
-      |> assign(:action, Routes.repository_path(conn, :update, org.slug.slug))
-      |> assign(:changeset, changeset)
-      |> assign_current_organisation(org)
-      |> assign(:current_repository, repo)
-      |> assign(:repo, repo)
-      |> render("edit.html")
+      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
     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))
+    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 RepositoryManager.update_repository(repo, params["repository"]) do
+          {:ok, repo} ->
+            conn
+            |> redirect(to: Routes.repository_path(conn, :show, params["owner"], Repository.splat(repo)))
+          {:error, changeset} ->
+            IO.inspect(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
     else
       not_found(conn)
diff --git a/lib/kmxgit_web/controllers/slug_controller.ex b/lib/kmxgit_web/controllers/slug_controller.ex
index ba40c07..366a542 100644
--- a/lib/kmxgit_web/controllers/slug_controller.ex
+++ b/lib/kmxgit_web/controllers/slug_controller.ex
@@ -23,14 +23,17 @@ defmodule KmxgitWeb.SlugController do
         conn
         |> assign(:page_title, gettext("User %{login}", login: user.slug.slug))
         |> assign(:user, user)
-        |> render(UserView, "show.html")
+        |> put_view(UserView)
+        |> render("show.html")
       else
         org = slug.organisation
         if org do
           conn
           |> assign(:current_organisation, org)
           |> assign(:org, org)
-          |> render(OrganisationView, "show.html")
+          |> assign(:page_title, org.name || org.slug.slug)
+          |> put_view(OrganisationView)
+          |> render("show.html")
         else
           not_found(conn)
         end
diff --git a/lib/kmxgit_web/templates/organisation/show.html.heex b/lib/kmxgit_web/templates/organisation/show.html.heex
index 04c9cf2..ddf0dc6 100644
--- a/lib/kmxgit_web/templates/organisation/show.html.heex
+++ b/lib/kmxgit_web/templates/organisation/show.html.heex
@@ -4,6 +4,9 @@
       <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" %>
@@ -15,6 +18,9 @@
     <div class="col col-12 col-md-7">
       <hr/>
       <h2><%= gettext "Repositories" %></h2>
+      <%= for repo <- @org.repositories do %>
+        <%= link Repository.full_slug(repo), to: Routes.repository_path(@conn, :show, @org.slug.slug, Repository.splat(repo)) %>
+      <% end %>
     </div>
     <div class="col col-12 col-md-4">
       <hr/>
diff --git a/lib/kmxgit_web/templates/repository/edit.html.heex b/lib/kmxgit_web/templates/repository/edit.html.heex
new file mode 100644
index 0000000..a8e8bf7
--- /dev/null
+++ b/lib/kmxgit_web/templates/repository/edit.html.heex
@@ -0,0 +1,7 @@
+<div class="container-fluid">
+  <h1>
+    <%= gettext "Edit repository" %>
+    <%= Repository.full_slug(@repo) %>
+  </h1>
+  <%= render "form.html", assigns %>
+</div>
diff --git a/lib/kmxgit_web/views/organisation_view.ex b/lib/kmxgit_web/views/organisation_view.ex
index 12fbdd5..1e9b731 100644
--- a/lib/kmxgit_web/views/organisation_view.ex
+++ b/lib/kmxgit_web/views/organisation_view.ex
@@ -1,3 +1,5 @@
 defmodule KmxgitWeb.OrganisationView do
   use KmxgitWeb, :view
+
+  alias Kmxgit.RepositoryManager.Repository
 end