metasploit-credential 0.14.7 → 0.14.8
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 +4 -4
- data/CONTRIBUTING.md +41 -9
- data/lib/metasploit/credential/exporter/core.rb +2 -2
- data/lib/metasploit/credential/exporter/pwdump.rb +2 -2
- data/lib/metasploit/credential/migrator.rb +1 -1
- data/lib/metasploit/credential/version.rb +12 -21
- data/spec/dummy/db/structure.sql +0 -1
- data/spec/lib/metasploit/credential/creation_spec.rb +8 -6
- data/spec/lib/metasploit/credential/exporter/core_spec.rb +85 -100
- data/spec/lib/metasploit/credential/exporter/pwdump_spec.rb +16 -14
- data/spec/lib/metasploit/credential/importer/core_spec.rb +12 -10
- data/spec/lib/metasploit/credential/importer/multi_spec.rb +6 -4
- data/spec/lib/metasploit/credential/importer/pwdump_spec.rb +13 -11
- data/spec/lib/metasploit/credential/importer/zip_spec.rb +7 -5
- data/spec/lib/metasploit/credential/migrator_spec.rb +13 -13
- data/spec/lib/metasploit/credential/version_spec.rb +141 -3
- data/spec/lib/metasploit/credential_spec.rb +15 -4
- data/spec/models/mdm/service_spec.rb +5 -3
- data/spec/models/mdm/session_spec.rb +4 -2
- data/spec/models/mdm/task_spec.rb +6 -4
- data/spec/models/mdm/user_spec.rb +4 -2
- data/spec/models/mdm/workspace_spec.rb +4 -2
- data/spec/models/metasploit/credential/blank_username_spec.rb +7 -5
- data/spec/models/metasploit/credential/core_spec.rb +45 -43
- data/spec/models/metasploit/credential/login/status_spec.rb +21 -19
- data/spec/models/metasploit/credential/login_spec.rb +38 -36
- data/spec/models/metasploit/credential/nonreplayable_hash_spec.rb +5 -3
- data/spec/models/metasploit/credential/ntlm_hash_spec.rb +15 -13
- data/spec/models/metasploit/credential/origin/cracked_password_spec.rb +7 -5
- data/spec/models/metasploit/credential/origin/import_spec.rb +10 -8
- data/spec/models/metasploit/credential/origin/manual_spec.rb +9 -7
- data/spec/models/metasploit/credential/origin/service_spec.rb +12 -10
- data/spec/models/metasploit/credential/origin/session_spec.rb +13 -11
- data/spec/models/metasploit/credential/password_hash_spec.rb +6 -4
- data/spec/models/metasploit/credential/password_spec.rb +5 -3
- data/spec/models/metasploit/credential/postgres_md5_spec.rb +6 -4
- data/spec/models/metasploit/credential/private_spec.rb +10 -8
- data/spec/models/metasploit/credential/public_spec.rb +7 -5
- data/spec/models/metasploit/credential/realm_spec.rb +16 -14
- data/spec/models/metasploit/credential/replayable_hash_spec.rb +5 -3
- data/spec/models/metasploit/credential/ssh_key_spec.rb +17 -15
- data/spec/models/metasploit/credential/username_spec.rb +8 -6
- data/spec/models/metasploit_data_models/search/visitor/relation_spec.rb +3 -1
- data/spec/spec_helper.rb +25 -95
- data/spec/support/shared/contexts/mdm/workspace.rb +1 -1
- data/spec/support/shared/examples/core_validations.rb +42 -117
- data/spec/support/shared/examples/single_table_inheritance_database_columns.rb +2 -2
- data/spec/support/shared/examples/timestamp_database_column.rb +2 -2
- metadata +8 -22
@@ -1,10 +1,12 @@
|
|
1
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metasploit::Credential::Login do
|
2
4
|
it_should_behave_like 'Metasploit::Concern.run'
|
3
5
|
|
4
6
|
context 'associations' do
|
5
|
-
it {
|
6
|
-
it {
|
7
|
-
it {
|
7
|
+
it { should belong_to(:core).class_name('Metasploit::Credential::Core') }
|
8
|
+
it { should have_one(:host).class_name('Mdm::Host') }
|
9
|
+
it { should belong_to(:service).class_name('Mdm::Service')}
|
8
10
|
end
|
9
11
|
|
10
12
|
context 'callbacks' do
|
@@ -37,7 +39,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
37
39
|
''
|
38
40
|
end
|
39
41
|
|
40
|
-
it {
|
42
|
+
it { should be_nil }
|
41
43
|
end
|
42
44
|
|
43
45
|
context 'with nil' do
|
@@ -45,7 +47,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
45
47
|
nil
|
46
48
|
end
|
47
49
|
|
48
|
-
it {
|
50
|
+
it { should be_nil }
|
49
51
|
end
|
50
52
|
|
51
53
|
context 'with present' do
|
@@ -64,21 +66,21 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
64
66
|
|
65
67
|
context 'database' do
|
66
68
|
context 'columns' do
|
67
|
-
it {
|
68
|
-
it {
|
69
|
-
it {
|
69
|
+
it { should have_db_column(:access_level).of_type(:string).with_options(null: true) }
|
70
|
+
it { should have_db_column(:last_attempted_at).of_type(:datetime).with_options(null: true) }
|
71
|
+
it { should have_db_column(:status).of_type(:string).with_options(null: false) }
|
70
72
|
|
71
73
|
it_should_behave_like 'timestamp database columns'
|
72
74
|
|
73
75
|
context 'foreign keys' do
|
74
|
-
it {
|
75
|
-
it {
|
76
|
+
it { should have_db_column(:core_id).of_type(:integer).with_options(null: false) }
|
77
|
+
it { should have_db_column(:service_id).of_type(:integer).with_options(null: false) }
|
76
78
|
end
|
77
79
|
end
|
78
80
|
|
79
81
|
context 'indices' do
|
80
|
-
it {
|
81
|
-
it {
|
82
|
+
it { should have_db_index([:core_id, :service_id]).unique(true) }
|
83
|
+
it { should have_db_index([:service_id, :core_id]).unique(true) }
|
82
84
|
end
|
83
85
|
end
|
84
86
|
|
@@ -90,7 +92,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
90
92
|
FactoryGirl.build(:metasploit_credential_login)
|
91
93
|
end
|
92
94
|
|
93
|
-
it {
|
95
|
+
it { should be_valid }
|
94
96
|
|
95
97
|
context '#status' do
|
96
98
|
subject(:metasploit_credential_login) do
|
@@ -105,7 +107,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
105
107
|
Metasploit::Model::Login::Status::DENIED_ACCESS
|
106
108
|
end
|
107
109
|
|
108
|
-
it {
|
110
|
+
it { should be_valid }
|
109
111
|
end
|
110
112
|
|
111
113
|
context 'with Metasploit::Model::Login::Status::DISABLED' do
|
@@ -113,7 +115,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
113
115
|
Metasploit::Model::Login::Status::DISABLED
|
114
116
|
end
|
115
117
|
|
116
|
-
it {
|
118
|
+
it { should be_valid }
|
117
119
|
end
|
118
120
|
|
119
121
|
context 'with Metasploit::Model::Login::Status::LOCKED_OUT' do
|
@@ -121,7 +123,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
121
123
|
Metasploit::Model::Login::Status::LOCKED_OUT
|
122
124
|
end
|
123
125
|
|
124
|
-
it {
|
126
|
+
it { should be_valid }
|
125
127
|
end
|
126
128
|
|
127
129
|
context 'with Metasploit::Model::Login::Status::SUCCESSFUL' do
|
@@ -129,7 +131,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
129
131
|
Metasploit::Model::Login::Status::SUCCESSFUL
|
130
132
|
end
|
131
133
|
|
132
|
-
it {
|
134
|
+
it { should be_valid }
|
133
135
|
end
|
134
136
|
|
135
137
|
context 'with Metasploit::Model::Login::Status::UNABLE_TO_CONNECT' do
|
@@ -137,7 +139,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
137
139
|
Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
|
138
140
|
end
|
139
141
|
|
140
|
-
it {
|
142
|
+
it { should be_valid }
|
141
143
|
end
|
142
144
|
|
143
145
|
context 'with Metasploit::Model::Login::Status::UNTRIED' do
|
@@ -145,21 +147,21 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
145
147
|
Metasploit::Model::Login::Status::UNTRIED
|
146
148
|
end
|
147
149
|
|
148
|
-
it {
|
150
|
+
it { should be_valid }
|
149
151
|
end
|
150
152
|
end
|
151
153
|
end
|
152
154
|
end
|
153
155
|
|
154
156
|
context 'mass assignment security' do
|
155
|
-
it {
|
157
|
+
it { should allow_mass_assignment_of(:access_level) }
|
156
158
|
it { should_not allow_mass_assignment_of(:core) }
|
157
159
|
it { should_not allow_mass_assignment_of(:core_id) }
|
158
160
|
it { should_not allow_mass_assignment_of(:created_at) }
|
159
|
-
it {
|
161
|
+
it { should allow_mass_assignment_of(:last_attempted_at) }
|
160
162
|
it { should_not allow_mass_assignment_of(:service) }
|
161
163
|
it { should_not allow_mass_assignment_of(:service_id) }
|
162
|
-
it {
|
164
|
+
it { should allow_mass_assignment_of(:status) }
|
163
165
|
it { should_not allow_mass_assignment_of(:updated_at) }
|
164
166
|
end
|
165
167
|
|
@@ -189,7 +191,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
189
191
|
end
|
190
192
|
|
191
193
|
context 'validations' do
|
192
|
-
it {
|
194
|
+
it { should validate_presence_of :core }
|
193
195
|
|
194
196
|
context 'with existent Metasploit::Credential::Login' do
|
195
197
|
include_context 'Mdm::Workspace'
|
@@ -202,11 +204,11 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
202
204
|
)
|
203
205
|
end
|
204
206
|
|
205
|
-
it {
|
207
|
+
it { should validate_uniqueness_of(:core_id).scoped_to(:service_id) }
|
206
208
|
end
|
207
209
|
|
208
|
-
it {
|
209
|
-
it {
|
210
|
+
it { should validate_presence_of :service }
|
211
|
+
it { should ensure_inclusion_of(:status).in_array(Metasploit::Model::Login::Status::ALL) }
|
210
212
|
|
211
213
|
context '#consistent_last_attempted_at' do
|
212
214
|
include_context 'Mdm::Workspace'
|
@@ -250,7 +252,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
250
252
|
DateTime.now.utc
|
251
253
|
end
|
252
254
|
|
253
|
-
it {
|
255
|
+
it { should include(error) }
|
254
256
|
end
|
255
257
|
|
256
258
|
context 'without #last_attempted' do
|
@@ -288,7 +290,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
288
290
|
nil
|
289
291
|
end
|
290
292
|
|
291
|
-
it {
|
293
|
+
it { should include(error) }
|
292
294
|
end
|
293
295
|
end
|
294
296
|
end
|
@@ -361,7 +363,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
361
363
|
FactoryGirl.build(:mdm_workspace)
|
362
364
|
end
|
363
365
|
|
364
|
-
it {
|
366
|
+
it { should include(error) }
|
365
367
|
end
|
366
368
|
end
|
367
369
|
|
@@ -370,7 +372,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
370
372
|
nil
|
371
373
|
end
|
372
374
|
|
373
|
-
it {
|
375
|
+
it { should include(error) }
|
374
376
|
end
|
375
377
|
end
|
376
378
|
|
@@ -379,7 +381,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
379
381
|
nil
|
380
382
|
end
|
381
383
|
|
382
|
-
it {
|
384
|
+
it { should include(error) }
|
383
385
|
end
|
384
386
|
end
|
385
387
|
|
@@ -388,7 +390,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
388
390
|
nil
|
389
391
|
end
|
390
392
|
|
391
|
-
it {
|
393
|
+
it { should include(error) }
|
392
394
|
end
|
393
395
|
end
|
394
396
|
|
@@ -420,7 +422,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
420
422
|
FactoryGirl.build(:mdm_workspace)
|
421
423
|
end
|
422
424
|
|
423
|
-
it {
|
425
|
+
it { should include(error) }
|
424
426
|
end
|
425
427
|
|
426
428
|
context 'without Mdm::Host#workspace' do
|
@@ -477,7 +479,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
477
479
|
FactoryGirl.build(:mdm_workspace)
|
478
480
|
end
|
479
481
|
|
480
|
-
it {
|
482
|
+
it { should include(error) }
|
481
483
|
end
|
482
484
|
|
483
485
|
context 'without Mdm::Host#workspace' do
|
@@ -520,7 +522,7 @@ RSpec.describe Metasploit::Credential::Login, type: :model do
|
|
520
522
|
subject(:login){ FactoryGirl.create :metasploit_credential_login, core: core}
|
521
523
|
|
522
524
|
it 'should find the right objects' do
|
523
|
-
|
525
|
+
Metasploit::Credential::Login.in_workspace_including_hosts_and_services(service.host.workspace).should include(login)
|
524
526
|
end
|
525
527
|
end
|
526
528
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metasploit::Credential::NonreplayableHash do
|
2
4
|
it_should_behave_like 'Metasploit::Concern.run'
|
3
5
|
|
4
|
-
it {
|
6
|
+
it { should be_a Metasploit::Credential::PasswordHash }
|
5
7
|
|
6
8
|
context 'factories' do
|
7
9
|
context 'metasploit_credential_nonreplayable_hash' do
|
@@ -9,7 +11,7 @@ RSpec.describe Metasploit::Credential::NonreplayableHash, type: :model do
|
|
9
11
|
FactoryGirl.build(:metasploit_credential_nonreplayable_hash)
|
10
12
|
end
|
11
13
|
|
12
|
-
it {
|
14
|
+
it { should be_valid }
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metasploit::Credential::NTLMHash do
|
2
4
|
it_should_behave_like 'Metasploit::Concern.run'
|
3
5
|
|
4
|
-
it {
|
6
|
+
it { should be_a Metasploit::Credential::ReplayableHash }
|
5
7
|
|
6
8
|
context 'CONSTANTS' do
|
7
9
|
context 'DATA_REGEXP' do
|
@@ -36,7 +38,7 @@ RSpec.describe Metasploit::Credential::NTLMHash, type: :model do
|
|
36
38
|
described_class::LAN_MANAGER_MAX_CHARACTERS
|
37
39
|
end
|
38
40
|
|
39
|
-
it {
|
41
|
+
it { should == 14 }
|
40
42
|
end
|
41
43
|
|
42
44
|
context 'LAN_MANAGER_HEX_DIGEST_REGEXP' do
|
@@ -99,7 +101,7 @@ RSpec.describe Metasploit::Credential::NTLMHash, type: :model do
|
|
99
101
|
nil
|
100
102
|
end
|
101
103
|
|
102
|
-
it {
|
104
|
+
it { should be_nil }
|
103
105
|
end
|
104
106
|
|
105
107
|
context 'with upper case characters' do
|
@@ -131,7 +133,7 @@ RSpec.describe Metasploit::Credential::NTLMHash, type: :model do
|
|
131
133
|
FactoryGirl.build(:metasploit_credential_ntlm_hash)
|
132
134
|
end
|
133
135
|
|
134
|
-
it {
|
136
|
+
it { should be_valid }
|
135
137
|
end
|
136
138
|
end
|
137
139
|
|
@@ -189,7 +191,7 @@ RSpec.describe Metasploit::Credential::NTLMHash, type: :model do
|
|
189
191
|
super().gsub(':', '')
|
190
192
|
end
|
191
193
|
|
192
|
-
it {
|
194
|
+
it { should include(error) }
|
193
195
|
end
|
194
196
|
|
195
197
|
context 'without LAN Manager hex_digest' do
|
@@ -197,7 +199,7 @@ RSpec.describe Metasploit::Credential::NTLMHash, type: :model do
|
|
197
199
|
":#{nt_lan_manager_hex_digest}"
|
198
200
|
end
|
199
201
|
|
200
|
-
it {
|
202
|
+
it { should include(error) }
|
201
203
|
end
|
202
204
|
|
203
205
|
context 'with incorrect hash length(s)' do
|
@@ -205,7 +207,7 @@ RSpec.describe Metasploit::Credential::NTLMHash, type: :model do
|
|
205
207
|
"123456:abcdef"
|
206
208
|
end
|
207
209
|
|
208
|
-
it {
|
210
|
+
it { should include(error) }
|
209
211
|
end
|
210
212
|
end
|
211
213
|
end
|
@@ -373,26 +375,26 @@ RSpec.describe Metasploit::Credential::NTLMHash, type: :model do
|
|
373
375
|
context 'blank_password?' do
|
374
376
|
|
375
377
|
it 'returns true if the hash is for a blank password' do
|
376
|
-
expect(blank_password_hash.blank_password?).to
|
378
|
+
expect(blank_password_hash.blank_password?).to be_true
|
377
379
|
end
|
378
380
|
|
379
381
|
it 'returns false if the hash is not for a blank password' do
|
380
|
-
expect(non_blank_password.blank_password?).to
|
382
|
+
expect(non_blank_password.blank_password?).to be_false
|
381
383
|
end
|
382
384
|
|
383
385
|
it 'returns false if the nt hash is not blank but the lm hash is' do
|
384
|
-
expect(no_lm_hash.blank_password?).to
|
386
|
+
expect(no_lm_hash.blank_password?).to be_false
|
385
387
|
end
|
386
388
|
end
|
387
389
|
|
388
390
|
context 'lm_hash_present?' do
|
389
391
|
|
390
392
|
it 'returns false if the lm_hash is blank' do
|
391
|
-
expect(no_lm_hash.lm_hash_present?).to
|
393
|
+
expect(no_lm_hash.lm_hash_present?).to be_false
|
392
394
|
end
|
393
395
|
|
394
396
|
it 'returns true if the lm_hash is not blank' do
|
395
|
-
expect(non_blank_password.lm_hash_present?).to
|
397
|
+
expect(non_blank_password.lm_hash_present?).to be_true
|
396
398
|
end
|
397
399
|
end
|
398
400
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metasploit::Credential::Origin::CrackedPassword do
|
2
4
|
it_should_behave_like 'Metasploit::Concern.run'
|
3
5
|
|
4
6
|
context 'associations' do
|
5
|
-
it {
|
6
|
-
it {
|
7
|
+
it { should have_many(:cores).class_name('Metasploit::Credential::Core').dependent(:destroy) }
|
8
|
+
it { should belong_to(:originating_core).class_name('Metasploit::Credential::Core') }
|
7
9
|
end
|
8
10
|
|
9
11
|
context 'database' do
|
@@ -11,13 +13,13 @@ RSpec.describe Metasploit::Credential::Origin::CrackedPassword, type: :model do
|
|
11
13
|
it_should_behave_like 'timestamp database columns'
|
12
14
|
|
13
15
|
context 'foreign keys' do
|
14
|
-
it {
|
16
|
+
it { should have_db_column(:metasploit_credential_core_id).of_type(:integer).with_options(null: false) }
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
18
20
|
context 'indices' do
|
19
21
|
context 'foreign keys' do
|
20
|
-
it {
|
22
|
+
it { should have_db_index(:metasploit_credential_core_id) }
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
@@ -1,25 +1,27 @@
|
|
1
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metasploit::Credential::Origin::Import do
|
2
4
|
it_should_behave_like 'Metasploit::Concern.run'
|
3
5
|
|
4
6
|
context 'associations' do
|
5
|
-
it {
|
6
|
-
it {
|
7
|
+
it { should have_many(:cores).class_name('Metasploit::Credential::Core').dependent(:destroy) }
|
8
|
+
it { should belong_to(:task).class_name('Mdm::Task') }
|
7
9
|
end
|
8
10
|
|
9
11
|
context 'database' do
|
10
12
|
context 'columns' do
|
11
|
-
it {
|
13
|
+
it { should have_db_column(:filename).of_type(:text).with_options(null: false) }
|
12
14
|
|
13
15
|
it_should_behave_like 'timestamp database columns'
|
14
16
|
|
15
17
|
context 'foreign keys' do
|
16
|
-
it {
|
18
|
+
it { should have_db_column(:task_id).of_type(:integer) }
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
22
|
context 'indices' do
|
21
23
|
context 'foreign keys' do
|
22
|
-
it {
|
24
|
+
it { should have_db_index(:task_id) }
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
@@ -31,12 +33,12 @@ RSpec.describe Metasploit::Credential::Origin::Import, type: :model do
|
|
31
33
|
FactoryGirl.build(:metasploit_credential_origin_import)
|
32
34
|
end
|
33
35
|
|
34
|
-
it {
|
36
|
+
it { should be_valid }
|
35
37
|
end
|
36
38
|
|
37
39
|
context 'mass assignment security' do
|
38
40
|
it { should_not allow_mass_assignment_of :created_at }
|
39
|
-
it {
|
41
|
+
it { should allow_mass_assignment_of :filename }
|
40
42
|
it { should_not allow_mass_assignment_of :task }
|
41
43
|
it { should_not allow_mass_assignment_of :task_id }
|
42
44
|
it { should_not allow_mass_assignment_of :updated_at }
|
@@ -1,15 +1,17 @@
|
|
1
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metasploit::Credential::Origin::Manual do
|
2
4
|
it_should_behave_like 'Metasploit::Concern.run'
|
3
5
|
|
4
6
|
context 'associations' do
|
5
|
-
it {
|
6
|
-
it {
|
7
|
+
it { should have_many(:cores).class_name('Metasploit::Credential::Core').dependent(:destroy) }
|
8
|
+
it { should belong_to(:user).class_name('Mdm::User') }
|
7
9
|
end
|
8
10
|
|
9
11
|
context 'database' do
|
10
12
|
context 'columns' do
|
11
13
|
context 'foreign keys' do
|
12
|
-
it {
|
14
|
+
it { should have_db_column(:user_id).of_type(:integer).with_options(null: false) }
|
13
15
|
end
|
14
16
|
|
15
17
|
it_should_behave_like 'timestamp database columns'
|
@@ -17,7 +19,7 @@ RSpec.describe Metasploit::Credential::Origin::Manual, type: :model do
|
|
17
19
|
|
18
20
|
context 'indices' do
|
19
21
|
context 'foreign keys' do
|
20
|
-
it {
|
22
|
+
it { should have_db_index(:user_id) }
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
@@ -28,11 +30,11 @@ RSpec.describe Metasploit::Credential::Origin::Manual, type: :model do
|
|
28
30
|
FactoryGirl.build(:metasploit_credential_origin_manual)
|
29
31
|
end
|
30
32
|
|
31
|
-
it {
|
33
|
+
it { should be_valid }
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
35
37
|
context 'validations' do
|
36
|
-
it {
|
38
|
+
it { should validate_presence_of :user }
|
37
39
|
end
|
38
40
|
end
|