ddr-models 1.2.0 → 1.2.1
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 +16 -2
- data/db/migrate/20141103192146_create_workflow_state.rb +14 -8
- data/db/migrate/20141107124012_add_columns_to_user.rb +46 -0
- data/lib/ddr/auth/ability.rb +1 -26
- data/lib/ddr/models.rb +0 -1
- data/lib/ddr/models/error.rb +2 -5
- data/lib/ddr/models/version.rb +1 -1
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/schema.rb +1 -1
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +1715 -1626
- data/spec/dummy/log/test.log +35454 -42999
- metadata +3 -23
- data/config/initializers/devise.rb~ +0 -245
- data/db/migrate/20141104181418_create_users.rb~ +0 -6
- data/lib/ddr/auth.rb~ +0 -47
- data/lib/ddr/auth/ability.rb~ +0 -204
- data/lib/ddr/auth/group_service.rb~ +0 -53
- data/lib/ddr/auth/grouper_service.rb~ +0 -77
- data/lib/ddr/auth/remote_group_service.rb~ +0 -35
- data/lib/ddr/auth/superuser.rb~ +0 -9
- data/lib/ddr/auth/user.rb~ +0 -65
- data/spec/factories/user_factories.rb~ +0 -7
- data/spec/features/grouper_integration_spec.rb~ +0 -21
- data/spec/models/ability_spec.rb~ +0 -245
- data/spec/models/superuser_spec.rb~ +0 -13
- data/spec/models/user_spec.rb~ +0 -56
- data/spec/services/group_service_spec.rb~ +0 -71
@@ -1,53 +0,0 @@
|
|
1
|
-
module Ddr
|
2
|
-
module Auth
|
3
|
-
class GroupService
|
4
|
-
|
5
|
-
class_attribute :include_role_mapper_groups
|
6
|
-
self.include_role_mapper_groups = RoleMapper.role_names.present? rescue false
|
7
|
-
|
8
|
-
def role_mapper_user_groups(user)
|
9
|
-
RoleMapper.roles(user) rescue []
|
10
|
-
end
|
11
|
-
|
12
|
-
def role_mapper_groups
|
13
|
-
RoleMapper.role_names rescue []
|
14
|
-
end
|
15
|
-
|
16
|
-
def groups
|
17
|
-
default_groups | append_groups
|
18
|
-
end
|
19
|
-
|
20
|
-
def user_groups(user)
|
21
|
-
default_user_groups(user) | append_user_groups(user)
|
22
|
-
end
|
23
|
-
|
24
|
-
def superuser_group
|
25
|
-
Ddr::Auth.superuser_group
|
26
|
-
end
|
27
|
-
|
28
|
-
def append_groups
|
29
|
-
[]
|
30
|
-
end
|
31
|
-
|
32
|
-
def append_user_groups(user)
|
33
|
-
[]
|
34
|
-
end
|
35
|
-
|
36
|
-
def default_groups
|
37
|
-
dg = [Ddr::Auth.everyone_group, Ddr::Auth.authenticated_users_group]
|
38
|
-
dg += role_mapper_groups if include_role_mapper_groups
|
39
|
-
dg
|
40
|
-
end
|
41
|
-
|
42
|
-
def default_user_groups(user)
|
43
|
-
dug = [Hydra::AccessControls::AccessRight::PERMISSION_TEXT_VALUE_PUBLIC]
|
44
|
-
if user && user.persisted?
|
45
|
-
dug << Hydra::AccessControls::AccessRight::PERMISSION_TEXT_VALUE_AUTHENTICATED
|
46
|
-
dug += role_mapper_user_groups(user) if include_role_mapper_groups
|
47
|
-
end
|
48
|
-
dug
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
require 'dul_hydra'
|
2
|
-
require 'grouper-rest-client'
|
3
|
-
|
4
|
-
module DulHydra
|
5
|
-
module Services
|
6
|
-
class GrouperService
|
7
|
-
|
8
|
-
class_attribute :config
|
9
|
-
|
10
|
-
def self.configured?
|
11
|
-
!config.nil?
|
12
|
-
end
|
13
|
-
|
14
|
-
# List of all grouper groups for the repository
|
15
|
-
def self.repository_groups
|
16
|
-
groups = []
|
17
|
-
begin
|
18
|
-
client do |c|
|
19
|
-
g = c.groups(DulHydra.remote_groups_name_filter)
|
20
|
-
groups = g if c.ok?
|
21
|
-
end
|
22
|
-
rescue Ddr::Models::Error
|
23
|
-
end
|
24
|
-
groups
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.repository_group_names
|
28
|
-
repository_groups.collect { |g| g["name"] }
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.user_groups(user)
|
32
|
-
groups = []
|
33
|
-
begin
|
34
|
-
client do |c|
|
35
|
-
request_body = {
|
36
|
-
"WsRestGetGroupsRequest" => {
|
37
|
-
"subjectLookups" => [{"subjectIdentifier" => subject_id(user)}]
|
38
|
-
}
|
39
|
-
}
|
40
|
-
# Have to use :call b/c grouper-rest-client :subjects method doesn't support POST
|
41
|
-
response = c.call("subjects", :post, request_body)
|
42
|
-
if c.ok?
|
43
|
-
result = response["WsGetGroupsResults"]["results"].first
|
44
|
-
# Have to manually filter results b/c Grouper WS version 1.5 does not support filter parameter
|
45
|
-
if result && result["wsGroups"]
|
46
|
-
groups = result["wsGroups"].select { |g| g["name"] =~ /^#{DulHydra.remote_groups_name_filter}/ }
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
rescue StandardError => e
|
51
|
-
Rails.logger.error e
|
52
|
-
end
|
53
|
-
groups
|
54
|
-
end
|
55
|
-
|
56
|
-
def self.user_group_names(user)
|
57
|
-
user_groups(user).collect { |g| g["name"] }
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.subject_id(user)
|
61
|
-
user.user_key.split('@').first
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def self.client
|
67
|
-
raise Ddr::Models::Error unless configured?
|
68
|
-
yield Grouper::Rest::Client::Resource.new(config["url"],
|
69
|
-
user: config["user"],
|
70
|
-
password: config["password"],
|
71
|
-
timeout: config.fetch("timeout", 5).to_i
|
72
|
-
)
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module DulHydra
|
2
|
-
module Services
|
3
|
-
class RemoteGroupService < GroupService
|
4
|
-
|
5
|
-
attr_reader :env
|
6
|
-
|
7
|
-
def initialize(env = nil)
|
8
|
-
@env = env
|
9
|
-
end
|
10
|
-
|
11
|
-
def append_groups
|
12
|
-
GrouperService.repository_group_names
|
13
|
-
end
|
14
|
-
|
15
|
-
def append_user_groups(user)
|
16
|
-
if env && env.key?(DulHydra.remote_groups_env_key)
|
17
|
-
remote_groups
|
18
|
-
else
|
19
|
-
GrouperService.user_group_names(user)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def remote_groups
|
24
|
-
# get the raw list of values
|
25
|
-
groups = env[DulHydra.remote_groups_env_key].split(DulHydra.remote_groups_env_value_delim)
|
26
|
-
# munge values to proper Grouper group names, if necessary
|
27
|
-
groups = groups.collect { |g| g.sub(*DulHydra.remote_groups_env_value_sub) } if DulHydra.remote_groups_env_value_sub
|
28
|
-
# filter group list as configured
|
29
|
-
groups = groups.select { |g| g =~ /^#{DulHydra.remote_groups_name_filter}/ } if DulHydra.remote_groups_name_filter
|
30
|
-
groups
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
data/lib/ddr/auth/superuser.rb~
DELETED
data/lib/ddr/auth/user.rb~
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
module Ddr
|
2
|
-
module Auth
|
3
|
-
module User
|
4
|
-
extend ActiveSupport::Concern
|
5
|
-
|
6
|
-
included do
|
7
|
-
include Blacklight::User
|
8
|
-
include Hydra::User
|
9
|
-
|
10
|
-
# has_many :batches, :inverse_of => :user, :class_name => DulHydra::Batch::Models::Batch
|
11
|
-
# has_many :ingest_folders, :inverse_of => :user
|
12
|
-
# has_many :metadata_files, :inverse_of => :user
|
13
|
-
# has_many :export_sets, :dependent => :destroy
|
14
|
-
has_many :events, inverse_of: :user, class_name: "Ddr::Events::Event"
|
15
|
-
|
16
|
-
delegate :can?, :cannot?, to: :ability
|
17
|
-
|
18
|
-
validates_uniqueness_of :username, :case_sensitive => false
|
19
|
-
validates_format_of :email, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/
|
20
|
-
|
21
|
-
# TODO Remove :trackable, :validatable
|
22
|
-
devise :remote_user_authenticatable, :database_authenticatable, :rememberable, :trackable, :validatable
|
23
|
-
|
24
|
-
attr_writer :group_service
|
25
|
-
end
|
26
|
-
|
27
|
-
def group_service
|
28
|
-
@group_service ||= Ddr::Auth::GroupService.new
|
29
|
-
end
|
30
|
-
|
31
|
-
def to_s
|
32
|
-
user_key
|
33
|
-
end
|
34
|
-
|
35
|
-
def ability
|
36
|
-
@ability ||= ::Ability.new(self)
|
37
|
-
end
|
38
|
-
|
39
|
-
def groups
|
40
|
-
@groups ||= group_service.user_groups(self)
|
41
|
-
end
|
42
|
-
|
43
|
-
def member_of?(group)
|
44
|
-
group ? self.groups.include?(group) : false
|
45
|
-
end
|
46
|
-
|
47
|
-
def authorized_to_act_as_superuser?
|
48
|
-
member_of? group_service.superuser_group
|
49
|
-
end
|
50
|
-
|
51
|
-
def principal_name
|
52
|
-
user_key
|
53
|
-
end
|
54
|
-
|
55
|
-
def principals
|
56
|
-
groups.dup << principal_name
|
57
|
-
end
|
58
|
-
|
59
|
-
def has_role?(obj, role)
|
60
|
-
obj.principal_has_role?(principals, role)
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,21 +0,0 @@
|
|
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
|
@@ -1,245 +0,0 @@
|
|
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
|