Commit 0cd4a9bc44a61c5da96f2f5ceb8c18ff2d7cd5d8

Thomas de Grivel 2021-12-11T12:13:29

public access repositories

diff --git a/lib/kmxgit/repository_manager/repository.ex b/lib/kmxgit/repository_manager/repository.ex
index 5b92bf0..7a485ad 100644
--- a/lib/kmxgit/repository_manager/repository.ex
+++ b/lib/kmxgit/repository_manager/repository.ex
@@ -14,6 +14,7 @@ defmodule Kmxgit.RepositoryManager.Repository do
     belongs_to :forked_from, __MODULE__
     belongs_to :organisation, Organisation, on_replace: :nilify
     field :owner_slug, :string, virtual: true
+    field :public_access, :boolean, null: false, default: false
     field :slug, :string
     belongs_to :user, User, on_replace: :nilify
     many_to_many :members, User, join_through: "users_repositories", on_replace: :delete, on_delete: :delete_all
@@ -22,30 +23,27 @@ defmodule Kmxgit.RepositoryManager.Repository do
 
   def changeset(repository, attrs) do
     repository
-    |> cast(attrs, [:deploy_keys, :description, :slug])
-    |> common_changeset()
+    |> common_changeset(attrs)
   end
 
   def owner_changeset(repository, attrs, owner, forked_from \\ nil)
   def owner_changeset(repository, attrs, owner = %Organisation{}, forked_from) do
     repository
-    |> cast(attrs, [:deploy_keys, :description, :slug])
     |> put_change(:organisation_id, owner.id)
     |> put_change(:user_id, nil)
     |> put_assoc(:organisation, owner)
     |> put_assoc(:user, nil)
     |> put_forked_from(forked_from)
-    |> common_changeset()
+    |> common_changeset(attrs)
   end
   def owner_changeset(repository, attrs, owner = %User{}, forked_from) do
     repository
-    |> cast(attrs, [:deploy_keys, :description, :slug])
     |> put_change(:organisation_id, nil)
     |> put_change(:user_id, owner.id)
     |> put_assoc(:organisation, nil)
     |> put_assoc(:user, owner)
     |> put_forked_from(forked_from)
-    |> common_changeset()
+    |> common_changeset(attrs)
   end
 
   defp put_forked_from(changeset, nil) do
@@ -56,10 +54,11 @@ defmodule Kmxgit.RepositoryManager.Repository do
     |> put_change(:forked_from, forked_from)
   end
 
-  defp common_changeset(changeset) do
+  defp common_changeset(changeset, attrs) 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})*$|)
+    |> cast(attrs, [:deploy_keys, :description, :public_access, :slug])
+    |> validate_required([:public_access, :slug])
+    |> validate_format(:slug, ~r|^[A-Za-z][-_+.@0-9A-Za-z]{0,63}(/[A-Za-z][-_+.@0-9A-Za-z]{0,63})*$|)
     |> validate_required_owner()
     |> validate_unique_slug()
     |> Markdown.validate_markdown(:description)
@@ -133,9 +132,11 @@ defmodule Kmxgit.RepositoryManager.Repository do
   end
 
   def owner?(repo, user) do
-    repo
-    |> owners()
-    |> Enum.find(fn u -> u.id == user.id end)
+    if user do
+      repo
+      |> owners()
+      |> Enum.find(fn u -> u.id == user.id end)
+    end
   end
 
   def members(repo) do
@@ -146,9 +147,11 @@ defmodule Kmxgit.RepositoryManager.Repository do
   end
 
   def member?(repo, user) do
-    repo
-    |> members()
-    |> Enum.find(fn u -> u.id == user.id end)
+    if user do
+      repo
+      |> members()
+      |> Enum.find(fn u -> u.id == user.id end)
+    end
   end
 
   def auth(repo) do
diff --git a/lib/kmxgit_web/controllers/repository_controller.ex b/lib/kmxgit_web/controllers/repository_controller.ex
index 62f001b..547492e 100644
--- a/lib/kmxgit_web/controllers/repository_controller.ex
+++ b/lib/kmxgit_web/controllers/repository_controller.ex
@@ -95,12 +95,12 @@ defmodule KmxgitWeb.RepositoryController do
   end
 
   def show(conn, params) do
-    current_user = conn.assigns.current_user
+    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 && Repository.member?(repo, current_user) do
+    if repo && repo.public_access || Repository.member?(repo, current_user) do
       org = repo.organisation
       user = repo.user
       git = setup_git(repo, branch || "master", path, conn)
diff --git a/lib/kmxgit_web/router.ex b/lib/kmxgit_web/router.ex
index 1084dbc..9cc3bd6 100644
--- a/lib/kmxgit_web/router.ex
+++ b/lib/kmxgit_web/router.ex
@@ -36,11 +36,11 @@ defmodule KmxgitWeb.Router do
     get  "/_new_admin",               PageController, :new_admin
     post "/_new_admin",               PageController, :new_admin_post
 
-    delete "/users/log_out",        UserSessionController, :delete
-    get    "/users/confirm",        UserConfirmationController, :new
-    post   "/users/confirm",        UserConfirmationController, :create
-    get    "/users/confirm/:token", UserConfirmationController, :edit
-    post   "/users/confirm/:token", UserConfirmationController, :update
+    delete "/_log_out",        UserSessionController, :delete
+    get    "/_confirm",        UserConfirmationController, :new
+    post   "/_confirm",        UserConfirmationController, :create
+    get    "/_confirm/:token", UserConfirmationController, :edit
+    post   "/_confirm/:token", UserConfirmationController, :update
   end
 
     ## Authentication routes
@@ -131,7 +131,10 @@ defmodule KmxgitWeb.Router do
       import Phoenix.LiveDashboard.Router
       live_dashboard "/dashboard", metrics: KmxgitWeb.Telemetry
     end
+  end
 
+  scope "/", KmxgitWeb do
+    pipe_through [:browser]
     get "/:slug", SlugController, :show
     get "/:owner/*slug", RepositoryController, :show
   end
diff --git a/lib/kmxgit_web/templates/admin/repository/form.html.heex b/lib/kmxgit_web/templates/admin/repository/form.html.heex
index 265f2ad..8ebfafb 100644
--- a/lib/kmxgit_web/templates/admin/repository/form.html.heex
+++ b/lib/kmxgit_web/templates/admin/repository/form.html.heex
@@ -11,6 +11,12 @@
     <%= error_tag f, :slug %>
   </div>
 
+  <div class="mb-3 form-check">
+    <%= checkbox f, :public_access, class: "form-check-input" %>
+    <%= label f, :public_access, class: "form-check-label" %>
+    <%= error_tag f, :public_access %>
+  </div>
+
   <div class="mb-3">
     <%= label f, :description, class: "form-label" %>
     <%= textarea f, :description, class: "form-control" %>
diff --git a/lib/kmxgit_web/templates/admin/repository/show.html.heex b/lib/kmxgit_web/templates/admin/repository/show.html.heex
index 390af70..d1d0864 100644
--- a/lib/kmxgit_web/templates/admin/repository/show.html.heex
+++ b/lib/kmxgit_web/templates/admin/repository/show.html.heex
@@ -24,6 +24,16 @@
       <td><%= link Repository.full_slug(@repo), to: Routes.repository_path(@conn, :show, Repository.owner_slug(@repo), Repository.splat(@repo)) %></td>
     </tr>
     <tr>
+      <th><%= gettext "Public access ?" %></th>
+      <td>
+        <%= if @repo.public_access do %>
+          <%= gettext "public" %>
+        <% else %>
+          <%= gettext "private" %>
+        <% end %>
+      </td>
+    </tr>
+    <tr>
       <th><%= gettext "Description" %></th>
       <td>
         <%= if @repo.description do %>
diff --git a/lib/kmxgit_web/templates/layout/admin_nav.html.heex b/lib/kmxgit_web/templates/layout/admin_nav.html.heex
index de4ee7a..6c8faa7 100644
--- a/lib/kmxgit_web/templates/layout/admin_nav.html.heex
+++ b/lib/kmxgit_web/templates/layout/admin_nav.html.heex
@@ -22,7 +22,7 @@
           <%= link "kmx git", to: "/", class: "nav-link" %>
         </li>
         <li class="navbar-item">
-          <%= link gettext("Logout"), to: Routes.user_session_path(@conn, :delete), class: "nav-link" %>
+          <%= link gettext("Logout"), method: :delete, to: Routes.user_session_path(@conn, :delete), class: "nav-link" %>
         </li>
       </ul>
     </div>
diff --git a/lib/kmxgit_web/templates/layout/nav_connected.html.heex b/lib/kmxgit_web/templates/layout/nav_connected.html.heex
index 1e688fe..c7481f9 100644
--- a/lib/kmxgit_web/templates/layout/nav_connected.html.heex
+++ b/lib/kmxgit_web/templates/layout/nav_connected.html.heex
@@ -21,5 +21,5 @@
   </li>
 <% end %>
 <li class="nav-item">
-  <%= link gettext("Logout"), to: Routes.user_session_path(@conn, :delete), class: "nav-link" %>
+  <%= link gettext("Logout"), method: :delete, to: Routes.user_session_path(@conn, :delete), class: "nav-link" %>
 </li>
diff --git a/lib/kmxgit_web/templates/repository/form.html.heex b/lib/kmxgit_web/templates/repository/form.html.heex
index de9b8b8..eccf747 100644
--- a/lib/kmxgit_web/templates/repository/form.html.heex
+++ b/lib/kmxgit_web/templates/repository/form.html.heex
@@ -11,6 +11,12 @@
     <%= error_tag f, :slug %>
   </div>
 
+  <div class="mb-3 form-check">
+    <%= checkbox f, :public_access, class: "form-check-input" %>
+    <%= label f, :public_access, class: "form-check-label" %>
+    <%= error_tag f, :public_access %>
+  </div>
+
   <div class="mb-3">
     <%= label f, :description, class: "form-label" %>
     <%= textarea f, :description, class: "form-control" %>
diff --git a/lib/kmxgit_web/templates/repository/show.html.heex b/lib/kmxgit_web/templates/repository/show.html.heex
index 6627cb8..40fcb11 100644
--- a/lib/kmxgit_web/templates/repository/show.html.heex
+++ b/lib/kmxgit_web/templates/repository/show.html.heex
@@ -14,7 +14,9 @@
             to: Routes.repository_path(@conn, :edit, Repository.owner_slug(@repo), Repository.splat(@repo)),
             class: "btn btn-primary" %>
       <% end %>
-      <%= link gettext("Fork"), to: Routes.repository_path(@conn, :fork, Repository.owner_slug(@repo), Repository.splat(@repo)), class: "btn btn-primary" %>
+      <%= if @current_user do %>
+        <%= link gettext("Fork"), to: Routes.repository_path(@conn, :fork, Repository.owner_slug(@repo), Repository.splat(@repo)), class: "btn btn-primary" %>
+      <% end %>
     </div>
   </div>
 
@@ -56,6 +58,16 @@
           <td><%= Repository.ssh_url(@repo) %></td>
         </tr>
         <tr>
+          <th><%= gettext "Public access ?" %></th>
+          <td>
+            <%= if @repo.public_access do %>
+              <%= gettext "public" %>
+            <% else %>
+              <%= gettext "private" %>
+            <% end %>
+          </td>
+        </tr>
+        <tr>
           <th><%= gettext "Description" %></th>
           <td>
             <%= if @repo.description do %>
diff --git a/lib/kmxgit_web/templates/user/show.html.heex b/lib/kmxgit_web/templates/user/show.html.heex
index 7a96ba5..817a0f8 100644
--- a/lib/kmxgit_web/templates/user/show.html.heex
+++ b/lib/kmxgit_web/templates/user/show.html.heex
@@ -4,7 +4,7 @@
       <h1><%= @user.slug.slug %></h1>
     </div>
     <div class="col col-12 col-sm-4">
-      <%= if @user.id == @current_user.id do %>
+      <%= if @current_user && @user.id == @current_user.id do %>
         <%= link gettext("New repository"),
             to: Routes.repository_path(@conn, :new, @user.slug.slug),
             class: "btn btn-primary" %>
@@ -63,7 +63,7 @@
         <tr>
           <th>
             <%= gettext "Organisations" %><br/>
-            <%= if @user.id == @current_user.id do %>
+            <%= if @current_user && @user.id == @current_user.id do %>
               <%= link("+", to: Routes.organisation_path(@conn, :new), class: "btn btn-primary btn-sm") %>
             <% end %>
           </th>
diff --git a/priv/repo/migrations/20211211103413_add_public_access_to_repositories.exs b/priv/repo/migrations/20211211103413_add_public_access_to_repositories.exs
new file mode 100644
index 0000000..db26084
--- /dev/null
+++ b/priv/repo/migrations/20211211103413_add_public_access_to_repositories.exs
@@ -0,0 +1,9 @@
+defmodule Kmxgit.Repo.Migrations.AddPublicAccessToRepositories do
+  use Ecto.Migration
+
+  def change do
+    alter table(:repositories) do
+      add :public_access, :boolean, null: false, default: false
+    end
+  end
+end