• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mgmodell / devise_token_auth_multi_email / #663

17 Mar 2026 01:12AM UTC coverage: 12.22% (-78.4%) from 90.649%
#663

push

mgmodell
switching back to mult-email

202 of 1653 relevant lines covered (12.22%)

0.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/app/controllers/devise_token_auth/passwords_controller.rb
1
# frozen_string_literal: true
2

3
module DeviseTokenAuth
×
4
  class PasswordsController < DeviseTokenAuth::ApplicationController
×
5
    before_action :validate_redirect_url_param, only: [:create, :edit]
×
6
    skip_after_action :update_auth_header, only: [:create, :edit]
×
7

8
    # this action is responsible for generating password reset tokens and sending emails
9
    def create
×
10
      return render_create_error_missing_email unless resource_params[:email]
×
11

12
      @email = get_case_insensitive_field_from_resource_params(:email)
×
13
      @resource = find_resource(:uid, @email)
×
14

15
      if @resource
×
16
        yield @resource if block_given?
×
17
        @resource.send_reset_password_instructions(
×
18
          email: @email,
×
19
          provider: 'email',
×
20
          redirect_url: @redirect_url,
×
21
          client_config: params[:config_name]
×
22
        )
×
23

24
        if @resource.errors.empty?
×
25
          return render_create_success
×
26
        else
×
27
          render_create_error @resource.errors
×
28
        end
×
29
      else
×
30
        render_not_found_error
×
31
      end
×
32
    end
×
33

34
    # this is where users arrive after visiting the password reset confirmation link
35
    def edit
×
36
      # if a user is not found, return nil
37
      @resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
×
38

39
      if @resource && @resource.reset_password_period_valid?
×
40
        token = @resource.create_token unless require_client_password_reset_token?
×
41

42
        # ensure that user is confirmed
43
        @resource.skip_confirmation! if confirmable_enabled? && !@resource.confirmed_at
×
44
        # allow user to change password once without current_password
45
        @resource.allow_password_change = true if recoverable_enabled?
×
46

47
        @resource.save!
×
48

49
        yield @resource if block_given?
×
50

51
        if require_client_password_reset_token?
×
52
          redirect_to DeviseTokenAuth::Url.generate(@redirect_url, reset_password_token: resource_params[:reset_password_token]),
×
53
          redirect_options
×
54
        else
×
55
          if DeviseTokenAuth.cookie_enabled
×
56
            set_token_in_cookie(@resource, token)
×
57
          end
×
58

59
          redirect_header_options = { reset_password: true, reset_password_token: resource_params[:reset_password_token] }
×
60
          redirect_headers = build_redirect_headers(token.token,
×
61
                                                    token.client,
×
62
                                                    redirect_header_options)
×
63
          redirect_to(@resource.build_auth_url(@redirect_url,
×
64
                                               redirect_headers),
×
65
                                               redirect_options)
×
66
        end
×
67
      else
×
68
        render_edit_error
×
69
      end
×
70
    end
×
71

72
    def update
×
73
      # make sure user is authorized
74
      if require_client_password_reset_token? && resource_params[:reset_password_token]
×
75
        @resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
×
76
        return render_update_error_unauthorized unless @resource && @resource.reset_password_period_valid?
×
77

78
        @token = @resource.create_token
×
79
      else
×
80
        @resource = set_user_by_token
×
81
      end
×
82

83
      return render_update_error_unauthorized unless @resource
×
84

85
      # make sure account doesn't use oauth2 provider
86
      unless @resource.provider == 'email'
×
87
        return render_update_error_password_not_required
×
88
      end
×
89

90
      # ensure that password params were sent
91
      unless password_resource_params[:password] && password_resource_params[:password_confirmation]
×
92
        return render_update_error_missing_password
×
93
      end
×
94

95
      if @resource.send(resource_update_method, password_resource_params)
×
96
        @resource.allow_password_change = false if recoverable_enabled?
×
97
        @resource.save!
×
98

99
        yield @resource if block_given?
×
100
        return render_update_success
×
101
      else
×
102
        return render_update_error
×
103
      end
×
104
    end
×
105

106
    protected
×
107

108
    def resource_update_method
×
109
      allow_password_change = recoverable_enabled? && @resource.allow_password_change == true || require_client_password_reset_token?
×
110
      if DeviseTokenAuth.check_current_password_before_update == false || allow_password_change
×
111
        'update'
×
112
      else
×
113
        'update_with_password'
×
114
      end
×
115
    end
×
116

117
    def render_create_error_missing_email
×
118
      render_error(401, I18n.t('devise_token_auth.passwords.missing_email'))
×
119
    end
×
120

121
    def render_create_error_missing_redirect_url
×
122
      render_error(401, I18n.t('devise_token_auth.passwords.missing_redirect_url'))
×
123
    end
×
124

125
    def render_error_not_allowed_redirect_url
×
126
      response = {
×
127
        status: 'error',
×
128
        data:   resource_data
×
129
      }
×
130
      message = I18n.t('devise_token_auth.passwords.not_allowed_redirect_url', redirect_url: @redirect_url)
×
131
      render_error(422, message, response)
×
132
    end
×
133

134
    def render_create_success
×
135
      render json: {
×
136
        success: true,
×
137
        message: success_message('passwords', @email)
×
138
      }
×
139
    end
×
140

141
    def render_create_error(errors)
×
142
      render json: {
×
143
        success: false,
×
144
        errors: errors
×
145
      }, status: 400
×
146
    end
×
147

148
    def render_edit_error
×
149
      raise ActionController::RoutingError, 'Not Found'
×
150
    end
×
151

152
    def render_update_error_unauthorized
×
153
      render_error(401, 'Unauthorized')
×
154
    end
×
155

156
    def render_update_error_password_not_required
×
157
      render_error(422, I18n.t('devise_token_auth.passwords.password_not_required', provider: @resource.provider.humanize))
×
158
    end
×
159

160
    def render_update_error_missing_password
×
161
      render_error(422, I18n.t('devise_token_auth.passwords.missing_passwords'))
×
162
    end
×
163

164
    def render_update_success
×
165
      render json: {
×
166
        success: true,
×
167
        data: resource_data,
×
168
        message: I18n.t('devise_token_auth.passwords.successfully_updated')
×
169
      }
×
170
    end
×
171

172
    def render_update_error
×
173
      render json: {
×
174
        success: false,
×
175
        errors: resource_errors
×
176
      }, status: 422
×
177
    end
×
178

179
    private
×
180

181
    def resource_params
×
182
      params.permit(:email, :reset_password_token)
×
183
    end
×
184

185
    def password_resource_params
×
186
      params.permit(*params_for_resource(:account_update))
×
187
    end
×
188

189
    def render_not_found_error
×
190
      if Devise.paranoid
×
191
        render_create_success
×
192
      else
×
193
        render_error(404, I18n.t('devise_token_auth.passwords.user_not_found', email: @email))
×
194
      end
×
195
    end
×
196

197
    def validate_redirect_url_param
×
198
      # give redirect value from params priority
199
      @redirect_url = params.fetch(
×
200
        :redirect_url,
×
201
        DeviseTokenAuth.default_password_reset_url
×
202
      )
×
203

204
      return render_create_error_missing_redirect_url unless @redirect_url
×
205
      return render_error_not_allowed_redirect_url if blacklisted_redirect_url?(@redirect_url)
×
206
    end
×
207

208
    def reset_password_token_as_raw?(recoverable)
×
209
      recoverable && recoverable.reset_password_token.present? && !require_client_password_reset_token?
×
210
    end
×
211

212
    def require_client_password_reset_token?
×
213
      DeviseTokenAuth.require_client_password_reset_token
×
214
    end
×
215
  end
×
216
end
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc