class DeviseTokenAuth::PasswordsController

def create

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

def edit

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])
    else
      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))
    end
  else
    render_edit_error
  end
end

def password_resource_params

def password_resource_params
  params.permit(*params_for_resource(:account_update))
end

def render_create_error(errors)

def render_create_error(errors)
  render json: {
    success: false,
    errors: errors
  }, status: 400
end

def render_create_error_missing_email

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

def render_create_error_missing_redirect_url
  render_error(401, I18n.t('devise_token_auth.passwords.missing_redirect_url'))
end

def render_create_success

def render_create_success
  render json: {
    success: true,
    message: success_message('passwords', @email)
  }
end

def render_edit_error

def render_edit_error
  raise ActionController::RoutingError, 'Not Found'
end

def render_error_not_allowed_redirect_url

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_not_found_error

def render_not_found_error
  if Devise.paranoid
    render_error(404, I18n.t('devise_token_auth.passwords.sended_paranoid'))
  else
    render_error(404, I18n.t('devise_token_auth.passwords.user_not_found', email: @email))
  end
end

def render_update_error

def render_update_error
  render json: {
    success: false,
    errors: resource_errors
  }, status: 422
end

def render_update_error_missing_password

def render_update_error_missing_password
  render_error(422, I18n.t('devise_token_auth.passwords.missing_passwords'))
end

def render_update_error_password_not_required

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_unauthorized

def render_update_error_unauthorized
  render_error(401, 'Unauthorized')
end

def render_update_success

def render_update_success
  render json: {
    success: true,
    data: resource_data,
    message: I18n.t('devise_token_auth.passwords.successfully_updated')
  }
end

def require_client_password_reset_token?

def require_client_password_reset_token?
  DeviseTokenAuth.require_client_password_reset_token
end

def reset_password_token_as_raw?(recoverable)

def reset_password_token_as_raw?(recoverable)
  recoverable && recoverable.reset_password_token.present? && !require_client_password_reset_token?
end

def resource_params

def resource_params
  params.permit(:email, :reset_password_token)
end

def resource_update_method

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 update

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

def validate_redirect_url_param

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