rails_simple_auth 1.0.1 → 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 +77 -5
- 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/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 +21 -7
- 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 +15 -11
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsSimpleAuth
|
|
4
|
+
module Models
|
|
5
|
+
module Concerns
|
|
6
|
+
module TemporaryUser
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
included do
|
|
10
|
+
scope :temporary, -> { where(temporary: true) }
|
|
11
|
+
scope :permanent, -> { where(temporary: false) }
|
|
12
|
+
scope :temporary_expired, lambda { |days = nil|
|
|
13
|
+
cleanup_days = days || RailsSimpleAuth.configuration.temporary_user_cleanup_days
|
|
14
|
+
raise ConfigurationError, 'temporary_user_cleanup_days must be configured' unless cleanup_days&.positive?
|
|
15
|
+
|
|
16
|
+
temporary.where(created_at: ...cleanup_days.days.ago)
|
|
17
|
+
}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def temporary?
|
|
21
|
+
temporary == true
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def permanent?
|
|
25
|
+
!temporary?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Convert a temporary user to a permanent user with email and password
|
|
29
|
+
# Returns self on success, false on failure (with errors populated)
|
|
30
|
+
def convert_to_permanent!(email:, password:)
|
|
31
|
+
# Validate email uniqueness upfront (better UX than failing inside transaction)
|
|
32
|
+
if self.class.where.not(id: id).exists?(email: email)
|
|
33
|
+
errors.add(:email, 'has already been taken')
|
|
34
|
+
return false
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
transaction do
|
|
38
|
+
# Reload to discard any unpersisted changes from callbacks before locking
|
|
39
|
+
reload
|
|
40
|
+
lock!
|
|
41
|
+
|
|
42
|
+
unless temporary?
|
|
43
|
+
errors.add(:base, 'User is already permanent')
|
|
44
|
+
raise ActiveRecord::Rollback
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
attrs = {
|
|
48
|
+
email: email,
|
|
49
|
+
password: password,
|
|
50
|
+
temporary: false
|
|
51
|
+
}
|
|
52
|
+
# Reset confirmation so new email requires verification
|
|
53
|
+
attrs[:confirmed_at] = nil if respond_to?(:confirmed_at)
|
|
54
|
+
|
|
55
|
+
raise ActiveRecord::Rollback unless update(attrs)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Check if transaction was rolled back
|
|
59
|
+
return false if errors.any? || temporary?
|
|
60
|
+
|
|
61
|
+
invalidate_all_sessions!
|
|
62
|
+
send_conversion_confirmation_email
|
|
63
|
+
Rails.logger.info("[RailsSimpleAuth] Converted temporary user #{id} to permanent")
|
|
64
|
+
self
|
|
65
|
+
rescue ActiveRecord::RecordNotUnique
|
|
66
|
+
errors.add(:email, 'has already been taken')
|
|
67
|
+
false
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class_methods do
|
|
71
|
+
# Cleanup expired temporary users in batches
|
|
72
|
+
# @param days [Integer, nil] Override for cleanup_days config
|
|
73
|
+
# @param batch_size [Integer] Number of users to process per batch
|
|
74
|
+
# @return [Integer] Number of users destroyed
|
|
75
|
+
def cleanup_expired_temporary!(days: nil, batch_size: 100)
|
|
76
|
+
count = 0
|
|
77
|
+
temporary_expired(days).find_each(batch_size: batch_size) do |user|
|
|
78
|
+
user.destroy
|
|
79
|
+
count += 1
|
|
80
|
+
end
|
|
81
|
+
Rails.logger.info("[RailsSimpleAuth] Cleaned up #{count} expired temporary users")
|
|
82
|
+
count
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def send_conversion_confirmation_email
|
|
89
|
+
return unless RailsSimpleAuth.configuration.email_confirmation_enabled
|
|
90
|
+
return unless respond_to?(:generate_confirmation_token)
|
|
91
|
+
|
|
92
|
+
token = generate_confirmation_token
|
|
93
|
+
RailsSimpleAuth.configuration.mailer.confirmation(self, token).deliver_later
|
|
94
|
+
|
|
95
|
+
Rails.logger.info("[RailsSimpleAuth] Queued confirmation email for converted user #{id}")
|
|
96
|
+
rescue ArgumentError, NoMethodError, RailsSimpleAuth::ConfigurationError => e
|
|
97
|
+
# Configuration or method errors - log but don't fail conversion
|
|
98
|
+
Rails.logger.error(
|
|
99
|
+
"[RailsSimpleAuth] Failed to send confirmation email for user #{id}: #{e.class}: #{e.message}"
|
|
100
|
+
)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module RailsSimpleAuth
|
|
4
|
-
class Session <
|
|
5
|
-
self.table_name =
|
|
4
|
+
class Session < ::ApplicationRecord
|
|
5
|
+
self.table_name = 'sessions'
|
|
6
6
|
|
|
7
7
|
# Use lambda to defer class resolution until runtime
|
|
8
8
|
belongs_to :user, class_name: -> { RailsSimpleAuth.configuration.user_class_name }
|
|
9
9
|
|
|
10
|
-
validates :user_id, presence: true
|
|
11
|
-
|
|
12
10
|
scope :recent, -> { order(created_at: :desc) }
|
|
13
11
|
scope :active, -> { where(created_at: RailsSimpleAuth.configuration.session_expiry.ago..) }
|
|
14
12
|
scope :expired, -> { where(created_at: ...RailsSimpleAuth.configuration.session_expiry.ago) }
|
|
@@ -4,11 +4,11 @@ module RailsSimpleAuth
|
|
|
4
4
|
module Routes
|
|
5
5
|
def rails_simple_auth_routes(options = {})
|
|
6
6
|
controllers = {
|
|
7
|
-
sessions: options.fetch(:sessions_controller,
|
|
8
|
-
registrations: options.fetch(:registrations_controller,
|
|
9
|
-
passwords: options.fetch(:passwords_controller,
|
|
10
|
-
confirmations: options.fetch(:confirmations_controller,
|
|
11
|
-
omniauth: options.fetch(:omniauth_controller,
|
|
7
|
+
sessions: options.fetch(:sessions_controller, 'rails_simple_auth/sessions'),
|
|
8
|
+
registrations: options.fetch(:registrations_controller, 'rails_simple_auth/registrations'),
|
|
9
|
+
passwords: options.fetch(:passwords_controller, 'rails_simple_auth/passwords'),
|
|
10
|
+
confirmations: options.fetch(:confirmations_controller, 'rails_simple_auth/confirmations'),
|
|
11
|
+
omniauth: options.fetch(:omniauth_controller, 'rails_simple_auth/omniauth_callbacks')
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
config = RailsSimpleAuth.configuration
|
|
@@ -16,29 +16,29 @@ module RailsSimpleAuth
|
|
|
16
16
|
# Core authentication routes (always registered)
|
|
17
17
|
resource :session, only: %i[new create destroy], controller: controllers[:sessions]
|
|
18
18
|
|
|
19
|
-
get
|
|
20
|
-
post
|
|
19
|
+
get 'sign_up', to: "#{controllers[:registrations]}#new", as: :sign_up
|
|
20
|
+
post 'sign_up', to: "#{controllers[:registrations]}#create"
|
|
21
21
|
|
|
22
22
|
resources :passwords, param: :token, only: %i[new create edit update], controller: controllers[:passwords]
|
|
23
23
|
|
|
24
24
|
# Email confirmation routes (only when enabled)
|
|
25
25
|
if config.email_confirmation_enabled
|
|
26
26
|
resources :confirmations, only: %i[new create], controller: controllers[:confirmations]
|
|
27
|
-
get
|
|
27
|
+
get 'confirmations/:token', to: "#{controllers[:confirmations]}#show", as: :confirmation
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# Magic link routes (only when enabled)
|
|
31
31
|
if config.magic_link_enabled
|
|
32
|
-
get
|
|
33
|
-
post
|
|
34
|
-
get
|
|
32
|
+
get 'magic_link_form', to: "#{controllers[:sessions]}#magic_link_form", as: :magic_link_form
|
|
33
|
+
post 'request_magic_link', to: "#{controllers[:sessions]}#request_magic_link", as: :request_magic_link
|
|
34
|
+
get 'magic_link', to: "#{controllers[:sessions]}#magic_link_login", as: :magic_link
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
# OAuth routes (only when enabled)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
return unless config.oauth_enabled
|
|
39
|
+
|
|
40
|
+
get '/auth/:provider/callback', to: "#{controllers[:omniauth]}#create", as: :omniauth_callback
|
|
41
|
+
get '/auth/failure', to: "#{controllers[:omniauth]}#failure", as: :omniauth_failure
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
end
|
data/lib/rails_simple_auth.rb
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
3
|
+
require 'rails_simple_auth/version'
|
|
4
|
+
require 'rails_simple_auth/configuration'
|
|
5
|
+
require 'rails_simple_auth/engine'
|
|
6
6
|
|
|
7
7
|
# Model concerns
|
|
8
|
-
require
|
|
9
|
-
require
|
|
10
|
-
require
|
|
11
|
-
require
|
|
12
|
-
require
|
|
13
|
-
require
|
|
8
|
+
require 'rails_simple_auth/models/concerns/authenticatable'
|
|
9
|
+
require 'rails_simple_auth/models/concerns/confirmable'
|
|
10
|
+
require 'rails_simple_auth/models/concerns/magic_linkable'
|
|
11
|
+
require 'rails_simple_auth/models/concerns/oauth_connectable'
|
|
12
|
+
require 'rails_simple_auth/models/concerns/temporary_user'
|
|
13
|
+
require 'rails_simple_auth/models/current'
|
|
14
|
+
# Session is NOT required here - it depends on ApplicationRecord which isn't available at gem load time
|
|
15
|
+
# It will be autoloaded by the engine when Rails is ready
|
|
14
16
|
|
|
15
17
|
# Controller concerns
|
|
16
|
-
require
|
|
17
|
-
require
|
|
18
|
+
require 'rails_simple_auth/controllers/concerns/authentication'
|
|
19
|
+
require 'rails_simple_auth/controllers/concerns/session_management'
|
|
18
20
|
|
|
19
21
|
# Routes
|
|
20
|
-
require
|
|
22
|
+
require 'rails_simple_auth/routes'
|
|
21
23
|
|
|
22
24
|
module RailsSimpleAuth
|
|
23
25
|
class Error < StandardError; end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ivan Kuznetsov
|
|
@@ -10,33 +10,33 @@ cert_chain: []
|
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
|
-
name:
|
|
13
|
+
name: bcrypt
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
|
-
- - "
|
|
16
|
+
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '
|
|
18
|
+
version: '3.1'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
|
-
- - "
|
|
23
|
+
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '
|
|
25
|
+
version: '3.1'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
|
-
name:
|
|
27
|
+
name: rails
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
|
-
- - "
|
|
30
|
+
- - ">="
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
32
|
+
version: '8.0'
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
|
-
- - "
|
|
37
|
+
- - ">="
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '
|
|
39
|
+
version: '8.0'
|
|
40
40
|
description: 'A lightweight authentication gem built on Rails primitives: has_secure_password,
|
|
41
41
|
signed cookies, rate limiting. Supports email/password, magic links, email confirmation,
|
|
42
42
|
and OAuth.'
|
|
@@ -72,6 +72,9 @@ files:
|
|
|
72
72
|
- lib/generators/rails_simple_auth/install/install_generator.rb
|
|
73
73
|
- lib/generators/rails_simple_auth/install/templates/initializer.rb
|
|
74
74
|
- lib/generators/rails_simple_auth/install/templates/migration.rb
|
|
75
|
+
- lib/generators/rails_simple_auth/temporary_users/USAGE
|
|
76
|
+
- lib/generators/rails_simple_auth/temporary_users/templates/add_temporary_to_users.rb.erb
|
|
77
|
+
- lib/generators/rails_simple_auth/temporary_users/temporary_users_generator.rb
|
|
75
78
|
- lib/generators/rails_simple_auth/views/views_generator.rb
|
|
76
79
|
- lib/rails_simple_auth.rb
|
|
77
80
|
- lib/rails_simple_auth/configuration.rb
|
|
@@ -82,6 +85,7 @@ files:
|
|
|
82
85
|
- lib/rails_simple_auth/models/concerns/confirmable.rb
|
|
83
86
|
- lib/rails_simple_auth/models/concerns/magic_linkable.rb
|
|
84
87
|
- lib/rails_simple_auth/models/concerns/oauth_connectable.rb
|
|
88
|
+
- lib/rails_simple_auth/models/concerns/temporary_user.rb
|
|
85
89
|
- lib/rails_simple_auth/models/current.rb
|
|
86
90
|
- lib/rails_simple_auth/models/session.rb
|
|
87
91
|
- lib/rails_simple_auth/routes.rb
|