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

mgmodell / devise_token_auth_multi_email / #664

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

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/sessions_controller.rb
1
# frozen_string_literal: true
2

3
# see http://www.emilsoman.com/blog/2013/05/18/building-a-tested/
4
module DeviseTokenAuth
×
5
  class SessionsController < DeviseTokenAuth::ApplicationController
×
6
    before_action :set_user_by_token, only: [:destroy]
×
7
    after_action :reset_session, only: [:destroy]
×
8

9
    def new
×
10
      render_new_error
×
11
    end
×
12

13
    def create
×
14
      if field = (resource_params.keys.map(&:to_sym) & resource_class.authentication_keys).first
×
15
        q_value = get_case_insensitive_field_from_resource_params(field)
×
16

17
        @resource = find_resource(field, q_value)
×
18
      end
×
19

20
      if @resource && valid_params?(field, q_value) && (!@resource.respond_to?(:active_for_authentication?) || @resource.active_for_authentication?)
×
21
        valid_password = @resource.valid_password?(resource_params[:password])
×
22
        if (@resource.respond_to?(:valid_for_authentication?) && !@resource.valid_for_authentication? { valid_password }) || !valid_password
×
23
          return render_create_error_bad_credentials
×
24
        end
×
25

26
        create_and_assign_token
×
27

28
        sign_in(@resource, scope: :user, store: false, bypass: false)
×
29

30
        yield @resource if block_given?
×
31

32
        render_create_success
×
33
      elsif @resource && !Devise.paranoid && !(!@resource.respond_to?(:active_for_authentication?) || @resource.active_for_authentication?)
×
34
        if @resource.respond_to?(:locked_at) && @resource.locked_at
×
35
          render_create_error_account_locked
×
36
        else
×
37
          render_create_error_not_confirmed
×
38
        end
×
39
      else
×
40
        hash_password_in_paranoid_mode
×
41
        render_create_error_bad_credentials
×
42
      end
×
43
    end
×
44

45
    def destroy
×
46
      # remove auth instance variables so that after_action does not run
47
      user = remove_instance_variable(:@resource) if @resource
×
48
      client = @token.client
×
49
      @token.clear!
×
50

51
      if user && client && user.tokens[client]
×
52
        user.tokens.delete(client)
×
53
        user.save!
×
54

55
        if DeviseTokenAuth.cookie_enabled
×
56
          # If a cookie is set with a domain specified then it must be deleted with that domain specified
57
          # See https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html
58
          cookies.delete(DeviseTokenAuth.cookie_name, domain: DeviseTokenAuth.cookie_attributes[:domain])
×
59
        end
×
60

61
        yield user if block_given?
×
62

63
        render_destroy_success
×
64
      else
×
65
        render_destroy_error
×
66
      end
×
67
    end
×
68

69
    protected
×
70

71
    def valid_params?(key, val)
×
72
      resource_params[:password] && key && val
×
73
    end
×
74

75
    def get_auth_params
×
76
      auth_key = nil
×
77
      auth_val = nil
×
78
      # iterate thru allowed auth keys, use first found
79
      resource_class.authentication_keys.each do |k|
×
80
        if resource_params[k]
×
81
          auth_val = resource_params[k]
×
82
          auth_key = k
×
83
          break
×
84
        end
×
85
      end
×
86

87
      # honor devise configuration for case_insensitive_keys
88
      if resource_class.case_insensitive_keys.include?(auth_key)
×
89
        auth_val.downcase!
×
90
      end
×
91

92
      { key: auth_key, val: auth_val }
×
93
    end
×
94

95
    def render_new_error
×
96
      render_error(405, I18n.t('devise_token_auth.sessions.not_supported'))
×
97
    end
×
98

99
    def render_create_success
×
100
      render json: {
×
101
        data: resource_data(resource_json: @resource.token_validation_response)
×
102
      }
×
103
    end
×
104

105
    def render_create_error_not_confirmed
×
106
      render_error(401, I18n.t('devise_token_auth.sessions.not_confirmed', email: @resource.email))
×
107
    end
×
108

109
    def render_create_error_account_locked
×
110
      render_error(401, I18n.t('devise.mailer.unlock_instructions.account_lock_msg'))
×
111
    end
×
112

113
    def render_create_error_bad_credentials
×
114
      render_error(401, I18n.t('devise_token_auth.sessions.bad_credentials'))
×
115
    end
×
116

117
    def render_destroy_success
×
118
      render json: {
×
119
        success:true
×
120
      }, status: 200
×
121
    end
×
122

123
    def render_destroy_error
×
124
      render_error(404, I18n.t('devise_token_auth.sessions.user_not_found'))
×
125
    end
×
126

127
    private
×
128

129
    def resource_params
×
130
      params.permit(*params_for_resource(:sign_in))
×
131
    end
×
132

133
    def create_and_assign_token
×
134
      if @resource.respond_to?(:with_lock) && !@resource.changed?
×
135
        @resource.with_lock do
×
136
          @token = @resource.create_token
×
137
          @resource.save!
×
138
        end
×
139
      else
×
140
        @token = @resource.create_token
×
141
        @resource.save!
×
142
      end
×
143
    end
×
144

145
    def hash_password_in_paranoid_mode
×
146
      # In order to avoid timing attacks in paranoid mode, we want the password hash to be
147
      # calculated even if no resource has been found. Devise's DatabaseAuthenticatable warden
148
      # strategy handles this case similarly:
149
      # https://github.com/heartcombo/devise/blob/main/lib/devise/strategies/database_authenticatable.rb
150
      resource_class.new.password = resource_params[:password] if Devise.paranoid
×
151
    end
×
152
  end
×
153
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