Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support --live to phx.gen.auth #4872

Merged
merged 58 commits into from
Aug 1, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
f012729
generate auth liveviews
bemesa21 Jun 9, 2022
0e2bdd0
conditionally inject liveview authentication code
bemesa21 Jun 17, 2022
4e0c2a1
add auth liveviews tests
bemesa21 Jun 21, 2022
e0aadaa
update failing tests
bemesa21 Jun 21, 2022
8d439cd
fix formatting issues
bemesa21 Jun 23, 2022
480b310
Apply suggestions from code review
bemesa21 Jun 23, 2022
2268c1c
Fix issue with login after registration
bemesa21 Jun 24, 2022
dfff0c9
Update priv/templates/phx.gen.auth/login_live.ex
chrismccord Jun 27, 2022
7e682d4
Replace user menu with function component
chrismccord Jun 29, 2022
87fff3e
show errors live, optionally validate email uniqueness
bemesa21 Jun 27, 2022
cae6dd3
format routes
bemesa21 Jun 30, 2022
cf902c0
generates settings liveview code
bemesa21 Jun 30, 2022
b992b37
generate confirmation liveview
bemesa21 Jun 30, 2022
0ed9d04
fix injection issues
bemesa21 Jun 30, 2022
93af377
rename tests, add doc
bemesa21 Jun 30, 2022
ade1ca5
fix format issues
bemesa21 Jun 30, 2022
5ffc22a
add missing settings live tests
bemesa21 Jun 30, 2022
551f997
change logic to generate files
bemesa21 Jun 30, 2022
4667bbd
fix formatted issues
bemesa21 Jun 30, 2022
c83d6df
fix failing tests
bemesa21 Jun 30, 2022
f573fab
Consolidate login controller
chrismccord Jul 4, 2022
9ce9260
Update tests and bring up to speed with LV 0.18
chrismccord Jul 4, 2022
6171477
formatting
chrismccord Jul 5, 2022
d7e42d8
Use submit_form LiveViewTest function
chrismccord Jul 5, 2022
3829dc9
Fix missing file
chrismccord Jul 5, 2022
beb3a40
Temporary assigns where applicable
chrismccord Jul 6, 2022
66c59fa
Dedup
chrismccord Jul 6, 2022
87be3fd
Docs
chrismccord Jul 6, 2022
abe3347
Simply registration changeset handling
chrismccord Jul 6, 2022
88d8a6b
Update lib/mix/phoenix/schema.ex
chrismccord Jul 6, 2022
d0f92ef
Kill unused function
chrismccord Jul 6, 2022
798df3c
Add forgot password Liveview
bemesa21 Jul 8, 2022
94e2cb6
remove unused function
bemesa21 Jul 8, 2022
28f8ef9
Add ConfirmationInstructionsLive and tests
bemesa21 Jul 8, 2022
36a786a
update test
bemesa21 Jul 8, 2022
b8d0bd9
Inject the user nav directly in layout
chrismccord Jul 13, 2022
03068c0
Fix tests
chrismccord Jul 13, 2022
546f009
Dry up padding indent
chrismccord Jul 13, 2022
03ba277
Update priv/templates/phx.gen.auth/session_controller.ex
chrismccord Jul 13, 2022
ddf497b
add live_session
bemesa21 Jul 13, 2022
9b6a5a5
handle email confirmation token in mount callback
bemesa21 Jul 13, 2022
80f940f
unique email is not validated until changes are applied
bemesa21 Jul 13, 2022
677af57
reasign password changeset
bemesa21 Jul 13, 2022
8c33b8f
apply format
bemesa21 Jul 13, 2022
edee13f
Update priv/templates/phx.gen.auth/schema.ex
bemesa21 Jul 13, 2022
10ad509
Add method to registration form
bemesa21 Jul 13, 2022
2f8283a
live errors for reset password form
bemesa21 Jul 13, 2022
8181717
fix failing test
bemesa21 Jul 13, 2022
0b004df
Remove phx-change from login form
chrismccord Jul 14, 2022
9b9cb9e
interactive prompt for LiveView generation
bemesa21 Jul 14, 2022
1c42da1
update integration tests
bemesa21 Jul 14, 2022
aeba900
update settings live
bemesa21 Jul 18, 2022
4a887b7
update mix.lock
bemesa21 Jul 20, 2022
b379eb8
Bump docs
chrismccord Jul 29, 2022
76278db
Touchup
chrismccord Jul 29, 2022
487b097
Update for verified routes
chrismccord Aug 1, 2022
9828643
Final touch ups
chrismccord Aug 1, 2022
de86e2a
update prompt message
bemesa21 Aug 1, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
generate auth liveviews
  • Loading branch information
bemesa21 committed Aug 1, 2022
commit f012729f553646cda51d0c8f02ec802e1dbc346c
5 changes: 4 additions & 1 deletion lib/mix/tasks/phx.gen.auth.ex
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,10 @@ defmodule Mix.Tasks.Phx.Gen.Auth do
{:eex, "settings_view.ex", Path.join([web_prefix, "views", web_path, "#{schema.singular}_settings_view.ex"])},
{:eex, "settings_edit.html.heex", Path.join([web_prefix, "templates", web_path, "#{schema.singular}_settings", "edit.html.heex"])},
{:eex, "settings_controller.ex", Path.join([web_prefix, "controllers", web_path, "#{schema.singular}_settings_controller.ex"])},
{:eex, "settings_controller_test.exs", Path.join([web_test_prefix, "controllers", web_path, "#{schema.singular}_settings_controller_test.exs"])}
{:eex, "settings_controller_test.exs", Path.join([web_test_prefix, "controllers", web_path, "#{schema.singular}_settings_controller_test.exs"])},
{:eex, "registration_live.ex", Path.join([web_test_prefix, "live", web_path, "#{schema.singular}_registration_live.ex"])},
{:eex, "login_live.ex", Path.join([web_test_prefix, "live", web_path, "#{schema.singular}_login_live.ex"])},
{:eex, "reset_password_live.ex", Path.join([web_test_prefix, "live", web_path, "#{schema.singular}_reset_password_live.ex"])}
]
end

Expand Down
69 changes: 69 additions & 0 deletions priv/templates/phx.gen.auth/login_live.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>LoginLive do
use <%= inspect context.web_module %>, :live_view

def render(assigns) do
~H"""
<h1>Log in</h1>

<.form
let={f}
chrismccord marked this conversation as resolved.
Show resolved Hide resolved
for={:<%= schema.singular %>}
phx-change="validate"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should remove validate. :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note to self, removing validate is pending on me with a new LV feature that maintains form state in the event of phx-change absence

phx-submit="log_in"
phx-trigger-action={@trigger_submit}
action={Routes.<%= schema.singular %>_session_path(@socket, :create)}
as={:<%= schema.singular %>}
>
<%%= if @error_message do %>
<div class="alert alert-danger">
<p><%%= @error_message %></p>
</div>
<%% end %>

<%%= label f, :email %>
<%%= email_input f, :email, required: true, value: @email %>

<%%= label f, :password %>
<%%= password_input f, :password, required: true, value: @password %>

<%%= label f, :remember_me, "Keep me logged in for 60 days" %>
<%%= checkbox f, :remember_me, value: @remember_me %>

<div>
<%%= submit "Log in" %>
</div>
</.form>

<p>
<.link href={Routes.<%= schema.route_helper %>_registration_path(@conn, :new)}>Register</.link> |
<.link href={Routes.<%= schema.route_helper %>_reset_password_path(@conn, :new)}>Forgot your password?</.link>
</p>
"""
end

def mount(_params, _session, socket) do
{:ok,
assign(socket,
error_message: nil,
trigger_submit: false,
password: nil,
email: nil,
remember_me: false
)}
end

def handle_event("log_in", _params, socket) do
{:noreply, assign(socket, trigger_submit: true)}
end

def handle_event("validate", %{"<%= schema.singular %>" => <%= schema.singular %>_params}, socket) do
%{"email" => email, "password" => password, "remember_me" => remember_me} = <%= schema.singular %>_params

{:noreply,
assign(socket,
password: password,
email: email,
remember_me: remember_me
)}
end
end
77 changes: 77 additions & 0 deletions priv/templates/phx.gen.auth/registration_live.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>RegistrationLive do
use <%= inspect context.web_module %>, :live_view

alias <%= inspect context.module %>
alias <%= inspect schema.module %>

def render(assigns) do
~H"""
<h1>Register</h1>

<.form
let={f}
for={@changeset}
phx-submit="save"
phx-change="validate"
phx-trigger-action={@trigger_submit}
action={Routes.<%= schema.singular %>_session_path(@socket, :create)}
as={:<%= schema.singular %>}
>
<%%= if @changeset.action do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below.</p>
</div>
<%% end %>

<%%= label f, :email %>
<%%= email_input f, :email, required: true %>
<%%= error_tag f, :email %>

<%%= label f, :password %>
<%%= password_input f, :password, required: true %>
bemesa21 marked this conversation as resolved.
Show resolved Hide resolved
<%%= error_tag f, :password %>

<div>
<%%= submit "Register" %>
</div>
</.form>

<p>
<.link href={Routes.<%= schema.route_helper %>_login_path(@conn, :new)}>Log in</.link>
<.link href={Routes.<%= schema.route_helper %>_reset_password_path(@conn, :new)}>Forgot your password?</.link>
</p>
"""
end

def mount(_params, _session, socket) do
changeset = <%= inspect context.alias %>.change_<%= schema.singular %>_registration(%<%= inspect schema.alias %>{})
{:ok, assign(socket, changeset: changeset, trigger_submit: false)}
end

def handle_event("save", %{"<%= schema.singular %>" => <%= schema.singular %>_params}, socket) do
case <%= inspect context.alias %>.register_<%= schema.singular %>(<%= schema.singular %>_params) do
{:ok, <%= schema.singular %>} ->
{:ok, _} =
<%= inspect context.alias %>.deliver_<%= schema.singular %>_confirmation_instructions(
<%= schema.singular %>,
&Routes.<%= schema.route_helper %>_confirmation_url(conn, :edit, &1)
)

socket =
socket
|> put_flash(:info, "<%= inspect schema.alias %> created successfully.")
|> assign(:trigger_submit, true)

{:noreply, socket}

{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, :changeset, changeset)}
end
end

def handle_event("validate", %{"<%= schema.singular %>" => <%= schema.singular %>_params}, socket) do
changeset = <%= inspect context.alias %>.change_<%= schema.singular %>_registration(%<%= inspect schema.alias %>{}, <%= schema.singular %>_params)

{:noreply, assign(socket, :changeset, changeset)}
end
end
98 changes: 98 additions & 0 deletions priv/templates/phx.gen.auth/reset_password_live.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>ResetPasswordLive do
bemesa21 marked this conversation as resolved.
Show resolved Hide resolved
use <%= inspect context.web_module %>, :live_view

alias <%= inspect context.module %>

on_mount {<%= inspect auth_module %>, :get_<%= schema.singular %>_by_reset_password_token}

def render(%{live_action: :new} = assigns) do
~H"""
<h1>Forgot your password?</h1>

<.form let={f} for={:<%= schema.singular %>} phx-submit="send_email"}>
<%%= label f, :email %>
<%%= email_input f, :email, required: true %>

<div>
<%%= submit "Send instructions to reset password" %>
</div>
</.form>

<.link href={Routes.<%= schema.route_helper %>_registration_path(@conn, :new)}>Register</.link> |
<.link href={Routes.<%= schema.route_helper %>_login_path(@conn, :new)}>Log in</.link>
"""
end

def render(%{live_action: :edit} = assigns) do
~H"""
<h1>Reset password</h1>
<.form let={f} for={@changeset} phx-submit="reset_password" @token)}>
<%%= if @changeset.action do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below.</p>
</div>
<%% end %>

<%%= label f, :password, "New password" %>
<%%= password_input f, :password, required: true %>
<%%= error_tag f, :password %>

<%%= label f, :password_confirmation, "Confirm new password" %>
<%%= password_input f, :password_confirmation, required: true %>
<%%= error_tag f, :password_confirmation %>

<div>
<%%= submit "Reset password" %>
</div>
</.form>

<.link href={Routes.<%= schema.route_helper %>_registration_path(@conn, :new)}>Register</.link> |
<.link href={Routes.<%= schema.route_helper %>_login_path(@conn, :new)}>Log in</.link>

"""
end

def mount(_params, _session, socket) do
if socket.assigns.live_action == :edit do
changeset = <%= inspect context.alias %>.change_<%= schema.singular %>_password(socket.assigns.<%= schema.singular %>)
{:ok, assign(socket, :changeset, changeset)}
else
{:ok, socket}
end
end

# Do not log in the <%= schema.singular %> after reset password to avoid a
# leaked token giving the <%= schema.singular %> access to the account.
def handle_event("reset_password", %{"<%= schema.singular %>" => <%= schema.singular %>_params}, socket) do
case <%= inspect context.alias %>.reset_<%= schema.singular %>_password(socket.assigns.<%= schema.singular %>, <%= schema.singular %>_params) do
{:ok, _} ->
socket =
socket
|> put_flash(:info, "Password reset successfully.")
|> redirect(to: Routes.<%= schema.singular %>_login_path(socket, :new))

{:noreply, socket}

{:error, changeset} ->
{:noreply, assign(socket, :changeset, changeset)}
end
end

def handle_event("send_email", %{"<%= schema.singular %>" => %{"email" => email}}, socket) do
if <%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>_by_email(email) do
<%= inspect context.alias %>.deliver_<%= schema.singular %>_reset_password_instructions(
<%= schema.singular %>,
&Routes.<%= schema.singular %>_reset_password_url(socket, :edit, &1)
)
end

socket =
socket
|> put_flash(
:info,
"If your email is in our system, you will receive instructions to reset your password shortly."
)
|> redirect(to: "/")
{:noreply, socket}
end
end