authlogic 3.4.6 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE.md +13 -0
  3. data/.github/triage.md +87 -0
  4. data/.gitignore +4 -0
  5. data/.rubocop.yml +127 -0
  6. data/.rubocop_todo.yml +65 -0
  7. data/.travis.yml +18 -10
  8. data/CHANGELOG.md +156 -6
  9. data/CONTRIBUTING.md +71 -3
  10. data/Gemfile +2 -2
  11. data/README.md +386 -0
  12. data/Rakefile +13 -7
  13. data/UPGRADING.md +22 -0
  14. data/authlogic.gemspec +33 -22
  15. data/lib/authlogic.rb +60 -52
  16. data/lib/authlogic/acts_as_authentic/base.rb +40 -26
  17. data/lib/authlogic/acts_as_authentic/email.rb +96 -32
  18. data/lib/authlogic/acts_as_authentic/logged_in_status.rb +36 -12
  19. data/lib/authlogic/acts_as_authentic/login.rb +114 -49
  20. data/lib/authlogic/acts_as_authentic/magic_columns.rb +17 -6
  21. data/lib/authlogic/acts_as_authentic/password.rb +296 -139
  22. data/lib/authlogic/acts_as_authentic/perishable_token.rb +34 -20
  23. data/lib/authlogic/acts_as_authentic/persistence_token.rb +20 -24
  24. data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +67 -0
  25. data/lib/authlogic/acts_as_authentic/restful_authentication.rb +68 -23
  26. data/lib/authlogic/acts_as_authentic/session_maintenance.rb +128 -85
  27. data/lib/authlogic/acts_as_authentic/single_access_token.rb +41 -25
  28. data/lib/authlogic/acts_as_authentic/validations_scope.rb +8 -8
  29. data/lib/authlogic/authenticates_many/association.rb +22 -14
  30. data/lib/authlogic/authenticates_many/base.rb +35 -16
  31. data/lib/authlogic/config.rb +10 -10
  32. data/lib/authlogic/controller_adapters/abstract_adapter.rb +40 -12
  33. data/lib/authlogic/controller_adapters/rack_adapter.rb +15 -8
  34. data/lib/authlogic/controller_adapters/rails_adapter.rb +42 -22
  35. data/lib/authlogic/controller_adapters/sinatra_adapter.rb +3 -3
  36. data/lib/authlogic/crypto_providers.rb +91 -0
  37. data/lib/authlogic/crypto_providers/aes256.rb +42 -14
  38. data/lib/authlogic/crypto_providers/bcrypt.rb +35 -20
  39. data/lib/authlogic/crypto_providers/md5.rb +11 -9
  40. data/lib/authlogic/crypto_providers/scrypt.rb +26 -13
  41. data/lib/authlogic/crypto_providers/sha1.rb +14 -8
  42. data/lib/authlogic/crypto_providers/sha256.rb +16 -12
  43. data/lib/authlogic/crypto_providers/sha512.rb +8 -24
  44. data/lib/authlogic/crypto_providers/wordpress.rb +44 -15
  45. data/lib/authlogic/i18n.rb +33 -20
  46. data/lib/authlogic/i18n/translator.rb +1 -1
  47. data/lib/authlogic/random.rb +12 -29
  48. data/lib/authlogic/regex.rb +59 -27
  49. data/lib/authlogic/session/activation.rb +36 -23
  50. data/lib/authlogic/session/active_record_trickery.rb +13 -10
  51. data/lib/authlogic/session/base.rb +20 -8
  52. data/lib/authlogic/session/brute_force_protection.rb +87 -56
  53. data/lib/authlogic/session/callbacks.rb +99 -49
  54. data/lib/authlogic/session/cookies.rb +128 -59
  55. data/lib/authlogic/session/existence.rb +29 -19
  56. data/lib/authlogic/session/foundation.rb +70 -16
  57. data/lib/authlogic/session/http_auth.rb +39 -31
  58. data/lib/authlogic/session/id.rb +27 -15
  59. data/lib/authlogic/session/klass.rb +17 -13
  60. data/lib/authlogic/session/magic_columns.rb +78 -59
  61. data/lib/authlogic/session/magic_states.rb +50 -27
  62. data/lib/authlogic/session/params.rb +79 -50
  63. data/lib/authlogic/session/password.rb +197 -118
  64. data/lib/authlogic/session/perishable_token.rb +12 -6
  65. data/lib/authlogic/session/persistence.rb +20 -14
  66. data/lib/authlogic/session/priority_record.rb +20 -16
  67. data/lib/authlogic/session/scopes.rb +63 -33
  68. data/lib/authlogic/session/session.rb +40 -25
  69. data/lib/authlogic/session/timeout.rb +51 -34
  70. data/lib/authlogic/session/unauthorized_record.rb +24 -18
  71. data/lib/authlogic/session/validation.rb +32 -21
  72. data/lib/authlogic/test_case.rb +123 -35
  73. data/lib/authlogic/test_case/mock_controller.rb +14 -13
  74. data/lib/authlogic/test_case/mock_cookie_jar.rb +14 -5
  75. data/lib/authlogic/test_case/mock_logger.rb +1 -1
  76. data/lib/authlogic/test_case/mock_request.rb +9 -4
  77. data/lib/authlogic/test_case/rails_request_adapter.rb +8 -7
  78. data/lib/authlogic/version.rb +21 -0
  79. data/test/acts_as_authentic_test/base_test.rb +1 -1
  80. data/test/acts_as_authentic_test/email_test.rb +80 -63
  81. data/test/acts_as_authentic_test/logged_in_status_test.rb +14 -8
  82. data/test/acts_as_authentic_test/login_test.rb +91 -49
  83. data/test/acts_as_authentic_test/magic_columns_test.rb +13 -13
  84. data/test/acts_as_authentic_test/password_test.rb +82 -60
  85. data/test/acts_as_authentic_test/perishable_token_test.rb +31 -25
  86. data/test/acts_as_authentic_test/persistence_token_test.rb +9 -5
  87. data/test/acts_as_authentic_test/restful_authentication_test.rb +18 -9
  88. data/test/acts_as_authentic_test/session_maintenance_test.rb +86 -22
  89. data/test/acts_as_authentic_test/single_access_test.rb +15 -15
  90. data/test/adapter_test.rb +21 -0
  91. data/test/authenticates_many_test.rb +26 -11
  92. data/test/config_test.rb +9 -9
  93. data/test/crypto_provider_test/aes256_test.rb +3 -3
  94. data/test/crypto_provider_test/bcrypt_test.rb +1 -1
  95. data/test/crypto_provider_test/scrypt_test.rb +2 -2
  96. data/test/crypto_provider_test/sha1_test.rb +4 -4
  97. data/test/crypto_provider_test/sha256_test.rb +2 -2
  98. data/test/crypto_provider_test/sha512_test.rb +3 -3
  99. data/test/crypto_provider_test/wordpress_test.rb +24 -0
  100. data/test/gemfiles/Gemfile.rails-4.2.x +2 -2
  101. data/test/gemfiles/Gemfile.rails-5.0.x +6 -0
  102. data/test/gemfiles/Gemfile.rails-5.1.x +6 -0
  103. data/test/gemfiles/Gemfile.rails-5.2.x +6 -0
  104. data/test/gemfiles/Gemfile.rails-master +6 -0
  105. data/test/i18n_test.rb +9 -9
  106. data/test/libs/affiliate.rb +2 -2
  107. data/test/libs/company.rb +4 -4
  108. data/test/libs/employee.rb +2 -2
  109. data/test/libs/employee_session.rb +1 -1
  110. data/test/libs/ldaper.rb +1 -1
  111. data/test/libs/project.rb +1 -1
  112. data/test/libs/user_session.rb +2 -2
  113. data/test/random_test.rb +9 -38
  114. data/test/session_test/activation_test.rb +7 -7
  115. data/test/session_test/active_record_trickery_test.rb +9 -6
  116. data/test/session_test/brute_force_protection_test.rb +26 -21
  117. data/test/session_test/callbacks_test.rb +10 -4
  118. data/test/session_test/cookies_test.rb +54 -20
  119. data/test/session_test/existence_test.rb +45 -23
  120. data/test/session_test/foundation_test.rb +17 -1
  121. data/test/session_test/http_auth_test.rb +11 -12
  122. data/test/session_test/id_test.rb +3 -3
  123. data/test/session_test/klass_test.rb +2 -2
  124. data/test/session_test/magic_columns_test.rb +15 -17
  125. data/test/session_test/magic_states_test.rb +17 -19
  126. data/test/session_test/params_test.rb +26 -20
  127. data/test/session_test/password_test.rb +11 -12
  128. data/test/session_test/perishability_test.rb +5 -5
  129. data/test/session_test/persistence_test.rb +4 -3
  130. data/test/session_test/scopes_test.rb +15 -9
  131. data/test/session_test/session_test.rb +7 -6
  132. data/test/session_test/timeout_test.rb +16 -14
  133. data/test/session_test/unauthorized_record_test.rb +3 -3
  134. data/test/session_test/validation_test.rb +5 -5
  135. data/test/test_helper.rb +115 -49
  136. metadata +107 -36
  137. data/README.rdoc +0 -232
  138. data/test/gemfiles/Gemfile.rails-3.2.x +0 -7
  139. data/test/gemfiles/Gemfile.rails-4.0.x +0 -7
  140. data/test/gemfiles/Gemfile.rails-4.1.x +0 -7
@@ -1,22 +1,25 @@
1
1
  require "digest/sha2"
2
2
 
3
3
  module Authlogic
4
- # The acts_as_authentic method has a crypto_provider option. This allows you to use any type of encryption you like.
5
- # Just create a class with a class level encrypt and matches? method. See example below.
4
+ # The acts_as_authentic method has a crypto_provider option. This allows you
5
+ # to use any type of encryption you like. Just create a class with a class
6
+ # level encrypt and matches? method. See example below.
6
7
  #
7
8
  # === Example
8
9
  #
9
10
  # class MyAwesomeEncryptionMethod
10
11
  # def self.encrypt(*tokens)
11
- # # the tokens passed will be an array of objects, what type of object is irrelevant,
12
- # # just do what you need to do with them and return a single encrypted string.
13
- # # for example, you will most likely join all of the objects into a single string and then encrypt that string
12
+ # # the tokens passed will be an array of objects, what type of object
13
+ # # is irrelevant, just do what you need to do with them and return a
14
+ # # single encrypted string. for example, you will most likely join all
15
+ # # of the objects into a single string and then encrypt that string
14
16
  # end
15
17
  #
16
18
  # def self.matches?(crypted, *tokens)
17
- # # return true if the crypted string matches the tokens.
18
- # # depending on your algorithm you might decrypt the string then compare it to the token, or you might
19
- # # encrypt the tokens and make sure it matches the crypted string, its up to you
19
+ # # return true if the crypted string matches the tokens. Depending on
20
+ # # your algorithm you might decrypt the string then compare it to the
21
+ # # token, or you might encrypt the tokens and make sure it matches the
22
+ # # crypted string, its up to you.
20
23
  # end
21
24
  # end
22
25
  module CryptoProviders
@@ -26,21 +29,22 @@ module Authlogic
26
29
  class Sha256
27
30
  class << self
28
31
  attr_accessor :join_token
29
-
32
+
30
33
  # The number of times to loop through the encryption.
31
34
  def stretches
32
35
  @stretches ||= 20
33
36
  end
34
37
  attr_writer :stretches
35
-
38
+
36
39
  # Turns your raw password into a Sha256 hash.
37
40
  def encrypt(*tokens)
38
41
  digest = tokens.flatten.join(join_token)
39
42
  stretches.times { digest = Digest::SHA256.hexdigest(digest) }
40
43
  digest
41
44
  end
42
-
43
- # Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
45
+
46
+ # Does the crypted password match the tokens? Uses the same tokens that
47
+ # were used to encrypt.
44
48
  def matches?(crypted, *tokens)
45
49
  encrypt(*tokens) == crypted
46
50
  end
@@ -1,24 +1,6 @@
1
1
  require "digest/sha2"
2
2
 
3
3
  module Authlogic
4
- # The acts_as_authentic method has a crypto_provider option. This allows you to use any type of encryption you like.
5
- # Just create a class with a class level encrypt and matches? method. See example below.
6
- #
7
- # === Example
8
- #
9
- # class MyAwesomeEncryptionMethod
10
- # def self.encrypt(*tokens)
11
- # # the tokens passed will be an array of objects, what type of object is irrelevant,
12
- # # just do what you need to do with them and return a single encrypted string.
13
- # # for example, you will most likely join all of the objects into a single string and then encrypt that string
14
- # end
15
- #
16
- # def self.matches?(crypted, *tokens)
17
- # # return true if the crypted string matches the tokens.
18
- # # depending on your algorithm you might decrypt the string then compare it to the token, or you might
19
- # # encrypt the tokens and make sure it matches the crypted string, its up to you
20
- # end
21
- # end
22
4
  module CryptoProviders
23
5
  # = Sha512
24
6
  #
@@ -26,25 +8,27 @@ module Authlogic
26
8
  class Sha512
27
9
  class << self
28
10
  attr_accessor :join_token
29
-
30
- # The number of times to loop through the encryption. This is twenty because that is what restful_authentication defaults to.
11
+
12
+ # The number of times to loop through the encryption. This is twenty
13
+ # because that is what restful_authentication defaults to.
31
14
  def stretches
32
15
  @stretches ||= 20
33
16
  end
34
17
  attr_writer :stretches
35
-
18
+
36
19
  # Turns your raw password into a Sha512 hash.
37
20
  def encrypt(*tokens)
38
21
  digest = tokens.flatten.join(join_token)
39
22
  stretches.times { digest = Digest::SHA512.hexdigest(digest) }
40
23
  digest
41
24
  end
42
-
43
- # Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
25
+
26
+ # Does the crypted password match the tokens? Uses the same tokens that
27
+ # were used to encrypt.
44
28
  def matches?(crypted, *tokens)
45
29
  encrypt(*tokens) == crypted
46
30
  end
47
31
  end
48
32
  end
49
33
  end
50
- end
34
+ end
@@ -1,39 +1,68 @@
1
- require 'digest/md5'
1
+ require "digest/md5"
2
+
3
+ ::ActiveSupport::Deprecation.warn(
4
+ <<-EOS,
5
+ authlogic/crypto_providers/wordpress.rb is deprecated without replacement.
6
+ Yes, the entire file. Don't `require` it. Let us know ASAP if you are still
7
+ using it.
8
+
9
+ Reasons for deprecation: This file is not autoloaded by
10
+ `authlogic/crypto_providers.rb`. It's not documented. There are no tests.
11
+ So, it's likely used by a *very* small number of people, if any. It's never
12
+ had any contributions except by its original author, Jeffry Degrande, in
13
+ 2009. It is unclear why it should live in the main authlogic codebase. It
14
+ could be in a separate gem, authlogic-wordpress, or it could just live in
15
+ Jeffry's codebase, if he still even needs it, in 2018, nine years later.
16
+ EOS
17
+ caller(1)
18
+ )
19
+
2
20
  module Authlogic
3
21
  module CryptoProviders
22
+ # Crypto provider to transition from wordpress user accounts. Written by
23
+ # Jeffry Degrande in 2009. First released in 2.1.3.
24
+ #
25
+ # Problems:
26
+ #
27
+ # - There are no tests.
28
+ # - We can't even figure out how to run this without it crashing.
29
+ # - Presumably it implements some spec, but it doesn't mention which.
30
+ # - It is not documented anywhere.
31
+ # - There is no PR associated with this, and no discussion about it could be found.
32
+ #
4
33
  class Wordpress
5
34
  class << self
6
- ITOA64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
35
+ ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".freeze
7
36
 
8
37
  def matches?(crypted, *tokens)
9
- stretches = 1 << ITOA64.index(crypted[3,1])
10
- plain, salt = *tokens
11
- hashed = Digest::MD5.digest(salt+plain)
12
- stretches.times do |i|
13
- hashed = Digest::MD5.digest(hashed+plain)
38
+ stretches = 1 << ITOA64.index(crypted[3, 1])
39
+ plain, salt = *tokens
40
+ hashed = Digest::MD5.digest(salt + plain)
41
+ stretches.times do
42
+ hashed = Digest::MD5.digest(hashed + plain)
14
43
  end
15
- crypted[0,12]+encode_64(hashed, 16) == crypted
44
+ crypted[0, 12] + encode_64(hashed, 16) == crypted
16
45
  end
17
46
 
18
47
  def encode_64(input, length)
19
- output = ""
48
+ output = ""
20
49
  i = 0
21
50
  while i < length
22
- value = input[i]
23
- i+=1
51
+ value = input[i]
52
+ i += 1
24
53
  break if value.nil?
25
54
  output += ITOA64[value & 0x3f, 1]
26
55
  value |= input[i] << 8 if i < length
27
56
  output += ITOA64[(value >> 6) & 0x3f, 1]
28
57
 
29
- i+=1
58
+ i += 1
30
59
  break if i >= length
31
60
  value |= input[i] << 16 if i < length
32
- output += ITOA64[(value >> 12) & 0x3f,1]
61
+ output += ITOA64[(value >> 12) & 0x3f, 1]
33
62
 
34
- i+=1
63
+ i += 1
35
64
  break if i >= length
36
- output += ITOA64[(value >> 18) & 0x3f,1]
65
+ output += ITOA64[(value >> 18) & 0x3f, 1]
37
66
  end
38
67
  output
39
68
  end
@@ -1,38 +1,48 @@
1
1
  require "authlogic/i18n/translator"
2
2
 
3
3
  module Authlogic
4
- # This class allows any message in Authlogic to use internationalization. In earlier versions of Authlogic each message was translated via configuration.
5
- # This cluttered up the configuration and cluttered up Authlogic. So all translation has been extracted out into this class. Now all messages pass through
6
- # this class, making it much easier to implement in I18n library / plugin you want. Use this as a layer that sits between Authlogic and whatever I18n
7
- # library you want to use.
4
+ # This class allows any message in Authlogic to use internationalization. In
5
+ # earlier versions of Authlogic each message was translated via configuration.
6
+ # This cluttered up the configuration and cluttered up Authlogic. So all
7
+ # translation has been extracted out into this class. Now all messages pass
8
+ # through this class, making it much easier to implement in I18n library /
9
+ # plugin you want. Use this as a layer that sits between Authlogic and
10
+ # whatever I18n library you want to use.
8
11
  #
9
- # By default this uses the rails I18n library, if it exists. If it doesnt exist it just returns the default english message. The Authlogic I18n class
10
- # works EXACTLY like the rails I18n class. This is because the arguments are delegated to this class.
12
+ # By default this uses the rails I18n library, if it exists. If it doesn't
13
+ # exist it just returns the default English message. The Authlogic I18n class
14
+ # works EXACTLY like the rails I18n class. This is because the arguments are
15
+ # delegated to this class.
11
16
  #
12
17
  # Here is how all messages are translated internally with Authlogic:
13
18
  #
14
19
  # Authlogic::I18n.t('error_messages.password_invalid', :default => "is invalid")
15
20
  #
16
- # If you use a different I18n library just replace the build-in I18n::Translator class with your own. For example:
21
+ # If you use a different I18n library just replace the build-in
22
+ # I18n::Translator class with your own. For example:
17
23
  #
18
24
  # class MyAuthlogicI18nTranslator
19
25
  # def translate(key, options = {})
20
- # # you will have key which will be something like: "error_messages.password_invalid"
21
- # # you will also have options[:default], which will be the default english version of the message
26
+ # # you will have key which will be something like:
27
+ # # "error_messages.password_invalid"
28
+ # # you will also have options[:default], which will be the default
29
+ # # English version of the message
22
30
  # # do whatever you want here with the arguments passed to you.
23
31
  # end
24
32
  # end
25
- #
33
+ #
26
34
  # Authlogic::I18n.translator = MyAuthlogicI18nTranslator.new
27
35
  #
28
- # That it's! Here is a complete list of the keys that are passed. Just define these however you wish:
36
+ # That it's! Here is a complete list of the keys that are passed. Just define
37
+ # these however you wish:
29
38
  #
30
39
  # authlogic:
31
40
  # error_messages:
32
41
  # login_blank: can not be blank
33
42
  # login_not_found: is not valid
34
- # login_invalid: should use only letters, numbers, spaces, and .-_@ please.
35
- # consecutive_failed_logins_limit_exceeded: Consecutive failed logins limit exceeded, account is disabled.
43
+ # login_invalid: should use only letters, numbers, spaces, and .-_@+ please.
44
+ # consecutive_failed_logins_limit_exceeded: >
45
+ # Consecutive failed logins limit exceeded, account is disabled.
36
46
  # email_invalid: should look like an email address.
37
47
  # email_invalid_international: should look like an international email address.
38
48
  # password_blank: can not be blank
@@ -42,6 +52,7 @@ module Authlogic
42
52
  # not_approved: Your account is not approved
43
53
  # no_authentication_details: You did not provide any details for authentication.
44
54
  # general_credentials_error: Login/Password combination is not valid
55
+ # session_invalid: Your session is invalid and has the following errors:
45
56
  # models:
46
57
  # user_session: UserSession (or whatever name you are using)
47
58
  # attributes:
@@ -53,31 +64,33 @@ module Authlogic
53
64
  module I18n
54
65
  @@scope = :authlogic
55
66
  @@translator = nil
56
-
67
+
57
68
  class << self
58
69
  # Returns the current scope. Defaults to :authlogic
59
70
  def scope
60
71
  @@scope
61
72
  end
62
-
73
+
63
74
  # Sets the current scope. Used to set a custom scope.
64
75
  def scope=(scope)
65
76
  @@scope = scope
66
77
  end
67
-
78
+
68
79
  # Returns the current translator. Defaults to +Translator+.
69
80
  def translator
70
81
  @@translator ||= Translator.new
71
82
  end
72
-
83
+
73
84
  # Sets the current translator. Used to set a custom translator.
74
85
  def translator=(translator)
75
86
  @@translator = translator
76
87
  end
77
-
78
- # All message translation is passed to this method. The first argument is the key for the message. The second is options, see the rails I18n library for a list of options used.
88
+
89
+ # All message translation is passed to this method. The first argument is
90
+ # the key for the message. The second is options, see the rails I18n
91
+ # library for a list of options used.
79
92
  def translate(key, options = {})
80
- translator.translate key, { :scope => I18n.scope }.merge(options)
93
+ translator.translate key, { scope: I18n.scope }.merge(options)
81
94
  end
82
95
  alias :t :translate
83
96
  end
@@ -1,7 +1,7 @@
1
1
  module Authlogic
2
2
  module I18n
3
3
  class Translator
4
- # If the I18n gem is present, calls +I18n.translate+ passing all
4
+ # If the I18n gem is present, calls +I18n.translate+ passing all
5
5
  # arguments, else returns +options[:default]+.
6
6
  def translate(key, options = {})
7
7
  if defined?(::I18n)
@@ -1,33 +1,16 @@
1
+ require "securerandom"
2
+
1
3
  module Authlogic
2
- # Handles generating random strings. If SecureRandom is installed it will default to this and use it instead. SecureRandom comes with ActiveSupport.
3
- # So if you are using this in a rails app you should have this library.
4
+ # Generates random strings using ruby's SecureRandom library.
4
5
  module Random
5
- extend self
6
-
7
- SecureRandom = (defined?(::SecureRandom) && ::SecureRandom) || (defined?(::ActiveSupport::SecureRandom) && ::ActiveSupport::SecureRandom)
8
-
9
- if SecureRandom
10
- def hex_token
11
- SecureRandom.hex(64)
12
- end
13
-
14
- def friendly_token
15
- # use base64url as defined by RFC4648
16
- SecureRandom.base64(15).tr('+/=', '').strip.delete("\n")
17
- end
18
- else
19
- def hex_token
20
- Authlogic::CryptoProviders::Sha512.encrypt(Time.now.to_s + (1..10).collect{ rand.to_s }.join)
21
- end
22
-
23
- FRIENDLY_CHARS = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
24
-
25
- def friendly_token
26
- newpass = ""
27
- 1.upto(20) { |i| newpass << FRIENDLY_CHARS[rand(FRIENDLY_CHARS.size-1)] }
28
- newpass
29
- end
6
+ def self.hex_token
7
+ SecureRandom.hex(64)
8
+ end
9
+
10
+ # Returns a string in base64url format as defined by RFC-3548 and RFC-4648.
11
+ # We call this a "friendly" token because it is short and safe for URLs.
12
+ def self.friendly_token
13
+ SecureRandom.urlsafe_base64(15)
30
14
  end
31
-
32
15
  end
33
- end
16
+ end
@@ -1,47 +1,79 @@
1
- #encoding: utf-8
2
1
  module Authlogic
3
- # This is a module the contains regular expressions used throughout Authlogic. The point of extracting
4
- # them out into their own module is to make them easily available to you for other uses. Ex:
2
+ # This is a module the contains regular expressions used throughout Authlogic.
3
+ # The point of extracting them out into their own module is to make them
4
+ # easily available to you for other uses. Ex:
5
5
  #
6
6
  # validates_format_of :my_email_field, :with => Authlogic::Regex.email
7
7
  module Regex
8
- # A general email regular expression. It allows top level domains (TLD) to be from 2 - 13 in length.
9
- # The decisions behind this regular expression were made by analyzing the list of top-level domains
10
- # maintained by IANA and by reading this website: http://www.regular-expressions.info/email.html,
11
- # which is an excellent resource for regular expressions.
12
- def self.email
13
- @email_regex ||= begin
14
- email_name_regex = '[A-Z0-9_\.&%\+\-\']+'
15
- domain_head_regex = '(?:[A-Z0-9\-]+\.)+'
16
- domain_tld_regex = '(?:[A-Z]{2,13})'
17
- /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
18
- end
19
- end
8
+ # A general email regular expression. It allows top level domains (TLD) to
9
+ # be from 2 - 24 in length. The decisions behind this regular expression
10
+ # were made by analyzing the list of top-level domains maintained by IANA
11
+ # and by reading this website:
12
+ # http://www.regular-expressions.info/email.html, which is an excellent
13
+ # resource for regular expressions.
14
+ EMAIL = /
15
+ \A
16
+ [A-Z0-9_.&%+\-']+ # mailbox
17
+ @
18
+ (?:[A-Z0-9\-]+\.)+ # subdomains
19
+ (?:[A-Z]{2,25}) # TLD
20
+ \z
21
+ /ix
20
22
 
21
- # A draft regular expression for internationalized email addresses.
22
- # Given that the standard may be in flux, this simply emulates @email_regex but rather than
23
- # allowing specific characters for each part, it instead disallows the complement set of characters:
23
+ # A draft regular expression for internationalized email addresses. Given
24
+ # that the standard may be in flux, this simply emulates @email_regex but
25
+ # rather than allowing specific characters for each part, it instead
26
+ # disallows the complement set of characters:
27
+ #
24
28
  # - email_name_regex disallows: @[]^ !"#$()*,/:;<=>?`{|}~\ and control characters
25
29
  # - domain_head_regex disallows: _%+ and all characters in email_name_regex
26
30
  # - domain_tld_regex disallows: 0123456789- and all characters in domain_head_regex
31
+ #
27
32
  # http://en.wikipedia.org/wiki/Email_address#Internationalization
28
33
  # http://tools.ietf.org/html/rfc6530
29
34
  # http://www.unicode.org/faq/idn.html
30
35
  # http://ruby-doc.org/core-2.1.5/Regexp.html#class-Regexp-label-Character+Classes
31
36
  # http://en.wikipedia.org/wiki/Unicode_character_property#General_Category
37
+ EMAIL_NONASCII = /
38
+ \A
39
+ [^[:cntrl:][@\[\]\^ \!"\#$\(\)*,\/:;<=>?`{|}~\\]]+ # mailbox
40
+ @
41
+ (?:[^[:cntrl:][@\[\]\^ \!\"\#$&\(\)*,\/:;<=>\?`{|}~\\_.%+']]+\.)+ # subdomains
42
+ (?:[^[:cntrl:][@\[\]\^ \!\"\#$&\(\)*,\/:;<=>\?`{|}~\\_.%+\-'0-9]]{2,25}) # TLD
43
+ \z
44
+ /x
45
+
46
+ # A simple regular expression that only allows for letters, numbers, spaces, and
47
+ # .-_@+. Just a standard login / username regular expression.
48
+ LOGIN = /\A[a-zA-Z0-9_][a-zA-Z0-9\.+\-_@ ]+\z/
49
+
50
+ # Accessing the above constants using the following methods is deprecated.
51
+
52
+ # @deprecated
53
+ def self.email
54
+ ::ActiveSupport::Deprecation.warn(
55
+ "Authlogic::Regex.email is deprecated, use Authlogic::Regex::EMAIL",
56
+ caller(1)
57
+ )
58
+ EMAIL
59
+ end
60
+
61
+ # @deprecated
32
62
  def self.email_nonascii
33
- @email_nonascii_regex ||= begin
34
- email_name_regex = '[^[:cntrl:][@\[\]\^ \!\"#$\(\)*,/:;<=>\?`{|}~\\\]]+'
35
- domain_head_regex = '(?:[^[:cntrl:][@\[\]\^ \!\"#$&\(\)*,/:;<=>\?`{|}~\\\_\.%\+\']]+\.)+'
36
- domain_tld_regex = '(?:[^[:cntrl:][@\[\]\^ \!\"#$&\(\)*,/:;<=>\?`{|}~\\\_\.%\+\-\'0-9]]{2,13})'
37
- /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/
38
- end
63
+ ::ActiveSupport::Deprecation.warn(
64
+ "Authlogic::Regex.email_nonascii is deprecated, use Authlogic::Regex::EMAIL_NONASCII",
65
+ caller(1)
66
+ )
67
+ EMAIL_NONASCII
39
68
  end
40
69
 
41
- # A simple regular expression that only allows for letters, numbers, spaces, and .-_@. Just a standard login / username
42
- # regular expression.
70
+ # @deprecated
43
71
  def self.login
44
- /\A\w[\w\.+\-_@ ]+\z/
72
+ ::ActiveSupport::Deprecation.warn(
73
+ "Authlogic::Regex.login is deprecated, use Authlogic::Regex::LOGIN",
74
+ caller(1)
75
+ )
76
+ LOGIN
45
77
  end
46
78
  end
47
79
  end