mirror of
https://github.com/danbee/chess
synced 2025-03-04 08:39:06 +00:00
Add profile page to update name and email
* Also add ability to change password
This commit is contained in:
parent
344619ac4f
commit
bc5c6c4f04
@ -23,12 +23,26 @@ defmodule Chess.Store.User do
|
||||
@doc false
|
||||
def changeset(struct, params \\ %{}) do
|
||||
struct
|
||||
|> cast(params, required_attrs())
|
||||
|> validate_required(required_attrs())
|
||||
|> cast(params, registration_attrs())
|
||||
|> validate_required(registration_attrs())
|
||||
|> unique_constraint(:email)
|
||||
|> hash_password()
|
||||
end
|
||||
|
||||
def profile_changeset(struct, params \\ %{}) do
|
||||
struct
|
||||
|> cast(params, profile_attrs())
|
||||
|> validate_required(profile_attrs())
|
||||
|> unique_constraint(:email)
|
||||
end
|
||||
|
||||
def password_changeset(struct, params \\ %{}) do
|
||||
struct
|
||||
|> cast(params, [:password])
|
||||
|> validate_required([:password])
|
||||
|> hash_password()
|
||||
end
|
||||
|
||||
def opponents(user) do
|
||||
from user in "users",
|
||||
where: user.id != ^user.id,
|
||||
@ -45,5 +59,6 @@ defmodule Chess.Store.User do
|
||||
end
|
||||
end
|
||||
|
||||
defp required_attrs, do: ~w[name email password]a
|
||||
defp registration_attrs, do: ~w[name email password]a
|
||||
defp profile_attrs, do: ~w{name email}a
|
||||
end
|
||||
|
||||
29
lib/chess_web/controllers/password_controller.ex
Normal file
29
lib/chess_web/controllers/password_controller.ex
Normal file
@ -0,0 +1,29 @@
|
||||
defmodule ChessWeb.PasswordController do
|
||||
@moduledoc false
|
||||
|
||||
use ChessWeb, :controller
|
||||
|
||||
import Chess.Auth, only: [current_user: 1]
|
||||
|
||||
alias Chess.Store.User
|
||||
|
||||
def edit(conn, _params) do
|
||||
changeset = User.changeset(current_user(conn), %{})
|
||||
|
||||
conn
|
||||
|> render("edit.html", changeset: changeset)
|
||||
end
|
||||
|
||||
def update(conn, %{"user" => user}) do
|
||||
changeset = User.password_changeset(current_user(conn), user)
|
||||
|
||||
case Repo.update(changeset) do
|
||||
{:ok, _user} ->
|
||||
conn
|
||||
|> put_flash(:info, gettext("Password updated successfully."))
|
||||
|> redirect(to: page_path(conn, :index))
|
||||
{:error, changeset} ->
|
||||
render(conn, "edit.html", changeset: changeset)
|
||||
end
|
||||
end
|
||||
end
|
||||
29
lib/chess_web/controllers/profile_controller.ex
Normal file
29
lib/chess_web/controllers/profile_controller.ex
Normal file
@ -0,0 +1,29 @@
|
||||
defmodule ChessWeb.ProfileController do
|
||||
@moduledoc false
|
||||
|
||||
use ChessWeb, :controller
|
||||
|
||||
import Chess.Auth, only: [current_user: 1]
|
||||
|
||||
alias Chess.Store.User
|
||||
|
||||
def edit(conn, _params) do
|
||||
changeset = User.changeset(current_user(conn), %{})
|
||||
|
||||
conn
|
||||
|> render("edit.html", changeset: changeset)
|
||||
end
|
||||
|
||||
def update(conn, %{"user" => user}) do
|
||||
changeset = User.profile_changeset(current_user(conn), user)
|
||||
|
||||
case Repo.update(changeset) do
|
||||
{:ok, _user} ->
|
||||
conn
|
||||
|> put_flash(:info, gettext("Profile updated successfully."))
|
||||
|> redirect(to: page_path(conn, :index))
|
||||
{:error, changeset} ->
|
||||
render(conn, "edit.html", changeset: changeset)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -40,6 +40,10 @@ defmodule ChessWeb.Router do
|
||||
|
||||
resources "/games", GameController,
|
||||
only: [:index, :new, :create, :show, :delete]
|
||||
resources "/profile", ProfileController,
|
||||
only: [:edit, :update], singleton: true
|
||||
resources "/password", PasswordController,
|
||||
only: [:edit, :update], singleton: true
|
||||
end
|
||||
|
||||
# Other scopes may use custom stacks.
|
||||
|
||||
@ -18,7 +18,8 @@
|
||||
|
||||
<nav class="user-nav" role="user">
|
||||
<%= if current_user(@conn) do %>
|
||||
<%= current_user(@conn).name %> (<%= current_user(@conn).email %>)
|
||||
<%= link(current_user(@conn).name, to: profile_path(@conn, :edit)) %>
|
||||
(<%= current_user(@conn).email %>)
|
||||
|
|
||||
<%= link gettext("Log out"),
|
||||
to: session_path(@conn, :delete),
|
||||
|
||||
22
lib/chess_web/templates/password/edit.html.eex
Normal file
22
lib/chess_web/templates/password/edit.html.eex
Normal file
@ -0,0 +1,22 @@
|
||||
<div class="form">
|
||||
<h2><%= gettext "Password" %></h2>
|
||||
|
||||
<%= form_for @changeset, password_path(@conn, :update), [class: "update-password"], fn f -> %>
|
||||
<%= if @changeset.action do %>
|
||||
<div class="alert alert-danger">
|
||||
<p>
|
||||
<%= gettext "Oops, something went wrong! Please check the errors below." %>
|
||||
</p>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-field">
|
||||
<%= input f, :password, as: :password %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<%= submit gettext("Update Password"), class: "btn btn-primary" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
28
lib/chess_web/templates/profile/edit.html.eex
Normal file
28
lib/chess_web/templates/profile/edit.html.eex
Normal file
@ -0,0 +1,28 @@
|
||||
<div class="form">
|
||||
<h2><%= gettext "Profile" %></h2>
|
||||
|
||||
<%= form_for @changeset, profile_path(@conn, :update), [class: "update-profile"], fn f -> %>
|
||||
<%= if @changeset.action do %>
|
||||
<div class="alert alert-danger">
|
||||
<p>
|
||||
<%= gettext "Oops, something went wrong! Please check the errors below." %>
|
||||
</p>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-field">
|
||||
<%= input f, :name %>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<%= input f, :email, as: :email %>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<%= link gettext("Change password"), to: password_path(@conn, :edit) %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<%= submit gettext("Update Profile"), class: "btn btn-primary" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
3
lib/chess_web/views/password_view.ex
Normal file
3
lib/chess_web/views/password_view.ex
Normal file
@ -0,0 +1,3 @@
|
||||
defmodule ChessWeb.PasswordView do
|
||||
use ChessWeb, :view
|
||||
end
|
||||
3
lib/chess_web/views/profile_view.ex
Normal file
3
lib/chess_web/views/profile_view.ex
Normal file
@ -0,0 +1,3 @@
|
||||
defmodule ChessWeb.ProfileView do
|
||||
use ChessWeb, :view
|
||||
end
|
||||
48
test/features/password_test.exs
Normal file
48
test/features/password_test.exs
Normal file
@ -0,0 +1,48 @@
|
||||
defmodule Chess.Features.PasswordTest do
|
||||
use ChessWeb.FeatureCase
|
||||
|
||||
import Wallaby.Query
|
||||
import Chess.Factory
|
||||
|
||||
import Chess.AuthenticationHelpers
|
||||
|
||||
test "user can change their password", %{session: session} do
|
||||
user = insert(:user, %{
|
||||
name: "Link",
|
||||
email: "link@hyrule.com",
|
||||
password: "ilovezelda"
|
||||
})
|
||||
|
||||
session
|
||||
|> login(user.email, "ilovezelda")
|
||||
|
||||
session
|
||||
|> click(link(user.name))
|
||||
|> click(link("Change password"))
|
||||
|> fill_in(text_field("Password"), with: "ganonsucks")
|
||||
|> click(button("Update Password"))
|
||||
|
||||
assert session |> has_text?("Password updated successfully")
|
||||
end
|
||||
|
||||
test "password cannot be blank", %{session: session} do
|
||||
user = insert(:user, %{
|
||||
name: "Link",
|
||||
email: "link@hyrule.com",
|
||||
password: "ilovezelda"
|
||||
})
|
||||
|
||||
session
|
||||
|> login(user.email, "ilovezelda")
|
||||
|
||||
session
|
||||
|> click(link(user.name))
|
||||
|> click(link("Change password"))
|
||||
|> click(button("Update Password"))
|
||||
|
||||
session
|
||||
|> assert_has(
|
||||
css("[data-role='password-error']", text: "can't be blank")
|
||||
)
|
||||
end
|
||||
end
|
||||
68
test/features/profile_test.exs
Normal file
68
test/features/profile_test.exs
Normal file
@ -0,0 +1,68 @@
|
||||
defmodule Chess.Features.ProfileTest do
|
||||
use ChessWeb.FeatureCase
|
||||
|
||||
import Wallaby.Query
|
||||
import Chess.Factory
|
||||
|
||||
import Chess.AuthenticationHelpers
|
||||
|
||||
test "user can update their details", %{session: session} do
|
||||
user = insert(:user, %{
|
||||
name: "Link",
|
||||
email: "link@hyrule.com",
|
||||
password: "ilovezelda"
|
||||
})
|
||||
|
||||
session
|
||||
|> login(user.email, "ilovezelda")
|
||||
|
||||
session
|
||||
|> click(link(user.name))
|
||||
|> fill_in(text_field("Name"), with: "Not Zelda")
|
||||
|> click(button("Update Profile"))
|
||||
|
||||
assert session |> has_text?("Not Zelda")
|
||||
end
|
||||
|
||||
test "name cannot be blank", %{session: session} do
|
||||
user = insert(:user, %{
|
||||
name: "Link",
|
||||
email: "link@hyrule.com",
|
||||
password: "ilovezelda"
|
||||
})
|
||||
|
||||
session
|
||||
|> login(user.email, "ilovezelda")
|
||||
|
||||
session
|
||||
|> click(link(user.name))
|
||||
|> fill_in(text_field("Name"), with: "")
|
||||
|> click(button("Update Profile"))
|
||||
|
||||
session
|
||||
|> assert_has(
|
||||
css("[data-role='name-error']", text: "can't be blank")
|
||||
)
|
||||
end
|
||||
|
||||
test "email cannot be blank", %{session: session} do
|
||||
user = insert(:user, %{
|
||||
name: "Link",
|
||||
email: "link@hyrule.com",
|
||||
password: "ilovezelda"
|
||||
})
|
||||
|
||||
session
|
||||
|> login(user.email, "ilovezelda")
|
||||
|
||||
session
|
||||
|> click(link(user.name))
|
||||
|> fill_in(text_field("Email"), with: "")
|
||||
|> click(button("Update Profile"))
|
||||
|
||||
session
|
||||
|> assert_has(
|
||||
css("[data-role='email-error']", text: "can't be blank")
|
||||
)
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue
Block a user