rails_jwt_auth 1.7.3 → 2.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +188 -89
- data/app/controllers/concerns/rails_jwt_auth/authenticable_helper.rb +15 -7
- data/app/controllers/concerns/rails_jwt_auth/params_helper.rb +18 -4
- data/app/controllers/concerns/rails_jwt_auth/render_helper.rb +10 -2
- data/app/controllers/rails_jwt_auth/confirmations_controller.rb +48 -10
- data/app/controllers/rails_jwt_auth/invitations_controller.rb +27 -9
- data/app/controllers/rails_jwt_auth/profiles_controller.rb +51 -0
- data/app/controllers/rails_jwt_auth/reset_passwords_controller.rb +65 -0
- data/app/controllers/rails_jwt_auth/sessions_controller.rb +7 -22
- data/app/controllers/rails_jwt_auth/{unlocks_controller.rb → unlock_accounts_controller.rb} +2 -2
- data/app/mailers/rails_jwt_auth/mailer.rb +23 -28
- data/app/models/concerns/rails_jwt_auth/authenticatable.rb +60 -19
- data/app/models/concerns/rails_jwt_auth/confirmable.rb +49 -39
- data/app/models/concerns/rails_jwt_auth/invitable.rb +46 -72
- data/app/models/concerns/rails_jwt_auth/lockable.rb +38 -46
- data/app/models/concerns/rails_jwt_auth/recoverable.rb +27 -26
- data/app/models/concerns/rails_jwt_auth/trackable.rb +13 -2
- data/app/views/rails_jwt_auth/mailer/confirmation_instructions.html.erb +1 -1
- data/app/views/rails_jwt_auth/mailer/{send_invitation.html.erb → invitation_instructions.html.erb} +1 -1
- data/app/views/rails_jwt_auth/mailer/password_changed_notification.html.erb +3 -0
- data/app/views/rails_jwt_auth/mailer/reset_password_instructions.html.erb +1 -1
- data/app/views/rails_jwt_auth/mailer/{send_unlock_instructions.html.erb → unlock_instructions.html.erb} +1 -1
- data/config/locales/en.yml +6 -6
- data/lib/generators/rails_jwt_auth/install_generator.rb +11 -3
- data/lib/generators/templates/initializer.rb +43 -29
- data/lib/generators/templates/migration.rb +2 -1
- data/lib/rails_jwt_auth/jwt_manager.rb +2 -4
- data/lib/rails_jwt_auth/session.rb +128 -0
- data/lib/rails_jwt_auth/version.rb +1 -1
- data/lib/rails_jwt_auth.rb +46 -47
- metadata +11 -9
- data/app/controllers/rails_jwt_auth/passwords_controller.rb +0 -32
- data/app/views/rails_jwt_auth/mailer/set_password_instructions.html.erb +0 -5
- /data/app/views/rails_jwt_auth/mailer/{email_changed.html.erb → email_change_requested_notification.html.erb} +0 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
module RailsJwtAuth
|
2
|
+
class Session
|
3
|
+
attr_reader :user, :errors, :jwt
|
4
|
+
|
5
|
+
Errors = Struct.new :details # simulate ActiveModel::Errors
|
6
|
+
|
7
|
+
def initialize(params={})
|
8
|
+
@auth_field_value = (params[RailsJwtAuth.auth_field_name] || '').strip
|
9
|
+
@auth_field_value.downcase! if RailsJwtAuth.downcase_auth_field
|
10
|
+
@password = params[:password]
|
11
|
+
|
12
|
+
find_user if @auth_field_value.present?
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid?
|
16
|
+
validate!
|
17
|
+
|
18
|
+
!errors?
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate!(request)
|
22
|
+
if valid?
|
23
|
+
user.clean_reset_password if recoverable?
|
24
|
+
user.clean_lock if lockable?
|
25
|
+
user.track_session_info(request) if trackable?
|
26
|
+
user.load_auth_token
|
27
|
+
|
28
|
+
unless user.save
|
29
|
+
add_error(RailsJwtAuth.model_name.underscore, :invalid)
|
30
|
+
|
31
|
+
return false
|
32
|
+
end
|
33
|
+
|
34
|
+
generate_jwt(request)
|
35
|
+
|
36
|
+
true
|
37
|
+
else
|
38
|
+
user.failed_attempt if lockable?
|
39
|
+
|
40
|
+
false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def validate!
|
47
|
+
# Can't use ActiveModel::Validations since we have dynamic fields
|
48
|
+
@errors = Errors.new({})
|
49
|
+
|
50
|
+
validate_auth_field_presence
|
51
|
+
validate_password_presence
|
52
|
+
validate_user_exist
|
53
|
+
validate_user_is_confirmed if confirmable?
|
54
|
+
validate_user_is_not_locked if lockable?
|
55
|
+
validate_user_password unless errors?
|
56
|
+
validate_custom
|
57
|
+
end
|
58
|
+
|
59
|
+
def find_user
|
60
|
+
@user = RailsJwtAuth.model.where(RailsJwtAuth.auth_field_name => @auth_field_value).first
|
61
|
+
end
|
62
|
+
|
63
|
+
def confirmable?
|
64
|
+
@user&.kind_of?(RailsJwtAuth::Confirmable)
|
65
|
+
end
|
66
|
+
|
67
|
+
def lockable?
|
68
|
+
@user&.kind_of?(RailsJwtAuth::Lockable)
|
69
|
+
end
|
70
|
+
|
71
|
+
def recoverable?
|
72
|
+
@user&.kind_of?(RailsJwtAuth::Recoverable)
|
73
|
+
end
|
74
|
+
|
75
|
+
def trackable?
|
76
|
+
@user&.kind_of?(RailsJwtAuth::Trackable)
|
77
|
+
end
|
78
|
+
|
79
|
+
def user?
|
80
|
+
@user.present?
|
81
|
+
end
|
82
|
+
|
83
|
+
def field_error(field)
|
84
|
+
RailsJwtAuth.avoid_email_errors ? :session : field
|
85
|
+
end
|
86
|
+
|
87
|
+
def validate_auth_field_presence
|
88
|
+
add_error(RailsJwtAuth.auth_field_name, :blank) if @auth_field_value.blank?
|
89
|
+
end
|
90
|
+
|
91
|
+
def validate_password_presence
|
92
|
+
add_error(:password, :blank) if @password.blank?
|
93
|
+
end
|
94
|
+
|
95
|
+
def validate_user_exist
|
96
|
+
add_error(field_error(RailsJwtAuth.auth_field_name), :invalid) unless @user
|
97
|
+
end
|
98
|
+
|
99
|
+
def validate_user_password
|
100
|
+
add_error(field_error(:password), :invalid) unless @user.authenticate(@password)
|
101
|
+
end
|
102
|
+
|
103
|
+
def validate_user_is_confirmed
|
104
|
+
add_error(RailsJwtAuth.email_field_name, :unconfirmed) unless @user.confirmed?
|
105
|
+
end
|
106
|
+
|
107
|
+
def validate_user_is_not_locked
|
108
|
+
add_error(RailsJwtAuth.email_field_name, :locked) if @user.access_locked?
|
109
|
+
end
|
110
|
+
|
111
|
+
def validate_custom
|
112
|
+
# allow add custom validations overwriting this method
|
113
|
+
end
|
114
|
+
|
115
|
+
def add_error(field, detail)
|
116
|
+
@errors.details[field.to_sym] ||= []
|
117
|
+
@errors.details[field.to_sym].push({error: detail})
|
118
|
+
end
|
119
|
+
|
120
|
+
def errors?
|
121
|
+
@errors.details.any?
|
122
|
+
end
|
123
|
+
|
124
|
+
def generate_jwt(request)
|
125
|
+
@jwt = JwtManager.encode(user.to_token_payload(request))
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/rails_jwt_auth.rb
CHANGED
@@ -1,15 +1,16 @@
|
|
1
|
+
require 'active_support/core_ext/integer/time'
|
1
2
|
require 'bcrypt'
|
2
3
|
|
3
4
|
require 'rails_jwt_auth/engine'
|
4
5
|
require 'rails_jwt_auth/jwt_manager'
|
6
|
+
require 'rails_jwt_auth/session'
|
5
7
|
|
6
8
|
module RailsJwtAuth
|
7
|
-
InvalidEmailField = Class.new(StandardError)
|
8
|
-
InvalidAuthField = Class.new(StandardError)
|
9
9
|
NotConfirmationsUrl = Class.new(StandardError)
|
10
10
|
NotInvitationsUrl = Class.new(StandardError)
|
11
11
|
NotResetPasswordsUrl = Class.new(StandardError)
|
12
|
-
|
12
|
+
NotUnlockUrl = Class.new(StandardError)
|
13
|
+
InvalidJwtPayload = Class.new(StandardError)
|
13
14
|
|
14
15
|
mattr_accessor :model_name
|
15
16
|
self.model_name = 'User'
|
@@ -20,6 +21,12 @@ module RailsJwtAuth
|
|
20
21
|
mattr_accessor :email_field_name
|
21
22
|
self.email_field_name = 'email'
|
22
23
|
|
24
|
+
mattr_accessor :email_regex
|
25
|
+
self.email_regex = URI::MailTo::EMAIL_REGEXP
|
26
|
+
|
27
|
+
mattr_accessor :downcase_auth_field
|
28
|
+
self.downcase_auth_field = false
|
29
|
+
|
23
30
|
mattr_accessor :jwt_expiration_time
|
24
31
|
self.jwt_expiration_time = 7.days
|
25
32
|
|
@@ -29,11 +36,17 @@ module RailsJwtAuth
|
|
29
36
|
mattr_accessor :simultaneous_sessions
|
30
37
|
self.simultaneous_sessions = 2
|
31
38
|
|
39
|
+
mattr_accessor :mailer_name
|
40
|
+
self.mailer_name = 'RailsJwtAuth::Mailer'
|
41
|
+
|
32
42
|
mattr_accessor :mailer_sender
|
33
43
|
self.mailer_sender = 'initialize-mailer_sender@example.com'
|
34
44
|
|
35
|
-
mattr_accessor :
|
36
|
-
self.
|
45
|
+
mattr_accessor :send_email_change_requested_notification
|
46
|
+
self.send_email_change_requested_notification = true
|
47
|
+
|
48
|
+
mattr_accessor :send_password_changed_notification
|
49
|
+
self.send_password_changed_notification = true
|
37
50
|
|
38
51
|
mattr_accessor :confirmation_expiration_time
|
39
52
|
self.confirmation_expiration_time = 1.day
|
@@ -44,18 +57,6 @@ module RailsJwtAuth
|
|
44
57
|
mattr_accessor :invitation_expiration_time
|
45
58
|
self.invitation_expiration_time = 2.days
|
46
59
|
|
47
|
-
mattr_accessor :confirmations_url
|
48
|
-
self.confirmations_url = nil
|
49
|
-
|
50
|
-
mattr_accessor :reset_passwords_url
|
51
|
-
self.reset_passwords_url = nil
|
52
|
-
|
53
|
-
mattr_accessor :set_passwords_url
|
54
|
-
self.set_passwords_url = nil
|
55
|
-
|
56
|
-
mattr_accessor :invitations_url
|
57
|
-
self.invitations_url = nil
|
58
|
-
|
59
60
|
mattr_accessor :deliver_later
|
60
61
|
self.deliver_later = false
|
61
62
|
|
@@ -72,51 +73,49 @@ module RailsJwtAuth
|
|
72
73
|
self.unlock_in = 60.minutes
|
73
74
|
|
74
75
|
mattr_accessor :reset_attempts_in
|
75
|
-
self.
|
76
|
+
self.reset_attempts_in = 60.minutes
|
76
77
|
|
77
|
-
mattr_accessor :
|
78
|
-
self.
|
78
|
+
mattr_accessor :confirm_email_url
|
79
|
+
self.confirm_email_url = nil
|
79
80
|
|
80
|
-
|
81
|
-
|
82
|
-
end
|
81
|
+
mattr_accessor :reset_password_url
|
82
|
+
self.reset_password_url = nil
|
83
83
|
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
mattr_accessor :accept_invitation_url
|
85
|
+
self.accept_invitation_url = nil
|
86
|
+
|
87
|
+
mattr_accessor :unlock_account_url
|
88
|
+
self.unlock_account_url = nil
|
89
|
+
|
90
|
+
mattr_accessor :avoid_email_errors
|
91
|
+
self.avoid_email_errors = true
|
87
92
|
|
88
93
|
def self.setup
|
89
94
|
yield self
|
90
95
|
end
|
91
96
|
|
92
|
-
def self.
|
93
|
-
|
94
|
-
klass = RailsJwtAuth.model
|
95
|
-
|
96
|
-
unless field_name.present? &&
|
97
|
-
(klass.respond_to?(:column_names) && klass.column_names.include?(field_name) ||
|
98
|
-
klass.respond_to?(:fields) && klass.fields[field_name])
|
99
|
-
raise RailsJwtAuth::InvalidAuthField
|
100
|
-
end
|
101
|
-
|
102
|
-
field_name
|
97
|
+
def self.model
|
98
|
+
model_name.constantize
|
103
99
|
end
|
104
100
|
|
105
|
-
def self.
|
106
|
-
|
107
|
-
|
101
|
+
def self.mailer
|
102
|
+
mailer_name.constantize
|
103
|
+
end
|
108
104
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
raise RailsJwtAuth::InvalidEmailField
|
113
|
-
end
|
105
|
+
def self.table_name
|
106
|
+
model_name.underscore.pluralize
|
107
|
+
end
|
114
108
|
|
115
|
-
|
109
|
+
# Thanks to https://github.com/heartcombo/devise/blob/master/lib/devise.rb#L496
|
110
|
+
def self.friendly_token(length = 24)
|
111
|
+
# To calculate real characters, we must perform this operation.
|
112
|
+
# See SecureRandom.urlsafe_base64
|
113
|
+
rlength = (length * 3 / 4) - 1
|
114
|
+
SecureRandom.urlsafe_base64(rlength, true).tr('lIO0', 'sxyz')
|
116
115
|
end
|
117
116
|
|
118
117
|
def self.send_email(method, user)
|
119
|
-
mailer = RailsJwtAuth
|
118
|
+
mailer = RailsJwtAuth.mailer.with(user_id: user.id.to_s).public_send(method)
|
120
119
|
RailsJwtAuth.deliver_later ? mailer.deliver_later : mailer.deliver
|
121
120
|
end
|
122
121
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_jwt_auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- rjurado
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bcrypt
|
@@ -67,10 +67,11 @@ files:
|
|
67
67
|
- app/controllers/concerns/rails_jwt_auth/render_helper.rb
|
68
68
|
- app/controllers/rails_jwt_auth/confirmations_controller.rb
|
69
69
|
- app/controllers/rails_jwt_auth/invitations_controller.rb
|
70
|
-
- app/controllers/rails_jwt_auth/
|
70
|
+
- app/controllers/rails_jwt_auth/profiles_controller.rb
|
71
71
|
- app/controllers/rails_jwt_auth/registrations_controller.rb
|
72
|
+
- app/controllers/rails_jwt_auth/reset_passwords_controller.rb
|
72
73
|
- app/controllers/rails_jwt_auth/sessions_controller.rb
|
73
|
-
- app/controllers/rails_jwt_auth/
|
74
|
+
- app/controllers/rails_jwt_auth/unlock_accounts_controller.rb
|
74
75
|
- app/controllers/unauthorized_controller.rb
|
75
76
|
- app/mailers/rails_jwt_auth/mailer.rb
|
76
77
|
- app/models/concerns/rails_jwt_auth/authenticatable.rb
|
@@ -80,11 +81,11 @@ files:
|
|
80
81
|
- app/models/concerns/rails_jwt_auth/recoverable.rb
|
81
82
|
- app/models/concerns/rails_jwt_auth/trackable.rb
|
82
83
|
- app/views/rails_jwt_auth/mailer/confirmation_instructions.html.erb
|
83
|
-
- app/views/rails_jwt_auth/mailer/
|
84
|
+
- app/views/rails_jwt_auth/mailer/email_change_requested_notification.html.erb
|
85
|
+
- app/views/rails_jwt_auth/mailer/invitation_instructions.html.erb
|
86
|
+
- app/views/rails_jwt_auth/mailer/password_changed_notification.html.erb
|
84
87
|
- app/views/rails_jwt_auth/mailer/reset_password_instructions.html.erb
|
85
|
-
- app/views/rails_jwt_auth/mailer/
|
86
|
-
- app/views/rails_jwt_auth/mailer/send_unlock_instructions.html.erb
|
87
|
-
- app/views/rails_jwt_auth/mailer/set_password_instructions.html.erb
|
88
|
+
- app/views/rails_jwt_auth/mailer/unlock_instructions.html.erb
|
88
89
|
- config/locales/en.yml
|
89
90
|
- lib/generators/rails_jwt_auth/install_generator.rb
|
90
91
|
- lib/generators/rails_jwt_auth/migrate_generator.rb
|
@@ -93,6 +94,7 @@ files:
|
|
93
94
|
- lib/rails_jwt_auth.rb
|
94
95
|
- lib/rails_jwt_auth/engine.rb
|
95
96
|
- lib/rails_jwt_auth/jwt_manager.rb
|
97
|
+
- lib/rails_jwt_auth/session.rb
|
96
98
|
- lib/rails_jwt_auth/spec_helpers.rb
|
97
99
|
- lib/rails_jwt_auth/version.rb
|
98
100
|
homepage: https://github.com/rjurado01/rails_jwt_auth
|
@@ -114,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
114
116
|
- !ruby/object:Gem::Version
|
115
117
|
version: '0'
|
116
118
|
requirements: []
|
117
|
-
rubygems_version: 3.1.
|
119
|
+
rubygems_version: 3.1.4
|
118
120
|
signing_key:
|
119
121
|
specification_version: 4
|
120
122
|
summary: Rails jwt authentication.
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module RailsJwtAuth
|
2
|
-
class PasswordsController < ApplicationController
|
3
|
-
include ParamsHelper
|
4
|
-
include RenderHelper
|
5
|
-
|
6
|
-
def create
|
7
|
-
email_field = RailsJwtAuth.email_field_name
|
8
|
-
|
9
|
-
if password_create_params[email_field].blank?
|
10
|
-
return render_422(email_field => [{error: :blank}])
|
11
|
-
end
|
12
|
-
|
13
|
-
user = RailsJwtAuth.model.where(
|
14
|
-
email_field => password_create_params[email_field].to_s.strip.downcase
|
15
|
-
).first
|
16
|
-
|
17
|
-
return render_422(email_field => [{error: :not_found}]) unless user
|
18
|
-
|
19
|
-
user.send_reset_password_instructions ? render_204 : render_422(user.errors.details)
|
20
|
-
end
|
21
|
-
|
22
|
-
def update
|
23
|
-
return render_404 unless
|
24
|
-
params[:id] &&
|
25
|
-
(user = RailsJwtAuth.model.where(reset_password_token: params[:id]).first)
|
26
|
-
|
27
|
-
return render_422(password: [{error: :blank}]) if password_update_params[:password].blank?
|
28
|
-
|
29
|
-
user.update(password_update_params) ? render_204 : render_422(user.errors.details)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
File without changes
|