action_auth 0.1.4 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Ruby](https://github.com/kobaltz/action_auth/actions/workflows/test.yml/badge.svg)](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
|