Commit 2436c2616a8db3a59ad745d6dc25cf2fb9e62c21

Thomas de Grivel 2022-01-24T10:37:24

uploadable avatar

diff --git a/.gitignore b/.gitignore
index c37f598..9731313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,5 +35,6 @@ npm-debug.log
 /priv/git
 /.env
 
+/priv/avatar/
 /priv/repo/dumps/
 /priv/static/
diff --git a/lib/kmxgit/user_manager.ex b/lib/kmxgit/user_manager.ex
index fe3c1af..539ec2c 100644
--- a/lib/kmxgit/user_manager.ex
+++ b/lib/kmxgit/user_manager.ex
@@ -7,7 +7,7 @@ defmodule Kmxgit.UserManager do
 
   alias Kmxgit.Repo
   alias Kmxgit.SlugManager.Slug
-  alias Kmxgit.UserManager.{User, UserToken, UserNotifier}
+  alias Kmxgit.UserManager.{Avatar, User, UserToken, UserNotifier}
 
   def list_users do
     Repo.all from user in User, preload: :slug
@@ -56,7 +56,7 @@ defmodule Kmxgit.UserManager do
                 owned_repositories: [organisation: :slug,
                                      user: :slug]]
   end
-
+ 
   def register_user(attrs) do
     %User{}
     |> User.registration_changeset(attrs)
@@ -209,13 +209,17 @@ defmodule Kmxgit.UserManager do
   end
 
   def update_user(%User{} = user, attrs) do
-    old_login = user.slug.slug
+    old_login = User.login(user)
     case user
          |> User.changeset(attrs)
          |> Repo.update() do
       {:ok, u} ->
-        if u.slug.slug != old_login do
-          UserNotifier.deliver_login_changed_email(u, old_login, u.slug.slug)
+        if User.login(u) != old_login do
+          UserNotifier.deliver_login_changed_email(u, old_login, User.login(u))
+        end
+        if attrs["avatar"] do
+            %{path: path} = attrs["avatar"]
+            Avatar.set_image(u, path)
         end
         {:ok, u}
       x -> x
diff --git a/lib/kmxgit/user_manager/avatar.ex b/lib/kmxgit/user_manager/avatar.ex
new file mode 100644
index 0000000..725c293
--- /dev/null
+++ b/lib/kmxgit/user_manager/avatar.ex
@@ -0,0 +1,22 @@
+defmodule Kmxgit.UserManager.Avatar do
+  import Mogrify
+
+  alias Kmxgit.UserManager.User
+
+  @sizes [256, 48]
+
+  def path(user, size) do
+    dir = "priv/avatar/#{size}"
+    File.mkdir_p(dir)
+    "#{dir}/#{user.id}.png"
+  end
+
+  def set_image(user, path) do
+    original = open(path)
+    for size <- @sizes do
+      original
+      |> resize_to_fill("#{size}x#{size}")
+      |> save(path: path(user, size))
+    end
+  end
+end
diff --git a/lib/kmxgit_web/controllers/slug_controller.ex b/lib/kmxgit_web/controllers/slug_controller.ex
index e0b3622..698469a 100644
--- a/lib/kmxgit_web/controllers/slug_controller.ex
+++ b/lib/kmxgit_web/controllers/slug_controller.ex
@@ -23,7 +23,7 @@ defmodule KmxgitWeb.SlugController do
         |> assign(:disk_usage, Repository.disk_usage(owned_repos))
         |> assign(:disk_usage_all, Repository.disk_usage(repos))
         |> assign(:repos, repos)
-        |> assign(:page_title, gettext("User %{login}", login: user.slug.slug))
+        |> assign(:page_title, gettext("User %{login}", login: User.login(user)))
         |> assign(:user, user)
         |> put_view(UserView)
         |> render("show.html")
diff --git a/lib/kmxgit_web/controllers/user_controller.ex b/lib/kmxgit_web/controllers/user_controller.ex
index b6d36ed..88a50c7 100644
--- a/lib/kmxgit_web/controllers/user_controller.ex
+++ b/lib/kmxgit_web/controllers/user_controller.ex
@@ -4,9 +4,23 @@ defmodule KmxgitWeb.UserController do
   alias Kmxgit.GitManager
   alias Kmxgit.Repo
   alias Kmxgit.UserManager
-  alias Kmxgit.UserManager.User
+  alias Kmxgit.UserManager.{Avatar, User}
   alias KmxgitWeb.ErrorView
 
+  def avatar(conn, %{"login" => login,
+                     "size" => size}) do
+    user = UserManager.get_user_by_login(login)
+    if user do
+      path = Avatar.path(user, size)
+      conn
+      |> put_resp_content_type("image/png")
+      |> send_file(200, path)
+    end
+  end
+  def avatar(conn, _) do
+    not_found(conn)
+  end
+
   def edit(conn, params) do
     current_user = conn.assigns.current_user
     if params["login"] == User.login(current_user) do
@@ -30,11 +44,12 @@ defmodule KmxgitWeb.UserController do
     current_user = conn.assigns.current_user
     if params["login"] == User.login(current_user) do
       user = current_user
+      avatar_param = params["user"]["avatar"]
       case Repo.transaction(fn ->
             case UserManager.update_user(user, params["user"]) do
-              {:ok, user} ->
-                if user.slug.slug != user.slug.slug do
-                  case GitManager.rename_dir(user.slug.slug, user.slug.slug) 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)
                   end
@@ -50,7 +65,7 @@ defmodule KmxgitWeb.UserController do
             error -> IO.inspect(error)
           end
           conn
-          |> redirect(to: Routes.slug_path(conn, :show, user.slug.slug))
+          |> redirect(to: Routes.slug_path(conn, :show, User.login(user)))
         {:error, changeset} ->
           conn
           |> assign(:page_title, gettext("Edit user %{login}", login: user.slug.slug))
diff --git a/lib/kmxgit_web/router.ex b/lib/kmxgit_web/router.ex
index 973ff30..976fe9e 100644
--- a/lib/kmxgit_web/router.ex
+++ b/lib/kmxgit_web/router.ex
@@ -65,6 +65,8 @@ defmodule KmxgitWeb.Router do
   scope "/", KmxgitWeb do
     pipe_through [:browser, :require_authenticated_user]
 
+    get "/_avatar/:login/:size/avatar.png", UserController, :avatar
+
     get "/_settings", UserSettingsController, :edit
     put "/_settings", UserSettingsController, :update
     get "/_settings/confirm_email/:token", UserSettingsController, :confirm_email
diff --git a/lib/kmxgit_web/templates/user/avatar.html.heex b/lib/kmxgit_web/templates/user/avatar.html.heex
index d7ba2f6..16bf570 100644
--- a/lib/kmxgit_web/templates/user/avatar.html.heex
+++ b/lib/kmxgit_web/templates/user/avatar.html.heex
@@ -1,6 +1,7 @@
-<% user = Kmxgit.UserManager.get_user_by_email(@email) %>
+<% user = UserManager.get_user_by_email(@email) %>
 <%= if user do %>
-  <%= link to: Routes.slug_path(@conn, :show, user.slug.slug) do %><img src={Exgravatar.gravatar_url(@email, s: @size)} alt={@title} title={@title} class={@class} /><% end %>
+  <% avatar_path = Avatar.path(user, @size) |> IO.inspect() %>
+  <%= link to: Routes.slug_path(@conn, :show, User.login(user)) do %><%= if File.exists?(avatar_path) do %><%= img_tag(Routes.user_path(@conn, :avatar, User.login(user), @size), alt: @title, title: @title, class: @class) %><% else %><img src={Exgravatar.gravatar_url(@email, s: @size)} alt={@title} title={@title} class={@class} /><% end %><% end %>
 <% else %>
   <img src={Exgravatar.gravatar_url(@email, s: @size)} alt={@title} title={@title} class={@class} />
 <% end %>
diff --git a/lib/kmxgit_web/templates/user/edit.html.heex b/lib/kmxgit_web/templates/user/edit.html.heex
index 4e6ba30..89cf31a 100644
--- a/lib/kmxgit_web/templates/user/edit.html.heex
+++ b/lib/kmxgit_web/templates/user/edit.html.heex
@@ -1,7 +1,7 @@
 <div class="container-fluid center">
   <h1>Edit user <%= User.login(@user) %></h1>
 
-  <%= form_for @changeset, Routes.user_path(@conn, :update, User.login(@user)), fn f -> %>
+  <%= form_for @changeset, Routes.user_path(@conn, :update, User.login(@user)), [multipart: true], fn f -> %>
 
     <div class="mb-3">
       <%= label f, :name, class: "form-label" %>
@@ -18,6 +18,12 @@
     <% end %>
 
     <div class="mb-3">
+      <%= label f, :avatar, class: "form-label" %>
+      <%= file_input f, :avatar, class: "form-control" %>
+      <%= error_tag f, :avatar %>
+    </div>
+
+    <div class="mb-3">
       <%= label f, :description, class: "form-label" %>
       <%= textarea f, :description, class: "form-control" %>
       <%= error_tag f, :description %>
diff --git a/lib/kmxgit_web/templates/user/show.html.heex b/lib/kmxgit_web/templates/user/show.html.heex
index 2a1efb7..ead47c8 100644
--- a/lib/kmxgit_web/templates/user/show.html.heex
+++ b/lib/kmxgit_web/templates/user/show.html.heex
@@ -17,7 +17,7 @@
   <div class="row">
     <div class="col col-12">
       <hr/>
-      <img src={Exgravatar.gravatar_url(@user.email, s: 256)} alt="Avatar" class="avatar-lg" />
+      <%= render("avatar.html", conn: @conn, email: @user.email, size: 256, title: User.login(@user), class: "avatar-lg") %>
       <h1><%= @user.name %></h1>
       <div class="col col-12 col-md-8">
         <%= if @user.description do %>
diff --git a/lib/kmxgit_web/views/user_view.ex b/lib/kmxgit_web/views/user_view.ex
index cbc67d4..062ca65 100644
--- a/lib/kmxgit_web/views/user_view.ex
+++ b/lib/kmxgit_web/views/user_view.ex
@@ -2,4 +2,6 @@ defmodule KmxgitWeb.UserView do
   use KmxgitWeb, :view
 
   alias Kmxgit.RepositoryManager.Repository
+  alias Kmxgit.UserManager
+  alias Kmxgit.UserManager.{Avatar, User}
 end
diff --git a/mix.exs b/mix.exs
index b1f5663..afc54ab 100644
--- a/mix.exs
+++ b/mix.exs
@@ -46,6 +46,7 @@ defmodule Kmxgit.MixProject do
       {:gettext, "~> 0.18"},
       {:guardian, "~> 2.0"},
       {:jason, "~> 1.2"},
+      {:mogrify, "~> 0.9.1"},
       {:phoenix, "~> 1.6.2"},
       {:phoenix_ecto, "~> 4.4"},
       {:phoenix_html, "~> 3.0"},
diff --git a/mix.lock b/mix.lock
index be50b43..551a923 100644
--- a/mix.lock
+++ b/mix.lock
@@ -34,6 +34,7 @@
   "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
   "mime": {:hex, :mime, "2.0.2", "0b9e1a4c840eafb68d820b0e2158ef5c49385d17fb36855ac6e7e087d4b1dcc5", [:mix], [], "hexpm", "e6a3f76b4c277739e36c2e21a2c640778ba4c3846189d5ab19f97f126df5f9b7"},
   "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
+  "mogrify": {:hex, :mogrify, "0.9.1", "a26f107c4987477769f272bd0f7e3ac4b7b75b11ba597fd001b877beffa9c068", [:mix], [], "hexpm", "134edf189337d2125c0948bf0c228fdeef975c594317452d536224069a5b7f05"},
   "number": {:hex, :number, "1.0.3", "932c8a2d478a181c624138958ca88a78070332191b8061717270d939778c9857", [:mix], [{:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "dd397bbc096b2ca965a6a430126cc9cf7b9ef7421130def69bcf572232ca0f18"},
   "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
   "phoenix": {:hex, :phoenix, "1.6.6", "281c8ce8dccc9f60607346b72cdfc597c3dde134dd9df28dff08282f0b751754", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "807bd646e64cd9dc83db016199715faba72758e6db1de0707eef0a2da4924364"},