-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
passwords_controller.rb
216 lines (176 loc) · 6.7 KB
/
passwords_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# frozen_string_literal: true
module DeviseTokenAuth
class PasswordsController < DeviseTokenAuth::ApplicationController
before_action :validate_redirect_url_param, only: [:create, :edit]
skip_after_action :update_auth_header, only: [:create, :edit]
# this action is responsible for generating password reset tokens and sending emails
def create
return render_create_error_missing_email unless resource_params[:email]
@email = get_case_insensitive_field_from_resource_params(:email)
@resource = find_resource(:uid, @email)
if @resource
yield @resource if block_given?
@resource.send_reset_password_instructions(
email: @email,
provider: 'email',
redirect_url: @redirect_url,
client_config: params[:config_name]
)
if @resource.errors.empty?
return render_create_success
else
render_create_error @resource.errors
end
else
render_not_found_error
end
end
# this is where users arrive after visiting the password reset confirmation link
def edit
# if a user is not found, return nil
@resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
if @resource && @resource.reset_password_period_valid?
token = @resource.create_token unless require_client_password_reset_token?
# ensure that user is confirmed
@resource.skip_confirmation! if confirmable_enabled? && !@resource.confirmed_at
# allow user to change password once without current_password
@resource.allow_password_change = true if recoverable_enabled?
@resource.save!
yield @resource if block_given?
if require_client_password_reset_token?
redirect_to DeviseTokenAuth::Url.generate(@redirect_url, reset_password_token: resource_params[:reset_password_token]),
redirect_options
else
if DeviseTokenAuth.cookie_enabled
set_token_in_cookie(@resource, token)
end
redirect_header_options = { reset_password: true }
redirect_headers = build_redirect_headers(token.token,
token.client,
redirect_header_options)
redirect_to(@resource.build_auth_url(@redirect_url,
redirect_headers),
redirect_options)
end
else
render_edit_error
end
end
def update
# make sure user is authorized
if require_client_password_reset_token? && resource_params[:reset_password_token]
@resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
return render_update_error_unauthorized unless @resource
@token = @resource.create_token
else
@resource = set_user_by_token
end
return render_update_error_unauthorized unless @resource
# make sure account doesn't use oauth2 provider
unless @resource.provider == 'email'
return render_update_error_password_not_required
end
# ensure that password params were sent
unless password_resource_params[:password] && password_resource_params[:password_confirmation]
return render_update_error_missing_password
end
if @resource.send(resource_update_method, password_resource_params)
@resource.allow_password_change = false if recoverable_enabled?
@resource.save!
yield @resource if block_given?
return render_update_success
else
return render_update_error
end
end
protected
def resource_update_method
allow_password_change = recoverable_enabled? && @resource.allow_password_change == true || require_client_password_reset_token?
if DeviseTokenAuth.check_current_password_before_update == false || allow_password_change
'update'
else
'update_with_password'
end
end
def render_create_error_missing_email
render_error(401, I18n.t('devise_token_auth.passwords.missing_email'))
end
def render_create_error_missing_redirect_url
render_error(401, I18n.t('devise_token_auth.passwords.missing_redirect_url'))
end
def render_error_not_allowed_redirect_url
response = {
status: 'error',
data: resource_data
}
message = I18n.t('devise_token_auth.passwords.not_allowed_redirect_url', redirect_url: @redirect_url)
render_error(422, message, response)
end
def render_create_success
render json: {
success: true,
message: success_message('passwords', @email)
}
end
def render_create_error(errors)
render json: {
success: false,
errors: errors
}, status: 400
end
def render_edit_error
raise ActionController::RoutingError, 'Not Found'
end
def render_update_error_unauthorized
render_error(401, 'Unauthorized')
end
def render_update_error_password_not_required
render_error(422, I18n.t('devise_token_auth.passwords.password_not_required', provider: @resource.provider.humanize))
end
def render_update_error_missing_password
render_error(422, I18n.t('devise_token_auth.passwords.missing_passwords'))
end
def render_update_success
render json: {
success: true,
data: resource_data,
message: I18n.t('devise_token_auth.passwords.successfully_updated')
}
end
def render_update_error
render json: {
success: false,
errors: resource_errors
}, status: 422
end
private
def resource_params
params.permit(:email, :reset_password_token)
end
def password_resource_params
params.permit(*params_for_resource(:account_update))
end
def render_not_found_error
if Devise.paranoid
render_create_success
else
render_error(404, I18n.t('devise_token_auth.passwords.user_not_found', email: @email))
end
end
def validate_redirect_url_param
# give redirect value from params priority
@redirect_url = params.fetch(
:redirect_url,
DeviseTokenAuth.default_password_reset_url
)
return render_create_error_missing_redirect_url unless @redirect_url
return render_error_not_allowed_redirect_url if blacklisted_redirect_url?(@redirect_url)
end
def reset_password_token_as_raw?(recoverable)
recoverable && recoverable.reset_password_token.present? && !require_client_password_reset_token?
end
def require_client_password_reset_token?
DeviseTokenAuth.require_client_password_reset_token
end
end
end