htauth 2.2.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY.md +21 -1
  3. data/Manifest.txt +5 -27
  4. data/README.md +51 -31
  5. data/exe/htdigest-ruby +14 -0
  6. data/exe/htpasswd-ruby +14 -0
  7. data/htauth.gemspec +33 -0
  8. data/lib/htauth/algorithm.rb +42 -29
  9. data/lib/htauth/argon2.rb +86 -0
  10. data/lib/htauth/bcrypt.rb +17 -11
  11. data/lib/htauth/cli/digest.rb +42 -49
  12. data/lib/htauth/cli/passwd.rb +127 -114
  13. data/lib/htauth/cli.rb +5 -4
  14. data/lib/htauth/console.rb +9 -6
  15. data/lib/htauth/crypt.rb +11 -9
  16. data/lib/htauth/descendant_tracker.rb +11 -9
  17. data/lib/htauth/digest_entry.rb +22 -19
  18. data/lib/htauth/digest_file.rb +25 -18
  19. data/lib/htauth/entry.rb +3 -1
  20. data/lib/htauth/error.rb +6 -5
  21. data/lib/htauth/file.rb +35 -39
  22. data/lib/htauth/md5.rb +35 -34
  23. data/lib/htauth/passwd_entry.rb +29 -38
  24. data/lib/htauth/passwd_file.rb +32 -27
  25. data/lib/htauth/plaintext.rb +7 -5
  26. data/lib/htauth/sha1.rb +9 -7
  27. data/lib/htauth/version.rb +3 -1
  28. data/lib/htauth.rb +29 -28
  29. metadata +24 -113
  30. data/Rakefile +0 -27
  31. data/bin/htdigest-ruby +0 -12
  32. data/bin/htpasswd-ruby +0 -12
  33. data/spec/algorithm_spec.rb +0 -8
  34. data/spec/bcrypt_spec.rb +0 -33
  35. data/spec/cli/digest_spec.rb +0 -149
  36. data/spec/cli/passwd_spec.rb +0 -330
  37. data/spec/crypt_spec.rb +0 -12
  38. data/spec/digest_entry_spec.rb +0 -60
  39. data/spec/digest_file_spec.rb +0 -65
  40. data/spec/md5_spec.rb +0 -13
  41. data/spec/passwd_entry_spec.rb +0 -159
  42. data/spec/passwd_file_spec.rb +0 -84
  43. data/spec/plaintext_spec.rb +0 -11
  44. data/spec/sha1_spec.rb +0 -11
  45. data/spec/spec_helper.rb +0 -28
  46. data/spec/test.add.digest +0 -3
  47. data/spec/test.add.passwd +0 -3
  48. data/spec/test.delete.digest +0 -1
  49. data/spec/test.delete.passwd +0 -1
  50. data/spec/test.original.digest +0 -2
  51. data/spec/test.original.passwd +0 -2
  52. data/spec/test.update.digest +0 -2
  53. data/spec/test.update.passwd +0 -2
  54. data/tasks/default.rake +0 -242
  55. data/tasks/this.rb +0 -208
  56. /data/{LICENSE → LICENSE.txt} +0 -0
@@ -1,16 +1,14 @@
1
- require 'htauth/version'
2
- require 'htauth/error'
3
- require 'htauth/digest_file'
4
- require 'htauth/console'
1
+ # frozen_string_literal: true
5
2
 
6
- require 'ostruct'
7
- require 'optparse'
3
+ require "htauth/cli"
4
+
5
+ require "ostruct"
6
+ require "optparse"
8
7
 
9
8
  module HTAuth
10
9
  module CLI
11
10
  # Internal: Implemenation of the commandline htdigest-ruby
12
11
  class Digest
13
-
14
12
  MAX_PASSWD_LENGTH = 255
15
13
 
16
14
  attr_accessor :digest_file
@@ -22,7 +20,7 @@ module HTAuth
22
20
  end
23
21
 
24
22
  def options
25
- if @options.nil? then
23
+ if @options.nil?
26
24
  @options = ::OpenStruct.new
27
25
  @options.show_version = false
28
26
  @options.show_help = false
@@ -36,24 +34,22 @@ module HTAuth
36
34
  end
37
35
 
38
36
  def option_parser
39
- if not @option_parser then
40
- @option_parser = OptionParser.new(nil, 14) do |op|
41
- op.banner = "Usage: #{op.program_name} [options] passwordfile realm username"
42
- op.on("-c", "--create", "Create a new digest password file; this overwrites an existing file.") do |c|
43
- options.file_mode = DigestFile::CREATE
44
- end
45
-
46
- op.on("-D", "--delete", "Delete the specified user.") do |d|
47
- options.delete_entry = d
48
- end
49
-
50
- op.on("-h", "--help", "Display this help.") do |h|
51
- options.show_help = h
52
- end
53
-
54
- op.on("-v", "--version", "Show version info.") do |v|
55
- options.show_version = v
56
- end
37
+ @option_parser ||= OptionParser.new(nil, 14) do |op|
38
+ op.banner = "Usage: #{op.program_name} [options] passwordfile realm username"
39
+ op.on("-c", "--create", "Create a new digest password file; this overwrites an existing file.") do |_c|
40
+ options.file_mode = DigestFile::CREATE
41
+ end
42
+
43
+ op.on("-D", "--delete", "Delete the specified user.") do |d|
44
+ options.delete_entry = d
45
+ end
46
+
47
+ op.on("-h", "--help", "Display this help.") do |h|
48
+ options.show_help = h
49
+ end
50
+
51
+ op.on("-v", "--version", "Show version info.") do |v|
52
+ options.show_version = v
57
53
  end
58
54
  end
59
55
  @option_parser
@@ -70,27 +66,25 @@ module HTAuth
70
66
  end
71
67
 
72
68
  def parse_options(argv)
73
- begin
74
- option_parser.parse!(argv)
75
- show_version if options.show_version
76
- show_help if options.show_help or argv.size < 3
77
-
78
- options.passwdfile = argv.shift
79
- options.realm = argv.shift
80
- options.username = argv.shift
81
- rescue ::OptionParser::ParseError => pe
82
- $stderr.puts "ERROR: #{option_parser.program_name} - #{pe}"
83
- $stderr.puts "Try `#{option_parser.program_name} --help` for more information"
84
- exit 1
85
- end
69
+ option_parser.parse!(argv)
70
+ show_version if options.show_version
71
+ show_help if options.show_help || (argv.size < 3)
72
+
73
+ options.passwdfile = argv.shift
74
+ options.realm = argv.shift
75
+ options.username = argv.shift
76
+ rescue ::OptionParser::ParseError => e
77
+ warn "ERROR: #{option_parser.program_name} - #{e}"
78
+ warn "Try `#{option_parser.program_name} --help` for more information"
79
+ exit 1
86
80
  end
87
81
 
88
- def run(argv, env = ENV)
82
+ def run(argv, _env = ENV)
89
83
  begin
90
84
  parse_options(argv)
91
85
  digest_file = DigestFile.new(options.passwdfile, options.file_mode)
92
86
 
93
- if options.delete_entry then
87
+ if options.delete_entry
94
88
  digest_file.delete(options.username, options.realm)
95
89
  else
96
90
  console = Console.new
@@ -109,18 +103,17 @@ module HTAuth
109
103
  end
110
104
 
111
105
  digest_file.save!
112
-
113
- rescue HTAuth::FileAccessError => fae
106
+ rescue HTAuth::FileAccessError => e
114
107
  msg = "Could not open password file #{options.passwdfile} "
115
- $stderr.puts "#{msg}: #{fae.message}"
116
- $stderr.puts fae.backtrace.join("\n")
108
+ warn "#{msg}: #{e.message}"
109
+ warn e.backtrace.join("\n")
117
110
  exit 1
118
- rescue HTAuth::Error => pe
119
- $stderr.puts "#{pe.message}"
111
+ rescue HTAuth::Error => e
112
+ warn e.message
120
113
  exit 1
121
- rescue SignalException => se
114
+ rescue SignalException => e
122
115
  $stderr.puts
123
- $stderr.puts "Interrupted #{se}"
116
+ warn "Interrupted #{e}"
124
117
  exit 1
125
118
  end
126
119
  exit 0
@@ -1,15 +1,14 @@
1
- require 'htauth/error'
2
- require 'htauth/passwd_file'
3
- require 'htauth/console'
1
+ # frozen_string_literal: true
4
2
 
5
- require 'ostruct'
6
- require 'optparse'
3
+ require "htauth/cli"
4
+
5
+ require "ostruct"
6
+ require "optparse"
7
7
 
8
8
  module HTAuth
9
9
  module CLI
10
10
  # Internal: Implemenation of the commandline htpasswd-ruby
11
11
  class Passwd
12
-
13
12
  MAX_PASSWD_LENGTH = 255
14
13
 
15
14
  attr_accessor :passwd_file
@@ -21,14 +20,14 @@ module HTAuth
21
20
  end
22
21
 
23
22
  def options
24
- if @options.nil? then
23
+ if @options.nil?
25
24
  @options = ::OpenStruct.new
26
25
  @options.batch_mode = false
27
26
  @options.file_mode = File::ALTER
28
27
  @options.passwdfile = nil
29
28
  @options.algorithm = Algorithm::EXISTING
30
29
  @options.algorithm_args = {}
31
- @options.read_stdin_once= false
30
+ @options.read_stdin_once = false
32
31
  @options.send_to_stdout = false
33
32
  @options.show_version = false
34
33
  @options.show_help = false
@@ -40,92 +39,94 @@ module HTAuth
40
39
  end
41
40
 
42
41
  def option_parser
43
- if not @option_parser then
44
- @option_parser = OptionParser.new(nil, 16) do |op|
45
- op.banner = <<-EOB
46
- Usage:
47
- #{op.program_name} [-cimBdpsD] [-C cost] passwordfile username
48
- #{op.program_name} -b[cmBdpsD] [-C cost] passwordfile username password
42
+ @option_parser ||= OptionParser.new(nil, 16) do |op|
43
+ op.banner = <<~BANNER
44
+ Usage:
45
+ #{op.program_name} [-acimBdpsD] [--verify] [-C cost] passwordfile username
46
+ #{op.program_name} -b[acmBdpsD] [--verify] [-C cost] passwordfile username password
49
47
 
50
- #{op.program_name} -n[imBdps] [-C cost] username
51
- #{op.program_name} -nb[mBdps] [-C cost] username password
52
- EOB
48
+ #{op.program_name} -n[imBdps] [-C cost] username
49
+ #{op.program_name} -nb[mBdps] [-C cost] username password
50
+ BANNER
53
51
 
54
- op.separator ""
52
+ op.separator ""
55
53
 
56
- op.on("-b", "--batch", "Batch mode, get the password from the command line, rather than prompt") do |b|
57
- options.batch_mode = b
58
- end
54
+ op.on("--argon2", "Force argon2 encryption of the password.") do |_a|
55
+ options.algorithm = Algorithm::ARGON2
56
+ end
59
57
 
60
- op.on("-B", "--bcrypt", "Force bcrypt encryption of the password.") do |b|
61
- options.algorithm = Algorithm::BCRYPT
62
- end
58
+ op.on("-b", "--batch", "Batch mode, get the password from the command line, rather than prompt.") do |b|
59
+ options.batch_mode = b
60
+ end
63
61
 
64
- op.on("-CCOST", "--cost COST", "Set the computing time used for the bcrypt algorithm",
65
- "(higher is more secure but slower, default: 5, valid: 4 to 31).") do |c|
66
- if c !~ /\A\d+\z/ then
67
- raise ::OptionParser::ParseError, "the bcrypt cost must be an integer from 4 to 31, `#{c}` is invalid"
68
- end
69
-
70
- cost = c.to_i
71
- if (4..31).include?(cost)
72
- options.algorithm_args = { :cost => cost }
73
- else
74
- raise ::OptionParser::ParseError, "the bcrypt cost must be an integer from 4 to 31, `#{c}` is invalid"
75
- end
76
- end
62
+ op.on("-B", "--bcrypt", "Force bcrypt encryption of the password.") do |_b|
63
+ options.algorithm = Algorithm::BCRYPT
64
+ end
77
65
 
78
- op.on("-c", "--create", "Create a new file; this overwrites an existing file.") do |c|
79
- options.file_mode = HTAuth::File::CREATE
80
- options.operation << :add_or_update
66
+ op.on("-CCOST", "--cost COST", "Set the computing time used for the bcrypt algorithm",
67
+ "(higher is more secure but slower, default: 5, valid: 4 to 31).") do |c|
68
+ unless /\A\d+\z/.match?(c)
69
+ raise ::OptionParser::ParseError, "the bcrypt cost must be an integer from 4 to 31, `#{c}` is invalid"
81
70
  end
82
71
 
83
- op.on("-d", "--crypt", "Force CRYPT encryption of the password.") do |c|
84
- options.algorithm = Algorithm::CRYPT
72
+ cost = c.to_i
73
+ unless (4..31).cover?(cost)
74
+ raise ::OptionParser::ParseError, "the bcrypt cost must be an integer from 4 to 31, `#{c}` is invalid"
85
75
  end
86
76
 
87
- op.on("-D", "--delete", "Delete the specified user.") do |d|
88
- options.operation << :delete
89
- end
77
+ options.algorithm_args = { cost: cost }
78
+ end
90
79
 
91
- op.on("-h", "--help", "Display this help.") do |h|
92
- options.show_help = h
93
- end
80
+ op.on("-c", "--create", "Create a new file; this overwrites an existing file.") do |_c|
81
+ options.file_mode = HTAuth::File::CREATE
82
+ options.operation << :add_or_update
83
+ end
94
84
 
95
- op.on("-i", "--stdin", "Read the passwod from stdin without verivication (for script usage).") do |i|
96
- options.read_stdin_once = true
97
- end
85
+ op.on("-d", "--crypt", "Force CRYPT encryption of the password.") do |_c|
86
+ options.algorithm = Algorithm::CRYPT
87
+ end
98
88
 
99
- op.on("-m", "--md5", "Force MD5 encryption of the password (default).") do |m|
100
- options.algorithm = Algorithm::MD5
101
- end
89
+ op.on("-D", "--delete", "Delete the specified user.") do |_d|
90
+ options.operation << :delete
91
+ end
102
92
 
103
- op.on("-n", "--stdout", "Do not update the file; Display the results on stdout instead.") do |n|
104
- options.send_to_stdout = true
105
- options.passwdfile = HTAuth::File::STDOUT_FLAG
106
- options.operation << :stdout
107
- end
93
+ op.on("-h", "--help", "Display this help.") do |h|
94
+ options.show_help = h
95
+ end
108
96
 
109
- op.on("-p", "--plaintext", "Do not encrypt the password (plaintext).") do |p|
110
- options.algorithm = Algorithm::PLAINTEXT
111
- end
97
+ op.on("-i", "--stdin", "Read the passwod from stdin without verivication (for script usage).") do |_i|
98
+ options.read_stdin_once = true
99
+ end
112
100
 
113
- op.on("-s", "--sha1", "Force SHA encryption of the password.") do |s|
114
- options.algorithm = Algorithm::SHA1
115
- end
101
+ op.on("-m", "--md5", "Force MD5 encryption of the password (default).") do |_m|
102
+ options.algorithm = Algorithm::MD5
103
+ end
116
104
 
117
- op.on("-v", "--version", "Show version info.") do |v|
118
- options.show_version = v
119
- end
105
+ op.on("-n", "--stdout", "Do not update the file; Display the results on stdout instead.") do |_n|
106
+ options.send_to_stdout = true
107
+ options.passwdfile = HTAuth::File::STDOUT_FLAG
108
+ options.operation << :stdout
109
+ end
120
110
 
121
- op.on("--verify", "Verify password for the specified user") do |v|
122
- options.operation << :verify
123
- end
111
+ op.on("-p", "--plaintext", "Do not encrypt the password (plaintext).") do |_p|
112
+ options.algorithm = Algorithm::PLAINTEXT
113
+ end
124
114
 
125
- op.separator ""
115
+ op.on("-s", "--sha1", "Force SHA encryption of the password.") do |_s|
116
+ options.algorithm = Algorithm::SHA1
117
+ end
126
118
 
127
- op.separator "The SHA algorihtm does not use a salt and is less secure than the MD5 algorithm."
119
+ op.on("-v", "--version", "Show version info.") do |v|
120
+ options.show_version = v
128
121
  end
122
+
123
+ op.on("--verify", "Verify password for the specified user.") do |_v|
124
+ options.operation << :verify
125
+ end
126
+
127
+ op.separator ""
128
+
129
+ op.separator "The SHA algorihtm does not use a salt and is less secure than the MD5 algorithm."
129
130
  end
130
131
  @option_parser
131
132
  end
@@ -141,35 +142,48 @@ Usage:
141
142
  end
142
143
 
143
144
  def parse_options(argv)
144
- begin
145
- option_parser.parse!(argv)
146
- show_version if options.show_version
147
- show_help if options.show_help
148
-
149
- raise ::OptionParser::ParseError, "only one of --create, --stdout, --verify, --delete may be specified" if options.operation.size > 1
150
- raise ::OptionParser::ParseError, "Unable to send to stdout AND create a new file" if options.send_to_stdout and (options.file_mode == File::CREATE)
151
- raise ::OptionParser::ParseError, "a username is needed" if options.send_to_stdout and argv.size < 1
152
- raise ::OptionParser::ParseError, "a username and password are needed" if options.send_to_stdout and options.batch_mode and ( argv.size < 2 )
153
- raise ::OptionParser::ParseError, "a passwordfile, username and password are needed " if not options.send_to_stdout and options.batch_mode and ( argv.size < 3 )
154
- raise ::OptionParser::ParseError, "a passwordfile and username are needed" if argv.size < 2
155
- raise ::OptionParser::ParseError, "options -i and -b are mutually exclusive" if options.batch_mode && options.read_stdin_once
156
-
157
- options.operation = options.operation.shift || :add_or_update
158
- options.passwdfile = argv.shift unless options.send_to_stdout
159
- options.username = argv.shift
160
- options.password = argv.shift if options.batch_mode
161
-
162
- rescue ::OptionParser::ParseError => pe
163
- $stderr.puts "ERROR: #{option_parser.program_name} - #{pe}"
164
- show_help
165
- exit 1
145
+ option_parser.parse!(argv)
146
+ show_version if options.show_version
147
+ show_help if options.show_help
148
+
149
+ if options.operation.size > 1
150
+ raise ::OptionParser::ParseError,
151
+ "only one of --create, --stdout, --verify, --delete may be specified"
152
+ end
153
+ if options.send_to_stdout && (options.file_mode == File::CREATE)
154
+ raise ::OptionParser::ParseError,
155
+ "Unable to send to stdout AND create a new file"
156
+ end
157
+ raise ::OptionParser::ParseError, "a username is needed" if options.send_to_stdout && argv.empty?
158
+ if options.send_to_stdout && options.batch_mode && (argv.size < 2)
159
+ raise ::OptionParser::ParseError,
160
+ "a username and password are needed"
166
161
  end
162
+ if !options.send_to_stdout && options.batch_mode && (argv.size < 3)
163
+ raise ::OptionParser::ParseError,
164
+ "a passwordfile, username and password are needed "
165
+ end
166
+ raise ::OptionParser::ParseError, "a passwordfile and username are needed" if argv.size < 2
167
+ if options.batch_mode && options.read_stdin_once
168
+ raise ::OptionParser::ParseError,
169
+ "options -i and -b are mutually exclusive"
170
+ end
171
+
172
+ options.operation = options.operation.shift || :add_or_update
173
+ options.passwdfile = argv.shift unless options.send_to_stdout
174
+ options.username = argv.shift
175
+ options.password = argv.shift if options.batch_mode
176
+ rescue ::OptionParser::ParseError => e
177
+ warn "ERROR: #{option_parser.program_name} - #{e}"
178
+ show_help
179
+ exit 1
167
180
  end
168
181
 
169
- def fetch_password(width=20)
182
+ def fetch_password(width = 20)
170
183
  return options.password if options.batch_mode
184
+
171
185
  console = Console.new
172
- if options.read_stdin_once then
186
+ if options.read_stdin_once
173
187
  pw_in = console.read_answer
174
188
  return pw_in
175
189
  end
@@ -186,10 +200,10 @@ Usage:
186
200
  raise PasswordError, "They don't match, sorry." unless pw_in == pw_validate
187
201
  end
188
202
 
189
- return pw_in
203
+ pw_in
190
204
  end
191
205
 
192
- def run(argv, env = ENV)
206
+ def run(argv, _env = ENV)
193
207
  begin
194
208
  parse_options(argv)
195
209
  console = Console.new
@@ -199,16 +213,15 @@ Usage:
199
213
  passwd_file.delete(options.username)
200
214
  passwd_file.save!
201
215
  when :verify
202
- if passwd_file.has_entry?(options.username) then
203
- pw_in = fetch_password
204
- if passwd_file.authenticated?(options.username, pw_in) then
205
- $stderr.puts "Password for user #{options.username} correct."
206
- else
207
- raise HTAuth::Error, "Password verification for user #{options.username} failed."
208
- end
209
- else
210
- raise HTAuth::Error, "User #{options.username} not found"
216
+ raise HTAuth::Error, "User #{options.username} not found" unless passwd_file.has_entry?(options.username)
217
+
218
+ pw_in = fetch_password
219
+ unless passwd_file.authenticated?(options.username, pw_in)
220
+ raise HTAuth::Error, "Password verification for user #{options.username} failed."
211
221
  end
222
+
223
+ warn "Password for user #{options.username} correct."
224
+
212
225
  when :add_or_update
213
226
  options.password = fetch_password
214
227
  action = passwd_file.has_entry?(options.username) ? "Changing" : "Adding"
@@ -220,16 +233,16 @@ Usage:
220
233
  passwd_file.add_or_update(options.username, options.password, options.algorithm, options.algorithm_args)
221
234
  passwd_file.save!
222
235
  end
223
- rescue HTAuth::FileAccessError => fae
236
+ rescue HTAuth::FileAccessError => e
224
237
  msg = "Password file failure (#{options.passwdfile}) "
225
- $stderr.puts "#{msg}: #{fae.message}"
238
+ warn "#{msg}: #{e.message}"
226
239
  exit 1
227
- rescue HTAuth::Error => pe
228
- $stderr.puts "#{pe.message}"
240
+ rescue HTAuth::Error => e
241
+ warn e.message
229
242
  exit 1
230
- rescue SignalException => se
243
+ rescue SignalException => e
231
244
  $stderr.puts
232
- $stderr.puts "Interrupted #{se}"
245
+ warn "Interrupted #{e}"
233
246
  exit 1
234
247
  end
235
248
  exit 0
data/lib/htauth/cli.rb CHANGED
@@ -1,8 +1,9 @@
1
- require 'htauth'
1
+ # frozen_string_literal: true
2
+
3
+ require "htauth"
4
+ require "htauth/console"
2
5
  module HTAuth
6
+ # Internal: Commande Line Module
3
7
  module CLI
4
-
5
8
  end
6
9
  end
7
- require 'htauth/cli/digest'
8
- require 'htauth/cli/passwd'
@@ -1,13 +1,14 @@
1
- require 'io/console'
2
- require 'htauth/error'
1
+ # frozen_string_literal: true
2
+
3
+ require "io/console"
4
+ require "htauth/error"
3
5
 
4
6
  # With many thanks to JEG2 - http://graysoftinc.com/terminal-tricks/random-access-terminal
5
7
  #
6
8
  module HTAuth
7
9
  # Internal: Utility class for managing console input/output
8
10
  class Console
9
- attr_reader :input
10
- attr_reader :output
11
+ attr_reader :input, :output
11
12
 
12
13
  def initialize(input = $stdin, output = $stdout)
13
14
  @input = input
@@ -23,9 +24,11 @@ module HTAuth
23
24
  answer = read_answer
24
25
  output.puts
25
26
  raise ConsoleError, "No input given" if answer.nil?
27
+
26
28
  answer.strip!
27
- raise ConsoleError, "No input given" if answer.length == 0
28
- return answer
29
+ raise ConsoleError, "No input given" if answer.empty?
30
+
31
+ answer
29
32
  end
30
33
 
31
34
  def read_answer
data/lib/htauth/crypt.rb CHANGED
@@ -1,26 +1,28 @@
1
- require 'htauth/algorithm'
1
+ # frozen_string_literal: true
2
+
3
+ require "htauth/algorithm"
2
4
 
3
5
  module HTAuth
4
6
  # Internal: The basic crypt algorithm
5
7
  class Crypt < Algorithm
6
-
7
8
  ENTRY_LENGTH = 13
8
- ENTRY_REGEX = %r{\A[^$:\s]{#{ENTRY_LENGTH}}\z}
9
+ ENTRY_REGEX = /\A[^$:\s]{#{ENTRY_LENGTH}}\z/
9
10
 
10
11
  def self.handles?(password_entry)
11
12
  ENTRY_REGEX.match?(password_entry)
12
13
  end
13
14
 
14
15
  def self.extract_salt_from_existing_password_field(existing)
15
- existing[0,2]
16
+ existing[0, 2]
16
17
  end
17
18
 
18
19
  def initialize(params = {})
19
- if existing = (params['existing'] || params[:existing]) then
20
- @salt = self.class.extract_salt_from_existing_password_field(existing)
21
- else
22
- @salt = params[:salt] || params['salt'] || gen_salt
23
- end
20
+ super()
21
+ @salt = if (existing = params["existing"] || params[:existing])
22
+ self.class.extract_salt_from_existing_password_field(existing)
23
+ else
24
+ params[:salt] || params["salt"] || gen_salt
25
+ end
24
26
  end
25
27
 
26
28
  def encode(password)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HTAuth
2
4
  #
3
5
  # Use by either
@@ -18,28 +20,28 @@ module HTAuth
18
20
  # them in a Set that is available via the 'children' method.
19
21
  #
20
22
  module DescendantTracker
21
- def inherited( klass )
22
- return unless klass.instance_of?( Class )
23
- self.children << klass
23
+ def inherited(klass)
24
+ super
25
+ return unless klass.instance_of?(Class)
26
+
27
+ children << klass
24
28
  end
25
29
 
26
30
  #
27
31
  # The list of children that are registered
28
32
  #
29
33
  def children
30
- unless defined? @children
31
- @children = Array.new
32
- end
33
- return @children
34
+ @children = [] unless defined? @children
35
+ @children
34
36
  end
35
37
 
36
38
  #
37
39
  # find the child that returns truthy for then given method and
38
40
  # parameters
39
41
  #
40
- def find_child( method, *args )
42
+ def find_child(method, *args)
41
43
  children.find do |child|
42
- child.send( method, *args )
44
+ child.send(method, *args)
43
45
  end
44
46
  end
45
47
  end