From cf1be80746eaabaa2beabceffaf0213fc25d4456 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sun, 31 Mar 2019 11:52:20 -0400 Subject: [PATCH] Add password changing --- lib/frenzy/user.ex | 20 +++++-- .../controllers/account_controller.ex | 59 +++++++++++++++++++ lib/frenzy_web/router.ex | 4 ++ .../account/change_password.html.eex | 19 ++++++ .../templates/account/show.html.eex | 4 ++ lib/frenzy_web/views/account_view.ex | 3 + 6 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 lib/frenzy_web/controllers/account_controller.ex create mode 100644 lib/frenzy_web/templates/account/change_password.html.eex create mode 100644 lib/frenzy_web/templates/account/show.html.eex create mode 100644 lib/frenzy_web/views/account_view.ex diff --git a/lib/frenzy/user.ex b/lib/frenzy/user.ex index 9b06b0b..021b1b9 100644 --- a/lib/frenzy/user.ex +++ b/lib/frenzy/user.ex @@ -29,17 +29,29 @@ defmodule Frenzy.User do |> validate_length(:password, min: 8) |> validate_length(:fever_password, min: 8) |> put_password_hash() + |> put_fever_token() + end + + def change_password_changeset(user, attrs) do + user + |> cast(attrs, [:password]) + |> validate_length(:password, min: 8) + |> put_password_hash() end defp put_password_hash( + %Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset + ) do + change(changeset, Bcrypt.add_hash(password)) + end + + defp put_fever_token( %Ecto.Changeset{ valid?: true, - changes: %{username: username, password: password, fever_password: fever_password} + changes: %{username: username, fever_password: fever_password} } = changeset ) do - changeset - |> change(Bcrypt.add_hash(password)) - |> change(%{ + change(changeset, %{ fever_auth_token: :crypto.hash(:md5, "#{username}:#{fever_password}") |> Base.encode16(case: :lower) }) diff --git a/lib/frenzy_web/controllers/account_controller.ex b/lib/frenzy_web/controllers/account_controller.ex new file mode 100644 index 0000000..3a74d23 --- /dev/null +++ b/lib/frenzy_web/controllers/account_controller.ex @@ -0,0 +1,59 @@ +defmodule FrenzyWeb.AccountController do + use FrenzyWeb, :controller + alias Frenzy.{Repo, User} + alias FrenzyWeb.Router.Helpers, as: Routes + alias FrenzyWeb.Endpoint + + def show(conn, _params) do + user = conn.assigns[:user] + + render(conn, "show.html", %{ + user: user + }) + end + + def change_password(conn, _params) do + render(conn, "change_password.html") + end + + def do_change_password(conn, %{ + "old_password" => old, + "new_password" => new, + "confirm_new_password" => confirm + }) do + user = conn.assigns[:user] |> Repo.preload([:approved_clients, :groups]) + + case Bcrypt.check_pass(user, old) do + {:ok, user} -> + case new do + ^old -> + conn + |> put_flash(:error, "New password cannot be the same as old password.") + |> redirect(to: Routes.account_path(Endpoint, :change_password)) + + ^confirm -> + changeset = User.change_password_changeset(user, %{password: new}) + + {:ok, user} = Repo.update(changeset) + + conn + |> put_flash(:info, "Password changed.") + |> redirect(to: Routes.account_path(Endpoint, :show)) + + _ -> + conn + |> put_flash(:error, "New password and confirmation did not match.") + |> redirect(to: Routes.account_path(Endpoint, :change_password)) + end + + {:error, _reason} -> + conn + |> put_flash(:error, "Invalid old password.") + |> redirect(to: Routes.account_path(Endpoint, :change_password)) + end + end + + def do_change_password(conn, _params) do + redirect(conn, to: Routes.account_path(Endpoint, :change_password)) + end +end diff --git a/lib/frenzy_web/router.ex b/lib/frenzy_web/router.ex index 5790f86..1a2b36d 100644 --- a/lib/frenzy_web/router.ex +++ b/lib/frenzy_web/router.ex @@ -35,6 +35,10 @@ defmodule FrenzyWeb.Router do pipe_through :browser pipe_through :browser_authenticate + get "/account", AccountController, :show + get "/account/change_password", AccountController, :change_password + post "/account/change_password", AccountController, :do_change_password + get "/", GroupController, :index resources "/groups", GroupController, except: [:edit, :update] diff --git a/lib/frenzy_web/templates/account/change_password.html.eex b/lib/frenzy_web/templates/account/change_password.html.eex new file mode 100644 index 0000000..dfc8c23 --- /dev/null +++ b/lib/frenzy_web/templates/account/change_password.html.eex @@ -0,0 +1,19 @@ +

Change Password

+ +<%= form_tag Routes.account_path(@conn, :do_change_password), method: :post do %> +
+ + +
+
+ + +
+
+ + +
+
+ <%= submit "Change Password" %> +
+<% end %> \ No newline at end of file diff --git a/lib/frenzy_web/templates/account/show.html.eex b/lib/frenzy_web/templates/account/show.html.eex new file mode 100644 index 0000000..a72dba2 --- /dev/null +++ b/lib/frenzy_web/templates/account/show.html.eex @@ -0,0 +1,4 @@ +

User Settings

+

<%= @user.username %>

+ +Change Password \ No newline at end of file diff --git a/lib/frenzy_web/views/account_view.ex b/lib/frenzy_web/views/account_view.ex new file mode 100644 index 0000000..76c1c75 --- /dev/null +++ b/lib/frenzy_web/views/account_view.ex @@ -0,0 +1,3 @@ +defmodule FrenzyWeb.AccountView do + use FrenzyWeb, :view +end