ddr-models 1.2.1 → 1.3.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 +4 -4
- data/README.md +75 -1
- data/app/models/attachment.rb +6 -1
- data/app/models/collection.rb +19 -1
- data/app/models/component.rb +6 -1
- data/app/models/item.rb +6 -1
- data/app/models/solr_document.rb +3 -0
- data/app/models/target.rb +8 -1
- data/config/initializers/devise.rb~ +245 -0
- data/db/migrate/20141104181418_create_users.rb~ +6 -0
- data/lib/ddr/auth.rb +6 -1
- data/lib/ddr/auth.rb~ +47 -0
- data/lib/ddr/auth/ability.rb +5 -0
- data/lib/ddr/auth/ability.rb~ +204 -0
- data/lib/ddr/auth/group_service.rb~ +53 -0
- data/lib/ddr/auth/grouper_service.rb~ +77 -0
- data/lib/ddr/auth/remote_group_service.rb~ +35 -0
- data/lib/ddr/auth/superuser.rb~ +9 -0
- data/lib/ddr/auth/user.rb~ +65 -0
- data/lib/ddr/index_fields.rb +2 -2
- data/lib/ddr/models.rb +21 -4
- data/lib/ddr/models/engine.rb +26 -13
- data/lib/ddr/models/version.rb +1 -1
- data/lib/ddr/services/id_service.rb +4 -2
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/log/development.log +2727 -1701
- data/spec/dummy/log/test.log +56845 -35270
- data/spec/factories/attachment_factories.rb +0 -4
- data/spec/factories/collection_factories.rb +0 -8
- data/spec/factories/component_factories.rb +1 -6
- data/spec/factories/item_factories.rb +0 -8
- data/spec/factories/user_factories.rb~ +7 -0
- data/spec/features/grouper_integration_spec.rb~ +21 -0
- data/spec/models/ability_spec.rb +11 -24
- data/spec/models/ability_spec.rb~ +245 -0
- data/spec/models/superuser_spec.rb~ +13 -0
- data/spec/models/user_spec.rb~ +56 -0
- data/spec/services/group_service_spec.rb~ +71 -0
- data/spec/spec_helper.rb +16 -25
- metadata +23 -18
- data/config/initializers/ddr.rb +0 -8
- data/lib/ddr/configurable.rb +0 -34
@@ -3,14 +3,6 @@ FactoryGirl.define do
|
|
3
3
|
factory :collection do
|
4
4
|
title [ "Test Collection" ]
|
5
5
|
sequence(:identifier) { |n| [ "coll%05d" % n ] }
|
6
|
-
|
7
|
-
trait :has_item do
|
8
|
-
children { [ FactoryGirl.create(:item) ] }
|
9
|
-
end
|
10
|
-
|
11
|
-
trait :has_target do
|
12
|
-
targets { [ FactoryGirl.create(:target) ] }
|
13
|
-
end
|
14
6
|
end
|
15
7
|
|
16
8
|
end
|
@@ -5,11 +5,6 @@ FactoryGirl.define do
|
|
5
5
|
sequence(:identifier) { |n| [ "cmp%05d" % n ] }
|
6
6
|
after(:build) do |c|
|
7
7
|
c.upload File.new(File.join(Ddr::Models::Engine.root.to_s, "spec", "fixtures", "library-devil.tiff"))
|
8
|
-
end
|
9
|
-
|
10
|
-
trait :has_parent do
|
11
|
-
item
|
12
|
-
end
|
13
|
-
|
8
|
+
end
|
14
9
|
end
|
15
10
|
end
|
@@ -3,14 +3,6 @@ FactoryGirl.define do
|
|
3
3
|
factory :item do
|
4
4
|
title [ "Test Item" ]
|
5
5
|
sequence(:identifier) { |n| [ "item%05d" % n ] }
|
6
|
-
|
7
|
-
trait :member_of_collection do
|
8
|
-
collection
|
9
|
-
end
|
10
|
-
|
11
|
-
trait :has_part do
|
12
|
-
children { [ FactoryGirl.create(:component) ] }
|
13
|
-
end
|
14
6
|
end
|
15
7
|
|
16
8
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dul_hydra'
|
3
|
+
|
4
|
+
describe "Grouper integration", :type => :feature do
|
5
|
+
let(:user) { FactoryGirl.create(:user) }
|
6
|
+
let(:object) { FactoryGirl.create(:collection) }
|
7
|
+
before do
|
8
|
+
object.title = [ "Grouper Works!" ]
|
9
|
+
object.read_groups = ["duke:library:repository:ddr:foo:bar"]
|
10
|
+
object.save!
|
11
|
+
Warden.on_next_request do |proxy|
|
12
|
+
proxy.env[DulHydra.remote_groups_env_key] = "urn:mace:duke.edu:groups:library:repository:ddr:foo:bar"
|
13
|
+
proxy.set_user user
|
14
|
+
end
|
15
|
+
end
|
16
|
+
it "should honor Grouper group access control" do
|
17
|
+
visit url_for(object)
|
18
|
+
expect(page).to have_content("Grouper Works!")
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/spec/models/ability_spec.rb
CHANGED
@@ -8,6 +8,17 @@ module Ddr
|
|
8
8
|
subject { described_class.new(user) }
|
9
9
|
let(:user) { FactoryGirl.create(:user) }
|
10
10
|
|
11
|
+
describe "collection permissions" do
|
12
|
+
before { allow(Ddr::Auth).to receive(:collection_creators_group) { "Collection Creators" } }
|
13
|
+
context "user is a collection creator" do
|
14
|
+
before { allow(user).to receive(:groups) { ["Collection Creators"] } }
|
15
|
+
it { is_expected.to be_able_to(:create, Collection) }
|
16
|
+
end
|
17
|
+
context "user is not a collection creator" do
|
18
|
+
it { is_expected.not_to be_able_to(:create, Collection) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
11
22
|
describe "#upload_permissions", uploads: true do
|
12
23
|
let(:resource) { FactoryGirl.build(:component) }
|
13
24
|
context "user has edit permission" do
|
@@ -181,30 +192,6 @@ module Ddr
|
|
181
192
|
end
|
182
193
|
end
|
183
194
|
|
184
|
-
# describe "#export_sets_permissions", export_sets: true do
|
185
|
-
# let(:resource) { ExportSet.new(user: user) }
|
186
|
-
# context "associated user" do
|
187
|
-
# it { is_expected.to be_able_to(:manage, resource) }
|
188
|
-
# end
|
189
|
-
# context "other user" do
|
190
|
-
# subject { described_class.new(other_user) }
|
191
|
-
# let(:other_user) { FactoryGirl.create(:user) }
|
192
|
-
# it { is_expected.not_to be_able_to(:read, resource) }
|
193
|
-
# end
|
194
|
-
# end
|
195
|
-
|
196
|
-
# describe "#ingest_folders_permissions", ingest_folders: true do
|
197
|
-
# let(:resource) { IngestFolder }
|
198
|
-
# context "user has no permitted ingest folders" do
|
199
|
-
# before { allow(resource).to receive(:permitted_folders).with(user).and_return([]) }
|
200
|
-
# it { is_expected.not_to be_able_to(:create, resource) }
|
201
|
-
# end
|
202
|
-
# context "user has at least one permitted ingest folder" do
|
203
|
-
# before { allow(resource).to receive(:permitted_folders).with(user).and_return(['dir']) }
|
204
|
-
# it { is_expected.to be_able_to(:create, resource) }
|
205
|
-
# end
|
206
|
-
# end
|
207
|
-
|
208
195
|
describe "#attachment_permissions", attachments: true do
|
209
196
|
context "object can have attachments" do
|
210
197
|
let(:resource) { FactoryGirl.build(:test_model_omnibus) }
|
@@ -0,0 +1,245 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dul_hydra'
|
3
|
+
require 'cancan/matchers'
|
4
|
+
|
5
|
+
describe Ability, type: :model, abilities: true do
|
6
|
+
|
7
|
+
subject { described_class.new(user) }
|
8
|
+
let(:user) { FactoryGirl.create(:user) }
|
9
|
+
|
10
|
+
describe "#upload_permissions", uploads: true do
|
11
|
+
let(:resource) { FactoryGirl.build(:component) }
|
12
|
+
context "user has edit permission" do
|
13
|
+
before { subject.can(:edit, resource) }
|
14
|
+
it { is_expected.to be_able_to(:upload, resource) }
|
15
|
+
end
|
16
|
+
context "user does not have edit permission" do
|
17
|
+
before { subject.cannot(:edit, resource) }
|
18
|
+
it { is_expected.not_to be_able_to(:upload, resource) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#download_permissions", downloads: true do
|
23
|
+
context "on an object" do
|
24
|
+
context "which is a Component", components: true do
|
25
|
+
let!(:resource) { FactoryGirl.create(:component) }
|
26
|
+
context "and user does NOT have the downloader role" do
|
27
|
+
context "and user has edit permission" do
|
28
|
+
before do
|
29
|
+
resource.edit_users = [user.user_key]
|
30
|
+
resource.save
|
31
|
+
end
|
32
|
+
it { is_expected.to be_able_to(:download, resource) }
|
33
|
+
end
|
34
|
+
context "and user has read permission" do
|
35
|
+
before do
|
36
|
+
resource.read_users = [user.user_key]
|
37
|
+
resource.save
|
38
|
+
end
|
39
|
+
it { is_expected.not_to be_able_to(:download, resource) }
|
40
|
+
end
|
41
|
+
context "and user lacks read permission" do
|
42
|
+
it { is_expected.not_to be_able_to(:download, resource) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "and user has the downloader role", roles: true do
|
47
|
+
before do
|
48
|
+
resource.roleAssignments.downloader << user.principal_name
|
49
|
+
resource.save
|
50
|
+
end
|
51
|
+
context "and user has edit permission" do
|
52
|
+
before do
|
53
|
+
resource.edit_users = [user.user_key]
|
54
|
+
resource.save
|
55
|
+
end
|
56
|
+
it { is_expected.to be_able_to(:download, resource) }
|
57
|
+
end
|
58
|
+
context "and user has read permission" do
|
59
|
+
before do
|
60
|
+
resource.read_users = [user.user_key]
|
61
|
+
resource.save
|
62
|
+
end
|
63
|
+
it { is_expected.to be_able_to(:download, resource) }
|
64
|
+
end
|
65
|
+
context "and user lacks read permission" do
|
66
|
+
it { is_expected.not_to be_able_to(:download, resource) }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "which is not a Component" do
|
72
|
+
let(:resource) { FactoryGirl.create(:test_content) }
|
73
|
+
context "and user has read permission" do
|
74
|
+
before do
|
75
|
+
resource.read_users = [user.user_key]
|
76
|
+
resource.save
|
77
|
+
end
|
78
|
+
it { is_expected.to be_able_to(:download, resource) }
|
79
|
+
end
|
80
|
+
context "and user lacks read permission" do
|
81
|
+
it { is_expected.not_to be_able_to(:download, resource) }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "on a datastream", datastreams: true do
|
87
|
+
|
88
|
+
context "named 'content'", content: true do
|
89
|
+
let(:resource) { obj.content }
|
90
|
+
context "and object is a Component", components: true do
|
91
|
+
let(:obj) { FactoryGirl.create(:component) }
|
92
|
+
context "and user does not have the downloader role" do
|
93
|
+
context "and user has read permission on the object" do
|
94
|
+
before do
|
95
|
+
obj.read_users = [user.user_key]
|
96
|
+
obj.save
|
97
|
+
end
|
98
|
+
it { is_expected.not_to be_able_to(:download, resource) }
|
99
|
+
end
|
100
|
+
context "and user lacks read permission on the object" do
|
101
|
+
it { is_expected.not_to be_able_to(:download, resource) }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context "and user has the downloader role", roles: true do
|
106
|
+
before do
|
107
|
+
obj.roleAssignments.downloader << user.principal_name
|
108
|
+
obj.save
|
109
|
+
end
|
110
|
+
context "and user has read permission on the object" do
|
111
|
+
before do
|
112
|
+
obj.read_users = [user.user_key]
|
113
|
+
obj.save
|
114
|
+
end
|
115
|
+
it { is_expected.to be_able_to(:download, resource) }
|
116
|
+
end
|
117
|
+
context "and user lacks read permission on the object" do
|
118
|
+
it { is_expected.not_to be_able_to(:download, resource) }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context "and object is not a Component" do
|
124
|
+
let(:obj) { FactoryGirl.create(:test_content) }
|
125
|
+
context "and user has read permission on the object" do
|
126
|
+
before do
|
127
|
+
obj.read_users = [user.user_key]
|
128
|
+
obj.save
|
129
|
+
end
|
130
|
+
it { is_expected.to be_able_to(:download, resource) }
|
131
|
+
end
|
132
|
+
context "and user lacks read permission on the object" do
|
133
|
+
it { is_expected.not_to be_able_to(:download, resource) }
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
context "not named 'content'" do
|
140
|
+
let(:obj) { FactoryGirl.create(:test_model) }
|
141
|
+
let(:resource) { obj.descMetadata }
|
142
|
+
context "and user has read permission on the object" do
|
143
|
+
before do
|
144
|
+
obj.read_users = [user.user_key]
|
145
|
+
obj.save
|
146
|
+
end
|
147
|
+
it { is_expected.to be_able_to(:download, resource) }
|
148
|
+
end
|
149
|
+
context "and user lacks read permission on the object" do
|
150
|
+
it { is_expected.not_to be_able_to(:download, resource) }
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
end # download_permissions
|
157
|
+
|
158
|
+
describe "#discover_permissions" do
|
159
|
+
# TODO
|
160
|
+
end
|
161
|
+
|
162
|
+
describe "#events_permissions", events: true do
|
163
|
+
let(:object) { FactoryGirl.create(:test_model) }
|
164
|
+
let(:resource) { Ddr::Events::Event.new(pid: object.pid) }
|
165
|
+
context "event is associated with a user" do
|
166
|
+
before { resource.user = user }
|
167
|
+
it { is_expected.to be_able_to(:read, resource) }
|
168
|
+
end
|
169
|
+
context "event is not associated with a user" do
|
170
|
+
context "and can read object" do
|
171
|
+
before do
|
172
|
+
object.read_users = [user.user_key]
|
173
|
+
object.save!
|
174
|
+
end
|
175
|
+
it { is_expected.to be_able_to(:read, resource) }
|
176
|
+
end
|
177
|
+
context "and cannot read object" do
|
178
|
+
it { is_expected.not_to be_able_to(:read, resource) }
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "#export_sets_permissions", export_sets: true do
|
184
|
+
let(:resource) { ExportSet.new(user: user) }
|
185
|
+
context "associated user" do
|
186
|
+
it { is_expected.to be_able_to(:manage, resource) }
|
187
|
+
end
|
188
|
+
context "other user" do
|
189
|
+
subject { described_class.new(other_user) }
|
190
|
+
let(:other_user) { FactoryGirl.create(:user) }
|
191
|
+
it { is_expected.not_to be_able_to(:read, resource) }
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
describe "#ingest_folders_permissions", ingest_folders: true do
|
196
|
+
let(:resource) { IngestFolder }
|
197
|
+
context "user has no permitted ingest folders" do
|
198
|
+
before { allow(resource).to receive(:permitted_folders).with(user).and_return([]) }
|
199
|
+
it { is_expected.not_to be_able_to(:create, resource) }
|
200
|
+
end
|
201
|
+
context "user has at least one permitted ingest folder" do
|
202
|
+
before { allow(resource).to receive(:permitted_folders).with(user).and_return(['dir']) }
|
203
|
+
it { is_expected.to be_able_to(:create, resource) }
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "#attachment_permissions", attachments: true do
|
208
|
+
context "object can have attachments" do
|
209
|
+
let(:resource) { FactoryGirl.build(:test_model_omnibus) }
|
210
|
+
context "and user lacks edit rights" do
|
211
|
+
before { subject.cannot(:edit, resource) }
|
212
|
+
it { is_expected.not_to be_able_to(:add_attachment, resource) }
|
213
|
+
end
|
214
|
+
context "and user has edit rights" do
|
215
|
+
before { subject.can(:edit, resource) }
|
216
|
+
it { is_expected.to be_able_to(:add_attachment, resource) }
|
217
|
+
end
|
218
|
+
end
|
219
|
+
context "object cannot have attachments" do
|
220
|
+
let(:resource) { FactoryGirl.build(:test_model) }
|
221
|
+
before { subject.can(:edit, resource) }
|
222
|
+
it { is_expected.not_to be_able_to(:add_attachment, resource) }
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "#children_permissions", children: true do
|
227
|
+
context "user has edit rights on object" do
|
228
|
+
before { subject.can(:edit, resource) }
|
229
|
+
context "and object can have children" do
|
230
|
+
let(:resource) { FactoryGirl.build(:collection) }
|
231
|
+
it { is_expected.to be_able_to(:add_children, resource) }
|
232
|
+
end
|
233
|
+
context "but object cannot have children" do
|
234
|
+
let(:resource) { FactoryGirl.build(:component) }
|
235
|
+
it { is_expected.not_to be_able_to(:add_children, resource) }
|
236
|
+
end
|
237
|
+
end
|
238
|
+
context "user lacks edit rights on attached_to object" do
|
239
|
+
let(:resource) { FactoryGirl.build(:collection) }
|
240
|
+
before { subject.cannot(:edit, resource) }
|
241
|
+
it { is_expected.not_to be_able_to(:add_children, resource) }
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'cancan/matchers'
|
3
|
+
|
4
|
+
module Ddr
|
5
|
+
module Auth
|
6
|
+
describe Superuser, type: :model, abilities: true do
|
7
|
+
subject { described_class.new }
|
8
|
+
it "should be able to manage all" do
|
9
|
+
expect(subject).to be_able_to(:manage, :all)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe User, :type => :model do
|
4
|
+
|
5
|
+
subject { FactoryGirl.build(:user) }
|
6
|
+
|
7
|
+
describe "#member_of?" do
|
8
|
+
it "should return true if the user is a member of the group" do
|
9
|
+
allow(subject).to receive(:groups).and_return(["foo", "bar"])
|
10
|
+
expect(subject).to be_member_of("foo")
|
11
|
+
end
|
12
|
+
it "should return false if the user is not a member of the group" do
|
13
|
+
allow(subject).to receive(:groups).and_return(["foo", "bar"])
|
14
|
+
expect(subject).not_to be_member_of("baz")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#authorized_to_act_as_superuser?" do
|
19
|
+
it "should return false if the superuser group is not defined (nil)" do
|
20
|
+
DulHydra.superuser_group = nil
|
21
|
+
expect(subject).not_to be_authorized_to_act_as_superuser
|
22
|
+
end
|
23
|
+
it "should return false if the user is not a member of the superuser group" do
|
24
|
+
DulHydra.superuser_group = "superusers"
|
25
|
+
allow(subject).to receive(:groups).and_return(["normal"])
|
26
|
+
expect(subject).not_to be_authorized_to_act_as_superuser
|
27
|
+
end
|
28
|
+
it "should return true if the user is a member of the superuser group" do
|
29
|
+
DulHydra.superuser_group = "superusers"
|
30
|
+
allow(subject).to receive(:groups).and_return(["superusers"])
|
31
|
+
expect(subject).to be_authorized_to_act_as_superuser
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#principal_name" do
|
36
|
+
it "should return the principal name for the user" do
|
37
|
+
expect(subject.principal_name).to eq subject.user_key
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#principals" do
|
42
|
+
it "should be a list of the user's groups + the user's principal_name" do
|
43
|
+
allow(subject).to receive(:groups) { ["foo", "bar"] }
|
44
|
+
expect(subject.principals).to match_array ["foo", "bar", subject.principal_name]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#has_role?" do
|
49
|
+
let(:obj) { double }
|
50
|
+
it "should send :principal_has_role? to the object with the user's principals" do
|
51
|
+
expect(obj).to receive(:principal_has_role?).with(subject.principals, :administrator)
|
52
|
+
subject.has_role?(obj, :administrator)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|