action_auth 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 45ce58405d5a45e6c9bf204378b2d187b468285401d889fe9e8323ce9649e345
4
- data.tar.gz: 1e94b9b8e23d211d93ce96f8ff1e4ea1f6b816ca0ed9de8144b72a03273a7de7
3
+ metadata.gz: d680d8d34330e5aec31d3ab30576b677f4b3320c9cb9383b0a2ea2d5369c4541
4
+ data.tar.gz: 6c5d816b40895ec52e7b6ec331127263e5e82a80b6e838a6fd1e047366de1ea5
5
5
  SHA512:
6
- metadata.gz: 889f0be20c9e05507bfa12035ce2c06254b751161191bf3e1ae99eaba39643bbbb7b995a94b74dc4ba6453350e8201ae5265f938caaf50a85a149eae975e9a30
7
- data.tar.gz: caecc465fce527d29225ab23ef7cc33c6cd992496864e5a224ab426a3a81378c2290a020b83dff6053c2f159d4bf9d8c579b9033ab48db8990b4796bacd024ab
6
+ metadata.gz: 19e8c186624ccf06148d16932b6026143560479594d07e2bed4298f4c18b83df65a17e1ee88149c7fc6a9b0a1b1afbebc4a95023cebee81d15d393bbe984f6c1
7
+ data.tar.gz: 27e0a47e5cc73e646bacb873610a514211fc0bbd471d38776da5af2f419a73d85da135998a452a041e0ae3871fb4cec983204297923b274b98b6cd80fa256c36
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # ActionAuth
2
- This is a placeholder for the ActionAuth gem. It is not yet ready for use.
2
+ ActionAuth is a Rails engine that provides a simple authentication system for your Rails application.
3
+ It uses the latest methods for authentication and handling reset tokens from Rails 7.1.0.
4
+ It is designed to be simple and easy to use and allows you to focus on building your application.
5
+ The functionality of this gem relies on ActiveSupport::CurrentAttributes the methods are
6
+ designed to have a similar experience as Devise.
3
7
 
4
8
  ## Installation
5
9
  Add this line to your application's Gemfile:
@@ -8,6 +12,25 @@ Add this line to your application's Gemfile:
8
12
  bundle add action_auth
9
13
  bin/rails action_auth:install:migrations
10
14
  ```
15
+
16
+ Modify config/routes.rb to include the following:
17
+
18
+ ```ruby
19
+ mount ActionAuth::Engine => 'action_auth'
20
+ ```
21
+
22
+ In your view layout
23
+
24
+ ```ruby
25
+ <% if user_signed_in? %>
26
+ <li><%= link_to "Sessions", user_sessions_path %></li>
27
+ <li><%= button_to "Sign Out", user_session_path(current_session), method: :delete %></li>
28
+ <% else %>
29
+ <li><%= link_to "Sign In", new_user_session_path %></li>
30
+ <li><%= link_to "Sign Up", new_user_registration_path %></li>
31
+ <% end %>
32
+ ```
33
+
11
34
  ## Usage
12
35
 
13
36
  ### Routes
@@ -15,18 +38,19 @@ bin/rails action_auth:install:migrations
15
38
  Within your application, you'll have access to these routes. They have been styled to be consistent with Devise.
16
39
 
17
40
  Method Verb Params Description
18
- user_sessions_path GET Device session management
19
- user_session_path DELETE [:id] Log Out
20
- new_user_session_path GET Log in
21
- new_user_registration_path GET Sign Up
41
+ user_sessions_path GET Device session management
42
+ user_session_path DELETE [:id] Log Out
43
+ new_user_session_path GET Log in
44
+ new_user_registration_path GET Sign Up
45
+ edit_password_path GET Change Password
46
+ password_path PATCH Update Password
22
47
 
23
48
  ### Helper Methods
24
49
 
25
50
  Method Description
26
- current_user Returns the currently logged in user
51
+ current_user Returns the currently logged in user
27
52
  user_signed_in? Returns true if the user is logged in
28
- current_session Returns the current session
29
-
53
+ current_session Returns the current session
30
54
 
31
55
  ## License
32
56
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -1,15 +1,101 @@
1
- /*
2
- * This is a manifest file that'll be compiled into application.css, which will include all the files
3
- * listed below.
4
- *
5
- * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
- * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
- *
8
- * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
- * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
- * files in this directory. Styles in this file should be added after the last require_* statement.
11
- * It is generally better to create a new file per style scope.
12
- *
13
- *= require_tree .
14
- *= require_self
15
- */
1
+ body {
2
+ box-sizing: border-box;
3
+ margin: 0;
4
+ font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
5
+ font-size: 1rem;
6
+ font-weight: 400;
7
+ line-height: 1.5;
8
+ color: #212529;
9
+ text-align: left;
10
+ /* Assuming default alignment should be left */
11
+ -webkit-text-size-adjust: 100%;
12
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
13
+ margin-top: 25px;
14
+ background-color: rgb(248, 249, 250) !important;
15
+ }
16
+
17
+ .container {
18
+ -webkit-text-size-adjust: 100%;
19
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
20
+ box-sizing: border-box;
21
+ width: 400px;
22
+ padding-right: 12px;
23
+ padding-left: 12px;
24
+ margin-right: auto;
25
+ margin-left: auto;
26
+ max-width: 1140px;
27
+ border: solid 1px rgb(222, 226, 230) !important;
28
+ padding-bottom: 1rem !important;
29
+ background-color: rgb(255, 255, 255) !important;
30
+ }
31
+
32
+ input[type="text"],
33
+ input[type="email"],
34
+ input[type="password"] {
35
+ -webkit-text-size-adjust: 100%;
36
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
37
+ box-sizing: border-box;
38
+ margin: 0;
39
+ font-family: inherit;
40
+ display: block;
41
+ width: 100%;
42
+ padding: 0.375rem 0.75rem;
43
+ font-size: 1rem;
44
+ font-weight: 400;
45
+ line-height: 1.5;
46
+ color: #212529;
47
+ appearance: none;
48
+ background-color: #fff;
49
+ background-clip: padding-box;
50
+ border: 1px solid #dee2e6;
51
+ border-radius: 0.375rem;
52
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
53
+ }
54
+
55
+ .mb-3 {
56
+ margin-bottom: 1rem !important;
57
+ }
58
+
59
+ .btn {
60
+ padding: 0.375rem 0.75rem;
61
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
62
+ font-size: 1rem;
63
+ font-weight: 400;
64
+ line-height: 1.5;
65
+ color: #333;
66
+ text-align: center;
67
+ text-decoration: none;
68
+ vertical-align: middle;
69
+ user-select: none;
70
+ border: 1px solid #007bff;
71
+ border-radius: 0.25rem;
72
+ background-color: #007bff;
73
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
74
+ transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
75
+ cursor: pointer;
76
+ }
77
+
78
+ .btn:hover {
79
+ color: #fff;
80
+ background-color: #0056b3;
81
+ border-color: #004085;
82
+ }
83
+
84
+ .btn:focus {
85
+ outline: 0;
86
+ box-shadow: 0 0 0 0.25rem rgba(49, 132, 253, .5);
87
+ }
88
+
89
+ .btn:disabled {
90
+ color: #fff;
91
+ background-color: #007bff;
92
+ border-color: #007bff;
93
+ opacity: 0.65;
94
+ pointer-events: none;
95
+ }
96
+
97
+ .btn-primary {
98
+ color: #fff;
99
+ background-color: #007bff;
100
+ border-color: #007bff;
101
+ }
@@ -0,0 +1,30 @@
1
+ module ActionAuth
2
+ module Identity
3
+ class EmailVerificationsController < ApplicationController
4
+ before_action :set_user, only: :show
5
+
6
+ def show
7
+ @user.update! verified: true
8
+ redirect_to main_app.root_path, notice: "Thank you for verifying your email address"
9
+ end
10
+
11
+ def create
12
+ send_email_verification
13
+ redirect_to main_app.root_path, notice: "We sent a verification email to your email address"
14
+ end
15
+
16
+ private
17
+
18
+ def set_user
19
+ @user = ActionAuth::User.find_by_token_for!(:email_verification, params[:sid])
20
+ rescue StandardError
21
+ redirect_to edit_identity_email_path, alert: "That email verification link is invalid"
22
+ end
23
+
24
+ def send_email_verification
25
+ return unless Current.user
26
+ UserMailer.with(user: Current.user).email_verification.deliver_later
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,41 @@
1
+ module ActionAuth
2
+ module Identity
3
+ class EmailsController < ApplicationController
4
+ before_action :set_user
5
+
6
+ def edit
7
+ end
8
+
9
+ def update
10
+ if @user.update(user_params)
11
+ redirect_to_root
12
+ else
13
+ render :edit, status: :unprocessable_entity
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def set_user
20
+ @user = Current.user
21
+ end
22
+
23
+ def user_params
24
+ params.permit(:email, :password_challenge).with_defaults(password_challenge: "")
25
+ end
26
+
27
+ def redirect_to_root
28
+ if @user.email_previously_changed?
29
+ resend_email_verification
30
+ redirect_to main_app.root_path, notice: "Your email has been changed"
31
+ else
32
+ redirect_to main_app.root_path
33
+ end
34
+ end
35
+
36
+ def resend_email_verification
37
+ UserMailer.with(user: @user).email_verification.deliver_later
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,46 @@
1
+ module ActionAuth
2
+ module Identity
3
+ class PasswordResetsController < ApplicationController
4
+ before_action :set_user, only: %i[ edit update ]
5
+
6
+ def new
7
+ end
8
+
9
+ def edit
10
+ end
11
+
12
+ def create
13
+ if @user = ActionAuth::User.find_by(email: params[:email], verified: true)
14
+ send_password_reset_email
15
+ redirect_to sign_in_path, notice: "Check your email for reset instructions"
16
+ else
17
+ redirect_to new_identity_password_reset_path, alert: "You can't reset your password until you verify your email"
18
+ end
19
+ end
20
+
21
+ def update
22
+ if @user.update(user_params)
23
+ redirect_to sign_in_path, notice: "Your password was reset successfully. Please sign in"
24
+ else
25
+ render :edit, status: :unprocessable_entity
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def set_user
32
+ @user = ActionAuth::User.find_by_token_for!(:password_reset, params[:sid])
33
+ rescue StandardError
34
+ redirect_to new_identity_password_reset_path, alert: "That password reset link is invalid"
35
+ end
36
+
37
+ def user_params
38
+ params.permit(:password, :password_confirmation)
39
+ end
40
+
41
+ def send_password_reset_email
42
+ UserMailer.with(user: @user).password_reset.deliver_later
43
+ end
44
+ end
45
+ end
46
+ end
@@ -7,7 +7,7 @@ module ActionAuth
7
7
 
8
8
  def update
9
9
  if @user.update(user_params)
10
- redirect_to root_path, notice: "Your password has been changed"
10
+ redirect_to main_app.root_path, notice: "Your password has been changed"
11
11
  else
12
12
  render :edit, status: :unprocessable_entity
13
13
  end
@@ -7,7 +7,7 @@ module ActionAuth
7
7
  def create
8
8
  @user = User.new(user_params)
9
9
 
10
- if @user.save!
10
+ if @user.save
11
11
  session_record = @user.action_auth_sessions.create!
12
12
  cookies.signed.permanent[:session_token] = { value: session_record.id, httponly: true }
13
13
 
@@ -1,6 +1,7 @@
1
1
  module ActionAuth
2
2
  class SessionsController < ApplicationController
3
3
  before_action :set_current_request_details
4
+
4
5
  def index
5
6
  @sessions = Current.user.action_auth_sessions.order(created_at: :desc)
6
7
  end
@@ -0,0 +1,46 @@
1
+
2
+ <% if user_signed_in? && Current.user.verified? %>
3
+ <% header_text = "Change Your Email" %>
4
+ <% label_text = "New email" %>
5
+ <% button_text = "Save changes" %>
6
+ <% else %>
7
+ <% header_text = "Verify Your Email" %>
8
+ <% label_text = "Email" %>
9
+ <% button_text = "Send verification email" %>
10
+ <% end %>
11
+ <h1><%= header_text %></h1>
12
+
13
+ <p style="color: red"><%= alert %></p>
14
+
15
+ <%= form_with(url: identity_email_path, method: :patch) do |form| %>
16
+ <% if @user&.errors&.any? %>
17
+ <div style="color: red">
18
+ <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
19
+ <ul>
20
+ <% @user.errors.each do |error| %>
21
+ <li><%= error.full_message %></li>
22
+ <% end %>
23
+ </ul>
24
+ </div>
25
+ <% end %>
26
+
27
+ <div class="mb-3">
28
+ <%= form.label :email, label_text, style: "display: block" %>
29
+ <%= form.email_field :email, required: true, autofocus: true %>
30
+ </div>
31
+
32
+ <div class="mb-3">
33
+ <% if user_signed_in? && Current.user.verified? %>
34
+ <%= form.submit button_text, class: "btn btn-primary" %>
35
+ <% else %>
36
+ <%= button_to button_text, identity_email_verification_path, class: "btn btn-primary" %>
37
+ <% end %>
38
+
39
+ </div>
40
+ <% end %>
41
+
42
+ <div class="mb-3">
43
+ <%= link_to "Sign In", sign_in_path %> |
44
+ <%= link_to "Sign Up", sign_up_path %> |
45
+ <%= link_to "Reset Password", new_identity_password_reset_path %>
46
+ </div>
@@ -0,0 +1,32 @@
1
+ <h1>Reset your password</h1>
2
+
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>
7
+
8
+ <ul>
9
+ <% @user.errors.each do |error| %>
10
+ <li><%= error.full_message %></li>
11
+ <% end %>
12
+ </ul>
13
+ </div>
14
+ <% end %>
15
+
16
+ <%= form.hidden_field :sid, value: params[:sid] %>
17
+
18
+ <div>
19
+ <%= form.label :password, "New password", style: "display: block" %>
20
+ <%= form.password_field :password, required: true, autofocus: true, autocomplete: "new-password" %>
21
+ <div>12 characters minimum.</div>
22
+ </div>
23
+
24
+ <div>
25
+ <%= form.label :password_confirmation, "Confirm new password", style: "display: block" %>
26
+ <%= form.password_field :password_confirmation, required: true, autocomplete: "new-password" %>
27
+ </div>
28
+
29
+ <div>
30
+ <%= form.submit "Save changes" %>
31
+ </div>
32
+ <% end %>
@@ -0,0 +1,19 @@
1
+ <h1>Forgot your password?</h1>
2
+ <p style="color: red"><%= alert %></p>
3
+
4
+ <%= form_with(url: identity_password_reset_path) do |form| %>
5
+ <div class="mb-3">
6
+ <%= form.label :email, style: "display: block" %>
7
+ <%= form.email_field :email, required: true, autofocus: true %>
8
+ </div>
9
+
10
+ <div class="mb-3">
11
+ <%= form.submit "Send password reset email", class: "btn btn-primary" %>
12
+ </div>
13
+ <% end %>
14
+
15
+ <div class="mb-3">
16
+ <%= link_to "Sign In", sign_in_path %> |
17
+ <%= link_to "Sign Up", sign_up_path %> |
18
+ <%= link_to "Verify Email", identity_email_verification_path %>
19
+ </div>
@@ -39,5 +39,5 @@
39
39
  <br>
40
40
 
41
41
  <div>
42
- <%= link_to "Back", root_path %>
42
+ <%= link_to "Back", main_app.root_path %>
43
43
  </div>
@@ -13,23 +13,29 @@
13
13
  </div>
14
14
  <% end %>
15
15
 
16
- <div>
16
+ <div class="mb-3">
17
17
  <%= form.label :email, style: "display: block" %>
18
18
  <%= form.email_field :email, value: @user.email, required: true, autofocus: true, autocomplete: "email" %>
19
19
  </div>
20
20
 
21
- <div>
21
+ <div class="mb-3">
22
22
  <%= form.label :password, style: "display: block" %>
23
23
  <%= form.password_field :password, required: true, autocomplete: "new-password" %>
24
24
  <div>12 characters minimum.</div>
25
25
  </div>
26
26
 
27
- <div>
27
+ <div class="mb-3">
28
28
  <%= form.label :password_confirmation, style: "display: block" %>
29
29
  <%= form.password_field :password_confirmation, required: true, autocomplete: "new-password" %>
30
30
  </div>
31
31
 
32
- <div>
33
- <%= form.submit "Sign up" %>
32
+ <div class="mb-3">
33
+ <%= form.submit "Sign up", class: "btn btn-primary" %>
34
34
  </div>
35
35
  <% end %>
36
+
37
+ <div class="mb-3">
38
+ <%= link_to "Sign In", sign_in_path %> |
39
+ <%= link_to "Reset Password", new_identity_password_reset_path %> |
40
+ <%= link_to "Verify Email", identity_email_verification_path %>
41
+ </div>
@@ -4,27 +4,23 @@
4
4
  <h1>Sign in</h1>
5
5
 
6
6
  <%= form_with(url: sign_in_path) do |form| %>
7
- <div>
7
+ <div class="mb-3">
8
8
  <%= form.label :email, style: "display: block" %>
9
9
  <%= form.email_field :email, value: params[:email_hint], required: true, autofocus: true, autocomplete: "email" %>
10
10
  </div>
11
11
 
12
- <div>
12
+ <div class="mb-3">
13
13
  <%= form.label :password, style: "display: block" %>
14
14
  <%= form.password_field :password, required: true, autocomplete: "current-password" %>
15
15
  </div>
16
16
 
17
- <div>
18
- <%= form.submit "Sign in" %>
17
+ <div class="mb-3">
18
+ <%= form.submit "Sign in", class: "btn btn-primary" %>
19
19
  </div>
20
20
  <% end %>
21
21
 
22
- <br>
23
-
24
-
25
- <br>
26
-
27
- <div>
28
- <%= link_to "Sign up", sign_up_path %> |
29
- <%# link_to "Forgot your password?", new_identity_password_reset_path %>
22
+ <div class="mb-3">
23
+ <%= link_to "Sign Up", sign_up_path %> |
24
+ <%= link_to "Reset Password", new_identity_password_reset_path %> |
25
+ <%= link_to "Verify Email", identity_email_verification_path %>
30
26
  </div>
@@ -7,9 +7,9 @@
7
7
 
8
8
  <%= stylesheet_link_tag "action_auth/application", media: "all" %>
9
9
  </head>
10
- <body>
11
-
12
- <%= yield %>
13
-
10
+ <body class="bg-light">
11
+ <div class="container bg-white border pb-3">
12
+ <%= yield %>
13
+ </div>
14
14
  </body>
15
15
  </html>
data/config/routes.rb CHANGED
@@ -5,4 +5,9 @@ ActionAuth::Engine.routes.draw do
5
5
  post "sign_up", to: "registrations#create"
6
6
  resources :sessions, only: [:index, :show, :destroy]
7
7
  resource :password, only: [:edit, :update]
8
+ namespace :identity do
9
+ resource :email, only: [:edit, :update]
10
+ resource :email_verification, only: [:show, :create]
11
+ resource :password_reset, only: [:new, :edit, :create, :update]
12
+ end
8
13
  end
@@ -14,7 +14,6 @@ module ActionAuth
14
14
 
15
15
  def user_signed_in?; Current.user.present?; end
16
16
  helper_method :user_signed_in?
17
-
18
17
  end
19
18
 
20
19
  private
@@ -14,6 +14,7 @@ module ActionAuth
14
14
  ActiveSupport.on_load :action_controller_base do
15
15
  helper_method :user_sessions_path, :user_session_path, :new_user_session_path
16
16
  helper_method :new_user_registration_path
17
+ helper_method :edit_user_password_path
17
18
  end
18
19
  end
19
20
  end
@@ -16,6 +16,14 @@ module ActionAuth
16
16
  def new_user_registration_path
17
17
  action_auth.sign_up_path
18
18
  end
19
+
20
+ def edit_password_path
21
+ action_auth.edit_password_path
22
+ end
23
+
24
+ def password_path
25
+ action_auth.password_path
26
+ end
19
27
  end
20
28
  end
21
29
  end
@@ -1,3 +1,3 @@
1
1
  module ActionAuth
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: action_auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dave Kimura
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-08 00:00:00.000000000 Z
11
+ date: 2023-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -52,6 +52,9 @@ files:
52
52
  - app/assets/config/action_auth_manifest.js
53
53
  - app/assets/stylesheets/action_auth/application.css
54
54
  - app/controllers/action_auth/application_controller.rb
55
+ - app/controllers/action_auth/identity/email_verifications_controller.rb
56
+ - app/controllers/action_auth/identity/emails_controller.rb
57
+ - app/controllers/action_auth/identity/password_resets_controller.rb
55
58
  - app/controllers/action_auth/passwords_controller.rb
56
59
  - app/controllers/action_auth/registrations_controller.rb
57
60
  - app/controllers/action_auth/sessions_controller.rb
@@ -63,6 +66,9 @@ files:
63
66
  - app/models/action_auth/current.rb
64
67
  - app/models/action_auth/session.rb
65
68
  - app/models/action_auth/user.rb
69
+ - app/views/action_auth/identity/emails/edit.html.erb
70
+ - app/views/action_auth/identity/password_resets/edit.html.erb
71
+ - app/views/action_auth/identity/password_resets/new.html.erb
66
72
  - app/views/action_auth/passwords/edit.html.erb
67
73
  - app/views/action_auth/registrations/new.html.erb
68
74
  - app/views/action_auth/sessions/index.html.erb