Commit c5b35fe0545740b3213fcf1d669a2a60c6d2ff89

Thomas de Grivel 2022-06-19T11:38:30

user slug_

diff --git a/lib/kmxgit/slug_manager.ex b/lib/kmxgit/slug_manager.ex
index f19ce19..0021c4b 100644
--- a/lib/kmxgit/slug_manager.ex
+++ b/lib/kmxgit/slug_manager.ex
@@ -5,10 +5,11 @@ defmodule Kmxgit.SlugManager do
   alias Kmxgit.Repo
   alias Kmxgit.OrganisationManager.Organisation
   alias Kmxgit.SlugManager.Slug
+  alias Kmxgit.UserManager.User
 
   def list_all_slugs do
     Slug
-    |> Repo.all
+    |> Repo.all()
   end
 
   def create_slug(slug) when is_binary(slug) do
@@ -21,6 +22,11 @@ defmodule Kmxgit.SlugManager do
     |> Slug.create_changeset(%{slug: slug, organisation_id: id})
     |> Repo.insert()
   end
+  def create_slug(%User{id: id, slug_: slug}) do
+    %Slug{}
+    |> Slug.create_changeset(%{slug: slug, user_id: id})
+    |> Repo.insert()
+  end
 
   def update_slug(slug, attrs) do
     slug
diff --git a/lib/kmxgit/user_manager.ex b/lib/kmxgit/user_manager.ex
index decd7d8..0a96525 100644
--- a/lib/kmxgit/user_manager.ex
+++ b/lib/kmxgit/user_manager.ex
@@ -8,19 +8,16 @@ defmodule Kmxgit.UserManager do
   alias Kmxgit.IndexParams
   alias Kmxgit.Pagination
   alias Kmxgit.Repo
-  alias Kmxgit.SlugManager.Slug
   alias Kmxgit.UserManager.{Avatar, User, UserToken, UserNotifier}
 
-  @user_preload [:slug,
-                 organisations: :slug,
-                 owned_repositories: [members: :slug,
-                                      organisation: :slug,
-                                      user: :slug]]
+  @user_preload [:organisations,
+                 owned_repositories: [:members,
+                                      :organisation,
+                                      :user]]
 
   def list_all_users() do
     from(u in User)
-    |> join(:inner, [u], s in Slug, on: s.user_id == u.id)
-    |> order_by([u, s], fragment("lower(?)", s.slug))
+    |> order_by([u], fragment("lower(?)", u.slug_))
     |> preload([:owned_repositories, :slug])
     |> Repo.all()
   end
@@ -28,16 +25,15 @@ defmodule Kmxgit.UserManager do
   def list_users(params \\ %IndexParams{}) do
     update_disk_usage()
     from(u in User)
-    |> join(:inner, [u], s in Slug, on: s.user_id == u.id)
     |> search(params)
     |> index_order_by(params)
-    |> Pagination.page(params, preload: [:owned_repositories, :slug])
+    |> Pagination.page(params, preload: [:owned_repositories])
   end
 
   def search(query, %IndexParams{search: search}) do
     expr = "%#{search}%"
     query
-    |> where([u, s], ilike(u.name, ^expr) or ilike(s.slug, ^expr) or ilike(u.email, ^expr))
+    |> where([u], ilike(u.name, ^expr) or ilike(u.slug_, ^expr) or ilike(u.email, ^expr))
   end
 
   def index_order_by(query, %IndexParams{column: "id", reverse: true}) do
@@ -47,22 +43,22 @@ defmodule Kmxgit.UserManager do
     order_by(query, :id)
   end
   def index_order_by(query, %IndexParams{column: "name", reverse: true}) do
-    order_by(query, [u, s], [desc_nulls_last: fragment("lower(?)", u.name)])
+    order_by(query, [u], [desc_nulls_last: fragment("lower(?)", u.name)])
   end
   def index_order_by(query, %IndexParams{column: "name"}) do
-    order_by(query, [u, s], [asc_nulls_last: fragment("lower(?)", u.name)])
+    order_by(query, [u], [asc_nulls_last: fragment("lower(?)", u.name)])
   end
   def index_order_by(query, %IndexParams{column: "email", reverse: true}) do
-    order_by(query, [u, s], [desc_nulls_last: fragment("lower(?)", u.email)])
+    order_by(query, [u], [desc_nulls_last: fragment("lower(?)", u.email)])
   end
   def index_order_by(query, %IndexParams{column: "email"}) do
-    order_by(query, [u, s], [asc_nulls_last: fragment("lower(?)", u.email)])
+    order_by(query, [u], [asc_nulls_last: fragment("lower(?)", u.email)])
   end
   def index_order_by(query, %IndexParams{column: "login", reverse: true}) do
-    order_by(query, [u, s], [desc_nulls_last: fragment("lower(?)", s.slug)])
+    order_by(query, [u], [desc_nulls_last: fragment("lower(?)", u.slug_)])
   end
   def index_order_by(query, %IndexParams{column: "login"}) do
-    order_by(query, [u, s], [asc_nulls_last: fragment("lower(?)", s.slug)])
+    order_by(query, [u], [asc_nulls_last: fragment("lower(?)", u.slug_)])
   end
   def index_order_by(query, %IndexParams{column: "du", reverse: true}) do
     order_by(query, [desc: :disk_usage])
@@ -90,7 +86,7 @@ defmodule Kmxgit.UserManager do
   end
 
   def update_disk_usage() do
-    Repo.all(from user in User, preload: :slug)
+    Repo.all(from user in User)
     |> Enum.map(fn user ->
       user
       |> Ecto.Changeset.cast(%{}, [])
@@ -123,9 +119,7 @@ defmodule Kmxgit.UserManager do
 
   def get_user_by_login(login) do
     Repo.one from u in User,
-      join: s in Slug,
-      on: s.user_id == u.id,
-      where: fragment("lower(?)", s.slug) == ^String.downcase(login),
+      where: u.slug_ == ^login,
       limit: 1,
       preload: ^@user_preload
   end
@@ -336,9 +330,7 @@ defmodule Kmxgit.UserManager do
 
   def authenticate_user(login, password) do
     query = from u in User,
-      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),
+      where: u.slug_ == ^login or u.email == ^login,
       limit: 1
     case Repo.one(query) do
       nil ->
diff --git a/lib/kmxgit/user_manager/user.ex b/lib/kmxgit/user_manager/user.ex
index 16a2e07..df90984 100644
--- a/lib/kmxgit/user_manager/user.ex
+++ b/lib/kmxgit/user_manager/user.ex
@@ -19,7 +19,7 @@ defmodule Kmxgit.UserManager.User do
     field :name, :string
     field :totp_last, :integer, default: 0, redact: true
     field :totp_secret, :string, redact: true
-    has_many :owned_repositories, Repository
+    has_many :owned_repositories, Repository, on_delete: :delete_all
     field :password, :string, virtual: true, redact: true
     field :password_confirmation, :string, virtual: true, redact: true
     many_to_many :repositories, Repository, join_through: "users_repositories", on_delete: :delete_all
@@ -49,7 +49,7 @@ defmodule Kmxgit.UserManager.User do
   """
   def registration_changeset(user, attrs, opts \\ []) do
     user
-    |> cast(attrs, [:email, :password])
+    |> cast(attrs, [:email, :password, :slug_])
     |> generate_totp_secret()
     |> validate_email()
     |> validate_password(opts)
@@ -179,8 +179,7 @@ defmodule Kmxgit.UserManager.User do
 
   defp common_changeset(changeset) do
     changeset
-    |> cast_assoc(:slug)
-    |> validate_required([:deploy_only, :email, :hashed_password, :is_admin, :totp_secret, :slug, :slug_])
+    |> validate_required([:deploy_only, :email, :hashed_password, :is_admin, :totp_secret, :slug_])
     |> validate_email()
     |> Markdown.validate_markdown(:description)
     |> foreign_key_constraint(:owned_repositories, name: :repositories_user_id_fkey)
diff --git a/lib/kmxgit_web/controllers/user_controller.ex b/lib/kmxgit_web/controllers/user_controller.ex
index 1d1274d..803ef9f 100644
--- a/lib/kmxgit_web/controllers/user_controller.ex
+++ b/lib/kmxgit_web/controllers/user_controller.ex
@@ -4,6 +4,7 @@ defmodule KmxgitWeb.UserController do
   alias Kmxgit.GitAuth
   alias Kmxgit.GitManager
   alias Kmxgit.Repo
+  alias Kmxgit.SlugManager
   alias Kmxgit.UserManager
   alias Kmxgit.UserManager.{Avatar, User}
   alias KmxgitWeb.ErrorView
@@ -48,10 +49,15 @@ defmodule KmxgitWeb.UserController do
       case Repo.transaction(fn ->
             case UserManager.update_user(user, params["user"]) do
               {:ok, user1} ->
-                if User.login(user1) != User.login(user) do
-                  case GitManager.rename_dir(User.login(user), User.login(user1)) do
-                    :ok -> user
-                    {:error, err} -> Repo.rollback(err)
+                if User.login(user) != User.login(user1) do
+                  case SlugManager.rename_slug(User.login(user), User.login(user1)) do
+                    {:ok, _slug} ->
+                      case GitManager.rename_dir(User.login(user), User.login(user1)) do
+                        :ok -> user1
+                        {:error, err} -> Repo.rollback(err)
+                      end
+                    {:error, changeset} ->
+                      Repo.rollback(changeset)
                   end
                 else
                   user
diff --git a/lib/kmxgit_web/controllers/user_registration_controller.ex b/lib/kmxgit_web/controllers/user_registration_controller.ex
index 0e2713e..a5ac829 100644
--- a/lib/kmxgit_web/controllers/user_registration_controller.ex
+++ b/lib/kmxgit_web/controllers/user_registration_controller.ex
@@ -1,6 +1,8 @@
 defmodule KmxgitWeb.UserRegistrationController do
   use KmxgitWeb, :controller
 
+  alias Kmxgit.Repo
+  alias Kmxgit.SlugManager
   alias Kmxgit.UserManager
   alias Kmxgit.UserManager.User
   alias KmxgitWeb.UserAuth
@@ -11,19 +13,29 @@ defmodule KmxgitWeb.UserRegistrationController do
   end
 
   def create(conn, %{"user" => user_params}) do
-    case UserManager.register_user(user_params) do
+    case Repo.transaction(fn ->
+          case UserManager.register_user(user_params) do
+            {:ok, user} ->
+              case SlugManager.create_slug(user) do
+                {:ok, _slug} ->
+                  {:ok, _} =
+                    UserManager.deliver_user_confirmation_instructions(
+                      user,
+                      &Routes.user_confirmation_url(conn, :edit, &1))
+                  user
+                {:error, changeset} ->
+                  Repo.rollback(changeset)
+              end
+            {:error, changeset} ->
+              Repo.rollback(changeset)
+          end
+        end) do
       {:ok, user} ->
-        {:ok, _} =
-          UserManager.deliver_user_confirmation_instructions(
-            user,
-            &Routes.user_confirmation_url(conn, :edit, &1)
-          )
-
         conn
         |> put_flash(:info, "User created successfully.")
         |> UserAuth.log_in_user(user)
-
-      {:error, %Ecto.Changeset{} = changeset} ->
+      {:error, changeset} ->
+        IO.inspect(changeset)
         render(conn, "new.html", changeset: changeset)
     end
   end
diff --git a/lib/kmxgit_web/templates/user/edit.html.heex b/lib/kmxgit_web/templates/user/edit.html.heex
index 89cf31a..68c7705 100644
--- a/lib/kmxgit_web/templates/user/edit.html.heex
+++ b/lib/kmxgit_web/templates/user/edit.html.heex
@@ -9,13 +9,11 @@
       <%= error_tag f, :name %>
     </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, :slug_, gettext("Login"), class: "form-label" %>
+      <%= text_input f, :slug_, class: "form-control" %>
+      <%= error_tag f, :slug_ %>
+    </div>
 
     <div class="mb-3">
       <%= label f, :avatar, class: "form-label" %>
diff --git a/lib/kmxgit_web/templates/user_registration/new.html.heex b/lib/kmxgit_web/templates/user_registration/new.html.heex
index e6e76d7..06c01e9 100644
--- a/lib/kmxgit_web/templates/user_registration/new.html.heex
+++ b/lib/kmxgit_web/templates/user_registration/new.html.heex
@@ -20,13 +20,11 @@
       <%= error_tag f, :email %>
     </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", required: true %>
-        <%= error_tag ff, :slug %>
-      </div>
-    <% end %>
+    <div class="mb-3">
+      <%= label f, :slug_, gettext("Login"), class: "form-label" %>
+      <%= text_input f, :slug_, class: "form-control", required: true %>
+      <%= error_tag f, :slug_ %>
+    </div>
 
     <div class="mb-3">
       <%= label f, :password, class: "form-label" %>