action_auth 1.8.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +102 -0
  3. data/README.md +485 -36
  4. data/Rakefile +0 -2
  5. data/app/assets/javascripts/action_auth/application.js +72 -71
  6. data/app/assets/stylesheets/action_auth/application.css +38 -1
  7. data/app/controllers/action_auth/application_controller.rb +132 -1
  8. data/app/controllers/action_auth/connected_accounts_controller.rb +16 -0
  9. data/app/controllers/action_auth/identity/email_verifications_controller.rb +36 -5
  10. data/app/controllers/action_auth/identity/emails_controller.rb +16 -4
  11. data/app/controllers/action_auth/identity/password_resets_controller.rb +20 -22
  12. data/app/controllers/action_auth/magics/requests_controller.rb +27 -6
  13. data/app/controllers/action_auth/magics/sign_ins_controller.rb +22 -7
  14. data/app/controllers/action_auth/passwords_controller.rb +7 -18
  15. data/app/controllers/action_auth/provider_callbacks_controller.rb +147 -0
  16. data/app/controllers/action_auth/registrations_controller.rb +7 -25
  17. data/app/controllers/action_auth/sessions/passkeys_controller.rb +17 -9
  18. data/app/controllers/action_auth/sessions_controller.rb +27 -25
  19. data/app/controllers/action_auth/sms_auths/requests_controller.rb +40 -14
  20. data/app/controllers/action_auth/sms_auths/sign_ins_controller.rb +40 -15
  21. data/app/controllers/action_auth/users_controller.rb +35 -1
  22. data/app/controllers/action_auth/webauthn_credential_authentications_controller.rb +36 -51
  23. data/app/controllers/action_auth/webauthn_credentials_controller.rb +63 -51
  24. data/app/helpers/action_auth/application_helper.rb +83 -0
  25. data/app/mailers/action_auth/application_mailer.rb +1 -1
  26. data/app/mailers/action_auth/user_mailer.rb +7 -0
  27. data/app/models/action_auth/connected_account.rb +18 -0
  28. data/app/models/action_auth/session.rb +9 -1
  29. data/app/models/action_auth/user.rb +197 -4
  30. data/app/models/action_auth/webauthn_credential.rb +2 -0
  31. data/app/views/action_auth/identity/email_verifications/show.html.erb +23 -0
  32. data/app/views/action_auth/identity/emails/edit.html.erb +41 -42
  33. data/app/views/action_auth/identity/password_resets/edit.html.erb +10 -11
  34. data/app/views/action_auth/identity/password_resets/new.html.erb +4 -9
  35. data/app/views/action_auth/magics/requests/new.html.erb +4 -14
  36. data/app/views/action_auth/magics/sign_ins/show.html.erb +18 -0
  37. data/app/views/action_auth/passwords/edit.html.erb +9 -21
  38. data/app/views/action_auth/registrations/new.html.erb +5 -27
  39. data/app/views/action_auth/sessions/_account.html.erb +30 -0
  40. data/app/views/action_auth/sessions/_connected_accounts.html.erb +32 -0
  41. data/app/views/action_auth/sessions/_security_keys.html.erb +32 -0
  42. data/app/views/action_auth/sessions/_sessions.html.erb +28 -0
  43. data/app/views/action_auth/sessions/index.html.erb +10 -62
  44. data/app/views/action_auth/sessions/new.html.erb +3 -21
  45. data/app/views/action_auth/sessions/passkeys/new.html.erb +10 -4
  46. data/app/views/action_auth/shared/_errors.html.erb +10 -0
  47. data/app/views/action_auth/shared/_flash.html.erb +11 -0
  48. data/app/views/action_auth/shared/_links.html.erb +3 -0
  49. data/app/views/action_auth/shared/_oauth_buttons.html.erb +5 -0
  50. data/app/views/action_auth/shared/_webauthn_error.html.erb +1 -0
  51. data/app/views/action_auth/sms_auths/requests/new.html.erb +4 -14
  52. data/app/views/action_auth/sms_auths/sign_ins/show.html.erb +6 -2
  53. data/app/views/action_auth/user_mailer/account_locked.html.erb +17 -0
  54. data/app/views/action_auth/user_mailer/account_locked.text.erb +12 -0
  55. data/app/views/action_auth/user_mailer/email_verification.html.erb +5 -0
  56. data/app/views/action_auth/user_mailer/email_verification.text.erb +3 -0
  57. data/app/views/action_auth/user_mailer/magic_link.html.erb +4 -0
  58. data/app/views/action_auth/user_mailer/magic_link.text.erb +5 -0
  59. data/app/views/action_auth/user_mailer/password_reset.text.erb +1 -1
  60. data/app/views/action_auth/webauthn_credential_authentications/new.html.erb +9 -3
  61. data/app/views/action_auth/webauthn_credentials/new.html.erb +10 -3
  62. data/app/views/layouts/action_auth/application.html.erb +2 -7
  63. data/config/routes.rb +13 -3
  64. data/db/migrate/20261105120000_add_magic_link_used_at_to_users.rb +5 -0
  65. data/db/migrate/20261105130000_add_account_lockout_and_suspension_to_users.rb +7 -0
  66. data/db/migrate/20261105130100_create_action_auth_connected_accounts.rb +19 -0
  67. data/lib/action_auth/configuration.rb +96 -0
  68. data/lib/action_auth/controllers/helpers.rb +44 -11
  69. data/lib/action_auth/engine.rb +27 -1
  70. data/lib/action_auth/routing/helpers.rb +8 -0
  71. data/lib/action_auth/version.rb +1 -1
  72. data/lib/generators/action_auth/views/USAGE +8 -0
  73. data/lib/generators/action_auth/views/views_generator.rb +59 -0
  74. data/lib/tasks/action_auth_tasks.rake +19 -1
  75. metadata +28 -5
@@ -1,17 +1,16 @@
1
+ <%= render "action_auth/shared/flash" %>
2
+
1
3
  <h1>Reset your password</h1>
2
4
 
3
- <%= form_with(url: identity_password_reset_path, method: :patch) do |form| %>
4
- <% if @user.errors.any? %>
5
- <div style="color: red">
6
- <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
5
+ <% unless @user.verified? %>
6
+ <p>
7
+ This email address hasn't been verified yet, so resetting the password will also verify it and disconnect any
8
+ connected accounts.
9
+ </p>
10
+ <% end %>
7
11
 
8
- <ul>
9
- <% @user.errors.each do |error| %>
10
- <li><%= error.full_message %></li>
11
- <% end %>
12
- </ul>
13
- </div>
14
- <% end %>
12
+ <%= form_with(url: identity_password_reset_path, method: :patch) do |form| %>
13
+ <%= render "action_auth/shared/errors", record: @user %>
15
14
 
16
15
  <%= form.hidden_field :sid, value: params[:sid] %>
17
16
 
@@ -1,10 +1,11 @@
1
+ <%= render "action_auth/shared/flash" %>
2
+
1
3
  <h1>Forgot your password?</h1>
2
- <p style="color: red"><%= alert %></p>
3
4
 
4
5
  <%= form_with(url: identity_password_reset_path) do |form| %>
5
6
  <div class="mb-3">
6
7
  <%= form.label :email, style: "display: block" %>
7
- <%= form.email_field :email, required: true, autofocus: true %>
8
+ <%= form.email_field :email, required: true, autofocus: true, autocomplete: "email" %>
8
9
  </div>
9
10
 
10
11
  <div class="mb-3">
@@ -12,10 +13,4 @@
12
13
  </div>
13
14
  <% end %>
14
15
 
15
- <div class="mb-3">
16
- <%= link_to "Sign In", sign_in_path %>
17
- | <%= link_to "Sign Up", sign_up_path %>
18
- <% if ActionAuth.configuration.verify_email_on_sign_in %>
19
- | <%= link_to "Verify Email", identity_email_verification_path %>
20
- <% end %>
21
- </div>
16
+ <%= render "action_auth/shared/links" %>
@@ -1,26 +1,16 @@
1
+ <%= render "action_auth/shared/flash" %>
2
+
1
3
  <h1>Request Magic Link</h1>
2
4
 
3
5
  <%= form_with(url: magics_requests_path) do |form| %>
4
6
  <div class="mb-3">
5
7
  <%= form.label :email, style: "display: block" %>
6
- <%= form.email_field :email, required: true, autofocus: true, autocomplete: "email" %>
8
+ <%= form.email_field :email, value: params[:email], required: true, autofocus: true, autocomplete: "email" %>
7
9
  </div>
8
10
 
9
11
  <div class="mb-3">
10
12
  <%= form.submit "Request Magic Link", class: "btn btn-primary" %>
11
- <span class="mx-3">or</span>
12
- <%= link_to "Sign In", sign_in_path %>
13
- <% if ActionAuth.configuration.passkey_only? %>
14
- <span class="mx-3">or</span>
15
- <%= link_to "Passkey", new_sessions_passkey_path %>
16
- <% end %>
17
13
  </div>
18
14
  <% end %>
19
15
 
20
- <div class="mb-3">
21
- <%= link_to "Sign Up", sign_up_path %> |
22
- <%= link_to "Reset Password", new_identity_password_reset_path %>
23
- <% if ActionAuth.configuration.verify_email_on_sign_in %>
24
- | <%= link_to "Verify Email", identity_email_verification_path %>
25
- <% end %>
26
- </div>
16
+ <%= render "action_auth/shared/links" %>
@@ -0,0 +1,18 @@
1
+ <%= render "action_auth/shared/flash" %>
2
+
3
+ <h1>Sign in</h1>
4
+
5
+ <p>You're signing in as <strong><%= @user.email %></strong>. This link only works once.</p>
6
+
7
+ <%# Worded for both people who see it, who look the same from here: someone who chose a
8
+ password before verifying, and someone who has never had one. It's said here rather
9
+ than after signing in, because the app's own page may not display flash messages. %>
10
+ <% unless @user.verified? %>
11
+ <p>
12
+ This email address hasn't been verified yet, so signing in will also replace any password set on this account,
13
+ sign out its other devices and disconnect any connected accounts. You can choose a new password afterwards with
14
+ Reset Password.
15
+ </p>
16
+ <% end %>
17
+
18
+ <%= button_to "Sign in", magics_sign_ins_path, params: { token: params[:token] }, class: "btn btn-primary" %>
@@ -1,43 +1,31 @@
1
- <p style="color: red"><%= alert %></p>
1
+ <%= render "action_auth/shared/flash" %>
2
2
 
3
3
  <h1>Change your password</h1>
4
4
 
5
5
  <%= form_with(url: password_path, method: :patch) do |form| %>
6
- <% if @user.errors.any? %>
7
- <div style="color: red">
8
- <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
6
+ <%= render "action_auth/shared/errors", record: @user %>
9
7
 
10
- <ul>
11
- <% @user.errors.each do |error| %>
12
- <li><%= error.full_message %></li>
13
- <% end %>
14
- </ul>
15
- </div>
16
- <% end %>
17
-
18
- <div>
19
- <%= form.label :password_challenge, style: "display: block" %>
8
+ <div class="mb-3">
9
+ <%= form.label :password_challenge, "Current password", style: "display: block" %>
20
10
  <%= form.password_field :password_challenge, required: true, autofocus: true, autocomplete: "current-password" %>
21
11
  </div>
22
12
 
23
- <div>
13
+ <div class="mb-3">
24
14
  <%= form.label :password, "New password", style: "display: block" %>
25
15
  <%= form.password_field :password, required: true, autocomplete: "new-password" %>
26
16
  <div>12 characters minimum.</div>
27
17
  </div>
28
18
 
29
- <div>
19
+ <div class="mb-3">
30
20
  <%= form.label :password_confirmation, "Confirm new password", style: "display: block" %>
31
21
  <%= form.password_field :password_confirmation, required: true, autocomplete: "new-password" %>
32
22
  </div>
33
23
 
34
- <div>
35
- <%= form.submit "Save changes" %>
24
+ <div class="mb-3">
25
+ <%= form.submit "Save changes", class: "btn btn-primary" %>
36
26
  </div>
37
27
  <% end %>
38
28
 
39
- <br>
40
-
41
29
  <div>
42
- <%= link_to "Back", main_app.root_path %>
30
+ <%= link_to "Back", sessions_path %>
43
31
  </div>
@@ -1,17 +1,9 @@
1
+ <%= render "action_auth/shared/flash" %>
2
+
1
3
  <h1>Sign up</h1>
2
4
 
3
5
  <%= form_with(url: sign_up_path) do |form| %>
4
- <% if @user.errors.any? %>
5
- <div style="color: red">
6
- <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
7
-
8
- <ul>
9
- <% @user.errors.each do |error| %>
10
- <li><%= error.full_message %></li>
11
- <% end %>
12
- </ul>
13
- </div>
14
- <% end %>
6
+ <%= render "action_auth/shared/errors", record: @user %>
15
7
 
16
8
  <div class="mb-3">
17
9
  <%= form.label :email, style: "display: block" %>
@@ -34,19 +26,5 @@
34
26
  </div>
35
27
  <% end %>
36
28
 
37
- <div class="mb-3">
38
- <%= link_to "Sign In", sign_in_path %> |
39
- <% if ActionAuth.configuration.magic_link_enabled? %>
40
- <%= link_to "Magic Link", new_magics_requests_path %> |
41
- <% end %>
42
- <% if ActionAuth.configuration.sms_auth_enabled? %>
43
- <%= link_to "SMS Auth", new_sms_auths_requests_path %> |
44
- <% end %>
45
- <% if ActionAuth.configuration.passkey_only? %>
46
- <%= link_to "Passkey", new_sessions_passkey_path %> |
47
- <% end %>
48
- <%= link_to "Reset Password", new_identity_password_reset_path %>
49
- <% if ActionAuth.configuration.verify_email_on_sign_in %>
50
- | <%= link_to "Verify Email", identity_email_verification_path %>
51
- <% end %>
52
- </div>
29
+ <%= render "action_auth/shared/oauth_buttons" %>
30
+ <%= render "action_auth/shared/links" %>
@@ -0,0 +1,30 @@
1
+ <h2>Account</h2>
2
+ <%# Both of these ask for the current password, which a placeholder account can't know. %>
3
+ <% if ActionAuth::Current.user.password_usable? %>
4
+ <div class="mb-3">
5
+ <%= link_to "Change email", edit_identity_email_path %> |
6
+ <%= link_to "Change password", edit_password_path %>
7
+ </div>
8
+ <% end %>
9
+
10
+ <% if ActionAuth.configuration.allow_user_deletion? %>
11
+ <details class="mb-3">
12
+ <summary>Delete account</summary>
13
+ <p>This permanently deletes your account and signs you out everywhere. It can't be undone.</p>
14
+
15
+ <% if ActionAuth::Current.user.password_usable? %>
16
+ <%= form_with(url: users_path, method: :delete) do |form| %>
17
+ <div class="mb-3">
18
+ <%= form.label :password_challenge, "Current password", style: "display: block" %>
19
+ <%= form.password_field :password_challenge, required: true, autocomplete: "current-password" %>
20
+ <div>Don't know your password? <%= link_to "Reset it", new_identity_password_reset_path %> first.</div>
21
+ </div>
22
+
23
+ <%= form.submit "Permanently delete my account", class: "btn btn-danger" %>
24
+ <% end %>
25
+ <% else %>
26
+ <p>To confirm it's you, this only works within 10 minutes of signing in with <%= ActionAuth::Current.user.fresh_sign_in_method %>.</p>
27
+ <%= button_to "Permanently delete my account", users_path, method: :delete, class: "btn btn-danger" %>
28
+ <% end %>
29
+ </details>
30
+ <% end %>
@@ -0,0 +1,32 @@
1
+ <% connected_accounts = current_user.connected_accounts.order(:created_at).to_a %>
2
+
3
+ <h2>Connected Accounts</h2>
4
+
5
+ <% if connected_accounts.any? %>
6
+ <table class="action-auth--table">
7
+ <thead>
8
+ <tr>
9
+ <th>Provider</th>
10
+ <th>Account</th>
11
+ <th nowrap>Connected On</th>
12
+ <th nowrap></th>
13
+ </tr>
14
+ </thead>
15
+ <tbody>
16
+ <% connected_accounts.each do |connected_account| %>
17
+ <%= content_tag :tr, id: dom_id(connected_account) do %>
18
+ <td><%= connected_account.provider_label %></td>
19
+ <td><%= connected_account.display_name %></td>
20
+ <td nowrap><%= connected_account.created_at.strftime('%B %d, %Y') %></td>
21
+ <td nowrap><%= button_to "Disconnect", connected_account_path(connected_account), method: :delete, class: "btn btn-primary" %></td>
22
+ <% end %>
23
+ <% end %>
24
+ </tbody>
25
+ </table>
26
+ <% end %>
27
+
28
+ <% ActionAuth.configuration.oauth_providers.reject { |oauth| connected_accounts.any? { |account| account.provider == oauth.key } }.each do |oauth| %>
29
+ <div class="mb-3">
30
+ <%= button_to "Connect #{oauth.label}", oauth_request_path(oauth.key), form: { data: { turbo: false } }, class: "btn btn-primary" %>
31
+ </div>
32
+ <% end %>
@@ -0,0 +1,32 @@
1
+ <% if current_user.second_factor_enabled? %>
2
+ <h2>Your Security Keys</h2>
3
+ <table class="action-auth--table">
4
+ <thead>
5
+ <tr>
6
+ <th>Key</th>
7
+ <th>Type</th>
8
+ <th nowrap>Registered On</th>
9
+ <th nowrap></th>
10
+ </tr>
11
+ </thead>
12
+ <tbody>
13
+ <% current_user.webauthn_credentials.each do |credential| %>
14
+ <%= content_tag :tr, id: dom_id(credential) do %>
15
+ <td><%= credential.nickname %></td>
16
+ <td><%= credential.key_type %></td>
17
+ <td nowrap><%= credential.created_at.strftime('%B %d, %Y') %></td>
18
+ <td nowrap><%= button_to "Delete", credential, method: :delete, class: "btn btn-primary" %></td>
19
+ <% end %>
20
+ <% end %>
21
+ </tbody>
22
+ </table>
23
+
24
+ <div class="mb-3">
25
+ <%= link_to "Register new Security Key", new_webauthn_credential_path, class: "btn btn-primary" %>
26
+ </div>
27
+ <% else %>
28
+ <h2>Enable Two-Factor Authentication</h2>
29
+ <div class="mb-3">
30
+ <%= link_to "Add a passkey", new_webauthn_credential_path, class: "btn btn-primary" %>
31
+ </div>
32
+ <% end %>
@@ -0,0 +1,28 @@
1
+ <h2>Sessions</h2>
2
+ <div id="sessions">
3
+ <table class="action-auth--table">
4
+ <thead>
5
+ <tr>
6
+ <th>User Agent</th>
7
+ <th nowrap>Ip Address</th>
8
+ <th nowrap>Created at</th>
9
+ <th nowrap></th>
10
+ </tr>
11
+ </thead>
12
+ <tbody>
13
+ <% sessions.each do |session| %>
14
+ <%= content_tag :tr, id: dom_id(session) do %>
15
+ <td>
16
+ <%= session.user_agent %>
17
+ <% if session == current_session %>
18
+ <strong>(this device)</strong>
19
+ <% end %>
20
+ </td>
21
+ <td nowrap><%= session.ip_address %></td>
22
+ <td><%= session.created_at %></td>
23
+ <td><%= button_to "Log out", session, method: :delete, class: "btn btn-primary" %></td>
24
+ <% end %>
25
+ <% end %>
26
+ </tbody>
27
+ </table>
28
+ </div>
@@ -1,68 +1,16 @@
1
- <p style="color: green"><%= notice %></p>
1
+ <%= render "action_auth/shared/flash" %>
2
2
 
3
- <h1>
4
- Devices & Sessions
5
- </h1>
6
- <small><%= link_to "back to app", main_app.root_path %></small>
3
+ <h1>Devices &amp; Sessions</h1>
4
+ <small><%= link_to "back to app", after_sign_in_path %></small>
7
5
 
8
- <h2>Sessions</h2>
9
- <div id="sessions">
10
- <table class="action-auth--table">
11
- <thead>
12
- <tr>
13
- <th>User Agent</th>
14
- <th nowrap>Ip Address</th>
15
- <th nowrap>Created at</th>
16
- <th nowrap></th>
17
- </tr>
18
- </thead>
19
- <tbody>
20
- <% @sessions.each do |session| %>
21
- <%= content_tag :tr, id: dom_id(session) do %>
22
- <td><%= session.user_agent %></td>
23
- <td nowrap><%= session.ip_address %></td>
24
- <td><%= session.created_at %></td>
25
- <td><%= button_to "Log out", session, method: :delete, class: "btn btn-primary" %></td>
26
- <% end %>
27
- <% end %>
28
- </tbody>
29
- </table>
30
- </div>
6
+ <%= render "action_auth/sessions/sessions", sessions: @sessions %>
31
7
 
32
8
  <% if ActionAuth.configuration.webauthn_enabled? %>
33
- <% if current_user.second_factor_enabled? %>
34
- <h3>Your Security Keys:</h3>
35
- <table class="action-auth--table">
36
- <thead>
37
- <tr>
38
- <th>Key</th>
39
- <th>Type</th>
40
- <th nowrap>Registered On</th>
41
- <th nowrap></th>
42
- </tr>
43
- </thead>
44
- <tbody>
45
- <% current_user.webauthn_credentials.each do |credential| %>
46
- <%= content_tag :tr, id: dom_id(credential) do %>
47
- <td><%= credential.nickname %></td>
48
- <td><%= credential.key_type %></td>
49
- <td nowrap><%= credential.created_at.strftime('%B %d, %Y') %></td>
50
- <td nowrap><%= button_to "Delete", credential, method: :delete, class: "btn btn-primary" %></td>
51
- <% end %>
52
- <% end %>
53
- </tbody>
54
- </table>
9
+ <%= render "action_auth/sessions/security_keys" %>
10
+ <% end %>
55
11
 
56
- <div>
57
- <%= button_to("Register new Security Key",
58
- new_webauthn_credential_path,
59
- method: :get,
60
- class: "btn btn-primary") %>
61
- </div>
62
- <% else %>
63
- <h2>Enable Two-Factor Authentication</h2>
64
- <div class="">
65
- <%= link_to "Add a passkey", new_webauthn_credential_path, class: "btn btn-primary" %>
66
- </div>
67
- <% end %>
12
+ <% if ActionAuth.configuration.oauth_enabled? && ActionAuth::ConnectedAccount.table_exists? %>
13
+ <%= render "action_auth/sessions/connected_accounts" %>
68
14
  <% end %>
15
+
16
+ <%= render "action_auth/sessions/account" %>
@@ -1,5 +1,4 @@
1
- <p style="color: green"><%= notice %></p>
2
- <p style="color: red"><%= alert %></p>
1
+ <%= render "action_auth/shared/flash" %>
3
2
 
4
3
  <h1>Sign in</h1>
5
4
 
@@ -16,25 +15,8 @@
16
15
 
17
16
  <div class="mb-3">
18
17
  <%= form.submit "Sign in", class: "btn btn-primary" %>
19
- <% if ActionAuth.configuration.magic_link_enabled? %>
20
- <span class="mx-3">or</span>
21
- <%= link_to "Magic Link", new_magics_requests_path %>
22
- <% end %>
23
- <% if ActionAuth.configuration.sms_auth_enabled? %>
24
- <span class="mx-3">or</span>
25
- <%= link_to "SMS Auth", new_sms_auths_requests_path %> |
26
- <% end %>
27
- <% if ActionAuth.configuration.passkey_only? %>
28
- <span class="mx-3">or</span>
29
- <%= link_to "Passkey", new_sessions_passkey_path %>
30
- <% end %>
31
18
  </div>
32
19
  <% end %>
33
20
 
34
- <div class="mb-3">
35
- <%= link_to "Sign Up", sign_up_path %> |
36
- <%= link_to "Reset Password", new_identity_password_reset_path %>
37
- <% if ActionAuth.configuration.verify_email_on_sign_in %>
38
- | <%= link_to "Verify Email", identity_email_verification_path %>
39
- <% end %>
40
- </div>
21
+ <%= render "action_auth/shared/oauth_buttons" %>
22
+ <%= render "action_auth/shared/links" %>
@@ -1,5 +1,11 @@
1
+ <%= render "action_auth/shared/flash" %>
2
+
3
+ <%= action_auth_webauthn_tags %>
4
+ <%= tag.meta name: "passkey_auth_url", content: sessions_passkeys_url %>
5
+
1
6
  <h2 class="action-auth--text-center">Use a passkey to sign in</h2>
2
- <%= tag :meta, name: :passkey_auth_url, content: action_auth.sessions_passkeys_url %>
7
+
8
+ <%= render "action_auth/shared/webauthn_error" %>
3
9
 
4
10
  <%= content_tag :div,
5
11
  id: "webauthn_credential_form",
@@ -15,6 +21,6 @@
15
21
  </div>
16
22
  <% end %>
17
23
 
18
- <%= content_for :cancel_path do %>
19
- <%= link_to "Cancel", action_auth.sign_in_path %>
20
- <% end %>
24
+ <div class="action-auth--text-center">
25
+ <%= link_to "Cancel", sign_in_path %>
26
+ </div>
@@ -0,0 +1,10 @@
1
+ <% if record&.errors&.any? %>
2
+ <div class="action-auth--errors" role="alert">
3
+ <h2><%= pluralize(record.errors.count, "error") %> prohibited this user from being saved:</h2>
4
+ <ul>
5
+ <% record.errors.each do |error| %>
6
+ <li><%= error.full_message %></li>
7
+ <% end %>
8
+ </ul>
9
+ </div>
10
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <%# Shown here rather than in the layout so that messages appear in any layout, and
2
+ removed once shown so that a layout which also displays flash doesn't repeat
3
+ them. To use your layout's own flash instead, make this partial empty. %>
4
+ <% if notice.present? %>
5
+ <p class="action-auth--notice" role="status"><%= notice %></p>
6
+ <% end %>
7
+ <% if alert.present? %>
8
+ <p class="action-auth--alert" role="alert"><%= alert %></p>
9
+ <% end %>
10
+ <% flash.delete(:notice) %>
11
+ <% flash.delete(:alert) %>
@@ -0,0 +1,3 @@
1
+ <div class="mb-3 action-auth--links">
2
+ <%= safe_join(action_auth_links.map { |label, path| link_to(label, path) }, " | ") %>
3
+ </div>
@@ -0,0 +1,5 @@
1
+ <% action_auth_oauth_providers.each do |label, path| %>
2
+ <div class="mb-3">
3
+ <%= button_to "Continue with #{label}", path, form: { data: { turbo: false } }, class: "btn btn-primary" %>
4
+ </div>
5
+ <% end %>
@@ -0,0 +1 @@
1
+ <p id="webauthn_error" class="action-auth--alert" role="alert" hidden></p>
@@ -1,26 +1,16 @@
1
+ <%= render "action_auth/shared/flash" %>
2
+
1
3
  <h1>Request SMS Code</h1>
2
4
 
3
5
  <%= form_with(url: sms_auths_requests_path) do |form| %>
4
6
  <div class="mb-3">
5
7
  <%= form.label :phone_number, style: "display: block" %>
6
- <%= form.telephone_field :phone_number, required: true, autofocus: true, autocomplete: "mobile" %>
8
+ <%= form.telephone_field :phone_number, value: params[:phone_number], required: true, autofocus: true, autocomplete: "tel" %>
7
9
  </div>
8
10
 
9
11
  <div class="mb-3">
10
12
  <%= form.submit "Request SMS Code", class: "btn btn-primary" %>
11
- <span class="mx-3">or</span>
12
- <%= link_to "Sign In", sign_in_path %>
13
- <% if ActionAuth.configuration.passkey_only? %>
14
- <span class="mx-3">or</span>
15
- <%= link_to "Passkey", new_sessions_passkey_path %>
16
- <% end %>
17
13
  </div>
18
14
  <% end %>
19
15
 
20
- <div class="mb-3">
21
- <%= link_to "Sign Up", sign_up_path %> |
22
- <%= link_to "Reset Password", new_identity_password_reset_path %>
23
- <% if ActionAuth.configuration.verify_email_on_sign_in %>
24
- | <%= link_to "Verify Email", identity_email_verification_path %>
25
- <% end %>
26
- </div>
16
+ <%= render "action_auth/shared/links" %>
@@ -1,10 +1,11 @@
1
+ <%= render "action_auth/shared/flash" %>
2
+
1
3
  <h1>Verify SMS Code</h1>
2
4
 
3
5
  <%= form_with(url: sms_auths_sign_ins_path) do |form| %>
4
- <%= form.hidden_field :phone_number, value: cookies.signed[:sms_auth_phone_number] %>
5
6
  <div class="mb-3">
6
7
  <%= form.label :sms_code, style: "display: block" %>
7
- <%= form.number_field :sms_code, required: true, autofocus: true, autocomplete: "one-time-code" %>
8
+ <%= form.text_field :sms_code, required: true, autofocus: true, autocomplete: "one-time-code", inputmode: "numeric" %>
8
9
  </div>
9
10
 
10
11
  <div class="mb-3">
@@ -12,3 +13,6 @@
12
13
  </div>
13
14
  <% end %>
14
15
 
16
+ <div>
17
+ <%= link_to "Send a new code", new_sms_auths_requests_path %>
18
+ </div>
@@ -0,0 +1,17 @@
1
+ <p>Hey there,</p>
2
+
3
+ <p>
4
+ There have been too many failed attempts to sign in to <strong><%= @user.email %></strong>,
5
+ so we've locked sign in with a password<% if @duration %> for the next <%= distance_of_time_in_words(@duration) %><% end %>.
6
+ </p>
7
+
8
+ <p>
9
+ If that was you, you can get back in now by
10
+ <%= link_to "resetting your password", new_identity_password_reset_url %>.
11
+ </p>
12
+
13
+ <p>
14
+ If it wasn't, someone may be trying to guess your password. Those attempts failed,
15
+ and devices you're already signed in on aren't affected. Consider changing
16
+ your password if you use it anywhere else.
17
+ </p>
@@ -0,0 +1,12 @@
1
+ Hey there,
2
+
3
+ There have been too many failed attempts to sign in to <%= @user.email %>,
4
+ so we've locked sign in with a password<% if @duration %> for the next <%= distance_of_time_in_words(@duration) %><% end %>.
5
+
6
+ If that was you, you can get back in now by resetting your password:
7
+
8
+ <%= new_identity_password_reset_url %>
9
+
10
+ If it wasn't, someone may be trying to guess your password. Those attempts failed,
11
+ and devices you're already signed in on aren't affected. Consider changing
12
+ your password if you use it anywhere else.
@@ -15,3 +15,8 @@
15
15
  <p>
16
16
  <%= link_to "Yes, use this email for my account", identity_email_verification_url(sid: @signed_id) %>
17
17
  </p>
18
+
19
+ <p>
20
+ You'll be asked for your password. If you didn't sign up, you can safely ignore
21
+ this email and nothing will change.
22
+ </p>
@@ -7,3 +7,6 @@ that's where we'll email a reset link.
7
7
  You must click the link below to confirm that you received this email.
8
8
 
9
9
  <%= identity_email_verification_url(sid: @signed_id) %>
10
+
11
+ You'll be asked for your password. If you didn't sign up, you can safely ignore
12
+ this email and nothing will change.
@@ -1,3 +1,7 @@
1
1
  <p>
2
2
  Use this <%= link_to "link", magics_sign_ins_url(token: @signed_id) %> to sign in.
3
3
  </p>
4
+
5
+ <p>
6
+ It expires in 20 minutes and only works once. If you didn't request it you can safely ignore this email.
7
+ </p>
@@ -0,0 +1,5 @@
1
+ Use this link to sign in:
2
+
3
+ <%= magics_sign_ins_url(token: @signed_id) %>
4
+
5
+ It expires in 20 minutes and only works once. If you didn't request it you can safely ignore this email.
@@ -1,6 +1,6 @@
1
1
  Hey there,
2
2
 
3
- Can't remember your password for <strong><%= @user.email %></strong>?
3
+ Can't remember your password for <%= @user.email %>?
4
4
  That's OK, it happens. Just hit the link below to set a new one.
5
5
 
6
6
  <%= edit_identity_password_reset_url(sid: @signed_id) %>