rails_simple_auth 1.0.0 → 1.0.2
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 +144 -2
- data/app/assets/stylesheets/rails_simple_auth/application.css +234 -0
- data/app/controllers/rails_simple_auth/confirmations_controller.rb +19 -17
- data/app/controllers/rails_simple_auth/omniauth_callbacks_controller.rb +6 -4
- data/app/controllers/rails_simple_auth/passwords_controller.rb +13 -12
- data/app/controllers/rails_simple_auth/registrations_controller.rb +6 -4
- data/app/controllers/rails_simple_auth/sessions_controller.rb +21 -16
- data/app/mailers/rails_simple_auth/auth_mailer.rb +10 -7
- data/app/views/layouts/rails_simple_auth.html.erb +37 -0
- data/app/views/rails_simple_auth/confirmations/new.html.erb +2 -2
- data/app/views/rails_simple_auth/passwords/new.html.erb +2 -2
- data/app/views/rails_simple_auth/registrations/new.html.erb +5 -5
- data/app/views/rails_simple_auth/sessions/magic_link_form.html.erb +2 -2
- data/app/views/rails_simple_auth/sessions/new.html.erb +2 -2
- data/lib/generators/rails_simple_auth/css/css_generator.rb +20 -20
- data/lib/generators/rails_simple_auth/install/install_generator.rb +32 -32
- data/lib/generators/rails_simple_auth/install/templates/initializer.rb +3 -3
- data/lib/generators/rails_simple_auth/install/templates/migration.rb +2 -2
- data/lib/generators/rails_simple_auth/temporary_users/USAGE +21 -0
- data/lib/generators/rails_simple_auth/temporary_users/templates/add_temporary_to_users.rb.erb +8 -0
- data/lib/generators/rails_simple_auth/temporary_users/temporary_users_generator.rb +40 -0
- data/lib/generators/rails_simple_auth/views/views_generator.rb +8 -8
- data/lib/rails_simple_auth/configuration.rb +23 -8
- data/lib/rails_simple_auth/controllers/concerns/authentication.rb +17 -18
- data/lib/rails_simple_auth/controllers/concerns/session_management.rb +24 -0
- data/lib/rails_simple_auth/engine.rb +1 -1
- data/lib/rails_simple_auth/models/concerns/authenticatable.rb +13 -5
- data/lib/rails_simple_auth/models/concerns/confirmable.rb +38 -3
- data/lib/rails_simple_auth/models/concerns/oauth_connectable.rb +5 -5
- data/lib/rails_simple_auth/models/concerns/temporary_user.rb +105 -0
- data/lib/rails_simple_auth/models/session.rb +2 -4
- data/lib/rails_simple_auth/routes.rb +15 -15
- data/lib/rails_simple_auth/version.rb +1 -1
- data/lib/rails_simple_auth.rb +14 -12
- metadata +19 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6d9299c78e7be2bfe4bc6e338150d03ec03d80e6c624616e09c30b48c5bf16c6
|
|
4
|
+
data.tar.gz: 145ebfad74f0188f138a9e8e006bfac26a6404b89d3690a0a8484246a5b01d9f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 92302e8e2c6d489ebda9e82b222e0a53f31c52f0b8958bf3af2a4240f654f0de7bd81892e350ee92892df16d747ef88d4b43ae69b6af0e510ee1504925755693
|
|
7
|
+
data.tar.gz: 07d17cb9ca09fe1f01446cf1faf4cc67fb303d5c0553b6e2c242595054700a88fff187838820aed8639c65b3fd839e3679771acb178700f7966cf17f0f1ce258
|
data/README.md
CHANGED
|
@@ -9,6 +9,7 @@ Simple, secure authentication for Rails 8+ applications. Built on Rails primitiv
|
|
|
9
9
|
- **Email confirmation** with signed tokens
|
|
10
10
|
- **Password reset** with signed tokens
|
|
11
11
|
- **OAuth support** (Google, GitHub, etc.)
|
|
12
|
+
- **Temporary users** (guest mode) with conversion to permanent
|
|
12
13
|
- **Rate limiting** built-in
|
|
13
14
|
- **Session tracking** with IP and user agent
|
|
14
15
|
- **Customizable styling** via CSS variables
|
|
@@ -67,7 +68,7 @@ class CreateUsers < ActiveRecord::Migration[8.0]
|
|
|
67
68
|
def change
|
|
68
69
|
create_table :users do |t|
|
|
69
70
|
# Required by gem
|
|
70
|
-
t.string :
|
|
71
|
+
t.string :email, null: false
|
|
71
72
|
t.string :password_digest, null: false
|
|
72
73
|
t.datetime :confirmed_at # if using Confirmable
|
|
73
74
|
|
|
@@ -81,7 +82,7 @@ class CreateUsers < ActiveRecord::Migration[8.0]
|
|
|
81
82
|
t.timestamps
|
|
82
83
|
end
|
|
83
84
|
|
|
84
|
-
add_index :users, :
|
|
85
|
+
add_index :users, :email, unique: true
|
|
85
86
|
end
|
|
86
87
|
end
|
|
87
88
|
```
|
|
@@ -156,6 +157,7 @@ RailsSimpleAuth.configure do |config|
|
|
|
156
157
|
|
|
157
158
|
# Mailer
|
|
158
159
|
config.mailer_sender = "auth@myapp.com"
|
|
160
|
+
# config.mailer_class = "UserMailer" # Use custom mailer (optional)
|
|
159
161
|
|
|
160
162
|
# Password requirements
|
|
161
163
|
config.password_minimum_length = 12
|
|
@@ -202,6 +204,77 @@ class User < ApplicationRecord
|
|
|
202
204
|
end
|
|
203
205
|
```
|
|
204
206
|
|
|
207
|
+
## Temporary Users (Guest Mode)
|
|
208
|
+
|
|
209
|
+
Allow visitors to try your app without signing up, then convert to permanent accounts later.
|
|
210
|
+
|
|
211
|
+
### Setup
|
|
212
|
+
|
|
213
|
+
1. Generate the migration:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
rails generate rails_simple_auth:temporary_users
|
|
217
|
+
rails db:migrate
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
2. Include the concern in your User model:
|
|
221
|
+
|
|
222
|
+
```ruby
|
|
223
|
+
class User < ApplicationRecord
|
|
224
|
+
include RailsSimpleAuth::Models::Concerns::Authenticatable
|
|
225
|
+
include RailsSimpleAuth::Models::Concerns::TemporaryUser # Add this
|
|
226
|
+
end
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
3. Enable in configuration:
|
|
230
|
+
|
|
231
|
+
```ruby
|
|
232
|
+
RailsSimpleAuth.configure do |config|
|
|
233
|
+
config.temporary_users_enabled = true
|
|
234
|
+
config.temporary_user_cleanup_days = 7 # Auto-cleanup after 7 days
|
|
235
|
+
end
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Creating Temporary Users
|
|
239
|
+
|
|
240
|
+
```ruby
|
|
241
|
+
# Create a temporary user (no email/password required)
|
|
242
|
+
temp_user = User.create!(
|
|
243
|
+
email: "temp_#{SecureRandom.hex(8)}@temp.local",
|
|
244
|
+
password: SecureRandom.hex(16),
|
|
245
|
+
temporary: true
|
|
246
|
+
)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Converting to Permanent Account
|
|
250
|
+
|
|
251
|
+
```ruby
|
|
252
|
+
# When user decides to sign up for real
|
|
253
|
+
temp_user.convert_to_permanent!(
|
|
254
|
+
email: "real@example.com",
|
|
255
|
+
password: "secure_password"
|
|
256
|
+
)
|
|
257
|
+
# Sends confirmation email automatically if email confirmation is enabled
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Scopes
|
|
261
|
+
|
|
262
|
+
```ruby
|
|
263
|
+
User.temporary # All temporary users
|
|
264
|
+
User.permanent # All permanent users
|
|
265
|
+
User.temporary_expired # Temporary users older than cleanup_days
|
|
266
|
+
User.temporary_expired(14) # Custom days
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Cleanup Task
|
|
270
|
+
|
|
271
|
+
Add to your scheduler (cron, Sidekiq, etc.):
|
|
272
|
+
|
|
273
|
+
```ruby
|
|
274
|
+
# Delete expired temporary users
|
|
275
|
+
User.temporary_expired.destroy_all
|
|
276
|
+
```
|
|
277
|
+
|
|
205
278
|
## Controller Customization
|
|
206
279
|
|
|
207
280
|
Subclass controllers for custom behavior:
|
|
@@ -222,6 +295,75 @@ Update routes to use your controller:
|
|
|
222
295
|
rails_simple_auth_routes(sessions_controller: "sessions")
|
|
223
296
|
```
|
|
224
297
|
|
|
298
|
+
## Mailer
|
|
299
|
+
|
|
300
|
+
The gem includes a built-in mailer (`RailsSimpleAuth::AuthMailer`) with email templates that work out of the box. No configuration required.
|
|
301
|
+
|
|
302
|
+
### Included Email Templates
|
|
303
|
+
|
|
304
|
+
| Email | Purpose |
|
|
305
|
+
|-------|---------|
|
|
306
|
+
| `confirmation` | Email confirmation when user signs up |
|
|
307
|
+
| `magic_link` | Passwordless sign-in link |
|
|
308
|
+
| `password_reset` | Password recovery link |
|
|
309
|
+
|
|
310
|
+
### Configuration
|
|
311
|
+
|
|
312
|
+
```ruby
|
|
313
|
+
RailsSimpleAuth.configure do |config|
|
|
314
|
+
# Sender address for all auth emails (required)
|
|
315
|
+
config.mailer_sender = "auth@myapp.com"
|
|
316
|
+
# Or use environment variable
|
|
317
|
+
config.mailer_sender = ENV.fetch("MAILER_FROM", "noreply@example.com")
|
|
318
|
+
end
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Custom Mailer (Optional)
|
|
322
|
+
|
|
323
|
+
For branded emails with your own design, use a custom mailer:
|
|
324
|
+
|
|
325
|
+
```ruby
|
|
326
|
+
# config/initializers/rails_simple_auth.rb
|
|
327
|
+
RailsSimpleAuth.configure do |config|
|
|
328
|
+
config.mailer_class = "UserMailer"
|
|
329
|
+
config.mailer_sender = "hello@myapp.com"
|
|
330
|
+
end
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Your custom mailer must implement these methods:
|
|
334
|
+
|
|
335
|
+
```ruby
|
|
336
|
+
# app/mailers/user_mailer.rb
|
|
337
|
+
class UserMailer < ApplicationMailer
|
|
338
|
+
def confirmation(user, token)
|
|
339
|
+
@user = user
|
|
340
|
+
@confirmation_url = edit_confirmation_url(token: token)
|
|
341
|
+
mail(to: user.email, subject: "Confirm your email")
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def magic_link(user, token)
|
|
345
|
+
@user = user
|
|
346
|
+
@magic_link_url = magic_link_login_url(token: token)
|
|
347
|
+
mail(to: user.email, subject: "Your sign-in link")
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def password_reset(user, token)
|
|
351
|
+
@user = user
|
|
352
|
+
@reset_url = edit_password_url(token: token)
|
|
353
|
+
mail(to: user.email, subject: "Reset your password")
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
Create corresponding views in `app/views/user_mailer/`:
|
|
359
|
+
|
|
360
|
+
```
|
|
361
|
+
app/views/user_mailer/
|
|
362
|
+
├── confirmation.html.erb
|
|
363
|
+
├── magic_link.html.erb
|
|
364
|
+
└── password_reset.html.erb
|
|
365
|
+
```
|
|
366
|
+
|
|
225
367
|
## Helpers
|
|
226
368
|
|
|
227
369
|
Available in controllers and views:
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* RailsSimpleAuth default styles
|
|
3
|
+
* These provide a minimal, clean appearance for auth pages.
|
|
4
|
+
* Override by providing your own layout in the initializer.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.rsa-body {
|
|
8
|
+
margin: 0;
|
|
9
|
+
padding: 0;
|
|
10
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
11
|
+
background-color: #f5f5f5;
|
|
12
|
+
min-height: 100vh;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.rsa-container {
|
|
16
|
+
max-width: 1200px;
|
|
17
|
+
margin: 0 auto;
|
|
18
|
+
padding: 0 1rem;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.rsa-header {
|
|
22
|
+
padding: 1.5rem 0;
|
|
23
|
+
text-align: center;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.rsa-header__title {
|
|
27
|
+
margin: 0;
|
|
28
|
+
font-size: 1.5rem;
|
|
29
|
+
font-weight: 600;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.rsa-header__title a {
|
|
33
|
+
color: #333;
|
|
34
|
+
text-decoration: none;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.rsa-header__title a:hover {
|
|
38
|
+
color: #007bff;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.rsa-main {
|
|
42
|
+
padding: 2rem 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.rsa-flash {
|
|
46
|
+
padding: 0.75rem 1rem;
|
|
47
|
+
margin-bottom: 1rem;
|
|
48
|
+
border-radius: 4px;
|
|
49
|
+
max-width: 400px;
|
|
50
|
+
margin-left: auto;
|
|
51
|
+
margin-right: auto;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.rsa-flash--notice,
|
|
55
|
+
.rsa-flash--success {
|
|
56
|
+
background-color: #d4edda;
|
|
57
|
+
color: #155724;
|
|
58
|
+
border: 1px solid #c3e6cb;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.rsa-flash--alert,
|
|
62
|
+
.rsa-flash--error {
|
|
63
|
+
background-color: #f8d7da;
|
|
64
|
+
color: #721c24;
|
|
65
|
+
border: 1px solid #f5c6cb;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.rsa-footer {
|
|
69
|
+
padding: 2rem 0;
|
|
70
|
+
text-align: center;
|
|
71
|
+
color: #666;
|
|
72
|
+
font-size: 0.875rem;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* Auth form styles */
|
|
76
|
+
.rsa-auth-form {
|
|
77
|
+
max-width: 400px;
|
|
78
|
+
margin: 0 auto;
|
|
79
|
+
padding: 2rem;
|
|
80
|
+
background: #fff;
|
|
81
|
+
border-radius: 8px;
|
|
82
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.rsa-auth-form__title {
|
|
86
|
+
margin: 0 0 1.5rem;
|
|
87
|
+
font-size: 1.5rem;
|
|
88
|
+
font-weight: 600;
|
|
89
|
+
text-align: center;
|
|
90
|
+
color: #333;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.rsa-auth-form__form {
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-direction: column;
|
|
96
|
+
gap: 1rem;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.rsa-auth-form__group {
|
|
100
|
+
display: flex;
|
|
101
|
+
flex-direction: column;
|
|
102
|
+
gap: 0.25rem;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.rsa-auth-form__label {
|
|
106
|
+
font-size: 0.875rem;
|
|
107
|
+
font-weight: 500;
|
|
108
|
+
color: #333;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.rsa-auth-form__input {
|
|
112
|
+
padding: 0.75rem;
|
|
113
|
+
border: 1px solid #ddd;
|
|
114
|
+
border-radius: 4px;
|
|
115
|
+
font-size: 1rem;
|
|
116
|
+
transition: border-color 0.2s;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.rsa-auth-form__input:focus {
|
|
120
|
+
outline: none;
|
|
121
|
+
border-color: #007bff;
|
|
122
|
+
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.rsa-auth-form__submit {
|
|
126
|
+
padding: 0.75rem 1.5rem;
|
|
127
|
+
background-color: #007bff;
|
|
128
|
+
color: #fff;
|
|
129
|
+
border: none;
|
|
130
|
+
border-radius: 4px;
|
|
131
|
+
font-size: 1rem;
|
|
132
|
+
font-weight: 500;
|
|
133
|
+
cursor: pointer;
|
|
134
|
+
transition: background-color 0.2s;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.rsa-auth-form__submit:hover {
|
|
138
|
+
background-color: #0056b3;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.rsa-auth-form__submit:disabled {
|
|
142
|
+
background-color: #6c757d;
|
|
143
|
+
cursor: not-allowed;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.rsa-auth-form__divider {
|
|
147
|
+
text-align: center;
|
|
148
|
+
color: #666;
|
|
149
|
+
font-size: 0.875rem;
|
|
150
|
+
margin: 1rem 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.rsa-auth-form__magic-link-button {
|
|
154
|
+
display: flex;
|
|
155
|
+
align-items: center;
|
|
156
|
+
justify-content: center;
|
|
157
|
+
gap: 0.5rem;
|
|
158
|
+
padding: 0.75rem 1.5rem;
|
|
159
|
+
background-color: #6c757d;
|
|
160
|
+
color: #fff;
|
|
161
|
+
border: none;
|
|
162
|
+
border-radius: 4px;
|
|
163
|
+
font-size: 1rem;
|
|
164
|
+
text-decoration: none;
|
|
165
|
+
transition: background-color 0.2s;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.rsa-auth-form__magic-link-button:hover {
|
|
169
|
+
background-color: #5a6268;
|
|
170
|
+
color: #fff;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.rsa-auth-form__oauth {
|
|
174
|
+
display: flex;
|
|
175
|
+
flex-direction: column;
|
|
176
|
+
gap: 0.5rem;
|
|
177
|
+
margin-top: 1rem;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.rsa-auth-form__oauth-button {
|
|
181
|
+
display: flex;
|
|
182
|
+
align-items: center;
|
|
183
|
+
justify-content: center;
|
|
184
|
+
gap: 0.5rem;
|
|
185
|
+
padding: 0.75rem 1.5rem;
|
|
186
|
+
background-color: #fff;
|
|
187
|
+
color: #333;
|
|
188
|
+
border: 1px solid #ddd;
|
|
189
|
+
border-radius: 4px;
|
|
190
|
+
font-size: 1rem;
|
|
191
|
+
text-decoration: none;
|
|
192
|
+
transition: background-color 0.2s, border-color 0.2s;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.rsa-auth-form__oauth-button:hover {
|
|
196
|
+
background-color: #f8f9fa;
|
|
197
|
+
border-color: #ccc;
|
|
198
|
+
color: #333;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.rsa-auth-form__oauth-button img {
|
|
202
|
+
width: 20px;
|
|
203
|
+
height: 20px;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.rsa-auth-form__links {
|
|
207
|
+
display: flex;
|
|
208
|
+
justify-content: space-between;
|
|
209
|
+
margin-top: 1.5rem;
|
|
210
|
+
font-size: 0.875rem;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.rsa-auth-form__link {
|
|
214
|
+
color: #007bff;
|
|
215
|
+
text-decoration: none;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.rsa-auth-form__link:hover {
|
|
219
|
+
text-decoration: underline;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.rsa-auth-form__error {
|
|
223
|
+
padding: 0.75rem;
|
|
224
|
+
background-color: #f8d7da;
|
|
225
|
+
color: #721c24;
|
|
226
|
+
border: 1px solid #f5c6cb;
|
|
227
|
+
border-radius: 4px;
|
|
228
|
+
margin-bottom: 1rem;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.rsa-auth-form__error ul {
|
|
232
|
+
margin: 0;
|
|
233
|
+
padding-left: 1.25rem;
|
|
234
|
+
}
|
|
@@ -6,33 +6,35 @@ module RailsSimpleAuth
|
|
|
6
6
|
|
|
7
7
|
unless Rails.env.local?
|
|
8
8
|
rate_limit to: 3, within: 1.hour, by: -> { client_ip }, only: :create,
|
|
9
|
-
with:
|
|
9
|
+
with: lambda {
|
|
10
|
+
redirect_to new_confirmation_path, alert: 'Too many confirmation requests. Please try again later.'
|
|
11
|
+
}
|
|
10
12
|
end
|
|
11
13
|
|
|
12
|
-
def
|
|
14
|
+
def show
|
|
15
|
+
user = user_class.find_signed(params[:token], purpose: :confirm_email)
|
|
16
|
+
|
|
17
|
+
if user
|
|
18
|
+
user.confirm! if user.respond_to?(:confirm!)
|
|
19
|
+
run_after_confirmation_callback(user)
|
|
20
|
+
redirect_to resolve_path(:after_confirmation_path), notice: 'Email confirmed! You can now sign in.'
|
|
21
|
+
else
|
|
22
|
+
redirect_to new_confirmation_path, alert: 'Invalid or expired confirmation link.'
|
|
23
|
+
end
|
|
13
24
|
end
|
|
14
25
|
|
|
26
|
+
def new; end
|
|
27
|
+
|
|
15
28
|
def create
|
|
16
|
-
user = user_class.
|
|
29
|
+
user = user_class.find_by(email: params[:email])
|
|
17
30
|
|
|
18
|
-
if user
|
|
31
|
+
if user.respond_to?(:unconfirmed_or_reconfirming?) && user.unconfirmed_or_reconfirming?
|
|
19
32
|
token = user.generate_confirmation_token
|
|
20
33
|
RailsSimpleAuth.configuration.mailer.confirmation(user, token).deliver_later
|
|
21
34
|
end
|
|
22
35
|
|
|
23
|
-
redirect_to new_session_path,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def show
|
|
27
|
-
user = user_class.find_signed(params[:token], purpose: :email_confirmation)
|
|
28
|
-
|
|
29
|
-
if user
|
|
30
|
-
user.confirm! if user.respond_to?(:confirm!)
|
|
31
|
-
run_after_confirmation_callback(user)
|
|
32
|
-
redirect_to resolve_path(:after_confirmation_path), notice: "Email confirmed! You can now sign in."
|
|
33
|
-
else
|
|
34
|
-
redirect_to new_confirmation_path, alert: "Invalid or expired confirmation link."
|
|
35
|
-
end
|
|
36
|
+
redirect_to new_session_path,
|
|
37
|
+
notice: 'If an unconfirmed account exists with that email, confirmation instructions have been sent.'
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
private
|
|
@@ -6,27 +6,29 @@ module RailsSimpleAuth
|
|
|
6
6
|
skip_before_action :verify_authenticity_token, only: :create
|
|
7
7
|
|
|
8
8
|
def create
|
|
9
|
-
auth_hash = request.env[
|
|
9
|
+
auth_hash = request.env['omniauth.auth']
|
|
10
10
|
provider = params[:provider]
|
|
11
11
|
|
|
12
12
|
unless RailsSimpleAuth.configuration.oauth_provider_enabled?(provider)
|
|
13
|
-
redirect_to new_session_path, alert:
|
|
13
|
+
redirect_to new_session_path, alert: 'OAuth provider not enabled.'
|
|
14
14
|
return
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
user = user_class.from_oauth(auth_hash)
|
|
18
18
|
|
|
19
19
|
if user&.persisted?
|
|
20
|
+
destroy_temporary_user_session(user)
|
|
20
21
|
create_session_for(user)
|
|
21
22
|
run_after_sign_in_callback(user)
|
|
22
|
-
redirect_to resolve_path(:after_sign_in_path),
|
|
23
|
+
redirect_to resolve_path(:after_sign_in_path),
|
|
24
|
+
notice: "Signed in successfully with #{provider.to_s.capitalize}."
|
|
23
25
|
else
|
|
24
26
|
redirect_to new_session_path, alert: "Could not authenticate with #{provider.to_s.capitalize}."
|
|
25
27
|
end
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
def failure
|
|
29
|
-
redirect_to new_session_path, alert:
|
|
31
|
+
redirect_to new_session_path, alert: 'Authentication failed. Please try again.'
|
|
30
32
|
end
|
|
31
33
|
end
|
|
32
34
|
end
|
|
@@ -7,31 +7,32 @@ module RailsSimpleAuth
|
|
|
7
7
|
|
|
8
8
|
unless Rails.env.local?
|
|
9
9
|
rate_limit to: 3, within: 1.hour, by: -> { client_ip }, only: :create,
|
|
10
|
-
with:
|
|
10
|
+
with: lambda {
|
|
11
|
+
redirect_to new_password_path, alert: 'Too many password reset requests. Please try again later.'
|
|
12
|
+
}
|
|
11
13
|
end
|
|
12
14
|
|
|
13
|
-
def new
|
|
14
|
-
|
|
15
|
+
def new; end
|
|
16
|
+
|
|
17
|
+
def edit; end
|
|
15
18
|
|
|
16
19
|
def create
|
|
17
|
-
user = user_class.
|
|
20
|
+
user = user_class.find_by(email: params[:email])
|
|
18
21
|
|
|
19
22
|
if user && can_reset_password?(user)
|
|
20
23
|
token = user.generate_password_reset_token
|
|
21
24
|
RailsSimpleAuth.configuration.mailer.password_reset(user, token).deliver_later
|
|
22
25
|
end
|
|
23
26
|
|
|
24
|
-
redirect_to new_session_path,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def edit
|
|
27
|
+
redirect_to new_session_path,
|
|
28
|
+
notice: 'If an account exists with that email, password reset instructions have been sent.'
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
def update
|
|
31
32
|
ActiveRecord::Base.transaction do
|
|
32
33
|
if @user.update(password_params)
|
|
33
34
|
@user.invalidate_all_sessions!
|
|
34
|
-
redirect_to new_session_path, notice:
|
|
35
|
+
redirect_to new_session_path, notice: 'Password has been reset. Please sign in with your new password.'
|
|
35
36
|
else
|
|
36
37
|
render :edit, status: :unprocessable_content
|
|
37
38
|
raise ActiveRecord::Rollback
|
|
@@ -42,14 +43,14 @@ module RailsSimpleAuth
|
|
|
42
43
|
"[RailsSimpleAuth] Session invalidation failed after password reset for user #{@user.id}: #{e.message}"
|
|
43
44
|
)
|
|
44
45
|
# Password was rolled back due to transaction, redirect with error
|
|
45
|
-
redirect_to new_password_path, alert:
|
|
46
|
+
redirect_to new_password_path, alert: 'Password reset failed. Please try again.'
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
private
|
|
49
50
|
|
|
50
51
|
def set_user_from_token
|
|
51
52
|
@user = user_class.find_signed(params[:token], purpose: :password_reset)
|
|
52
|
-
redirect_to new_password_path, alert:
|
|
53
|
+
redirect_to new_password_path, alert: 'Invalid or expired password reset link.' unless @user
|
|
53
54
|
end
|
|
54
55
|
|
|
55
56
|
def can_reset_password?(user)
|
|
@@ -60,7 +61,7 @@ module RailsSimpleAuth
|
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
def password_params
|
|
63
|
-
params.
|
|
64
|
+
params.expect(user: %i[password password_confirmation])
|
|
64
65
|
end
|
|
65
66
|
end
|
|
66
67
|
end
|
|
@@ -6,7 +6,7 @@ module RailsSimpleAuth
|
|
|
6
6
|
|
|
7
7
|
unless Rails.env.local?
|
|
8
8
|
rate_limit to: 5, within: 1.hour, by: -> { client_ip }, only: :create,
|
|
9
|
-
with: -> { redirect_to sign_up_path, alert:
|
|
9
|
+
with: -> { redirect_to sign_up_path, alert: 'Too many sign up attempts. Please try again later.' }
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def new
|
|
@@ -27,18 +27,20 @@ module RailsSimpleAuth
|
|
|
27
27
|
private
|
|
28
28
|
|
|
29
29
|
def registration_params
|
|
30
|
-
params.
|
|
30
|
+
params.expect(user: %i[email password])
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def after_successful_registration
|
|
34
|
+
destroy_temporary_user_session(@user)
|
|
35
|
+
|
|
34
36
|
if RailsSimpleAuth.configuration.email_confirmation_enabled
|
|
35
37
|
send_confirmation_email(@user)
|
|
36
38
|
run_after_sign_up_callback(@user)
|
|
37
|
-
redirect_to new_session_path, notice:
|
|
39
|
+
redirect_to new_session_path, notice: 'Account created! Please check your email to confirm your account.'
|
|
38
40
|
else
|
|
39
41
|
create_session_for(@user)
|
|
40
42
|
run_after_sign_up_callback(@user)
|
|
41
|
-
redirect_to resolve_path(:after_sign_up_path), notice:
|
|
43
|
+
redirect_to resolve_path(:after_sign_up_path), notice: 'Account created successfully!'
|
|
42
44
|
end
|
|
43
45
|
end
|
|
44
46
|
|