metasploit-credential 0.14.5 → 0.14.6

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