htauth 2.0.0 → 2.1.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.
- checksums.yaml +5 -5
- data/HISTORY.md +7 -0
- data/Manifest.txt +4 -0
- data/README.md +36 -22
- data/Rakefile +8 -4
- data/lib/htauth.rb +1 -0
- data/lib/htauth/algorithm.rb +32 -29
- data/lib/htauth/bcrypt.rb +35 -0
- data/lib/htauth/cli/digest.rb +1 -1
- data/lib/htauth/cli/passwd.rb +90 -30
- data/lib/htauth/console.rb +5 -1
- data/lib/htauth/crypt.rb +15 -4
- data/lib/htauth/descendant_tracker.rb +46 -0
- data/lib/htauth/md5.rb +27 -7
- data/lib/htauth/passwd_entry.rb +22 -17
- data/lib/htauth/passwd_file.rb +46 -12
- data/lib/htauth/plaintext.rb +11 -4
- data/lib/htauth/sha1.rb +8 -5
- data/lib/htauth/version.rb +1 -1
- data/spec/algorithm_spec.rb +8 -0
- data/spec/bcrypt_spec.rb +33 -0
- data/spec/cli/digest_spec.rb +22 -23
- data/spec/cli/passwd_spec.rb +160 -36
- data/spec/crypt_spec.rb +1 -5
- data/spec/digest_entry_spec.rb +19 -19
- data/spec/digest_file_spec.rb +10 -10
- data/spec/md5_spec.rb +1 -5
- data/spec/passwd_entry_spec.rb +63 -42
- data/spec/passwd_file_spec.rb +31 -13
- data/spec/plaintext_spec.rb +1 -5
- data/spec/sha1_spec.rb +1 -5
- data/tasks/default.rake +3 -3
- data/tasks/this.rb +2 -2
- metadata +32 -13
data/spec/passwd_entry_spec.rb
CHANGED
@@ -9,130 +9,151 @@ describe HTAuth::PasswdEntry do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
it "initializes with a user and realm" do
|
12
|
-
@alice.user.must_equal "alice"
|
12
|
+
_(@alice.user).must_equal "alice"
|
13
13
|
end
|
14
14
|
|
15
15
|
it "has the correct crypt password" do
|
16
16
|
@alice.password = "a secret"
|
17
|
-
@alice.digest.must_equal "mDwdZuXalQ5zk"
|
17
|
+
_(@alice.digest).must_equal "mDwdZuXalQ5zk"
|
18
18
|
end
|
19
19
|
|
20
20
|
it "encrypts correctly for md5" do
|
21
21
|
bob = HTAuth::PasswdEntry.new("bob", "b secret", "md5", { :salt => @salt })
|
22
|
-
bob.digest.must_equal "$apr1$lo1tk/..$CarApvZPee0F6Wj1U0GxZ1"
|
22
|
+
_(bob.digest).must_equal "$apr1$lo1tk/..$CarApvZPee0F6Wj1U0GxZ1"
|
23
23
|
end
|
24
24
|
|
25
25
|
it "encrypts correctly for sha1" do
|
26
26
|
bob = HTAuth::PasswdEntry.new("bob", "b secret", "sha1", { :salt => @salt })
|
27
|
-
bob.digest.must_equal "{SHA}b/tjGXbX80MEKVnF200S43ca4hY="
|
27
|
+
_(bob.digest).must_equal "{SHA}b/tjGXbX80MEKVnF200S43ca4hY="
|
28
28
|
end
|
29
29
|
|
30
30
|
it "encrypts correctly for plaintext" do
|
31
31
|
bob = HTAuth::PasswdEntry.new("bob", "b secret", "plaintext", { :salt => @salt })
|
32
|
-
bob.digest.must_equal "b secret"
|
32
|
+
_(bob.digest).must_equal "b secret"
|
33
33
|
end
|
34
34
|
|
35
35
|
it "encrypts with crypt as a default, when parsed from crypt()'d line" do
|
36
36
|
bob2 = HTAuth::PasswdEntry.from_line(@bob.to_s)
|
37
|
-
bob2.algorithm.must_be_instance_of(
|
38
|
-
bob2.algorithm.size.must_equal 2
|
37
|
+
_(bob2.algorithm).must_be_instance_of(HTAuth::Crypt)
|
39
38
|
bob2.password = "another secret"
|
40
|
-
bob2.algorithm.must_be_instance_of(HTAuth::Crypt)
|
39
|
+
_(bob2.algorithm).must_be_instance_of(HTAuth::Crypt)
|
41
40
|
end
|
42
41
|
|
43
42
|
it "encrypts with crypt as a default, when parsed from plaintext line" do
|
44
43
|
p = HTAuth::PasswdEntry.new('paul', 'p secret', 'plaintext')
|
45
44
|
p2 = HTAuth::PasswdEntry.from_line(p.to_s)
|
46
|
-
p2.algorithm.must_be_instance_of(
|
47
|
-
p2.algorithm.size.must_equal 2
|
45
|
+
_(p2.algorithm).must_be_instance_of(HTAuth::Plaintext)
|
48
46
|
p2.password = "another secret"
|
49
|
-
p2.algorithm.must_be_instance_of(HTAuth::Crypt)
|
47
|
+
_(p2.algorithm).must_be_instance_of(HTAuth::Crypt)
|
50
48
|
end
|
51
49
|
|
52
50
|
it "encrypts with md5 as default, when parsed from an md5 line" do
|
53
51
|
m = HTAuth::PasswdEntry.new("mary", "m secret", "md5")
|
54
52
|
m2 = HTAuth::PasswdEntry.from_line(m.to_s)
|
55
|
-
m2.algorithm.must_be_instance_of(HTAuth::Md5)
|
53
|
+
_(m2.algorithm).must_be_instance_of(HTAuth::Md5)
|
56
54
|
end
|
57
55
|
|
58
56
|
it "encrypts with sha1 as default, when parsed from an sha1 line" do
|
59
57
|
s = HTAuth::PasswdEntry.new("steve", "s secret", "sha1")
|
60
58
|
s2 = HTAuth::PasswdEntry.from_line(s.to_s)
|
61
|
-
s2.algorithm.must_be_instance_of(HTAuth::Sha1)
|
59
|
+
_(s2.algorithm).must_be_instance_of(HTAuth::Sha1)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "encrypts with bcrypt as default when parsed from a bcrypt line" do
|
63
|
+
b = HTAuth::PasswdEntry.new("brenda", "b secret", "bcrypt")
|
64
|
+
b2 = HTAuth::PasswdEntry.from_line(b.to_s)
|
65
|
+
_(b2.algorithm).must_be_instance_of(HTAuth::Bcrypt)
|
62
66
|
end
|
63
67
|
|
64
68
|
it "determins the algorithm to be crypt when checking a password" do
|
65
69
|
bob2 = HTAuth::PasswdEntry.from_line(@bob.to_s)
|
66
|
-
bob2.algorithm.must_be_instance_of(
|
67
|
-
bob2.
|
68
|
-
bob2.
|
69
|
-
bob2.algorithm.must_be_instance_of(HTAuth::Crypt)
|
70
|
+
_(bob2.algorithm).must_be_instance_of(HTAuth::Crypt)
|
71
|
+
_(bob2.authenticated?("b secret")).must_equal true
|
72
|
+
_(bob2.algorithm).must_be_instance_of(HTAuth::Crypt)
|
70
73
|
end
|
71
74
|
|
72
75
|
it "determins the algorithm to be plain when checking a password" do
|
73
76
|
bob2 = HTAuth::PasswdEntry.from_line("bob:b secret")
|
74
|
-
bob2.algorithm.must_be_instance_of(
|
75
|
-
bob2.
|
76
|
-
bob2.
|
77
|
-
bob2.algorithm.must_be_instance_of(HTAuth::Plaintext)
|
77
|
+
_(bob2.algorithm).must_be_instance_of(HTAuth::Plaintext)
|
78
|
+
_(bob2.authenticated?("b secret")).must_equal true
|
79
|
+
_(bob2.algorithm).must_be_instance_of(HTAuth::Plaintext)
|
78
80
|
end
|
79
81
|
|
80
82
|
it "authenticates correctly against md5" do
|
81
83
|
m = HTAuth::PasswdEntry.new("mary", "m secret", "md5")
|
82
84
|
m2 = HTAuth::PasswdEntry.from_line(m.to_s)
|
83
|
-
m2.authenticated?("m secret").must_equal true
|
85
|
+
_(m2.authenticated?("m secret")).must_equal true
|
84
86
|
end
|
85
87
|
|
86
88
|
it "authenticates correctly against sha1" do
|
87
89
|
s = HTAuth::PasswdEntry.new("steve", "s secret", "sha1")
|
88
90
|
s2 = HTAuth::PasswdEntry.from_line(s.to_s)
|
89
|
-
s2.authenticated?("s secret").must_equal true
|
91
|
+
_(s2.authenticated?("s secret")).must_equal true
|
92
|
+
end
|
93
|
+
|
94
|
+
it "authenticates correctly against bcrypt" do
|
95
|
+
s = HTAuth::PasswdEntry.new("brenda", "b secret", "bcrypt")
|
96
|
+
s2 = HTAuth::PasswdEntry.from_line(s.to_s)
|
97
|
+
_(s2.authenticated?("b secret")).must_equal true
|
90
98
|
end
|
91
99
|
|
100
|
+
it "can update the cost of an entry after initialization before encoding password" do
|
101
|
+
s = HTAuth::PasswdEntry.new("brenda", "b secret", "bcrypt")
|
102
|
+
_(s.algorithm.cost).must_equal(::HTAuth::Bcrypt::DEFAULT_APACHE_COST)
|
92
103
|
|
104
|
+
s2 = HTAuth::PasswdEntry.from_line(s.to_s)
|
105
|
+
s2.algorithm_args = { :cost => 12 }
|
106
|
+
s2.password = "b secret" # forces recalculation
|
93
107
|
|
108
|
+
_(s2.algorithm.cost).must_equal(12)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "raises an error if assinging an invalid algorithm" do
|
112
|
+
b = HTAuth::PasswdEntry.new("brenda", "b secret", "bcrypt")
|
113
|
+
_ { b.algorithm = 42 }.must_raise(HTAuth::InvalidAlgorithmError)
|
114
|
+
end
|
94
115
|
|
95
116
|
it "returns username for a key" do
|
96
|
-
@alice.key.must_equal "alice"
|
117
|
+
_(@alice.key).must_equal "alice"
|
97
118
|
end
|
98
119
|
|
99
120
|
it "checks the password correctly" do
|
100
|
-
@bob.authenticated?("b secret").must_equal true
|
121
|
+
_(@bob.authenticated?("b secret")).must_equal true
|
101
122
|
end
|
102
123
|
|
103
124
|
it "formats correctly when put to a string" do
|
104
|
-
@bob.to_s.must_equal "bob:b8Ml4Jp9I0N8E"
|
125
|
+
_(@bob.to_s).must_equal "bob:b8Ml4Jp9I0N8E"
|
105
126
|
end
|
106
127
|
|
107
128
|
it "parses an input line" do
|
108
129
|
@bob_new = HTAuth::PasswdEntry.from_line("bob:b8Ml4Jp9I0N8E")
|
109
|
-
@bob.user.must_equal @bob_new.user
|
110
|
-
@bob.digest.must_equal @bob_new.digest
|
130
|
+
_(@bob.user).must_equal @bob_new.user
|
131
|
+
_(@bob.digest).must_equal @bob_new.digest
|
111
132
|
end
|
112
133
|
|
113
134
|
it "knows if an input line is a possible entry and raises an exception" do
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
135
|
+
_ { HTAuth::PasswdEntry.is_entry!("#stuff") }.must_raise(HTAuth::InvalidPasswdEntry)
|
136
|
+
_ { HTAuth::PasswdEntry.is_entry!("this:that:other:stuff") }.must_raise(HTAuth::InvalidPasswdEntry)
|
137
|
+
_ { HTAuth::PasswdEntry.is_entry!("this:that:other") }.must_raise(HTAuth::InvalidPasswdEntry)
|
138
|
+
_ { HTAuth::PasswdEntry.is_entry!("this:that:0a90549e8ffb2dd62f98252a95d88xyz") }.must_raise(HTAuth::InvalidPasswdEntry)
|
118
139
|
end
|
119
140
|
|
120
141
|
it "knows if an input line is a possible entry and returns false" do
|
121
|
-
HTAuth::PasswdEntry.is_entry?("#stuff").must_equal false
|
122
|
-
HTAuth::PasswdEntry.is_entry?("this:that:other:stuff").must_equal false
|
123
|
-
HTAuth::PasswdEntry.is_entry?("this:that:other").must_equal false
|
124
|
-
HTAuth::PasswdEntry.is_entry?("this:that:0a90549e8ffb2dd62f98252a95d88xyz").must_equal false
|
142
|
+
_(HTAuth::PasswdEntry.is_entry?("#stuff")).must_equal false
|
143
|
+
_(HTAuth::PasswdEntry.is_entry?("this:that:other:stuff")).must_equal false
|
144
|
+
_(HTAuth::PasswdEntry.is_entry?("this:that:other")).must_equal false
|
145
|
+
_(HTAuth::PasswdEntry.is_entry?("this:that:0a90549e8ffb2dd62f98252a95d88xyz")).must_equal false
|
125
146
|
end
|
126
147
|
|
127
148
|
it "knows if an input line is a possible entry and returns true" do
|
128
|
-
HTAuth::PasswdEntry.is_entry?("bob:irRm0g.SDfCyI").must_equal true
|
129
|
-
HTAuth::PasswdEntry.is_entry?("bob:b secreat").must_equal true
|
130
|
-
HTAuth::PasswdEntry.is_entry?("bob:{SHA}b/tjGXbX80MEKVnF200S43ca4hY=").must_equal true
|
131
|
-
HTAuth::PasswdEntry.is_entry?("bob:$apr1$lo1tk/..$CarApvZPee0F6Wj1U0GxZ1").must_equal true
|
132
|
-
|
149
|
+
_(HTAuth::PasswdEntry.is_entry?("bob:irRm0g.SDfCyI")).must_equal true
|
150
|
+
_(HTAuth::PasswdEntry.is_entry?("bob:b secreat")).must_equal true
|
151
|
+
_(HTAuth::PasswdEntry.is_entry?("bob:{SHA}b/tjGXbX80MEKVnF200S43ca4hY=")).must_equal true
|
152
|
+
_(HTAuth::PasswdEntry.is_entry?("bob:$apr1$lo1tk/..$CarApvZPee0F6Wj1U0GxZ1")).must_equal true
|
153
|
+
_(HTAuth::PasswdEntry.is_entry?("bob:$2y$05$ts3k1r.t0Cne6j6DLt0/SepT5X4qthDFEdfqHBBMO5MhqzyMz34j2")).must_equal true
|
133
154
|
end
|
134
155
|
|
135
156
|
it "duplicates itself" do
|
136
|
-
@alice.dup.to_s.must_equal @alice.to_s
|
157
|
+
_(@alice.dup.to_s).must_equal @alice.to_s
|
137
158
|
end
|
138
159
|
end
|
data/spec/passwd_file_spec.rb
CHANGED
@@ -22,45 +22,63 @@ describe HTAuth::PasswdFile do
|
|
22
22
|
|
23
23
|
it "can add a new entry to an already existing passwd file" do
|
24
24
|
@passwd_file.add_or_update("charlie", "c secret", "sha1")
|
25
|
-
@passwd_file.contents.must_equal IO.read(PASSWD_ADD_TEST_FILE)
|
25
|
+
_(@passwd_file.contents).must_equal IO.read(PASSWD_ADD_TEST_FILE)
|
26
26
|
end
|
27
27
|
|
28
28
|
it "can tell if an entry already exists in the passwd file" do
|
29
|
-
@passwd_file.has_entry?("alice").must_equal true
|
30
|
-
@passwd_file.has_entry?("david").must_equal false
|
29
|
+
_(@passwd_file.has_entry?("alice")).must_equal true
|
30
|
+
_(@passwd_file.has_entry?("david")).must_equal false
|
31
31
|
end
|
32
32
|
|
33
33
|
it "can update an entry in an already existing passwd file, algorithm can change" do
|
34
34
|
@passwd_file.add_or_update("alice", "a new secret", "sha1")
|
35
|
-
@passwd_file.contents.must_equal IO.read(PASSWD_UPDATE_TEST_FILE)
|
35
|
+
_(@passwd_file.contents).must_equal IO.read(PASSWD_UPDATE_TEST_FILE)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "can update an entry in an already existing passwd file, algorithm and arguments can change" do
|
39
|
+
@passwd_file.add_or_update("brenda", "b secret", "bcrypt")
|
40
|
+
entry = @passwd_file.fetch("brenda")
|
41
|
+
_(entry.algorithm.cost).must_equal(::HTAuth::Bcrypt::DEFAULT_APACHE_COST)
|
42
|
+
@passwd_file.add_or_update("brenda", "b secret", "bcrypt", :cost => 12)
|
43
|
+
entry = @passwd_file.fetch("brenda")
|
44
|
+
_(entry.algorithm.cost).must_equal(12)
|
36
45
|
end
|
37
46
|
|
38
47
|
it "fetches a copy of an entry" do
|
39
|
-
@passwd_file.fetch("alice").to_s.must_equal "alice:$apr1$DghnA...$CsPcgerfsI/Ryy0AOAJtb0"
|
48
|
+
_(@passwd_file.fetch("alice").to_s).must_equal "alice:$apr1$DghnA...$CsPcgerfsI/Ryy0AOAJtb0"
|
40
49
|
end
|
41
50
|
|
42
|
-
it "raises an error if an attempt is made to alter a non-
|
43
|
-
|
51
|
+
it "raises an error if an attempt is made to alter a non-existent file" do
|
52
|
+
_ { HTAuth::PasswdFile.new("some-file") }.must_raise(HTAuth::FileAccessError)
|
44
53
|
end
|
45
54
|
|
46
55
|
# this test will only work on systems that have /etc/ssh_host_rsa_key
|
47
56
|
it "raises an error if an attempt is made to open a file where no permissions are granted" do
|
48
|
-
|
57
|
+
_ { HTAuth::PasswdFile.new("/etc/ssh_host_rsa_key") }.must_raise(HTAuth::FileAccessError)
|
49
58
|
end
|
50
59
|
|
51
60
|
it "deletes an entry" do
|
52
61
|
@passwd_file.delete("bob")
|
53
|
-
@passwd_file.contents.must_equal IO.read(PASSWD_DELETE_TEST_FILE)
|
62
|
+
_(@passwd_file.contents).must_equal IO.read(PASSWD_DELETE_TEST_FILE)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "checks authentication of an entry - true" do
|
66
|
+
_(@passwd_file.authenticated?("alice", "a secret")).must_equal true
|
54
67
|
end
|
55
68
|
|
56
|
-
it "
|
69
|
+
it "checks authentication of an entry - false" do
|
70
|
+
_(@passwd_file.authenticated?("alice", "the wrong secret")).must_equal false
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
it "is usable in a ruby manner and yields itself when opened" do
|
57
75
|
HTAuth::PasswdFile.open(@tf.path) do |pf|
|
58
76
|
pf.add_or_update("alice", "a new secret", "md5")
|
59
77
|
pf.delete('bob')
|
60
78
|
end
|
61
79
|
lines = IO.readlines(@tf.path)
|
62
|
-
lines.size.must_equal 1
|
63
|
-
lines.first.split(':').first.must_equal "alice"
|
64
|
-
lines.first.split(':').last.must_match( /\$apr1\$/ )
|
80
|
+
_(lines.size).must_equal 1
|
81
|
+
_(lines.first.split(':').first).must_equal "alice"
|
82
|
+
_(lines.first.split(':').last).must_match( /\$apr1\$/ )
|
65
83
|
end
|
66
84
|
end
|
data/spec/plaintext_spec.rb
CHANGED
@@ -2,14 +2,10 @@ require 'spec_helper'
|
|
2
2
|
require 'htauth/plaintext'
|
3
3
|
|
4
4
|
describe HTAuth::Plaintext do
|
5
|
-
it "has a prefix" do
|
6
|
-
HTAuth::Plaintext.new.prefix.must_equal ""
|
7
|
-
end
|
8
|
-
|
9
5
|
it "encrypts the same way that apache does" do
|
10
6
|
apache_result = "a secret"
|
11
7
|
pt = HTAuth::Plaintext.new
|
12
|
-
pt.encode("a secret").must_equal apache_result
|
8
|
+
_(pt.encode("a secret")).must_equal apache_result
|
13
9
|
end
|
14
10
|
end
|
15
11
|
|
data/spec/sha1_spec.rb
CHANGED
@@ -2,14 +2,10 @@ require 'spec_helper'
|
|
2
2
|
require 'htauth/sha1'
|
3
3
|
|
4
4
|
describe HTAuth::Sha1 do
|
5
|
-
it "has a prefix" do
|
6
|
-
HTAuth::Sha1.new.prefix.must_equal "{SHA}"
|
7
|
-
end
|
8
|
-
|
9
5
|
it "encrypts the same way that apache does" do
|
10
6
|
apache_result = "{SHA}ZrnlrvmM7ZCOV3FAvM7la89NKbk="
|
11
7
|
sha1 = HTAuth::Sha1.new
|
12
|
-
sha1.encode("a secret").must_equal apache_result
|
8
|
+
_(sha1.encode("a secret")).must_equal apache_result
|
13
9
|
end
|
14
10
|
end
|
15
11
|
|
data/tasks/default.rake
CHANGED
@@ -38,7 +38,7 @@ task :develop => "develop:default"
|
|
38
38
|
begin
|
39
39
|
require 'rake/testtask'
|
40
40
|
Rake::TestTask.new( :test ) do |t|
|
41
|
-
t.ruby_opts = %w[ -w
|
41
|
+
t.ruby_opts = %w[ -w ]
|
42
42
|
t.libs = %w[ lib spec test ]
|
43
43
|
t.pattern = "{test,spec}/**/{test_*,*_spec}.rb"
|
44
44
|
end
|
@@ -159,7 +159,7 @@ namespace :fixme do
|
|
159
159
|
end
|
160
160
|
|
161
161
|
desc "See if the fixme tools are outdated"
|
162
|
-
task :outdated
|
162
|
+
task :outdated do
|
163
163
|
if fixme_up_to_date? then
|
164
164
|
puts "Fixme files are up to date."
|
165
165
|
else
|
@@ -170,7 +170,7 @@ namespace :fixme do
|
|
170
170
|
end
|
171
171
|
|
172
172
|
desc "Update outdated fixme files"
|
173
|
-
task :update
|
173
|
+
task :update do
|
174
174
|
if fixme_up_to_date? then
|
175
175
|
puts "Fixme files are already up to date."
|
176
176
|
else
|
data/tasks/this.rb
CHANGED
@@ -28,7 +28,7 @@ class ThisProject
|
|
28
28
|
@exclude_from_manifest = Regexp.union(/\.(git|DS_Store)/,
|
29
29
|
/^(doc|coverage|pkg|tmp|Gemfile(\.lock)?)/,
|
30
30
|
/^[^\/]+\.gemspec/,
|
31
|
-
/\.(swp|jar|bundle|so|rvmrc|travis.yml)$/,
|
31
|
+
/\.(swp|jar|bundle|so|rvmrc|travis.yml|byebug_history|fossa.yml|ruby-version)$/,
|
32
32
|
/~$/)
|
33
33
|
@gemspecs = Hash.new
|
34
34
|
yield self if block_given?
|
@@ -146,7 +146,7 @@ class ThisProject
|
|
146
146
|
spec.rdoc_options = [ "--main" , 'README.md',
|
147
147
|
"--markup", "tomdoc" ]
|
148
148
|
|
149
|
-
spec.required_ruby_version = '>=
|
149
|
+
spec.required_ruby_version = '>= 2.2.2'
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
metadata
CHANGED
@@ -1,71 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: htauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Hinegardner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bcrypt
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.1'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rake
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - "~>"
|
18
32
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
33
|
+
version: '13.0'
|
20
34
|
type: :development
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
38
|
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
40
|
+
version: '13.0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: minitest
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version: '5.
|
47
|
+
version: '5.5'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: '5.
|
54
|
+
version: '5.5'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rdoc
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
61
|
+
version: '6.2'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
68
|
+
version: '6.2'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: simplecov
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
73
|
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0.
|
75
|
+
version: '0.17'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0.
|
82
|
+
version: '0.17'
|
69
83
|
description: HTAuth is a pure ruby replacement for the Apache support programs htdigest
|
70
84
|
and htpasswd. Command line and API access are provided for access to htdigest and
|
71
85
|
htpasswd files.
|
@@ -90,11 +104,13 @@ files:
|
|
90
104
|
- bin/htpasswd-ruby
|
91
105
|
- lib/htauth.rb
|
92
106
|
- lib/htauth/algorithm.rb
|
107
|
+
- lib/htauth/bcrypt.rb
|
93
108
|
- lib/htauth/cli.rb
|
94
109
|
- lib/htauth/cli/digest.rb
|
95
110
|
- lib/htauth/cli/passwd.rb
|
96
111
|
- lib/htauth/console.rb
|
97
112
|
- lib/htauth/crypt.rb
|
113
|
+
- lib/htauth/descendant_tracker.rb
|
98
114
|
- lib/htauth/digest_entry.rb
|
99
115
|
- lib/htauth/digest_file.rb
|
100
116
|
- lib/htauth/entry.rb
|
@@ -106,6 +122,8 @@ files:
|
|
106
122
|
- lib/htauth/plaintext.rb
|
107
123
|
- lib/htauth/sha1.rb
|
108
124
|
- lib/htauth/version.rb
|
125
|
+
- spec/algorithm_spec.rb
|
126
|
+
- spec/bcrypt_spec.rb
|
109
127
|
- spec/cli/digest_spec.rb
|
110
128
|
- spec/cli/passwd_spec.rb
|
111
129
|
- spec/crypt_spec.rb
|
@@ -143,21 +161,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
143
161
|
requirements:
|
144
162
|
- - ">="
|
145
163
|
- !ruby/object:Gem::Version
|
146
|
-
version:
|
164
|
+
version: 2.2.2
|
147
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
166
|
requirements:
|
149
167
|
- - ">="
|
150
168
|
- !ruby/object:Gem::Version
|
151
169
|
version: '0'
|
152
170
|
requirements: []
|
153
|
-
|
154
|
-
rubygems_version: 2.4.5
|
171
|
+
rubygems_version: 3.0.3
|
155
172
|
signing_key:
|
156
173
|
specification_version: 4
|
157
174
|
summary: HTAuth is a pure ruby replacement for the Apache support programs htdigest
|
158
175
|
and htpasswd. Command line and API access are provided for access to htdigest and
|
159
176
|
htpasswd files.
|
160
177
|
test_files:
|
178
|
+
- spec/algorithm_spec.rb
|
179
|
+
- spec/bcrypt_spec.rb
|
161
180
|
- spec/cli/digest_spec.rb
|
162
181
|
- spec/cli/passwd_spec.rb
|
163
182
|
- spec/crypt_spec.rb
|