• 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

44.12
/lib/devise_token_auth/token_factory.rb
1
require 'bcrypt'
1✔
2

3
module DeviseTokenAuth
1✔
4
  # A token management factory which allow generate token objects and check them.
5
  module TokenFactory
1✔
6
    # For BCrypt::Password class see:
7
    # https://github.com/codahale/bcrypt-ruby/blob/master/lib/bcrypt/password.rb
8

9
    # Creates a token instance. Takes an optional client, lifespan and cost options.
10
    # Example:
11
    #   DeviseTokenAuth::TokenFactory.create
12
    #   => #<struct DeviseTokenAuth::TokenFactory::Token client="tElcgkdZ7f9XEa0unZhrYQ", token="rAMcWOs0-mGHFMnIgJD2cA", token_hash="$2a$10$wrsdlHVRGlYW11wfImxU..jr0Ux3bHo/qbXcSfgp8zmvVUNHosita", expiry=1518982690>
13
    #
14
    #   DeviseTokenAuth::TokenFactory.create(lifespan: 10, cost: 4)
15
    #   => #<struct DeviseTokenAuth::TokenFactory::Token client="5qleT7_t9JPVcX9xmxkVYA", token="RBXX43u4xXNSO-fr2N_4pA", token_hash="$2a$04$9gpCaoFbu2dUKxU3qiTgluHX7jj9UzS.jq1QW0EkQmoaxARo1WxTy", expiry=1517773268>
16
    def self.create(client: nil, lifespan: nil, cost: nil)
1✔
17
      # obj_client  = client.nil? ? client() : client
18
      obj_client  = client || client()
×
19
      obj_token      = token
×
20
      obj_token_hash = token_hash(obj_token, cost)
×
21
      obj_expiry     = expiry(lifespan)
×
22

23
      Token.new(obj_client, obj_token, obj_token_hash, obj_expiry)
×
24
    end
25

26
    # Generates a random URL-safe client.
27
    # Example:
28
    #   DeviseTokenAuth::TokenFactory.client
29
    #   => "zNf0pNP5iGfuBItZJGCseQ"
30
    def self.client
1✔
31
      secure_string
×
32
    end
33

34
    # Generates a random URL-safe token.
35
    # Example:
36
    #   DeviseTokenAuth::TokenFactory.token
37
    #   => "6Bqs4K9x8ChLmZogvruF3A"
38
    def self.token
1✔
39
      secure_string
×
40
    end
41

42
    # Returns token hash for a token with given cost. If no cost value is specified,
43
    # the default value is used. The possible cost value is within range from 4 to 31.
44
    # It is recommended to not use a value more than 10.
45
    # Example:
46
    #   DeviseTokenAuth::TokenFactory.token_hash("_qxAxmc-biQLiYRHsmwd5Q")
47
    #   => "$2a$10$6/cTAtQ3CBLfpkeHW7dlt.PD2aVCbFRN5vDDJUUhGsZ6pzYFlh4Me"
48
    #
49
    #   DeviseTokenAuth::TokenFactory.token_hash("_qxAxmc-biQLiYRHsmwd5Q", 4)
50
    #   => "$2a$04$RkIrosbdRtuet2eUk3si8eS4ufeNpiPc/rSSsfpniRK8ogM5YFOWS"
51
    def self.token_hash(token, cost = nil)
1✔
52
      cost ||= DeviseTokenAuth.token_cost
×
53
      BCrypt::Password.create(token, cost: cost)
×
54
    end
55

56
    # Returns the value of time as an integer number of seconds. Takes one argument.
57
    # Example:
58
    #   DeviseTokenAuth::TokenFactory.expiry
59
    #   => 1518983359
60
    #   DeviseTokenAuth::TokenFactory.expiry(10)
61
    #   => 1517773781
62
    def self.expiry(lifespan = nil)
1✔
63
      lifespan ||= DeviseTokenAuth.token_lifespan
×
64
      (Time.zone.now + lifespan).to_i
×
65
    end
66

67
    # Generates a random URL-safe string.
68
    # Example:
69
    #   DeviseTokenAuth::TokenFactory.secure_string
70
    #   => "ADBoIaqXsEDnxIpOuumrTA"
71
    def self.secure_string
1✔
72
      # https://ruby-doc.org/stdlib-2.5.0/libdoc/securerandom/rdoc/Random/Formatter.html#method-i-urlsafe_base64
73
      SecureRandom.urlsafe_base64
×
74
    end
75

76
    # Returns true if token hash is a valid token hash.
77
    # Example:
78
    #   token_hash = "$2a$10$ArjX0tskRIa5Z/Tmapy59OCiAXLStfhrCiaDz.8fCb6hnX1gJ0p/2"
79
    #   DeviseTokenAuth::TokenFactory.valid_token_hash?(token_hash)
80
    #   => true
81
    def self.valid_token_hash?(token_hash)
1✔
82
      !!BCrypt::Password.valid_hash?(token_hash)
×
83
    end
84

85
    # Compares a potential token against the token hash. Returns true if the token is the original token, false otherwise.
86
    # Example:
87
    #   token = "4wZ9gcc900rMQD1McpcSNA"
88
    #   token_hash = "$2a$10$ArjX0tskRIa5Z/Tmapy59OCiAXLStfhrCiaDz.8fCb6hnX1gJ0p/2"
89
    #   DeviseTokenAuth::TokenFactory.token_hash_is_token?(token_hash, token)
90
    #   => true
91
    def self.token_hash_is_token?(token_hash, token)
1✔
92
      BCrypt::Password.new(token_hash).is_password?(token)
×
93
    rescue StandardError
94
      false
×
95
    end
96

97
    # Creates a token instance with instance variables equal nil.
98
    # Example:
99
    #   DeviseTokenAuth::TokenFactory.new
100
    #   => #<struct DeviseTokenAuth::TokenFactory::Token client=nil, token=nil, token_hash=nil, expiry=nil>
101
    def self.new
1✔
102
      Token.new
×
103
    end
104

105
    Token = Struct.new(:client, :token, :token_hash, :expiry) do
1✔
106
      # Sets all instance variables of the token to nil. It is faster than creating new empty token.
107
      # Example:
108
      #   token.clear!
109
      #   => true
110
      #   token
111
      #   => #<struct DeviseTokenAuth::TokenFactory::Token client=nil, token=nil, token_hash=nil, expiry=nil>
112
      def clear!
1✔
113
        size.times { |i| self[i] = nil }
×
114
        true
×
115
      end
116

117
      # Checks token attribute presence
118
      # Example:
119
      #   token.present?
120
      #   => true
121
      def present?
1✔
122
        token.present?
×
123
      end
124
    end
125
  end
126
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