action_auth 0.1.4 → 0.1.6
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.
- checksums.yaml +4 -4
- data/README.md +98 -16
- data/app/assets/stylesheets/action_auth/application.css +55 -0
- data/app/controllers/action_auth/identity/email_verifications_controller.rb +2 -5
- data/app/controllers/action_auth/sessions_controller.rb +1 -1
- data/app/models/action_auth/user.rb +0 -2
- data/app/views/action_auth/identity/emails/edit.html.erb +5 -1
- data/app/views/action_auth/sessions/index.html.erb +20 -22
- data/app/views/action_auth/user_mailer/email_verification.html.erb +1 -1
- data/app/views/layouts/action_auth/application-full-width.html.erb +14 -0
- data/app/views/layouts/action_auth/application.html.erb +2 -3
- data/lib/action_auth/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3241fccee9fc330469fa84edd693d48755d96c2d74396c16c101860ffe4cfbc9
|
4
|
+
data.tar.gz: 48a479437297feaff6eb40135dd9ae963821950b084a2f19cb877c752ca42261
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9fa30b51192ab5291349f95d0b49237a09cbd41c85dcea3e7920ae6cad3f889a95661356bce4de4b2bb89be8789e5c9023498aad166580aa7027af4562991b1
|
7
|
+
data.tar.gz: c5be4a6316acd4923803bbecd77e0252b438c8ff844983db495f5abf969a26576d280f5c0cd9d0844736620ec0e1cd67c4ed310180ac2bbc1197efb6811d64a2
|
data/README.md
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
# ActionAuth
|
2
|
-
ActionAuth is
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
ActionAuth is an authentication Rails engine crafted to integrate seamlessly
|
3
|
+
with your Rails application. Optimized for Rails 7.1.0, it employs the most modern authentication
|
4
|
+
techniques and streamlined token reset processes. Its simplicity and ease of use let you concentrate
|
5
|
+
on developing your application, while its reliance on ActiveSupport::CurrentAttributes ensures a
|
6
|
+
user experience akin to that offered by the well-regarded Devise gem.
|
7
|
+
|
8
|
+
[](https://github.com/kobaltz/action_auth/actions/workflows/test.yml)
|
7
9
|
|
8
10
|
## Installation
|
9
11
|
Add this line to your application's Gemfile:
|
@@ -31,26 +33,106 @@ In your view layout
|
|
31
33
|
<% end %>
|
32
34
|
```
|
33
35
|
|
36
|
+
## Features
|
37
|
+
|
38
|
+
These are the planned features for ActionAuth. The ones that are checked off are currently implemented. The ones that are not checked off are planned for future releases.
|
39
|
+
|
40
|
+
✅ - Sign Up, Sign In, Sign Out
|
41
|
+
|
42
|
+
✅ - Password reset
|
43
|
+
|
44
|
+
✅ - Account Email Verification
|
45
|
+
|
46
|
+
✅ - Cookie-based sessions
|
47
|
+
|
48
|
+
⏳ - Multifactor Authentication
|
49
|
+
|
50
|
+
⏳ - Passkeys/Hardware Security Keys
|
51
|
+
|
52
|
+
⏳ - Magic Links
|
53
|
+
|
54
|
+
⏳ - OAuth with Google, Facebook, Github, Twitter, etc.
|
55
|
+
|
56
|
+
⏳ - Account Deletion
|
57
|
+
|
58
|
+
⏳ - Account Lockout
|
59
|
+
|
60
|
+
⏳ - Account Suspension
|
61
|
+
|
62
|
+
⏳ - Account Impersonation
|
63
|
+
|
64
|
+
|
65
|
+
|
34
66
|
## Usage
|
35
67
|
|
36
68
|
### Routes
|
37
69
|
|
38
70
|
Within your application, you'll have access to these routes. They have been styled to be consistent with Devise.
|
39
71
|
|
40
|
-
Method
|
41
|
-
user_sessions_path
|
42
|
-
user_session_path
|
43
|
-
new_user_session_path
|
44
|
-
new_user_registration_path GET
|
45
|
-
edit_password_path
|
46
|
-
password_path
|
72
|
+
Method Verb Params Description
|
73
|
+
user_sessions_path GET Device session management
|
74
|
+
user_session_path DELETE [:id] Log Out
|
75
|
+
new_user_session_path GET Log in
|
76
|
+
new_user_registration_path GET Sign Up
|
77
|
+
edit_password_path GET Change Password
|
78
|
+
password_path PATCH Update Password
|
47
79
|
|
48
80
|
### Helper Methods
|
49
81
|
|
50
|
-
Method
|
51
|
-
current_user
|
52
|
-
user_signed_in?
|
53
|
-
current_session
|
82
|
+
Method Description
|
83
|
+
current_user Returns the currently logged in user
|
84
|
+
user_signed_in? Returns true if the user is logged in
|
85
|
+
current_session Returns the current session
|
86
|
+
|
87
|
+
### Restricting and Changing Routes with Constraints
|
88
|
+
|
89
|
+
Sometimes, there could be some routes that you would want to prevent access to unless the
|
90
|
+
user is an admin. These routes could be for managing users, or other sensitive data. You
|
91
|
+
can create a constraint to restrict access to these routes.
|
92
|
+
|
93
|
+
# app/constraints/admin_constraint.rb
|
94
|
+
|
95
|
+
class AdminConstraint
|
96
|
+
def self.matches?(request)
|
97
|
+
user = current_user(request)
|
98
|
+
user && user.admin?
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.current_user(request)
|
102
|
+
session_token = request.cookie_jar.signed[:session_token]
|
103
|
+
ActionAuth::Session.find_by(id: session_token)&.action_auth_user
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# config/routes.rb
|
108
|
+
|
109
|
+
constraints AdminConstraint do
|
110
|
+
mount GoodJob::Engine => 'good_job'
|
111
|
+
end
|
112
|
+
|
113
|
+
Other times, you may want to have a different kind of view for a user that is logged in
|
114
|
+
versus a user that is not logged in.
|
115
|
+
|
116
|
+
# app/constraints/authenticated_constraint.rb
|
117
|
+
class AuthenticatedConstraint
|
118
|
+
def self.matches?(request)
|
119
|
+
session_token = request.cookie_jar.signed[:session_token]
|
120
|
+
ActionAuth::Session.exists?(session_token)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# config/routes.rb
|
125
|
+
constraints AuthenticatedConstraint do
|
126
|
+
root to: 'dashboard#index'
|
127
|
+
end
|
128
|
+
root to: 'welcome#index'
|
129
|
+
|
54
130
|
|
55
131
|
## License
|
56
132
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
133
|
+
|
134
|
+
|
135
|
+
## Credits
|
136
|
+
|
137
|
+
Heavily inspired by [Drifting Ruby #300](https://www.driftingruby.com/episodes/authentication-from-scratch)
|
138
|
+
and [Authentication Zero](https://github.com/lazaronixon/authentication-zero).
|
@@ -29,6 +29,21 @@ body {
|
|
29
29
|
background-color: rgb(255, 255, 255) !important;
|
30
30
|
}
|
31
31
|
|
32
|
+
.container-fluid {
|
33
|
+
-webkit-text-size-adjust: 100%;
|
34
|
+
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
35
|
+
box-sizing: border-box;
|
36
|
+
width: 100%;
|
37
|
+
padding-right: 12px;
|
38
|
+
padding-left: 12px;
|
39
|
+
margin-right: auto;
|
40
|
+
margin-left: auto;
|
41
|
+
max-width: 1140px;
|
42
|
+
border: solid 1px rgb(222, 226, 230) !important;
|
43
|
+
padding-bottom: 1rem !important;
|
44
|
+
background-color: rgb(255, 255, 255) !important;
|
45
|
+
}
|
46
|
+
|
32
47
|
input[type="text"],
|
33
48
|
input[type="email"],
|
34
49
|
input[type="password"] {
|
@@ -99,3 +114,43 @@ input[type="password"] {
|
|
99
114
|
background-color: #007bff;
|
100
115
|
border-color: #007bff;
|
101
116
|
}
|
117
|
+
|
118
|
+
.action-auth--table {
|
119
|
+
width: 100%;
|
120
|
+
border-collapse: separate;
|
121
|
+
border-spacing: 0;
|
122
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
123
|
+
font-family: 'Arial', sans-serif;
|
124
|
+
overflow: hidden;
|
125
|
+
margin: 20px 0;
|
126
|
+
}
|
127
|
+
|
128
|
+
.action-auth--table thead {
|
129
|
+
background-color: #007BFF;
|
130
|
+
color: #ffffff;
|
131
|
+
}
|
132
|
+
|
133
|
+
.action-auth--table th,
|
134
|
+
.action-auth--table td {
|
135
|
+
padding: 12px 15px;
|
136
|
+
text-align: left;
|
137
|
+
border-bottom: 1px solid #dddddd;
|
138
|
+
}
|
139
|
+
|
140
|
+
.action-auth--table tr:last-child {
|
141
|
+
border-bottom: none;
|
142
|
+
}
|
143
|
+
|
144
|
+
.action-auth--table th {
|
145
|
+
position: sticky;
|
146
|
+
top: 0;
|
147
|
+
z-index: 10;
|
148
|
+
}
|
149
|
+
|
150
|
+
.action-auth--table tbody tr:hover {
|
151
|
+
background-color: #f1f1f1;
|
152
|
+
}
|
153
|
+
|
154
|
+
.action-auth--table td {
|
155
|
+
transition: background-color 0.3s;
|
156
|
+
}
|
@@ -9,7 +9,8 @@ module ActionAuth
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def create
|
12
|
-
|
12
|
+
user = ActionAuth::User.find_by(email: params[:email])
|
13
|
+
UserMailer.with(user: user).email_verification.deliver_later if user
|
13
14
|
redirect_to main_app.root_path, notice: "We sent a verification email to your email address"
|
14
15
|
end
|
15
16
|
|
@@ -21,10 +22,6 @@ module ActionAuth
|
|
21
22
|
redirect_to edit_identity_email_path, alert: "That email verification link is invalid"
|
22
23
|
end
|
23
24
|
|
24
|
-
def send_email_verification
|
25
|
-
return unless Current.user
|
26
|
-
UserMailer.with(user: Current.user).email_verification.deliver_later
|
27
|
-
end
|
28
25
|
end
|
29
26
|
end
|
30
27
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ActionAuth
|
2
2
|
class SessionsController < ApplicationController
|
3
3
|
before_action :set_current_request_details
|
4
|
-
|
4
|
+
layout "action_auth/application-full-width", only: :index
|
5
5
|
def index
|
6
6
|
@sessions = Current.user.action_auth_sessions.order(created_at: :desc)
|
7
7
|
end
|
@@ -10,7 +10,6 @@ module ActionAuth
|
|
10
10
|
password_salt.last(10)
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
13
|
has_many :action_auth_sessions, dependent: :destroy, class_name: "ActionAuth::Session", foreign_key: "action_auth_user_id"
|
15
14
|
|
16
15
|
validates :email, presence: true, uniqueness: true, format: { with: URI::MailTo::EMAIL_REGEXP }
|
@@ -18,7 +17,6 @@ module ActionAuth
|
|
18
17
|
|
19
18
|
normalizes :email, with: -> email { email.strip.downcase }
|
20
19
|
|
21
|
-
|
22
20
|
before_validation if: :email_changed?, on: :update do
|
23
21
|
self.verified = false
|
24
22
|
end
|
@@ -3,16 +3,20 @@
|
|
3
3
|
<% header_text = "Change Your Email" %>
|
4
4
|
<% label_text = "New email" %>
|
5
5
|
<% button_text = "Save changes" %>
|
6
|
+
<% form_url = identity_email_path %>
|
7
|
+
<% form_method = :patch %>
|
6
8
|
<% else %>
|
7
9
|
<% header_text = "Verify Your Email" %>
|
8
10
|
<% label_text = "Email" %>
|
9
11
|
<% button_text = "Send verification email" %>
|
12
|
+
<% form_url = identity_email_verification_path %>
|
13
|
+
<% form_method = :post %>
|
10
14
|
<% end %>
|
11
15
|
<h1><%= header_text %></h1>
|
12
16
|
|
13
17
|
<p style="color: red"><%= alert %></p>
|
14
18
|
|
15
|
-
<%= form_with(url:
|
19
|
+
<%= form_with(url: form_url, method: form_method) do |form| %>
|
16
20
|
<% if @user&.errors&.any? %>
|
17
21
|
<div style="color: red">
|
18
22
|
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
|
@@ -3,27 +3,25 @@
|
|
3
3
|
<h1>Devices & Sessions</h1>
|
4
4
|
|
5
5
|
<div id="sessions">
|
6
|
-
|
7
|
-
<
|
8
|
-
<
|
9
|
-
<
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
</p>
|
27
|
-
<% end %>
|
6
|
+
<table class="action-auth--table">
|
7
|
+
<thead>
|
8
|
+
<tr>
|
9
|
+
<th>User Agent</th>
|
10
|
+
<th nowrap>Ip Address</th>
|
11
|
+
<th nowrap>Created at</th>
|
12
|
+
<th nowrap></th>
|
13
|
+
</tr>
|
14
|
+
</thead>
|
15
|
+
<tbody>
|
16
|
+
<% @sessions.each do |session| %>
|
17
|
+
<%= content_tag :tr, id: dom_id(session) do %>
|
18
|
+
<td><%= session.user_agent %></td>
|
19
|
+
<td nowrap><%= session.ip_address %></td>
|
20
|
+
<td nowrap><%= session.created_at %></td>
|
21
|
+
<td nowrap><%= button_to "Log out", session, method: :delete, class: "btn btn-primary" %></td>
|
22
|
+
<% end %>
|
23
|
+
<% end %>
|
24
|
+
</tbody>
|
25
|
+
</table>
|
28
26
|
</div>
|
29
27
|
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
<p><strong>You must hit the link below to confirm that you received this email.</strong></p>
|
6
6
|
|
7
|
-
<p
|
7
|
+
<p><%= link_to "Yes, use this email for my account", identity_email_verification_url(sid: @signed_id) %></p>
|
8
8
|
|
9
9
|
<hr>
|
10
10
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Action Auth</title>
|
5
|
+
<%= csrf_meta_tags %>
|
6
|
+
<%= csp_meta_tag %>
|
7
|
+
<%= stylesheet_link_tag "action_auth/application", media: "all" %>
|
8
|
+
</head>
|
9
|
+
<body class="bg-light">
|
10
|
+
<div class="container-fluid bg-white border pb-3">
|
11
|
+
<%= yield %>
|
12
|
+
</div>
|
13
|
+
</body>
|
14
|
+
</html>
|
@@ -1,11 +1,10 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html>
|
3
3
|
<head>
|
4
|
-
<title>Action
|
4
|
+
<title>Action Auth</title>
|
5
5
|
<%= csrf_meta_tags %>
|
6
6
|
<%= csp_meta_tag %>
|
7
|
-
|
8
|
-
<%= stylesheet_link_tag "action_auth/application", media: "all" %>
|
7
|
+
<%= stylesheet_link_tag "action_auth/application", media: "all" %>
|
9
8
|
</head>
|
10
9
|
<body class="bg-light">
|
11
10
|
<div class="container bg-white border pb-3">
|
data/lib/action_auth/version.rb
CHANGED
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.
|
4
|
+
version: 0.1.6
|
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-
|
11
|
+
date: 2023-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -77,6 +77,7 @@ files:
|
|
77
77
|
- app/views/action_auth/user_mailer/email_verification.text.erb
|
78
78
|
- app/views/action_auth/user_mailer/password_reset.html.erb
|
79
79
|
- app/views/action_auth/user_mailer/password_reset.text.erb
|
80
|
+
- app/views/layouts/action_auth/application-full-width.html.erb
|
80
81
|
- app/views/layouts/action_auth/application.html.erb
|
81
82
|
- app/views/layouts/action_auth/mailer.html.erb
|
82
83
|
- app/views/layouts/action_auth/mailer.text.erb
|