devise_token_auth_skycocker_fork 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +13 -0
  3. data/README.md +97 -0
  4. data/Rakefile +42 -0
  5. data/app/controllers/devise_token_auth/application_controller.rb +79 -0
  6. data/app/controllers/devise_token_auth/concerns/resource_finder.rb +44 -0
  7. data/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +178 -0
  8. data/app/controllers/devise_token_auth/confirmations_controller.rb +39 -0
  9. data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +239 -0
  10. data/app/controllers/devise_token_auth/passwords_controller.rb +185 -0
  11. data/app/controllers/devise_token_auth/registrations_controller.rb +198 -0
  12. data/app/controllers/devise_token_auth/sessions_controller.rb +131 -0
  13. data/app/controllers/devise_token_auth/token_validations_controller.rb +31 -0
  14. data/app/controllers/devise_token_auth/unlocks_controller.rb +89 -0
  15. data/app/models/devise_token_auth/concerns/active_record_support.rb +34 -0
  16. data/app/models/devise_token_auth/concerns/mongoid_support.rb +19 -0
  17. data/app/models/devise_token_auth/concerns/user.rb +262 -0
  18. data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +28 -0
  19. data/app/validators/devise_token_auth/email_validator.rb +23 -0
  20. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  21. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  22. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  23. data/app/views/devise_token_auth/omniauth_external_window.html.erb +38 -0
  24. data/config/locales/da-DK.yml +50 -0
  25. data/config/locales/de.yml +49 -0
  26. data/config/locales/en.yml +50 -0
  27. data/config/locales/es.yml +49 -0
  28. data/config/locales/fr.yml +49 -0
  29. data/config/locales/it.yml +46 -0
  30. data/config/locales/ja.yml +46 -0
  31. data/config/locales/nl.yml +30 -0
  32. data/config/locales/pl.yml +48 -0
  33. data/config/locales/pt-BR.yml +46 -0
  34. data/config/locales/pt.yml +48 -0
  35. data/config/locales/ro.yml +46 -0
  36. data/config/locales/ru.yml +50 -0
  37. data/config/locales/sq.yml +46 -0
  38. data/config/locales/sv.yml +50 -0
  39. data/config/locales/uk.yml +59 -0
  40. data/config/locales/vi.yml +50 -0
  41. data/config/locales/zh-CN.yml +46 -0
  42. data/config/locales/zh-HK.yml +48 -0
  43. data/config/locales/zh-TW.yml +48 -0
  44. data/lib/devise_token_auth.rb +13 -0
  45. data/lib/devise_token_auth/blacklist.rb +2 -0
  46. data/lib/devise_token_auth/controllers/helpers.rb +161 -0
  47. data/lib/devise_token_auth/controllers/url_helpers.rb +10 -0
  48. data/lib/devise_token_auth/engine.rb +90 -0
  49. data/lib/devise_token_auth/errors.rb +8 -0
  50. data/lib/devise_token_auth/rails/routes.rb +116 -0
  51. data/lib/devise_token_auth/url.rb +41 -0
  52. data/lib/devise_token_auth/version.rb +5 -0
  53. data/lib/generators/devise_token_auth/USAGE +31 -0
  54. data/lib/generators/devise_token_auth/install_generator.rb +91 -0
  55. data/lib/generators/devise_token_auth/install_generator_helpers.rb +98 -0
  56. data/lib/generators/devise_token_auth/install_mongoid_generator.rb +46 -0
  57. data/lib/generators/devise_token_auth/install_views_generator.rb +18 -0
  58. data/lib/generators/devise_token_auth/templates/devise_token_auth.rb +50 -0
  59. data/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +56 -0
  60. data/lib/generators/devise_token_auth/templates/user.rb.erb +9 -0
  61. data/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb +63 -0
  62. data/lib/tasks/devise_token_auth_tasks.rake +6 -0
  63. data/test/controllers/custom/custom_confirmations_controller_test.rb +25 -0
  64. data/test/controllers/custom/custom_omniauth_callbacks_controller_test.rb +33 -0
  65. data/test/controllers/custom/custom_passwords_controller_test.rb +79 -0
  66. data/test/controllers/custom/custom_registrations_controller_test.rb +63 -0
  67. data/test/controllers/custom/custom_sessions_controller_test.rb +39 -0
  68. data/test/controllers/custom/custom_token_validations_controller_test.rb +42 -0
  69. data/test/controllers/demo_group_controller_test.rb +151 -0
  70. data/test/controllers/demo_mang_controller_test.rb +284 -0
  71. data/test/controllers/demo_user_controller_test.rb +629 -0
  72. data/test/controllers/devise_token_auth/confirmations_controller_test.rb +127 -0
  73. data/test/controllers/devise_token_auth/omniauth_callbacks_controller_test.rb +376 -0
  74. data/test/controllers/devise_token_auth/passwords_controller_test.rb +639 -0
  75. data/test/controllers/devise_token_auth/registrations_controller_test.rb +880 -0
  76. data/test/controllers/devise_token_auth/sessions_controller_test.rb +541 -0
  77. data/test/controllers/devise_token_auth/token_validations_controller_test.rb +102 -0
  78. data/test/controllers/devise_token_auth/unlocks_controller_test.rb +196 -0
  79. data/test/controllers/overrides/confirmations_controller_test.rb +47 -0
  80. data/test/controllers/overrides/omniauth_callbacks_controller_test.rb +53 -0
  81. data/test/controllers/overrides/passwords_controller_test.rb +64 -0
  82. data/test/controllers/overrides/registrations_controller_test.rb +46 -0
  83. data/test/controllers/overrides/sessions_controller_test.rb +35 -0
  84. data/test/controllers/overrides/token_validations_controller_test.rb +43 -0
  85. data/test/dummy/README.rdoc +28 -0
  86. data/test/dummy/app/active_record/lockable_user.rb +7 -0
  87. data/test/dummy/app/active_record/mang.rb +5 -0
  88. data/test/dummy/app/active_record/only_email_user.rb +7 -0
  89. data/test/dummy/app/active_record/scoped_user.rb +9 -0
  90. data/test/dummy/app/active_record/unconfirmable_user.rb +9 -0
  91. data/test/dummy/app/active_record/unregisterable_user.rb +9 -0
  92. data/test/dummy/app/active_record/user.rb +6 -0
  93. data/test/dummy/app/controllers/application_controller.rb +18 -0
  94. data/test/dummy/app/controllers/auth_origin_controller.rb +7 -0
  95. data/test/dummy/app/controllers/custom/confirmations_controller.rb +13 -0
  96. data/test/dummy/app/controllers/custom/omniauth_callbacks_controller.rb +13 -0
  97. data/test/dummy/app/controllers/custom/passwords_controller.rb +39 -0
  98. data/test/dummy/app/controllers/custom/registrations_controller.rb +39 -0
  99. data/test/dummy/app/controllers/custom/sessions_controller.rb +29 -0
  100. data/test/dummy/app/controllers/custom/token_validations_controller.rb +19 -0
  101. data/test/dummy/app/controllers/demo_group_controller.rb +15 -0
  102. data/test/dummy/app/controllers/demo_mang_controller.rb +14 -0
  103. data/test/dummy/app/controllers/demo_user_controller.rb +27 -0
  104. data/test/dummy/app/controllers/overrides/confirmations_controller.rb +28 -0
  105. data/test/dummy/app/controllers/overrides/omniauth_callbacks_controller.rb +16 -0
  106. data/test/dummy/app/controllers/overrides/passwords_controller.rb +35 -0
  107. data/test/dummy/app/controllers/overrides/registrations_controller.rb +29 -0
  108. data/test/dummy/app/controllers/overrides/sessions_controller.rb +36 -0
  109. data/test/dummy/app/controllers/overrides/token_validations_controller.rb +23 -0
  110. data/test/dummy/app/helpers/application_helper.rb +1058 -0
  111. data/test/dummy/app/models/concerns/favorite_color.rb +19 -0
  112. data/test/dummy/app/mongoid/lockable_user.rb +38 -0
  113. data/test/dummy/app/mongoid/mang.rb +53 -0
  114. data/test/dummy/app/mongoid/only_email_user.rb +33 -0
  115. data/test/dummy/app/mongoid/scoped_user.rb +57 -0
  116. data/test/dummy/app/mongoid/unconfirmable_user.rb +51 -0
  117. data/test/dummy/app/mongoid/unregisterable_user.rb +54 -0
  118. data/test/dummy/app/mongoid/user.rb +56 -0
  119. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  120. data/test/dummy/config.ru +18 -0
  121. data/test/dummy/config/application.rb +48 -0
  122. data/test/dummy/config/application.yml.bk +0 -0
  123. data/test/dummy/config/boot.rb +11 -0
  124. data/test/dummy/config/environment.rb +7 -0
  125. data/test/dummy/config/environments/development.rb +46 -0
  126. data/test/dummy/config/environments/production.rb +84 -0
  127. data/test/dummy/config/environments/test.rb +50 -0
  128. data/test/dummy/config/initializers/assets.rb +10 -0
  129. data/test/dummy/config/initializers/backtrace_silencers.rb +9 -0
  130. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  131. data/test/dummy/config/initializers/devise.rb +17 -0
  132. data/test/dummy/config/initializers/devise_token_auth.rb +24 -0
  133. data/test/dummy/config/initializers/figaro.rb +3 -0
  134. data/test/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  135. data/test/dummy/config/initializers/inflections.rb +18 -0
  136. data/test/dummy/config/initializers/mime_types.rb +6 -0
  137. data/test/dummy/config/initializers/omniauth.rb +10 -0
  138. data/test/dummy/config/initializers/session_store.rb +5 -0
  139. data/test/dummy/config/initializers/wrap_parameters.rb +16 -0
  140. data/test/dummy/config/routes.rb +55 -0
  141. data/test/dummy/config/spring.rb +3 -0
  142. data/test/dummy/db/migrate/20140715061447_devise_token_auth_create_users.rb +65 -0
  143. data/test/dummy/db/migrate/20140715061805_devise_token_auth_create_mangs.rb +64 -0
  144. data/test/dummy/db/migrate/20140829044006_add_operating_thetan_to_user.rb +8 -0
  145. data/test/dummy/db/migrate/20140916224624_add_favorite_color_to_mangs.rb +7 -0
  146. data/test/dummy/db/migrate/20141222035835_devise_token_auth_create_only_email_users.rb +62 -0
  147. data/test/dummy/db/migrate/20141222053502_devise_token_auth_create_unregisterable_users.rb +63 -0
  148. data/test/dummy/db/migrate/20150708104536_devise_token_auth_create_unconfirmable_users.rb +63 -0
  149. data/test/dummy/db/migrate/20160103235141_devise_token_auth_create_scoped_users.rb +63 -0
  150. data/test/dummy/db/migrate/20160629184441_devise_token_auth_create_lockable_users.rb +63 -0
  151. data/test/dummy/db/schema.rb +200 -0
  152. data/test/dummy/lib/migration_database_helper.rb +43 -0
  153. data/test/dummy/tmp/generators/app/models/user.rb +9 -0
  154. data/test/dummy/tmp/generators/config/initializers/devise_token_auth.rb +50 -0
  155. data/test/dummy/tmp/generators/db/migrate/20181030122248_devise_token_auth_create_users.rb +56 -0
  156. data/test/factories/users.rb +40 -0
  157. data/test/lib/devise_token_auth/blacklist_test.rb +11 -0
  158. data/test/lib/devise_token_auth/url_test.rb +26 -0
  159. data/test/lib/generators/devise_token_auth/install_generator_test.rb +217 -0
  160. data/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb +222 -0
  161. data/test/lib/generators/devise_token_auth/install_views_generator_test.rb +25 -0
  162. data/test/models/concerns/mongoid_support_test.rb +31 -0
  163. data/test/models/only_email_user_test.rb +37 -0
  164. data/test/models/user_test.rb +140 -0
  165. data/test/support/controllers/routes.rb +43 -0
  166. data/test/test_helper.rb +103 -0
  167. metadata +443 -0
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeviseTokenAuth
4
+ class ConfirmationsController < DeviseTokenAuth::ApplicationController
5
+ def show
6
+ @resource = resource_class.confirm_by_token(params[:confirmation_token])
7
+
8
+ if @resource.persisted?
9
+ expiry = nil
10
+ if defined?(@resource.sign_in_count) && @resource.sign_in_count > 0
11
+ expiry = (Time.zone.now + 1.second).to_i
12
+ end
13
+
14
+ client_id, token = @resource.create_token expiry: expiry
15
+
16
+ sign_in(@resource)
17
+ @resource.save!
18
+
19
+ yield @resource if block_given?
20
+
21
+ redirect_header_options = { account_confirmation_success: true }
22
+ redirect_headers = build_redirect_headers(token,
23
+ client_id,
24
+ redirect_header_options)
25
+
26
+ # give redirect value from params priority
27
+ @redirect_url = params[:redirect_url]
28
+
29
+ # fall back to default value if provided
30
+ @redirect_url ||= DeviseTokenAuth.default_confirm_success_url
31
+
32
+
33
+ redirect_to(@resource.build_auth_url(@redirect_url, redirect_headers))
34
+ else
35
+ raise ActionController::RoutingError, 'Not Found'
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,239 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeviseTokenAuth
4
+ class OmniauthCallbacksController < DeviseTokenAuth::ApplicationController
5
+ attr_reader :auth_params
6
+ skip_before_action :set_user_by_token, raise: false
7
+ skip_after_action :update_auth_header
8
+
9
+ # intermediary route for successful omniauth authentication. omniauth does
10
+ # not support multiple models, so we must resort to this terrible hack.
11
+ def redirect_callbacks
12
+
13
+ # derive target redirect route from 'resource_class' param, which was set
14
+ # before authentication.
15
+ devise_mapping = [request.env['omniauth.params']['namespace_name'],
16
+ request.env['omniauth.params']['resource_class'].underscore.gsub('/', '_')].compact.join('_')
17
+ path = "#{Devise.mappings[devise_mapping.to_sym].fullpath}/#{params[:provider]}/callback"
18
+ klass = request.scheme == 'https' ? URI::HTTPS : URI::HTTP
19
+ redirect_route = klass.build(host: request.host, port: request.port, path: path).to_s
20
+
21
+ # preserve omniauth info for success route. ignore 'extra' in twitter
22
+ # auth response to avoid CookieOverflow.
23
+ session['dta.omniauth.auth'] = request.env['omniauth.auth'].except('extra')
24
+ session['dta.omniauth.params'] = request.env['omniauth.params']
25
+
26
+ redirect_to redirect_route
27
+ end
28
+
29
+ def omniauth_success
30
+ get_resource_from_auth_hash
31
+ set_token_on_resource
32
+ create_auth_params
33
+
34
+ if confirmable_enabled?
35
+ # don't send confirmation email!!!
36
+ @resource.skip_confirmation!
37
+ end
38
+
39
+ sign_in(:user, @resource, store: false, bypass: false)
40
+
41
+ @resource.save!
42
+
43
+ yield @resource if block_given?
44
+
45
+ render_data_or_redirect('deliverCredentials', @auth_params.as_json, @resource.as_json)
46
+ end
47
+
48
+ def omniauth_failure
49
+ @error = params[:message]
50
+ render_data_or_redirect('authFailure', error: @error)
51
+ end
52
+
53
+ protected
54
+
55
+ # this will be determined differently depending on the action that calls
56
+ # it. redirect_callbacks is called upon returning from successful omniauth
57
+ # authentication, and the target params live in an omniauth-specific
58
+ # request.env variable. this variable is then persisted thru the redirect
59
+ # using our own dta.omniauth.params session var. the omniauth_success
60
+ # method will access that session var and then destroy it immediately
61
+ # after use. In the failure case, finally, the omniauth params
62
+ # are added as query params in our monkey patch to OmniAuth in engine.rb
63
+ def omniauth_params
64
+ unless defined?(@_omniauth_params)
65
+ if request.env['omniauth.params'] && request.env['omniauth.params'].any?
66
+ @_omniauth_params = request.env['omniauth.params']
67
+ elsif session['dta.omniauth.params'] && session['dta.omniauth.params'].any?
68
+ @_omniauth_params ||= session.delete('dta.omniauth.params')
69
+ @_omniauth_params
70
+ elsif params['omniauth_window_type']
71
+ @_omniauth_params = params.slice('omniauth_window_type', 'auth_origin_url', 'resource_class', 'origin')
72
+ else
73
+ @_omniauth_params = {}
74
+ end
75
+ end
76
+ @_omniauth_params
77
+
78
+ end
79
+
80
+ # break out provider attribute assignment for easy method extension
81
+ def assign_provider_attrs(user, auth_hash)
82
+ attrs = auth_hash['info'].slice(*user.attribute_names)
83
+ user.assign_attributes(attrs)
84
+ end
85
+
86
+ # derive allowed params from the standard devise parameter sanitizer
87
+ def whitelisted_params
88
+ whitelist = params_for_resource(:sign_up)
89
+
90
+ whitelist.inject({}) do |coll, key|
91
+ param = omniauth_params[key.to_s]
92
+ coll[key] = param if param
93
+ coll
94
+ end
95
+ end
96
+
97
+ def resource_class(mapping = nil)
98
+ if omniauth_params['resource_class']
99
+ omniauth_params['resource_class'].constantize
100
+ elsif params['resource_class']
101
+ params['resource_class'].constantize
102
+ else
103
+ raise 'No resource_class found'
104
+ end
105
+ end
106
+
107
+ def resource_name
108
+ resource_class
109
+ end
110
+
111
+ def omniauth_window_type
112
+ omniauth_params['omniauth_window_type']
113
+ end
114
+
115
+ def auth_origin_url
116
+ omniauth_params['auth_origin_url'] || omniauth_params['origin']
117
+ end
118
+
119
+ # in the success case, omniauth_window_type is in the omniauth_params.
120
+ # in the failure case, it is in a query param. See monkey patch above
121
+ def omniauth_window_type
122
+ omniauth_params.nil? ? params['omniauth_window_type'] : omniauth_params['omniauth_window_type']
123
+ end
124
+
125
+ # this sesison value is set by the redirect_callbacks method. its purpose
126
+ # is to persist the omniauth auth hash value thru a redirect. the value
127
+ # must be destroyed immediatly after it is accessed by omniauth_success
128
+ def auth_hash
129
+ @_auth_hash ||= session.delete('dta.omniauth.auth')
130
+ @_auth_hash
131
+ end
132
+
133
+ # ensure that this controller responds to :devise_controller? conditionals.
134
+ # this is used primarily for access to the parameter sanitizers.
135
+ def assert_is_devise_resource!
136
+ true
137
+ end
138
+
139
+ # necessary for access to devise_parameter_sanitizers
140
+ def devise_mapping
141
+ if omniauth_params
142
+ Devise.mappings[[omniauth_params['namespace_name'],
143
+ omniauth_params['resource_class'].underscore].compact.join('_').to_sym]
144
+ else
145
+ request.env['devise.mapping']
146
+ end
147
+ end
148
+
149
+ def set_random_password
150
+ # set crazy password for new oauth users. this is only used to prevent
151
+ # access via email sign-in.
152
+ p = SecureRandom.urlsafe_base64(nil, false)
153
+ @resource.password = p
154
+ @resource.password_confirmation = p
155
+ end
156
+
157
+ def create_auth_params
158
+ @auth_params = {
159
+ auth_token: @token,
160
+ client_id: @client_id,
161
+ uid: @resource.uid,
162
+ expiry: @expiry,
163
+ config: @config
164
+ }
165
+ @auth_params.merge!(oauth_registration: true) if @oauth_registration
166
+ @auth_params
167
+ end
168
+
169
+ def set_token_on_resource
170
+ @config = omniauth_params['config_name']
171
+ @client_id, @token, @expiry = @resource.create_token
172
+ end
173
+
174
+ def render_data(message, data)
175
+ @data = data.merge(message: message)
176
+ render layout: nil, template: 'devise_token_auth/omniauth_external_window'
177
+ end
178
+
179
+ def render_data_or_redirect(message, data, user_data = {})
180
+
181
+ # We handle inAppBrowser and newWindow the same, but it is nice
182
+ # to support values in case people need custom implementations for each case
183
+ # (For example, nbrustein does not allow new users to be created if logging in with
184
+ # an inAppBrowser)
185
+ #
186
+ # See app/views/devise_token_auth/omniauth_external_window.html.erb to understand
187
+ # why we can handle these both the same. The view is setup to handle both cases
188
+ # at the same time.
189
+ if ['inAppBrowser', 'newWindow'].include?(omniauth_window_type)
190
+ render_data(message, user_data.merge(data))
191
+
192
+ elsif auth_origin_url # default to same-window implementation, which forwards back to auth_origin_url
193
+
194
+ # build and redirect to destination url
195
+ redirect_to DeviseTokenAuth::Url.generate(auth_origin_url, data.merge(blank: true))
196
+ else
197
+
198
+ # there SHOULD always be an auth_origin_url, but if someone does something silly
199
+ # like coming straight to this url or refreshing the page at the wrong time, there may not be one.
200
+ # In that case, just render in plain text the error message if there is one or otherwise
201
+ # a generic message.
202
+ fallback_render data[:error] || 'An error occurred'
203
+ end
204
+ end
205
+
206
+ def fallback_render(text)
207
+ render inline: %Q(
208
+
209
+ <html>
210
+ <head></head>
211
+ <body>
212
+ #{text}
213
+ </body>
214
+ </html>)
215
+ end
216
+
217
+ def get_resource_from_auth_hash
218
+ # find or create user by provider and provider uid
219
+ @resource = resource_class.where(
220
+ uid: auth_hash['uid'],
221
+ provider: auth_hash['provider']
222
+ ).first_or_initialize
223
+
224
+ if @resource.new_record?
225
+ @oauth_registration = true
226
+ set_random_password
227
+ end
228
+
229
+ # sync user info with provider, update/generate auth token
230
+ assign_provider_attrs(@resource, auth_hash)
231
+
232
+ # assign any additional (whitelisted) attributes
233
+ extra_params = whitelisted_params
234
+ @resource.assign_attributes(extra_params) if extra_params
235
+
236
+ @resource
237
+ end
238
+ end
239
+ end
@@ -0,0 +1,185 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeviseTokenAuth
4
+ class PasswordsController < DeviseTokenAuth::ApplicationController
5
+ before_action :set_user_by_token, only: [:update]
6
+ skip_after_action :update_auth_header, only: [:create, :edit]
7
+
8
+ # this action is responsible for generating password reset tokens and
9
+ # sending emails
10
+ def create
11
+ return render_create_error_missing_email unless resource_params[:email]
12
+
13
+ # give redirect value from params priority
14
+ @redirect_url = params.fetch(
15
+ :redirect_url,
16
+ DeviseTokenAuth.default_password_reset_url
17
+ )
18
+
19
+ return render_create_error_missing_redirect_url unless @redirect_url
20
+ return render_create_error_not_allowed_redirect_url if blacklisted_redirect_url?
21
+
22
+ @email = get_case_insensitive_field_from_resource_params(:email)
23
+ @resource = find_resource(:uid, @email)
24
+
25
+ if @resource
26
+ yield @resource if block_given?
27
+ @resource.send_reset_password_instructions(
28
+ email: @email,
29
+ provider: 'email',
30
+ redirect_url: @redirect_url,
31
+ client_config: params[:config_name]
32
+ )
33
+
34
+ if @resource.errors.empty?
35
+ return render_create_success
36
+ else
37
+ render_create_error @resource.errors
38
+ end
39
+ else
40
+ render_not_found_error
41
+ end
42
+ end
43
+
44
+ # this is where users arrive after visiting the password reset confirmation link
45
+ def edit
46
+ # if a user is not found, return nil
47
+ @resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
48
+
49
+ if @resource && @resource.reset_password_period_valid?
50
+ client_id, token = @resource.create_token
51
+
52
+ # ensure that user is confirmed
53
+ @resource.skip_confirmation! if confirmable_enabled? && !@resource.confirmed_at
54
+
55
+ # allow user to change password once without current_password
56
+ @resource.allow_password_change = true if recoverable_enabled?
57
+
58
+ @resource.save!
59
+
60
+ yield @resource if block_given?
61
+
62
+ redirect_header_options = { reset_password: true }
63
+ redirect_headers = build_redirect_headers(token,
64
+ client_id,
65
+ redirect_header_options)
66
+ redirect_to(@resource.build_auth_url(params[:redirect_url],
67
+ redirect_headers))
68
+ else
69
+ render_edit_error
70
+ end
71
+ end
72
+
73
+ def update
74
+ # make sure user is authorized
75
+ return render_update_error_unauthorized unless @resource
76
+
77
+ # make sure account doesn't use oauth2 provider
78
+ unless @resource.provider == 'email'
79
+ return render_update_error_password_not_required
80
+ end
81
+
82
+ # ensure that password params were sent
83
+ unless password_resource_params[:password] && password_resource_params[:password_confirmation]
84
+ return render_update_error_missing_password
85
+ end
86
+
87
+ if @resource.send(resource_update_method, password_resource_params)
88
+ @resource.allow_password_change = false if recoverable_enabled?
89
+ @resource.save!
90
+
91
+ yield @resource if block_given?
92
+ return render_update_success
93
+ else
94
+ return render_update_error
95
+ end
96
+ end
97
+
98
+ protected
99
+
100
+ def resource_update_method
101
+ allow_password_change = recoverable_enabled? && @resource.allow_password_change == true
102
+ if DeviseTokenAuth.check_current_password_before_update == false || allow_password_change
103
+ 'update_attributes'
104
+ else
105
+ 'update_with_password'
106
+ end
107
+ end
108
+
109
+ def render_create_error_missing_email
110
+ render_error(401, I18n.t('devise_token_auth.passwords.missing_email'))
111
+ end
112
+
113
+ def render_create_error_missing_redirect_url
114
+ render_error(401, I18n.t('devise_token_auth.passwords.missing_redirect_url'))
115
+ end
116
+
117
+ def render_create_error_not_allowed_redirect_url
118
+ response = {
119
+ status: 'error',
120
+ data: resource_data
121
+ }
122
+ message = I18n.t('devise_token_auth.passwords.not_allowed_redirect_url', redirect_url: @redirect_url)
123
+ render_error(422, message, response)
124
+ end
125
+
126
+ def render_create_success
127
+ render json: {
128
+ success: true,
129
+ message: I18n.t('devise_token_auth.passwords.sended', email: @email)
130
+ }
131
+ end
132
+
133
+ def render_create_error(errors)
134
+ render json: {
135
+ success: false,
136
+ errors: errors
137
+ }, status: 400
138
+ end
139
+
140
+ def render_edit_error
141
+ raise ActionController::RoutingError, 'Not Found'
142
+ end
143
+
144
+ def render_update_error_unauthorized
145
+ render_error(401, 'Unauthorized')
146
+ end
147
+
148
+ def render_update_error_password_not_required
149
+ render_error(422, I18n.t('devise_token_auth.passwords.password_not_required', provider: @resource.provider.humanize))
150
+ end
151
+
152
+ def render_update_error_missing_password
153
+ render_error(422, I18n.t('devise_token_auth.passwords.missing_passwords'))
154
+ end
155
+
156
+ def render_update_success
157
+ render json: {
158
+ success: true,
159
+ data: resource_data,
160
+ message: I18n.t('devise_token_auth.passwords.successfully_updated')
161
+ }
162
+ end
163
+
164
+ def render_update_error
165
+ render json: {
166
+ success: false,
167
+ errors: resource_errors
168
+ }, status: 422
169
+ end
170
+
171
+ private
172
+
173
+ def resource_params
174
+ params.permit(:email, :reset_password_token)
175
+ end
176
+
177
+ def password_resource_params
178
+ params.permit(*params_for_resource(:account_update))
179
+ end
180
+
181
+ def render_not_found_error
182
+ render_error(404, I18n.t('devise_token_auth.passwords.user_not_found', email: @email))
183
+ end
184
+ end
185
+ end