rails_simple_auth 1.0.2 → 1.0.3
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/CHANGELOG.md +43 -0
- data/README.md +219 -34
- data/app/controllers/rails_simple_auth/confirmations_controller.rb +9 -3
- data/app/controllers/rails_simple_auth/sessions_controller.rb +7 -1
- data/app/mailers/rails_simple_auth/auth_mailer.rb +3 -0
- data/lib/rails_simple_auth/models/concerns/confirmable.rb +5 -1
- data/lib/rails_simple_auth/models/concerns/temporary_user.rb +12 -3
- data/lib/rails_simple_auth/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5fb876e2f8ec9c1f40ed2dbb8d97fdd984e7e5927e11c56be6a2ac4b2aa593a4
|
|
4
|
+
data.tar.gz: 29a914c7c8f77a85199d6f7188ce77ab24460554ca90421b22b38646f15464f5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8a7d0926e4e1e3a8c7da6ec9ab4de80768ae98a1316a32b6d9bf6aa790f266fc494598344b9a47444bfac1241ab55ea6d11c4c89a56bb2d270cff816a0bb3178
|
|
7
|
+
data.tar.gz: b9ea5fa54ad39f51e86dae6852df477760bfb8c28a3c002cae421c40d44e5d3fb74e0ecfaa6ab6d65705cb3ba579d72e4c47061aa2b06d848d5f4639ca9f1eaf
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,49 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.0.3] - 2025-01-19
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Temporary Users Support** - Allow users to try the app without signing up, then convert to permanent accounts
|
|
15
|
+
- `TemporaryUser` concern with `temporary?` and `permanent?` methods
|
|
16
|
+
- Scopes: `temporary`, `permanent`, `temporary_expired`
|
|
17
|
+
- `convert_to_permanent!(email:, password:)` method for account conversion
|
|
18
|
+
- Generator: `rails g rails_simple_auth:temporary_users` for migration
|
|
19
|
+
- Configuration options: `temporary_users_enabled`, `temporary_user_cleanup_days`
|
|
20
|
+
- Automatic cleanup of expired temporary users via `User.cleanup_expired_temporary!`
|
|
21
|
+
- Session invalidation on account conversion
|
|
22
|
+
- Automatic destruction of temporary user when signing in with different account
|
|
23
|
+
- **Email Reconfirmation Flow** - Support for users changing their email address
|
|
24
|
+
- `unconfirmed_email` column support for pending email changes
|
|
25
|
+
- `reconfirming?` and `unconfirmed_or_reconfirming?` helper methods
|
|
26
|
+
- `confirmable_email` helper returns the email needing confirmation
|
|
27
|
+
- Confirmation emails sent to new email address during reconfirmation
|
|
28
|
+
- Comprehensive test suite (126 tests, 247 assertions)
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- `confirm!` now uses `has_attribute?(:temporary)` instead of `respond_to?(:temporary?)` to prevent errors when `Authenticatable` is included without the temporary database column
|
|
33
|
+
- `confirm!` properly handles race conditions with `RecordNotUnique` rescue during reconfirmation
|
|
34
|
+
- `convert_to_permanent!` validates password presence to prevent users being left without credentials
|
|
35
|
+
- `convert_to_permanent!` reloads after transaction to check actual database state (not stale in-memory state)
|
|
36
|
+
- `convert_to_permanent!` resets `confirmed_at` to require email verification for new address
|
|
37
|
+
- `cleanup_expired_temporary!` now returns accurate count (only increments when destroy succeeds)
|
|
38
|
+
- `magic_link_login` checks `confirm!` return value and shows error if confirmation fails
|
|
39
|
+
- `confirmations_controller#show` checks `confirm!` return value and displays appropriate error message
|
|
40
|
+
- `destroy_temporary_user_session` skips destruction when user is re-authenticating as themselves
|
|
41
|
+
- `AuthMailer#confirmation` sends to `confirmable_email` for correct recipient during reconfirmation
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- Confirmation token purpose changed from `:email_confirmation` to `:confirm_email` (**Breaking**: existing confirmation tokens will be invalidated)
|
|
46
|
+
|
|
47
|
+
## [1.0.2] - 2025-01-18
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- Session invalidation and batch cleanup for temporary users
|
|
52
|
+
|
|
10
53
|
## [1.0.0] - 2025-01-18
|
|
11
54
|
|
|
12
55
|
### Added
|
data/README.md
CHANGED
|
@@ -4,16 +4,16 @@ Simple, secure authentication for Rails 8+ applications. Built on Rails primitiv
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **Email/Password authentication**
|
|
8
|
-
- **Magic link**
|
|
9
|
-
- **Email confirmation**
|
|
10
|
-
- **Password reset**
|
|
11
|
-
- **OAuth support**
|
|
12
|
-
- **Temporary users**
|
|
13
|
-
- **Rate limiting** built-in
|
|
14
|
-
- **Session tracking**
|
|
15
|
-
- **Customizable styling**
|
|
16
|
-
- **
|
|
7
|
+
- [**Email/Password authentication**](#installation) - secure session-based auth
|
|
8
|
+
- [**Magic link authentication**](#routes) - passwordless sign-in via email
|
|
9
|
+
- [**Email confirmation**](#routes) - verify user email addresses
|
|
10
|
+
- [**Password reset**](#routes) - secure password recovery flow
|
|
11
|
+
- [**OAuth support**](#oauth-setup) - Google, GitHub, and more
|
|
12
|
+
- [**Temporary users**](#temporary-users-guest-accounts) - guest accounts that convert to permanent
|
|
13
|
+
- [**Rate limiting**](#rate-limiting) - built-in protection on all endpoints
|
|
14
|
+
- [**Session tracking**](#session-management) - IP and user agent logging
|
|
15
|
+
- [**Customizable styling**](#styling) - CSS variables for easy theming
|
|
16
|
+
- [**Custom mailers**](#mailer) - use your own branded email templates
|
|
17
17
|
|
|
18
18
|
## Installation
|
|
19
19
|
|
|
@@ -204,9 +204,20 @@ class User < ApplicationRecord
|
|
|
204
204
|
end
|
|
205
205
|
```
|
|
206
206
|
|
|
207
|
-
## Temporary Users (Guest
|
|
207
|
+
## Temporary Users (Guest Accounts)
|
|
208
208
|
|
|
209
|
-
|
|
209
|
+
Temporary users allow visitors to try your app without creating an account. They get a real user record with full functionality, then can convert to a permanent account later by providing email and password.
|
|
210
|
+
|
|
211
|
+
### Why Use Temporary Users?
|
|
212
|
+
|
|
213
|
+
**Reduce friction**: Let users experience your app's value before asking them to sign up. This is especially useful for:
|
|
214
|
+
|
|
215
|
+
- **E-commerce**: Users can add items to cart, save preferences, then checkout as guest or create account
|
|
216
|
+
- **Productivity apps**: Users can create documents, try features, then save their work by signing up
|
|
217
|
+
- **Games**: Users can start playing immediately, then create account to save progress
|
|
218
|
+
- **Collaboration tools**: Users can join a shared workspace via link, then register to keep access
|
|
219
|
+
|
|
220
|
+
**Preserve data**: Unlike anonymous sessions, temporary users have real database records. When they convert, all their data (orders, documents, settings) stays linked to their account.
|
|
210
221
|
|
|
211
222
|
### Setup
|
|
212
223
|
|
|
@@ -217,7 +228,7 @@ rails generate rails_simple_auth:temporary_users
|
|
|
217
228
|
rails db:migrate
|
|
218
229
|
```
|
|
219
230
|
|
|
220
|
-
2.
|
|
231
|
+
2. Add the concern to your User model:
|
|
221
232
|
|
|
222
233
|
```ruby
|
|
223
234
|
class User < ApplicationRecord
|
|
@@ -237,42 +248,110 @@ end
|
|
|
237
248
|
|
|
238
249
|
### Creating Temporary Users
|
|
239
250
|
|
|
251
|
+
Create a temporary user when someone needs to use your app without signing up:
|
|
252
|
+
|
|
253
|
+
```ruby
|
|
254
|
+
# In your controller
|
|
255
|
+
def try_without_account
|
|
256
|
+
user = User.create!(
|
|
257
|
+
email: "temp_#{SecureRandom.hex(8)}@temporary.local",
|
|
258
|
+
password: SecureRandom.hex(32),
|
|
259
|
+
temporary: true
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
# Sign them in
|
|
263
|
+
create_session_for(user)
|
|
264
|
+
redirect_to dashboard_path
|
|
265
|
+
end
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Or create via an invite link:
|
|
269
|
+
|
|
240
270
|
```ruby
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
271
|
+
def accept_invite
|
|
272
|
+
# Create temporary user to access shared content
|
|
273
|
+
user = User.create!(temporary: true, ...)
|
|
274
|
+
create_session_for(user)
|
|
275
|
+
redirect_to shared_workspace_path(params[:workspace_id])
|
|
276
|
+
end
|
|
247
277
|
```
|
|
248
278
|
|
|
249
279
|
### Converting to Permanent Account
|
|
250
280
|
|
|
281
|
+
When a temporary user is ready to create a real account:
|
|
282
|
+
|
|
283
|
+
```ruby
|
|
284
|
+
# In your controller
|
|
285
|
+
def convert_account
|
|
286
|
+
if current_user.convert_to_permanent!(
|
|
287
|
+
email: params[:email],
|
|
288
|
+
password: params[:password]
|
|
289
|
+
)
|
|
290
|
+
redirect_to dashboard_path, notice: "Account created! Please check your email to confirm."
|
|
291
|
+
else
|
|
292
|
+
# Validation failed (email taken, password blank, etc.)
|
|
293
|
+
render :convert_form, status: :unprocessable_entity
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
The conversion:
|
|
299
|
+
- Updates email and password
|
|
300
|
+
- Sets `temporary: false`
|
|
301
|
+
- Resets `confirmed_at` (requires email confirmation for new address)
|
|
302
|
+
- Invalidates all existing sessions (security measure)
|
|
303
|
+
- Sends confirmation email automatically
|
|
304
|
+
|
|
305
|
+
### What Happens on Sign In?
|
|
306
|
+
|
|
307
|
+
When a temporary user signs in with a different account (or signs up), the temporary user is automatically destroyed:
|
|
308
|
+
|
|
309
|
+
```
|
|
310
|
+
Temporary User (browsing) → Signs in with existing account → Temp user deleted
|
|
311
|
+
Temporary User (browsing) → Creates new account → Temp user deleted
|
|
312
|
+
Temporary User (browsing) → Converts their temp account → Keeps same user record
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
This prevents orphaned temporary records and ensures clean data.
|
|
316
|
+
|
|
317
|
+
### Querying Users
|
|
318
|
+
|
|
251
319
|
```ruby
|
|
252
|
-
#
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
#
|
|
320
|
+
User.temporary # All temporary users
|
|
321
|
+
User.permanent # All permanent users
|
|
322
|
+
User.temporary_expired # Temporary users older than cleanup_days
|
|
323
|
+
|
|
324
|
+
current_user.temporary? # Is this a guest?
|
|
325
|
+
current_user.permanent? # Is this a real account?
|
|
258
326
|
```
|
|
259
327
|
|
|
260
|
-
###
|
|
328
|
+
### Cleanup
|
|
329
|
+
|
|
330
|
+
Temporary users are automatically eligible for cleanup after `temporary_user_cleanup_days`. Run cleanup manually or via scheduled job:
|
|
261
331
|
|
|
262
332
|
```ruby
|
|
263
|
-
|
|
264
|
-
User.
|
|
265
|
-
|
|
266
|
-
|
|
333
|
+
# In a rake task or background job
|
|
334
|
+
User.cleanup_expired_temporary!
|
|
335
|
+
|
|
336
|
+
# With custom retention period
|
|
337
|
+
User.cleanup_expired_temporary!(days: 14)
|
|
267
338
|
```
|
|
268
339
|
|
|
269
|
-
|
|
340
|
+
Add to your scheduler (e.g., `config/recurring.yml` for Solid Queue):
|
|
270
341
|
|
|
271
|
-
|
|
342
|
+
```yaml
|
|
343
|
+
cleanup_temporary_users:
|
|
344
|
+
schedule: every day at 3am
|
|
345
|
+
class: CleanupTemporaryUsersJob
|
|
346
|
+
```
|
|
272
347
|
|
|
273
348
|
```ruby
|
|
274
|
-
|
|
275
|
-
|
|
349
|
+
class CleanupTemporaryUsersJob < ApplicationJob
|
|
350
|
+
def perform
|
|
351
|
+
count = User.cleanup_expired_temporary!
|
|
352
|
+
Rails.logger.info "Cleaned up #{count} expired temporary users"
|
|
353
|
+
end
|
|
354
|
+
end
|
|
276
355
|
```
|
|
277
356
|
|
|
278
357
|
## Controller Customization
|
|
@@ -402,6 +481,112 @@ The gem adds these routes:
|
|
|
402
481
|
| POST | `/request_magic_link` | Send magic link |
|
|
403
482
|
| GET | `/magic_link` | Login via magic link |
|
|
404
483
|
|
|
484
|
+
## Rate Limiting
|
|
485
|
+
|
|
486
|
+
All authentication endpoints are rate limited using Rails 8's `rate_limit` DSL to prevent brute force attacks.
|
|
487
|
+
|
|
488
|
+
### Default Limits
|
|
489
|
+
|
|
490
|
+
| Action | Limit | Period | Scope |
|
|
491
|
+
|--------|-------|--------|-------|
|
|
492
|
+
| Sign in | 5 requests | 15 minutes | per IP |
|
|
493
|
+
| Sign up | 5 requests | 1 hour | per IP |
|
|
494
|
+
| Magic link request | 3 requests | 10 minutes | per email |
|
|
495
|
+
| Password reset | 3 requests | 1 hour | per IP |
|
|
496
|
+
| Email confirmation | 3 requests | 1 hour | per IP |
|
|
497
|
+
|
|
498
|
+
### Customizing Limits
|
|
499
|
+
|
|
500
|
+
```ruby
|
|
501
|
+
RailsSimpleAuth.configure do |config|
|
|
502
|
+
config.rate_limits = {
|
|
503
|
+
sign_in: { limit: 10, period: 30.minutes },
|
|
504
|
+
sign_up: { limit: 3, period: 1.hour },
|
|
505
|
+
magic_link: { limit: 5, period: 15.minutes },
|
|
506
|
+
password_reset: { limit: 5, period: 1.hour },
|
|
507
|
+
confirmation: { limit: 5, period: 1.hour }
|
|
508
|
+
}
|
|
509
|
+
end
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### Disabling Rate Limiting
|
|
513
|
+
|
|
514
|
+
To disable rate limiting for a specific action, set it to `nil`:
|
|
515
|
+
|
|
516
|
+
```ruby
|
|
517
|
+
config.rate_limits = {
|
|
518
|
+
sign_in: nil, # No rate limiting on sign in
|
|
519
|
+
sign_up: { limit: 5, period: 1.hour }
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
When rate limited, users see a "Too many requests" error and must wait for the period to expire.
|
|
524
|
+
|
|
525
|
+
## Session Management
|
|
526
|
+
|
|
527
|
+
Sessions track user authentication state with IP address and user agent for security auditing.
|
|
528
|
+
|
|
529
|
+
### What's Tracked
|
|
530
|
+
|
|
531
|
+
Each session stores:
|
|
532
|
+
- **user_id** - The authenticated user
|
|
533
|
+
- **ip_address** - Client IP at sign-in time
|
|
534
|
+
- **user_agent** - Browser/device information
|
|
535
|
+
- **created_at** - When the session was created
|
|
536
|
+
|
|
537
|
+
### Session Expiration
|
|
538
|
+
|
|
539
|
+
Sessions expire after 30 days by default:
|
|
540
|
+
|
|
541
|
+
```ruby
|
|
542
|
+
RailsSimpleAuth.configure do |config|
|
|
543
|
+
config.session_expiry = 30.days # Default
|
|
544
|
+
# config.session_expiry = 7.days # Shorter sessions
|
|
545
|
+
end
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### Querying Sessions
|
|
549
|
+
|
|
550
|
+
```ruby
|
|
551
|
+
# All sessions for a user
|
|
552
|
+
current_user.sessions
|
|
553
|
+
|
|
554
|
+
# Recent sessions first
|
|
555
|
+
current_user.sessions.recent
|
|
556
|
+
|
|
557
|
+
# Active sessions (not expired)
|
|
558
|
+
current_user.sessions.active
|
|
559
|
+
|
|
560
|
+
# Expired sessions
|
|
561
|
+
current_user.sessions.expired
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
### Session Cleanup
|
|
565
|
+
|
|
566
|
+
Expired sessions can be cleaned up manually or via scheduled job:
|
|
567
|
+
|
|
568
|
+
```ruby
|
|
569
|
+
# Clean up all expired sessions
|
|
570
|
+
RailsSimpleAuth::Session.cleanup_expired!
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
Add to your scheduler:
|
|
574
|
+
|
|
575
|
+
```ruby
|
|
576
|
+
class CleanupExpiredSessionsJob < ApplicationJob
|
|
577
|
+
def perform
|
|
578
|
+
count = RailsSimpleAuth::Session.cleanup_expired!
|
|
579
|
+
Rails.logger.info "Cleaned up #{count} expired sessions"
|
|
580
|
+
end
|
|
581
|
+
end
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
### Security Behaviors
|
|
585
|
+
|
|
586
|
+
- **Password change**: All sessions are invalidated when a user changes their password
|
|
587
|
+
- **Account conversion**: All sessions are invalidated when a temporary user converts to permanent
|
|
588
|
+
- **Sign out**: Only the current session is destroyed (other devices stay signed in)
|
|
589
|
+
|
|
405
590
|
## Security Features
|
|
406
591
|
|
|
407
592
|
- **BCrypt password hashing** with salts
|
|
@@ -15,9 +15,15 @@ module RailsSimpleAuth
|
|
|
15
15
|
user = user_class.find_signed(params[:token], purpose: :confirm_email)
|
|
16
16
|
|
|
17
17
|
if user
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
confirmed = user.respond_to?(:confirm!) ? user.confirm! : true
|
|
19
|
+
|
|
20
|
+
if confirmed
|
|
21
|
+
run_after_confirmation_callback(user)
|
|
22
|
+
redirect_to resolve_path(:after_confirmation_path), notice: 'Email confirmed! You can now sign in.'
|
|
23
|
+
else
|
|
24
|
+
error_message = user.errors.full_messages.first || 'Could not confirm email.'
|
|
25
|
+
redirect_to new_confirmation_path, alert: error_message
|
|
26
|
+
end
|
|
21
27
|
else
|
|
22
28
|
redirect_to new_confirmation_path, alert: 'Invalid or expired confirmation link.'
|
|
23
29
|
end
|
|
@@ -70,7 +70,13 @@ module RailsSimpleAuth
|
|
|
70
70
|
user = user_class.find_signed(params[:token], purpose: :magic_link)
|
|
71
71
|
|
|
72
72
|
if user
|
|
73
|
-
|
|
73
|
+
# Auto-confirm unconfirmed users via magic link (email ownership verified)
|
|
74
|
+
if user.respond_to?(:confirm!) && user.respond_to?(:unconfirmed?) && user.unconfirmed? && !user.confirm!
|
|
75
|
+
# Confirmation failed (e.g., email already taken during reconfirmation)
|
|
76
|
+
error_message = user.errors.full_messages.first || 'Could not confirm email.'
|
|
77
|
+
redirect_to new_session_path, alert: error_message
|
|
78
|
+
return
|
|
79
|
+
end
|
|
74
80
|
sign_in_and_redirect(user)
|
|
75
81
|
else
|
|
76
82
|
redirect_to new_session_path, alert: 'Invalid or expired magic link.'
|
|
@@ -4,6 +4,9 @@ module RailsSimpleAuth
|
|
|
4
4
|
class AuthMailer < ApplicationMailer
|
|
5
5
|
default from: -> { RailsSimpleAuth.configuration.mailer_sender }
|
|
6
6
|
|
|
7
|
+
# Use the mailers folder for templates instead of auth_mailer
|
|
8
|
+
self.mailer_name = 'rails_simple_auth/mailers'
|
|
9
|
+
|
|
7
10
|
def confirmation(user, token)
|
|
8
11
|
@user = user
|
|
9
12
|
@token = token
|
|
@@ -44,7 +44,7 @@ module RailsSimpleAuth
|
|
|
44
44
|
# Returns true on success, false on failure (with errors populated)
|
|
45
45
|
def confirm!
|
|
46
46
|
attrs = { confirmed_at: Time.current }
|
|
47
|
-
attrs[:temporary] = false if
|
|
47
|
+
attrs[:temporary] = false if has_attribute?(:temporary)
|
|
48
48
|
|
|
49
49
|
if reconfirming?
|
|
50
50
|
# Email change confirmation - check email uniqueness first
|
|
@@ -62,6 +62,10 @@ module RailsSimpleAuth
|
|
|
62
62
|
# Already confirmed and not reconfirming
|
|
63
63
|
true
|
|
64
64
|
end
|
|
65
|
+
rescue ActiveRecord::RecordNotUnique
|
|
66
|
+
# Race condition: email was taken between check and update
|
|
67
|
+
errors.add(:email, 'is already taken by another user')
|
|
68
|
+
false
|
|
65
69
|
end
|
|
66
70
|
|
|
67
71
|
# Generate email confirmation token using Rails signed_id
|
|
@@ -28,6 +28,12 @@ module RailsSimpleAuth
|
|
|
28
28
|
# Convert a temporary user to a permanent user with email and password
|
|
29
29
|
# Returns self on success, false on failure (with errors populated)
|
|
30
30
|
def convert_to_permanent!(email:, password:)
|
|
31
|
+
# Validate password presence upfront
|
|
32
|
+
if password.blank?
|
|
33
|
+
errors.add(:password, "can't be blank")
|
|
34
|
+
return false
|
|
35
|
+
end
|
|
36
|
+
|
|
31
37
|
# Validate email uniqueness upfront (better UX than failing inside transaction)
|
|
32
38
|
if self.class.where.not(id: id).exists?(email: email)
|
|
33
39
|
errors.add(:email, 'has already been taken')
|
|
@@ -55,7 +61,11 @@ module RailsSimpleAuth
|
|
|
55
61
|
raise ActiveRecord::Rollback unless update(attrs)
|
|
56
62
|
end
|
|
57
63
|
|
|
58
|
-
#
|
|
64
|
+
# Reload to get actual database state after transaction
|
|
65
|
+
# (in-memory attributes may be stale if transaction was rolled back)
|
|
66
|
+
reload
|
|
67
|
+
|
|
68
|
+
# Check if conversion actually succeeded
|
|
59
69
|
return false if errors.any? || temporary?
|
|
60
70
|
|
|
61
71
|
invalidate_all_sessions!
|
|
@@ -75,8 +85,7 @@ module RailsSimpleAuth
|
|
|
75
85
|
def cleanup_expired_temporary!(days: nil, batch_size: 100)
|
|
76
86
|
count = 0
|
|
77
87
|
temporary_expired(days).find_each(batch_size: batch_size) do |user|
|
|
78
|
-
user.destroy
|
|
79
|
-
count += 1
|
|
88
|
+
count += 1 if user.destroy
|
|
80
89
|
end
|
|
81
90
|
Rails.logger.info("[RailsSimpleAuth] Cleaned up #{count} expired temporary users")
|
|
82
91
|
count
|
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails_simple_auth
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ivan Kuznetsov
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: bin
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-01-19 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: bcrypt
|
|
@@ -100,6 +101,7 @@ metadata:
|
|
|
100
101
|
bug_tracker_uri: https://github.com/ivankuznetsov/rails_simple_auth/issues
|
|
101
102
|
documentation_uri: https://github.com/ivankuznetsov/rails_simple_auth#readme
|
|
102
103
|
rubygems_mfa_required: 'true'
|
|
104
|
+
post_install_message:
|
|
103
105
|
rdoc_options: []
|
|
104
106
|
require_paths:
|
|
105
107
|
- lib
|
|
@@ -114,7 +116,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
114
116
|
- !ruby/object:Gem::Version
|
|
115
117
|
version: '0'
|
|
116
118
|
requirements: []
|
|
117
|
-
rubygems_version: 3.
|
|
119
|
+
rubygems_version: 3.5.22
|
|
120
|
+
signing_key:
|
|
118
121
|
specification_version: 4
|
|
119
122
|
summary: Simple, secure authentication for Rails 8+ applications
|
|
120
123
|
test_files: []
|