token_authenticate_me 0.4.3 → 0.5.0
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/{LICENSE → MIT-LICENSE} +1 -1
- data/Rakefile +27 -11
- data/app/controllers/token_authenticate_me/api/v1/base_controller.rb +9 -0
- data/app/controllers/token_authenticate_me/api/v1/invites_controller.rb +14 -0
- data/app/controllers/token_authenticate_me/api/v1/password_resets_controller.rb +11 -0
- data/app/controllers/token_authenticate_me/api/v1/sessions_controller.rb +11 -0
- data/app/controllers/token_authenticate_me/api/v1/users_controller.rb +17 -0
- data/app/controllers/token_authenticate_me/application_controller.rb +5 -0
- data/app/helpers/token_authenticate_me/application_helper.rb +4 -0
- data/app/mailers/token_authenticate_me_mailer.rb +16 -9
- data/app/models/token_authenticate_me/invite.rb +11 -0
- data/app/models/token_authenticate_me/session.rb +8 -0
- data/app/models/token_authenticate_me/user.rb +11 -0
- data/app/views/token_authenticate_me_mailer/invite_user_email.html.erb +0 -0
- data/config/routes.rb +23 -0
- data/db/migrate/20160620184327_create_token_authenticate_me_invites.rb +14 -0
- data/db/migrate/20160621211347_create_token_authenticate_me_users.rb +18 -0
- data/db/migrate/20160622203801_create_token_authenticate_me_sessions.rb +14 -0
- data/lib/generators/token_authenticate_me/controllers/controllers_generator.rb +1 -76
- data/lib/generators/token_authenticate_me/install/install_generator.rb +9 -3
- data/lib/generators/token_authenticate_me/models/models_generator.rb +1 -59
- data/lib/generators/token_authenticate_me/policies/policies_generator.rb +15 -0
- data/lib/generators/token_authenticate_me/policies/templates/invite_policy.rb +31 -0
- data/lib/generators/token_authenticate_me/policies/templates/user_policy.rb +23 -0
- data/lib/tasks/token_authenticate_me_tasks.rake +4 -0
- data/lib/token_authenticate_me.rb +11 -0
- data/lib/token_authenticate_me/concerns/controllers/invitable.rb +58 -0
- data/lib/token_authenticate_me/concerns/controllers/password_resetable.rb +97 -0
- data/lib/token_authenticate_me/concerns/controllers/sessionable.rb +55 -0
- data/lib/token_authenticate_me/concerns/controllers/token_authenticateable.rb +45 -0
- data/lib/token_authenticate_me/concerns/models/authenticatable.rb +102 -0
- data/lib/token_authenticate_me/concerns/models/invitable.rb +20 -0
- data/lib/token_authenticate_me/concerns/models/sessionable.rb +44 -0
- data/lib/token_authenticate_me/configuration.rb +16 -0
- data/lib/token_authenticate_me/engine.rb +2 -2
- data/lib/token_authenticate_me/models.rb +4 -0
- data/lib/token_authenticate_me/version.rb +1 -1
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/{spec/internal → test/dummy}/app/controllers/application_controller.rb +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +25 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +3 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/log/test.log +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/fixtures/token_authenticate_me/invites.yml +11 -0
- data/test/fixtures/token_authenticate_me/sessions.yml +11 -0
- data/test/fixtures/token_authenticate_me/users.yml +11 -0
- data/test/integration/navigation_test.rb +7 -0
- data/test/models/token_authenticate_me/invite_test.rb +9 -0
- data/test/models/token_authenticate_me/session_test.rb +9 -0
- data/test/models/token_authenticate_me/user_test.rb +9 -0
- data/test/test_helper.rb +21 -0
- data/test/token_authenticate_me_test.rb +7 -0
- metadata +129 -160
- data/.editorconfig +0 -41
- data/.gitignore +0 -4
- data/.rubocop.yml +0 -8
- data/CHANGELOG.md +0 -2
- data/Gemfile +0 -7
- data/config.ru +0 -7
- data/lib/generators/token_authenticate_me/controllers/templates/password_reset.rb +0 -6
- data/lib/generators/token_authenticate_me/controllers/templates/sessions.rb +0 -6
- data/lib/generators/token_authenticate_me/controllers/templates/users.rb +0 -8
- data/lib/generators/token_authenticate_me/models/templates/authentication_migration.rb +0 -20
- data/lib/generators/token_authenticate_me/models/templates/authentication_model.rb +0 -11
- data/lib/generators/token_authenticate_me/models/templates/session_migration.rb +0 -17
- data/lib/generators/token_authenticate_me/models/templates/session_model.rb +0 -12
- data/lib/token_authenticate_me/controllers/password_resetable.rb +0 -95
- data/lib/token_authenticate_me/controllers/sessionable.rb +0 -53
- data/lib/token_authenticate_me/controllers/token_authenticateable.rb +0 -52
- data/lib/token_authenticate_me/models/authenticatable.rb +0 -93
- data/lib/token_authenticate_me/models/sessionable.rb +0 -36
- data/spec/acceptance/password_reset_api_spec.rb +0 -111
- data/spec/acceptance/session_api_spec.rb +0 -95
- data/spec/acceptance/users_api_spec.rb +0 -70
- data/spec/internal/app/controllers/password_resets_controller.rb +0 -5
- data/spec/internal/app/controllers/sessions_controller.rb +0 -5
- data/spec/internal/app/controllers/users_controller.rb +0 -7
- data/spec/internal/app/models/session.rb +0 -11
- data/spec/internal/app/models/user.rb +0 -11
- data/spec/internal/app/policies/user_policy.rb +0 -29
- data/spec/internal/app/serializers/user_serializer.rb +0 -3
- data/spec/internal/config/database.yml +0 -3
- data/spec/internal/config/routes.rb +0 -13
- data/spec/internal/db/fixtures/users.rb +0 -11
- data/spec/internal/db/schema.rb +0 -19
- data/spec/spec_helper.rb +0 -38
- data/token_authenticate_me.gemspec +0 -32
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module TokenAuthenticateMe
|
|
2
|
+
module Generators
|
|
3
|
+
class PoliciesGenerator < ::Rails::Generators::Base
|
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
|
5
|
+
|
|
6
|
+
def create_invite_poliocy
|
|
7
|
+
copy_file 'invite_policy.rb', 'app/policies/token_authenticate_me/invite_policy.rb'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def create_user_poliocy
|
|
11
|
+
copy_file 'user_policy.rb', 'app/policies/token_authenticate_me/user_policy.rb'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module TokenAuthenticateMe
|
|
2
|
+
class InvitePolicy < ApplicationPolicy
|
|
3
|
+
def create?
|
|
4
|
+
record.owner_id == current_user.id || super
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def show?
|
|
8
|
+
true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def update?
|
|
12
|
+
create?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def destroy?
|
|
16
|
+
record.owner_id == current_user.id || super
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def accept?
|
|
20
|
+
current_user
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def decline?
|
|
24
|
+
current_user
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def permitted_attributes
|
|
28
|
+
[:email, :accepted, :meta]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module TokenAuthenticateMe
|
|
2
|
+
class UserPolicy < ApplicationPolicy
|
|
3
|
+
def create?
|
|
4
|
+
true
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def show?
|
|
8
|
+
true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def update?
|
|
12
|
+
record.id == current_user.id || super
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def destroy?
|
|
16
|
+
record.id == current_user.id || super
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def permitted_attributes
|
|
20
|
+
[:username, :email, :password, :password_confirmation]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
require 'token_authenticate_me/engine'
|
|
2
2
|
require 'token_authenticate_me/version'
|
|
3
|
+
require 'token_authenticate_me/configuration'
|
|
3
4
|
|
|
4
5
|
module TokenAuthenticateMe
|
|
6
|
+
extend self
|
|
7
|
+
|
|
5
8
|
UUID_REGEX = /([a-f0-9]){32}/
|
|
9
|
+
|
|
10
|
+
def configure
|
|
11
|
+
yield configuration
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def configuration
|
|
15
|
+
Configuration.instance
|
|
16
|
+
end
|
|
6
17
|
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'api_me'
|
|
2
|
+
|
|
3
|
+
module TokenAuthenticateMe
|
|
4
|
+
module Concerns
|
|
5
|
+
module Controllers
|
|
6
|
+
module Invitable
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
include TokenAuthenticateMe::Controllers::TokenAuthenticateable
|
|
10
|
+
include ApiMe
|
|
11
|
+
|
|
12
|
+
included do |_base|
|
|
13
|
+
skip_before_action :authenticate, only: [:show]
|
|
14
|
+
|
|
15
|
+
def create
|
|
16
|
+
@object = model_klass.new(object_params)
|
|
17
|
+
authorize @object
|
|
18
|
+
@object.save!(object_params)
|
|
19
|
+
|
|
20
|
+
TokenAuthenticateMeMailer.invite_email(
|
|
21
|
+
@objec5,
|
|
22
|
+
request.base_url
|
|
23
|
+
).deliver_later
|
|
24
|
+
render status: 201, json: @object, serializer: serializer_klass
|
|
25
|
+
rescue ActiveRecord::RecordInvalid => e
|
|
26
|
+
handle_errors(e)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def accept
|
|
30
|
+
@object = model_klass.find(params[:id])
|
|
31
|
+
|
|
32
|
+
if @object.accepted.nil?
|
|
33
|
+
ActiveRecord::Base.transaction do
|
|
34
|
+
@object.accept!(current_user)
|
|
35
|
+
@object.update!(accepted: true)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
render status: 204, nothing: true
|
|
39
|
+
else
|
|
40
|
+
render json: { message: 'The request has already been processed' }, status: 422
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def decline
|
|
45
|
+
@object = model_klass.find(params[:id])
|
|
46
|
+
|
|
47
|
+
if @object.accepted.nil?
|
|
48
|
+
@object.update!(accepted: false)
|
|
49
|
+
render status: 204, nothing: true
|
|
50
|
+
else
|
|
51
|
+
render json: { message: 'The request has already been processed' }, status: 422
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
|
|
3
|
+
require 'token_authenticate_me/concerns/controllers/token_authenticateable'
|
|
4
|
+
|
|
5
|
+
module TokenAuthenticateMe
|
|
6
|
+
module Concerns
|
|
7
|
+
module Controllers
|
|
8
|
+
module PasswordResetable
|
|
9
|
+
extend ActiveSupport::Concern
|
|
10
|
+
|
|
11
|
+
include TokenAuthenticateMe::Concerns::Controllers::TokenAuthenticateable
|
|
12
|
+
|
|
13
|
+
included do
|
|
14
|
+
skip_before_action :authenticate, only: [:create, :update]
|
|
15
|
+
before_action :validate_reset_token, only: [:update]
|
|
16
|
+
|
|
17
|
+
# Send reset token to user with e-mail address
|
|
18
|
+
def create
|
|
19
|
+
@user = User.find_by_email(params[:email])
|
|
20
|
+
|
|
21
|
+
if @user
|
|
22
|
+
send_valid_reset_email(@user)
|
|
23
|
+
else
|
|
24
|
+
send_invalid_reset_email(params[:email])
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
render status: 204, nothing: true
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Allow user to reset password when the token is valid
|
|
31
|
+
# and not expired
|
|
32
|
+
def update
|
|
33
|
+
@user.update!(
|
|
34
|
+
password: params[:password],
|
|
35
|
+
password_confirmation: params[:password_confirmation],
|
|
36
|
+
reset_password_token: nil,
|
|
37
|
+
reset_password_token_exp: nil
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
render status: 204, nothing: true
|
|
41
|
+
rescue ActiveRecord::RecordInvalid => e
|
|
42
|
+
handle_errors(e)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def send_valid_reset_email(user)
|
|
48
|
+
user.create_reset_token!
|
|
49
|
+
|
|
50
|
+
TokenAuthenticateMeMailer.valid_user_reset_password_email(
|
|
51
|
+
request.base_url,
|
|
52
|
+
user
|
|
53
|
+
).deliver
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def send_invalid_reset_email(email)
|
|
57
|
+
TokenAuthenticateMeMailer.invalid_user_reset_password_email(
|
|
58
|
+
request.base_url,
|
|
59
|
+
email
|
|
60
|
+
).deliver
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def session_params
|
|
64
|
+
params.permit(:password, :password_confirmation)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def render_errors(errors, status = 422)
|
|
68
|
+
render(json: { errors: errors }, status: status)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def handle_errors(e)
|
|
72
|
+
render_errors(e.record.errors.messages)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def validate_reset_token
|
|
76
|
+
valid_reset_token? || render_not_found
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def render_not_found
|
|
80
|
+
render status: 404, nothing: true
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def valid_reset_token?
|
|
84
|
+
# Check for
|
|
85
|
+
# https://github.com/rails/rails/commit/e8572cf2f94872d81e7145da31d55c6e1b074247
|
|
86
|
+
# security issue when config.action_dispatch.perform_deep_munge = false is set
|
|
87
|
+
# which is common for JSON APIs
|
|
88
|
+
return false if params[:id].class == Array || params[:id].nil?
|
|
89
|
+
|
|
90
|
+
@user = User.find_by_reset_password_token(params[:id])
|
|
91
|
+
@user && @user.reset_password_token_exp > DateTime.now
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
|
|
3
|
+
require 'token_authenticate_me/concerns/controllers/token_authenticateable'
|
|
4
|
+
|
|
5
|
+
module TokenAuthenticateMe
|
|
6
|
+
module Concerns
|
|
7
|
+
module Controllers
|
|
8
|
+
module Sessionable
|
|
9
|
+
extend ActiveSupport::Concern
|
|
10
|
+
|
|
11
|
+
include TokenAuthenticateMe::Concerns::Controllers::TokenAuthenticateable
|
|
12
|
+
|
|
13
|
+
included do
|
|
14
|
+
skip_before_action :authenticate, only: [:create]
|
|
15
|
+
after_action :cleanup_sessions, only: [:destroy]
|
|
16
|
+
|
|
17
|
+
def create
|
|
18
|
+
resource = User.where('username=? OR email=?', params[:username], params[:username]).first
|
|
19
|
+
if resource && resource.authenticate(params[:password])
|
|
20
|
+
@session = Session.create(user_id: resource.id)
|
|
21
|
+
render json: @session, status: 201
|
|
22
|
+
else
|
|
23
|
+
render json: { message: 'Bad credentials' }, status: 401
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def show
|
|
28
|
+
@session = authenticate_token
|
|
29
|
+
render json: @session
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def destroy
|
|
33
|
+
authenticate_token.destroy
|
|
34
|
+
|
|
35
|
+
render status: 204, nothing: true
|
|
36
|
+
rescue
|
|
37
|
+
render_unauthorized
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def session_params
|
|
43
|
+
params.permit(:username, :email, :password)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def cleanup_sessions
|
|
47
|
+
ApiSession.where('expiration < ?', DateTime.now).delete_all
|
|
48
|
+
rescue
|
|
49
|
+
Rails.logger.warn 'Error cleaning up old authentication sessions'
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
|
|
3
|
+
module TokenAuthenticateMe
|
|
4
|
+
module Concerns
|
|
5
|
+
module Controllers
|
|
6
|
+
module TokenAuthenticateable
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
included do
|
|
10
|
+
before_action :authenticate
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
protected
|
|
14
|
+
|
|
15
|
+
def authenticate
|
|
16
|
+
authenticate_token || render_unauthorized
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def current_user
|
|
20
|
+
if authenticate_token
|
|
21
|
+
@current_user ||= User.find_by_id(authenticate_token.user_id)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def authenticate_token
|
|
26
|
+
@session ||= authenticate_with_http_token(&method(:token_handler))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def render_unauthorized
|
|
30
|
+
headers['WWW-Authenticate'] = 'Token realm="Application"'
|
|
31
|
+
render json: 'Bad credentials', status: 401
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def token_handler(token, _options)
|
|
35
|
+
session = TokenAuthenticateMe::Session.find_by_key(token)
|
|
36
|
+
if session && session.expiration > DateTime.now
|
|
37
|
+
session
|
|
38
|
+
else
|
|
39
|
+
false
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
|
|
3
|
+
module TokenAuthenticateMe
|
|
4
|
+
module Concerns
|
|
5
|
+
module Models
|
|
6
|
+
module Authenticatable
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
included do
|
|
10
|
+
has_secure_password validations: false
|
|
11
|
+
attr_accessor :current_password
|
|
12
|
+
|
|
13
|
+
has_many :sessions
|
|
14
|
+
has_many :invites, inverse_of: 'creator', foreign_key: 'creator_id'
|
|
15
|
+
|
|
16
|
+
validates(
|
|
17
|
+
:email,
|
|
18
|
+
presence: true,
|
|
19
|
+
uniqueness: { case_sensitive: false },
|
|
20
|
+
format: {
|
|
21
|
+
with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i,
|
|
22
|
+
message: 'invalid e-mail address'
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
validates(
|
|
27
|
+
:username,
|
|
28
|
+
format: { with: /\A[a-zA-Z0-9]+\Z/ },
|
|
29
|
+
presence: true,
|
|
30
|
+
uniqueness: { case_sensitive: false }
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
validates(
|
|
34
|
+
:password,
|
|
35
|
+
presence: true,
|
|
36
|
+
length: { in: 8..72 },
|
|
37
|
+
confirmation: true,
|
|
38
|
+
if: :password_required?
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
validate(
|
|
42
|
+
:current_password_correct,
|
|
43
|
+
if: :current_password_required?
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def attributes
|
|
47
|
+
{
|
|
48
|
+
'id' => id,
|
|
49
|
+
'username' => username,
|
|
50
|
+
'email' => email,
|
|
51
|
+
'created_at' => created_at,
|
|
52
|
+
'updated_at' => updated_at
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def as_json(options = nil)
|
|
57
|
+
{ user: super(options) }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def create_reset_token!
|
|
61
|
+
# rubocop:disable Lint/Loop
|
|
62
|
+
begin
|
|
63
|
+
self.reset_password_token = SecureRandom.hex
|
|
64
|
+
end while self.class.exists?(reset_password_token: reset_password_token)
|
|
65
|
+
|
|
66
|
+
self.reset_password_token_exp = password_expiration_hours.hours.from_now
|
|
67
|
+
save!
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def password_expiration_hours
|
|
71
|
+
8
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def password=(unencrypted_password)
|
|
75
|
+
super(unencrypted_password) unless unencrypted_password.blank? && !password_required?
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def current_password_correct
|
|
79
|
+
errors.add(:current_password, 'is required to change email and/or password') if current_password.blank? # rubocop:disable Metrics/LineLength
|
|
80
|
+
errors.add(:current_password, 'is incorrect') unless authenticate(current_password)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def current_password_required?
|
|
84
|
+
!new_record? && (email_changed? || attempting_to_change_password?) && !password_resetting?
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def password_resetting?
|
|
88
|
+
reset_password_token_changed? && reset_password_token_exp_changed?
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def password_required?
|
|
92
|
+
attempting_to_change_password? || new_record?
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def attempting_to_change_password?
|
|
96
|
+
(!password.blank? || !password_confirmation.blank?) && password_digest_changed?
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|