kingsman 0.0.0.beta → 0.1.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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -4
  3. data/app/controllers/kingsman/confirmations_controller.rb +54 -0
  4. data/app/controllers/kingsman/omniauth_callbacks_controller.rb +36 -0
  5. data/app/controllers/kingsman/passwords_controller.rb +83 -0
  6. data/app/controllers/kingsman/registrations_controller.rb +168 -0
  7. data/app/controllers/kingsman/sessions_controller.rb +83 -0
  8. data/app/controllers/kingsman/unlocks_controller.rb +52 -0
  9. data/app/controllers/kingsman_controller.rb +252 -0
  10. data/app/jobs/application_job.rb +2 -0
  11. data/app/mailers/kingsman/mailer.rb +30 -0
  12. data/app/views/kingsman/confirmations/new.html.erb +16 -0
  13. data/app/views/kingsman/home/index.html.erb +1 -0
  14. data/app/views/kingsman/mailer/confirmation_instructions.html.erb +5 -0
  15. data/app/views/kingsman/mailer/email_changed.html.erb +7 -0
  16. data/app/views/kingsman/mailer/password_change.html.erb +3 -0
  17. data/app/views/kingsman/mailer/reset_password_instructions.html.erb +8 -0
  18. data/app/views/kingsman/mailer/unlock_instructions.html.erb +7 -0
  19. data/app/views/kingsman/passwords/edit.html.erb +25 -0
  20. data/app/views/kingsman/passwords/new.html.erb +16 -0
  21. data/app/views/kingsman/registrations/edit.html.erb +42 -0
  22. data/app/views/kingsman/registrations/new.html.erb +29 -0
  23. data/app/views/kingsman/sessions/new.html.erb +26 -0
  24. data/app/views/kingsman/shared/_error_messages.html.erb +15 -0
  25. data/app/views/kingsman/shared/_links.html.erb +25 -0
  26. data/app/views/kingsman/unlocks/new.html.erb +16 -0
  27. data/app/views/kingsman/up/index.html.erb +11 -0
  28. data/config/application.rb +0 -0
  29. data/config/locales/en.yml +63 -0
  30. data/config.ru +6 -0
  31. data/lib/generators/active_record/kingsman_generator.rb +127 -0
  32. data/lib/generators/active_record/templates/migration.rb +20 -0
  33. data/lib/generators/active_record/templates/migration_existing.rb +27 -0
  34. data/lib/generators/kingsman/controllers_generator.rb +46 -0
  35. data/lib/generators/kingsman/install_generator.rb +42 -0
  36. data/lib/generators/kingsman/kingsman_generator.rb +28 -0
  37. data/lib/generators/kingsman/orm_helpers.rb +40 -0
  38. data/lib/generators/kingsman/views_generator.rb +145 -0
  39. data/lib/generators/mongoid/kingsman_generator.rb +57 -0
  40. data/lib/generators/templates/README +36 -0
  41. data/lib/generators/templates/controllers/README +14 -0
  42. data/lib/generators/templates/controllers/confirmations_controller.rb +30 -0
  43. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +30 -0
  44. data/lib/generators/templates/controllers/passwords_controller.rb +34 -0
  45. data/lib/generators/templates/controllers/registrations_controller.rb +62 -0
  46. data/lib/generators/templates/controllers/sessions_controller.rb +27 -0
  47. data/lib/generators/templates/controllers/unlocks_controller.rb +30 -0
  48. data/lib/generators/templates/kingsman.rb +313 -0
  49. data/lib/generators/templates/markerb/confirmation_instructions.markerb +5 -0
  50. data/lib/generators/templates/markerb/email_changed.markerb +7 -0
  51. data/lib/generators/templates/markerb/password_change.markerb +3 -0
  52. data/lib/generators/templates/markerb/reset_password_instructions.markerb +8 -0
  53. data/lib/generators/templates/markerb/unlock_instructions.markerb +7 -0
  54. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +20 -0
  55. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +27 -0
  56. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +18 -0
  57. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +35 -0
  58. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +25 -0
  59. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +20 -0
  60. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +19 -0
  61. data/lib/kingsman/autoloader.rb +31 -0
  62. data/lib/kingsman/controllers/helpers.rb +221 -0
  63. data/lib/kingsman/controllers/rememberable.rb +57 -0
  64. data/lib/kingsman/controllers/responder.rb +35 -0
  65. data/lib/kingsman/controllers/scoped_views.rb +19 -0
  66. data/lib/kingsman/controllers/sign_in_out.rb +112 -0
  67. data/lib/kingsman/controllers/store_location.rb +76 -0
  68. data/lib/kingsman/controllers/url_helpers.rb +72 -0
  69. data/lib/kingsman/delegator.rb +18 -0
  70. data/lib/kingsman/encryptor.rb +19 -0
  71. data/lib/kingsman/failure_app.rb +280 -0
  72. data/lib/kingsman/hooks/activatable.rb +12 -0
  73. data/lib/kingsman/hooks/csrf_cleaner.rb +14 -0
  74. data/lib/kingsman/hooks/forgetable.rb +11 -0
  75. data/lib/kingsman/hooks/lockable.rb +9 -0
  76. data/lib/kingsman/hooks/proxy.rb +23 -0
  77. data/lib/kingsman/hooks/rememberable.rb +9 -0
  78. data/lib/kingsman/hooks/timeoutable.rb +35 -0
  79. data/lib/kingsman/hooks/trackable.rb +11 -0
  80. data/lib/kingsman/hooks.rb +6 -0
  81. data/lib/kingsman/jets/routes.rb +195 -0
  82. data/lib/kingsman/jets/warden_compat.rb +15 -0
  83. data/lib/kingsman/jets.rb +39 -0
  84. data/lib/kingsman/mailers/helpers.rb +93 -0
  85. data/lib/kingsman/mapping.rb +148 -0
  86. data/lib/kingsman/models/authenticatable.rb +310 -0
  87. data/lib/kingsman/models/confirmable.rb +369 -0
  88. data/lib/kingsman/models/database_authenticatable.rb +206 -0
  89. data/lib/kingsman/models/lockable.rb +214 -0
  90. data/lib/kingsman/models/omniauthable.rb +29 -0
  91. data/lib/kingsman/models/recoverable.rb +156 -0
  92. data/lib/kingsman/models/registerable.rb +29 -0
  93. data/lib/kingsman/models/rememberable.rb +158 -0
  94. data/lib/kingsman/models/timeoutable.rb +45 -0
  95. data/lib/kingsman/models/trackable.rb +51 -0
  96. data/lib/kingsman/models/validatable.rb +68 -0
  97. data/lib/kingsman/models.rb +122 -0
  98. data/lib/kingsman/modules.rb +33 -0
  99. data/lib/kingsman/omniauth/config.rb +47 -0
  100. data/lib/kingsman/omniauth/url_helpers.rb +28 -0
  101. data/lib/kingsman/omniauth.rb +20 -0
  102. data/lib/kingsman/orm/active_record.rb +13 -0
  103. data/lib/kingsman/orm/mongoid.rb +8 -0
  104. data/lib/kingsman/orm.rb +37 -0
  105. data/lib/kingsman/parameter_filter.rb +44 -0
  106. data/lib/kingsman/parameter_sanitizer.rb +173 -0
  107. data/lib/kingsman/secret_key_finder.rb +27 -0
  108. data/lib/kingsman/strategies/authenticatable.rb +178 -0
  109. data/lib/kingsman/strategies/base.rb +22 -0
  110. data/lib/kingsman/strategies/database_authenticatable.rb +31 -0
  111. data/lib/kingsman/strategies/rememberable.rb +67 -0
  112. data/lib/kingsman/token_generator.rb +32 -0
  113. data/lib/kingsman/version.rb +1 -1
  114. data/lib/kingsman.rb +427 -3
  115. metadata +289 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d48d26f76dd2a261f622a2538474b0c30f28ec82502d5f0ffa213a3b29a4093
4
- data.tar.gz: a793bd466f2ec909d96e17fed93177c930baac7d62875bf9b290d5aed590972d
3
+ metadata.gz: 44b40ac359095d6878a5841602e2360373d490fba7c13e180666ea3adbc97d79
4
+ data.tar.gz: 0afcf6f9cfb29cb89cd022c1ef418964ac43f4de888bcc381645b862507382bd
5
5
  SHA512:
6
- metadata.gz: 905f8f722b1110cef7f42f95c7c3ef1ffa0c939a6085e9e5a5fe363b6ffdb612508c6f8c29f1c9eade16d9d7308a2004e06a23c15cc79636483c951adf72a85f
7
- data.tar.gz: 26623ba45589b56fde604d081bd0a2fdcd22732d1eacc347283be5d0c119a285f63420316ef696bfbd641ec8a0bc54f6e3ffc543dd92f27748a77ecf5064aa6e
6
+ metadata.gz: caa32d6b9d79bde12ad8f1b9c08229da3db75ef5bfaf7cdff7038ba02badfd60922a5a649e7fd01da7fb5aebb2d0323559c8fa8440cc72d545824318e2540158
7
+ data.tar.gz: 8a03dd4764e22651484cbdab1d642764465ba23c92ab325713e8d9367fa4dc20ba21a571f5b1c9c892e052528c6e7ac267c369570229b5a8d4137541cfc122d4
data/README.md CHANGED
@@ -1,10 +1,11 @@
1
1
  # Kingsman
2
2
 
3
- ## Installation
3
+ [![Gem Version](https://badge.fury.io/rb/jets-responders.png)](http://badge.fury.io/rb/jets-responders)
4
4
 
5
- Install the gem and add to the application's Gemfile by executing:
5
+ [![BoltOps Badge](https://img.boltops.com/boltops/badges/boltops-badge.png)](https://www.boltops.com)
6
6
 
7
- $ bundle add kingsman
7
+ [![BoltOps Learn Badge](https://img.boltops.com/boltops-learn/boltops-learn.png)](https://learn.boltops.com)
8
8
 
9
- ## Usage
9
+ Kingsman is a flexible authentication solution for Jets based on Warden. It is a port of [heartcombo/devise](https://github.com/heartcombo/devise) to Jets.
10
10
 
11
+ Docs: https://docs.rubyonjet.scom/docs/auth/kingsman/
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Kingsman::ConfirmationsController < KingsmanController
4
+ # GET /resource/confirmation/new
5
+ def new
6
+ self.resource = resource_class.new
7
+ end
8
+
9
+ # POST /resource/confirmation
10
+ def create
11
+ self.resource = resource_class.send_confirmation_instructions(resource_params)
12
+ yield resource if block_given?
13
+
14
+ if successfully_sent?(resource)
15
+ respond_with({}, location: after_resending_confirmation_instructions_path_for(resource_name))
16
+ else
17
+ respond_with(resource)
18
+ end
19
+ end
20
+
21
+ # GET /resource/confirmation?confirmation_token=abcdef
22
+ def show
23
+ self.resource = resource_class.confirm_by_token(params[:confirmation_token])
24
+ yield resource if block_given?
25
+
26
+ if resource.errors.empty?
27
+ set_flash_message!(:notice, :confirmed)
28
+ respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
29
+ else
30
+ # TODO: use `error_status` when the default changes to `:unprocessable_entity`.
31
+ respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
32
+ end
33
+ end
34
+
35
+ protected
36
+
37
+ # The path used after resending confirmation instructions.
38
+ def after_resending_confirmation_instructions_path_for(resource_name)
39
+ is_navigational_format? ? new_session_path(resource_name) : '/'
40
+ end
41
+
42
+ # The path used after confirmation.
43
+ def after_confirmation_path_for(resource_name, resource)
44
+ if signed_in?(resource_name)
45
+ signed_in_root_path(resource)
46
+ else
47
+ new_session_path(resource_name)
48
+ end
49
+ end
50
+
51
+ def translation_scope
52
+ 'kingsman.confirmations'
53
+ end
54
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Kingsman::OmniauthCallbacksController < KingsmanController
4
+ prepend_before_action { request.env["kingsman.skip_timeout"] = true }
5
+
6
+ def passthru
7
+ render status: 404, plain: "Not found. Authentication passthru."
8
+ end
9
+
10
+ def failure
11
+ set_flash_message! :alert, :failure, kind: OmniAuth::Utils.camelize(failed_strategy.name), reason: failure_message
12
+ redirect_to after_omniauth_failure_path_for(resource_name)
13
+ end
14
+
15
+ protected
16
+
17
+ def failed_strategy
18
+ request.respond_to?(:get_header) ? request.get_header("omniauth.error.strategy") : request.env["omniauth.error.strategy"]
19
+ end
20
+
21
+ def failure_message
22
+ exception = request.respond_to?(:get_header) ? request.get_header("omniauth.error") : request.env["omniauth.error"]
23
+ error = exception.error_reason if exception.respond_to?(:error_reason)
24
+ error ||= exception.error if exception.respond_to?(:error)
25
+ error ||= (request.respond_to?(:get_header) ? request.get_header("omniauth.error.type") : request.env["omniauth.error.type"]).to_s
26
+ error.to_s.humanize if error
27
+ end
28
+
29
+ def after_omniauth_failure_path_for(scope)
30
+ new_session_path(scope)
31
+ end
32
+
33
+ def translation_scope
34
+ 'kingsman.omniauth_callbacks'
35
+ end
36
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Kingsman::PasswordsController < KingsmanController
4
+ prepend_before_action :require_no_authentication
5
+ # Render the #edit only if coming from a reset password email link
6
+ append_before_action :assert_reset_token_passed, only: :edit
7
+
8
+ # GET /resource/password/new
9
+ def new
10
+ self.resource = resource_class.new
11
+ end
12
+
13
+ # POST /resource/password
14
+ def create
15
+ self.resource = resource_class.send_reset_password_instructions(resource_params)
16
+ yield resource if block_given?
17
+
18
+ if successfully_sent?(resource)
19
+ respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name))
20
+ else
21
+ respond_with(resource)
22
+ end
23
+ end
24
+
25
+ # GET /resource/password/edit?reset_password_token=abcdef
26
+ def edit
27
+ self.resource = resource_class.new
28
+ set_minimum_password_length
29
+ resource.reset_password_token = params[:reset_password_token]
30
+ end
31
+
32
+ # PUT /resource/password
33
+ def update
34
+ self.resource = resource_class.reset_password_by_token(resource_params)
35
+ yield resource if block_given?
36
+
37
+ if resource.errors.empty?
38
+ resource.unlock_access! if unlockable?(resource)
39
+ if resource_class.sign_in_after_reset_password
40
+ flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
41
+ set_flash_message!(:notice, flash_message)
42
+ resource.after_database_authentication
43
+ sign_in(resource_name, resource)
44
+ else
45
+ set_flash_message!(:notice, :updated_not_active)
46
+ end
47
+ respond_with resource, location: after_resetting_password_path_for(resource)
48
+ else
49
+ set_minimum_password_length
50
+ respond_with resource
51
+ end
52
+ end
53
+
54
+ protected
55
+ def after_resetting_password_path_for(resource)
56
+ resource_class.sign_in_after_reset_password ? after_sign_in_path_for(resource) : new_session_path(resource_name)
57
+ end
58
+
59
+ # The path used after sending reset password instructions
60
+ def after_sending_reset_password_instructions_path_for(resource_name)
61
+ new_session_path(resource_name) if is_navigational_format?
62
+ end
63
+
64
+ # Check if a reset_password_token is provided in the request
65
+ def assert_reset_token_passed
66
+ if params[:reset_password_token].blank?
67
+ set_flash_message(:alert, :no_token)
68
+ redirect_to new_session_path(resource_name)
69
+ end
70
+ end
71
+
72
+ # Check if proper Lockable module methods are present & unlock strategy
73
+ # allows to unlock resource on password reset
74
+ def unlockable?(resource)
75
+ resource.respond_to?(:unlock_access!) &&
76
+ resource.respond_to?(:unlock_strategy_enabled?) &&
77
+ resource.unlock_strategy_enabled?(:email)
78
+ end
79
+
80
+ def translation_scope
81
+ 'kingsman.passwords'
82
+ end
83
+ end
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Kingsman::RegistrationsController < KingsmanController
4
+ prepend_before_action :require_no_authentication, only: [:new, :create, :cancel]
5
+ prepend_before_action :authenticate_scope!, only: [:edit, :update, :destroy]
6
+ prepend_before_action :set_minimum_password_length, only: [:new, :edit]
7
+
8
+ # GET /resource/sign_up
9
+ def new
10
+ build_resource
11
+ yield resource if block_given?
12
+ respond_with resource
13
+ end
14
+
15
+ # POST /resource
16
+ def create
17
+ build_resource(sign_up_params)
18
+
19
+ resource.save
20
+ yield resource if block_given?
21
+ if resource.persisted?
22
+ if resource.active_for_authentication?
23
+ set_flash_message! :notice, :signed_up
24
+ sign_up(resource_name, resource)
25
+ respond_with resource, location: after_sign_up_path_for(resource)
26
+ else
27
+ set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
28
+ expire_data_after_sign_in!
29
+ respond_with resource, location: after_inactive_sign_up_path_for(resource)
30
+ end
31
+ else
32
+ clean_up_passwords resource
33
+ set_minimum_password_length
34
+ respond_with resource
35
+ end
36
+ end
37
+
38
+ # GET /resource/edit
39
+ def edit
40
+ render :edit
41
+ end
42
+
43
+ # PUT /resource
44
+ # We need to use a copy of the resource because we don't want to change
45
+ # the current user in place.
46
+ def update
47
+ self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
48
+ prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
49
+
50
+ resource_updated = update_resource(resource, account_update_params)
51
+ yield resource if block_given?
52
+ if resource_updated
53
+ set_flash_message_for_update(resource, prev_unconfirmed_email)
54
+ bypass_sign_in resource, scope: resource_name if sign_in_after_change_password?
55
+
56
+ respond_with resource, location: after_update_path_for(resource)
57
+ else
58
+ clean_up_passwords resource
59
+ set_minimum_password_length
60
+ respond_with resource
61
+ end
62
+ end
63
+
64
+ # DELETE /resource
65
+ def destroy
66
+ resource.destroy
67
+ Kingsman.sign_out_all_scopes ? sign_out : sign_out(resource_name)
68
+ set_flash_message! :notice, :destroyed
69
+ yield resource if block_given?
70
+ respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name), status: Kingsman.responder.redirect_status }
71
+ end
72
+
73
+ # GET /resource/cancel
74
+ # Forces the session data which is usually expired after sign
75
+ # in to be expired now. This is useful if the user wants to
76
+ # cancel oauth signing in/up in the middle of the process,
77
+ # removing all OAuth session data.
78
+ def cancel
79
+ expire_data_after_sign_in!
80
+ redirect_to new_registration_path(resource_name)
81
+ end
82
+
83
+ protected
84
+
85
+ def update_needs_confirmation?(resource, previous)
86
+ resource.respond_to?(:pending_reconfirmation?) &&
87
+ resource.pending_reconfirmation? &&
88
+ previous != resource.unconfirmed_email
89
+ end
90
+
91
+ # By default we want to require a password checks on update.
92
+ # You can overwrite this method in your own RegistrationsController.
93
+ def update_resource(resource, params)
94
+ resource.update_with_password(params)
95
+ end
96
+
97
+ # Build a kingsman resource passing in the session. Useful to move
98
+ # temporary session data to the newly created user.
99
+ def build_resource(hash = {})
100
+ self.resource = resource_class.new_with_session(hash, session)
101
+ end
102
+
103
+ # Signs in a user on sign up. You can overwrite this method in your own
104
+ # RegistrationsController.
105
+ def sign_up(resource_name, resource)
106
+ sign_in(resource_name, resource)
107
+ end
108
+
109
+ # The path used after sign up. You need to overwrite this method
110
+ # in your own RegistrationsController.
111
+ def after_sign_up_path_for(resource)
112
+ after_sign_in_path_for(resource) if is_navigational_format?
113
+ end
114
+
115
+ # The path used after sign up for inactive accounts. You need to overwrite
116
+ # this method in your own RegistrationsController.
117
+ def after_inactive_sign_up_path_for(resource)
118
+ scope = Kingsman::Mapping.find_scope!(resource)
119
+ router_name = Kingsman.mappings[scope].router_name
120
+ context = router_name ? send(router_name) : self
121
+ context.respond_to?(:root_path) ? context.root_path : "/"
122
+ end
123
+
124
+ # The default url to be used after updating a resource. You need to overwrite
125
+ # this method in your own RegistrationsController.
126
+ def after_update_path_for(resource)
127
+ sign_in_after_change_password? ? signed_in_root_path(resource) : new_session_path(resource_name)
128
+ end
129
+
130
+ # Authenticates the current scope and gets the current resource from the session.
131
+ def authenticate_scope!
132
+ send(:"authenticate_#{resource_name}!", force: true)
133
+ self.resource = send(:"current_#{resource_name}")
134
+ end
135
+
136
+ def sign_up_params
137
+ kingsman_parameter_sanitizer.sanitize(:sign_up)
138
+ end
139
+
140
+ def account_update_params
141
+ kingsman_parameter_sanitizer.sanitize(:account_update)
142
+ end
143
+
144
+ def translation_scope
145
+ 'kingsman.registrations'
146
+ end
147
+
148
+ private
149
+
150
+ def set_flash_message_for_update(resource, prev_unconfirmed_email)
151
+ return unless is_flashing_format?
152
+
153
+ flash_key = if update_needs_confirmation?(resource, prev_unconfirmed_email)
154
+ :update_needs_confirmation
155
+ elsif sign_in_after_change_password?
156
+ :updated
157
+ else
158
+ :updated_but_not_signed_in
159
+ end
160
+ set_flash_message :notice, flash_key
161
+ end
162
+
163
+ def sign_in_after_change_password?
164
+ return true if account_update_params[:password].blank?
165
+
166
+ Kingsman.sign_in_after_change_password
167
+ end
168
+ end
@@ -0,0 +1,83 @@
1
+ class Kingsman::SessionsController < KingsmanController
2
+ prepend_before_action :require_no_authentication, only: [:new, :create]
3
+ prepend_before_action :allow_params_authentication!, only: :create
4
+ prepend_before_action :verify_signed_out_user, only: :destroy
5
+ prepend_before_action(only: [:create, :destroy]) { request.env["kingsman.skip_timeout"] = true }
6
+
7
+ # GET /resource/sign_in
8
+ def new
9
+ self.resource = resource_class.new(sign_in_params)
10
+ clean_up_passwords(resource)
11
+ yield resource if block_given?
12
+ respond_with(resource, serialize_options(resource))
13
+ end
14
+
15
+ # POST /resource/sign_in
16
+ def create
17
+ self.resource = warden.authenticate!(auth_options)
18
+ set_flash_message!(:notice, :signed_in)
19
+ sign_in(resource_name, resource)
20
+ yield resource if block_given?
21
+ respond_with resource, location: after_sign_in_path_for(resource)
22
+ end
23
+
24
+ # DELETE /resource/sign_out
25
+ def destroy
26
+ signed_out = (Kingsman.sign_out_all_scopes ? sign_out : sign_out(resource_name))
27
+ set_flash_message! :notice, :signed_out if signed_out
28
+ yield if block_given?
29
+ respond_to_on_destroy
30
+ end
31
+
32
+ protected
33
+
34
+ def sign_in_params
35
+ kingsman_parameter_sanitizer.sanitize(:sign_in)
36
+ end
37
+
38
+ def serialize_options(resource)
39
+ methods = resource_class.authentication_keys.dup
40
+ methods = methods.keys if methods.is_a?(Hash)
41
+ methods << :password if resource.respond_to?(:password)
42
+ { methods: methods, only: [:password] }
43
+ end
44
+
45
+ def auth_options
46
+ { scope: resource_name, recall: "#{controller_path}#new" }
47
+ end
48
+
49
+ def translation_scope
50
+ 'kingsman.sessions'
51
+ end
52
+
53
+ private
54
+
55
+ # Check if there is no signed in user before doing the sign out.
56
+ #
57
+ # If there is no signed in user, it will set the flash message and redirect
58
+ # to the after_sign_out path.
59
+ def verify_signed_out_user
60
+ if all_signed_out?
61
+ set_flash_message! :notice, :already_signed_out
62
+
63
+ respond_to_on_destroy
64
+ end
65
+ end
66
+
67
+ def all_signed_out?
68
+ users = Kingsman.mappings.keys.map { |s| warden.user(scope: s, run_callbacks: false) }
69
+
70
+ users.all?(&:blank?)
71
+ end
72
+
73
+ def respond_to_on_destroy
74
+ # We actually need to hardcode this as Rails default responder doesn't
75
+ # support returning empty response on GET request
76
+ respond_to do |format|
77
+ # Need format.js Jets ujs-compat uses AJAX delete requests to handle logout
78
+ format.js { render json: { location: "/" } }
79
+ format.all { head :no_content }
80
+ format.any(*navigational_formats) { redirect_to after_sign_out_path_for(resource_name), status: Kingsman.responder.redirect_status }
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Kingsman::UnlocksController < KingsmanController
4
+ prepend_before_action :require_no_authentication
5
+
6
+ # GET /resource/unlock/new
7
+ def new
8
+ self.resource = resource_class.new
9
+ end
10
+
11
+ # POST /resource/unlock
12
+ def create
13
+ self.resource = resource_class.send_unlock_instructions(resource_params)
14
+ yield resource if block_given?
15
+
16
+ if successfully_sent?(resource)
17
+ respond_with({}, location: after_sending_unlock_instructions_path_for(resource))
18
+ else
19
+ respond_with(resource)
20
+ end
21
+ end
22
+
23
+ # GET /resource/unlock?unlock_token=abcdef
24
+ def show
25
+ self.resource = resource_class.unlock_access_by_token(params[:unlock_token])
26
+ yield resource if block_given?
27
+
28
+ if resource.errors.empty?
29
+ set_flash_message! :notice, :unlocked
30
+ respond_with_navigational(resource){ redirect_to after_unlock_path_for(resource) }
31
+ else
32
+ # TODO: use `error_status` when the default changes to `:unprocessable_entity`.
33
+ respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
34
+ end
35
+ end
36
+
37
+ protected
38
+
39
+ # The path used after sending unlock password instructions
40
+ def after_sending_unlock_instructions_path_for(resource)
41
+ new_session_path(resource) if is_navigational_format?
42
+ end
43
+
44
+ # The path used after unlocking the resource
45
+ def after_unlock_path_for(resource)
46
+ new_session_path(resource) if is_navigational_format?
47
+ end
48
+
49
+ def translation_scope
50
+ 'kingsman.unlocks'
51
+ end
52
+ end