hyrax-acl 0.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 +7 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +174 -0
- data/README.md +7 -0
- data/hyrax-acl.gemspec +29 -0
- data/lib/hyrax/acl/access_control.rb +46 -0
- data/lib/hyrax/acl/access_control_change_set.rb +12 -0
- data/lib/hyrax/acl/access_control_list.rb +226 -0
- data/lib/hyrax/acl/agent.rb +20 -0
- data/lib/hyrax/acl/custom_queries/find_access_control.rb +30 -0
- data/lib/hyrax/acl/custom_queries.rb +13 -0
- data/lib/hyrax/acl/group.rb +35 -0
- data/lib/hyrax/acl/permission.rb +21 -0
- data/lib/hyrax/acl/version.rb +6 -0
- data/lib/hyrax/acl.rb +13 -0
- data/lib/hyrax.rb +2 -0
- metadata +88 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 4d6daf35ffa5e520d644843770558e98616318e3f46e7ff71ee790ed294e4151
|
|
4
|
+
data.tar.gz: fa15a23186d21120d9bdaeccf57adf244d51ec64854d4619915ac752c86af120
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 71bac13a9baf582a197e16939e4780514d015effd330c91bb7e583d3393f5cac1acc112f70a86910f78ba28ae33558ee63b599245af0d83e0c2c4bafc0fac8d1
|
|
7
|
+
data.tar.gz: 4de625e404ce9219d1ea20f2f84b02a88e6abff7037ba8e00cf3e3a1327cfd0957b42e372f6d9e6bafa41a78d762f52321203636104e1c1d08e15620eea24ecf
|
data/.rspec
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--require spec_helper
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
GEM
|
|
2
|
+
remote: https://rubygems.org/
|
|
3
|
+
specs:
|
|
4
|
+
actionpack (7.0.3)
|
|
5
|
+
actionview (= 7.0.3)
|
|
6
|
+
activesupport (= 7.0.3)
|
|
7
|
+
rack (~> 2.0, >= 2.2.0)
|
|
8
|
+
rack-test (>= 0.6.3)
|
|
9
|
+
rails-dom-testing (~> 2.0)
|
|
10
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
|
11
|
+
actionview (7.0.3)
|
|
12
|
+
activesupport (= 7.0.3)
|
|
13
|
+
builder (~> 3.1)
|
|
14
|
+
erubi (~> 1.4)
|
|
15
|
+
rails-dom-testing (~> 2.0)
|
|
16
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
|
17
|
+
activemodel (7.0.3)
|
|
18
|
+
activesupport (= 7.0.3)
|
|
19
|
+
activemodel-serializers-xml (1.0.2)
|
|
20
|
+
activemodel (> 5.x)
|
|
21
|
+
activesupport (> 5.x)
|
|
22
|
+
builder (~> 3.1)
|
|
23
|
+
activesupport (7.0.3)
|
|
24
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
25
|
+
i18n (>= 1.6, < 2)
|
|
26
|
+
minitest (>= 5.1)
|
|
27
|
+
tzinfo (~> 2.0)
|
|
28
|
+
builder (3.2.4)
|
|
29
|
+
concurrent-ruby (1.1.10)
|
|
30
|
+
crass (1.0.6)
|
|
31
|
+
declarative (0.0.20)
|
|
32
|
+
declarative-builder (0.1.0)
|
|
33
|
+
declarative-option (< 0.2.0)
|
|
34
|
+
declarative-option (0.1.1)
|
|
35
|
+
diff-lcs (1.5.0)
|
|
36
|
+
disposable (0.4.7)
|
|
37
|
+
declarative (>= 0.0.9, < 1.0.0)
|
|
38
|
+
declarative-builder (< 0.2.0)
|
|
39
|
+
declarative-option (< 0.2.0)
|
|
40
|
+
representable (>= 2.4.0, <= 3.1.0)
|
|
41
|
+
uber (< 0.2.0)
|
|
42
|
+
draper (4.0.2)
|
|
43
|
+
actionpack (>= 5.0)
|
|
44
|
+
activemodel (>= 5.0)
|
|
45
|
+
activemodel-serializers-xml (>= 1.0)
|
|
46
|
+
activesupport (>= 5.0)
|
|
47
|
+
request_store (>= 1.0)
|
|
48
|
+
ruby2_keywords
|
|
49
|
+
dry-configurable (0.15.0)
|
|
50
|
+
concurrent-ruby (~> 1.0)
|
|
51
|
+
dry-core (~> 0.6)
|
|
52
|
+
dry-container (0.9.0)
|
|
53
|
+
concurrent-ruby (~> 1.0)
|
|
54
|
+
dry-configurable (~> 0.13, >= 0.13.0)
|
|
55
|
+
dry-core (0.7.1)
|
|
56
|
+
concurrent-ruby (~> 1.0)
|
|
57
|
+
dry-inflector (0.2.1)
|
|
58
|
+
dry-logic (1.2.0)
|
|
59
|
+
concurrent-ruby (~> 1.0)
|
|
60
|
+
dry-core (~> 0.5, >= 0.5)
|
|
61
|
+
dry-struct (1.4.0)
|
|
62
|
+
dry-core (~> 0.5, >= 0.5)
|
|
63
|
+
dry-types (~> 1.5)
|
|
64
|
+
ice_nine (~> 0.11)
|
|
65
|
+
dry-types (1.5.1)
|
|
66
|
+
concurrent-ruby (~> 1.0)
|
|
67
|
+
dry-container (~> 0.3)
|
|
68
|
+
dry-core (~> 0.5, >= 0.5)
|
|
69
|
+
dry-inflector (~> 0.1, >= 0.1.2)
|
|
70
|
+
dry-logic (~> 1.0, >= 1.0.2)
|
|
71
|
+
erubi (1.10.0)
|
|
72
|
+
faraday (0.17.5)
|
|
73
|
+
multipart-post (>= 1.2, < 3)
|
|
74
|
+
htmlentities (4.3.4)
|
|
75
|
+
i18n (1.10.0)
|
|
76
|
+
concurrent-ruby (~> 1.0)
|
|
77
|
+
ice_nine (0.11.2)
|
|
78
|
+
json (2.6.2)
|
|
79
|
+
json-canonicalization (0.3.0)
|
|
80
|
+
json-ld (3.2.1)
|
|
81
|
+
htmlentities (~> 4.3)
|
|
82
|
+
json-canonicalization (~> 0.3)
|
|
83
|
+
link_header (~> 0.0, >= 0.0.8)
|
|
84
|
+
multi_json (~> 1.15)
|
|
85
|
+
rack (~> 2.2)
|
|
86
|
+
rdf (~> 3.2)
|
|
87
|
+
link_header (0.0.8)
|
|
88
|
+
loofah (2.18.0)
|
|
89
|
+
crass (~> 1.0.2)
|
|
90
|
+
nokogiri (>= 1.5.9)
|
|
91
|
+
method_source (1.0.0)
|
|
92
|
+
minitest (5.16.1)
|
|
93
|
+
multi_json (1.15.0)
|
|
94
|
+
multipart-post (2.2.3)
|
|
95
|
+
nokogiri (1.13.6-x86_64-linux)
|
|
96
|
+
racc (~> 1.4)
|
|
97
|
+
racc (1.6.0)
|
|
98
|
+
rack (2.2.3.1)
|
|
99
|
+
rack-test (2.0.0)
|
|
100
|
+
rack (>= 1.3)
|
|
101
|
+
rails-dom-testing (2.0.3)
|
|
102
|
+
activesupport (>= 4.2.0)
|
|
103
|
+
nokogiri (>= 1.6)
|
|
104
|
+
rails-html-sanitizer (1.4.3)
|
|
105
|
+
loofah (~> 2.3)
|
|
106
|
+
railties (7.0.3)
|
|
107
|
+
actionpack (= 7.0.3)
|
|
108
|
+
activesupport (= 7.0.3)
|
|
109
|
+
method_source
|
|
110
|
+
rake (>= 12.2)
|
|
111
|
+
thor (~> 1.0)
|
|
112
|
+
zeitwerk (~> 2.5)
|
|
113
|
+
rake (13.0.6)
|
|
114
|
+
rdf (3.2.8)
|
|
115
|
+
link_header (~> 0.0, >= 0.0.8)
|
|
116
|
+
rdf-vocab (3.2.1)
|
|
117
|
+
rdf (~> 3.2, >= 3.2.4)
|
|
118
|
+
reform (2.5.0)
|
|
119
|
+
disposable (>= 0.4.2, < 0.5.0)
|
|
120
|
+
representable (>= 2.4.0, < 3.1.0)
|
|
121
|
+
uber (< 0.2.0)
|
|
122
|
+
reform-rails (0.2.3)
|
|
123
|
+
activemodel (>= 5.0)
|
|
124
|
+
reform (>= 2.3.1, < 3.0.0)
|
|
125
|
+
representable (3.0.4)
|
|
126
|
+
declarative (< 0.1.0)
|
|
127
|
+
declarative-option (< 0.2.0)
|
|
128
|
+
uber (< 0.2.0)
|
|
129
|
+
request_store (1.5.1)
|
|
130
|
+
rack (>= 1.4)
|
|
131
|
+
rspec (3.11.0)
|
|
132
|
+
rspec-core (~> 3.11.0)
|
|
133
|
+
rspec-expectations (~> 3.11.0)
|
|
134
|
+
rspec-mocks (~> 3.11.0)
|
|
135
|
+
rspec-core (3.11.0)
|
|
136
|
+
rspec-support (~> 3.11.0)
|
|
137
|
+
rspec-expectations (3.11.0)
|
|
138
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
139
|
+
rspec-support (~> 3.11.0)
|
|
140
|
+
rspec-mocks (3.11.1)
|
|
141
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
142
|
+
rspec-support (~> 3.11.0)
|
|
143
|
+
rspec-support (3.11.0)
|
|
144
|
+
ruby2_keywords (0.0.5)
|
|
145
|
+
thor (1.2.1)
|
|
146
|
+
tzinfo (2.0.4)
|
|
147
|
+
concurrent-ruby (~> 1.0)
|
|
148
|
+
uber (0.1.0)
|
|
149
|
+
valkyrie (2.2.0)
|
|
150
|
+
activemodel
|
|
151
|
+
activesupport
|
|
152
|
+
disposable (~> 0.4.5)
|
|
153
|
+
draper
|
|
154
|
+
dry-struct
|
|
155
|
+
dry-types (~> 1.0)
|
|
156
|
+
faraday (< 1.0)
|
|
157
|
+
json
|
|
158
|
+
json-ld
|
|
159
|
+
railties
|
|
160
|
+
rdf (~> 3.0, >= 3.0.10)
|
|
161
|
+
rdf-vocab
|
|
162
|
+
reform (~> 2.2)
|
|
163
|
+
reform-rails
|
|
164
|
+
zeitwerk (2.6.0)
|
|
165
|
+
|
|
166
|
+
PLATFORMS
|
|
167
|
+
x86_64-linux
|
|
168
|
+
|
|
169
|
+
DEPENDENCIES
|
|
170
|
+
rspec
|
|
171
|
+
valkyrie (~> 2)
|
|
172
|
+
|
|
173
|
+
BUNDLED WITH
|
|
174
|
+
2.2.16
|
data/README.md
ADDED
data/hyrax-acl.gemspec
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'hyrax/acl/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.authors = ["Project Surfliner"]
|
|
8
|
+
spec.email = ["tomjohnson@ucsb.edu"]
|
|
9
|
+
spec.description = 'Access Control List models and support for Hyrax'
|
|
10
|
+
spec.summary = <<-SUMMARY
|
|
11
|
+
Hyrax Access Control List
|
|
12
|
+
SUMMARY
|
|
13
|
+
|
|
14
|
+
spec.homepage = "http://github.com/samvera-labs/hyrax-acl"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR).select { |f| File.dirname(f) !~ %r{\A"?spec\/?} }
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
|
18
|
+
spec.name = "hyrax-acl"
|
|
19
|
+
spec.require_paths = ["lib"]
|
|
20
|
+
spec.version = Hyrax::Acl::VERSION
|
|
21
|
+
spec.license = 'Apache-2.0'
|
|
22
|
+
spec.metadata = { "rubygems_mfa_required" => "true" }
|
|
23
|
+
|
|
24
|
+
spec.required_ruby_version = '>= 2.7'
|
|
25
|
+
|
|
26
|
+
spec.add_dependency "valkyrie", "~> 2"
|
|
27
|
+
|
|
28
|
+
spec.add_development_dependency "rspec"
|
|
29
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
module Acl
|
|
5
|
+
##
|
|
6
|
+
# A list of permissions pertaining to a specific object.
|
|
7
|
+
#
|
|
8
|
+
# `AccessControl`s consist of a set of permissions and an `#access_to`
|
|
9
|
+
# reference to the object that set governs.
|
|
10
|
+
#
|
|
11
|
+
# @see Hyrax::AccessControlList for a low level DSL for managing
|
|
12
|
+
# `AccessControl` and `Permission` relationships for `Hyrax::Resource`
|
|
13
|
+
# @see Hyrax::PermissionManager for `read_groups`/`read_users` style setters
|
|
14
|
+
# and getters
|
|
15
|
+
# @see Hyrax::VisibilityWriter, Hyrax::VisibilityReader for
|
|
16
|
+
# "open"/"restricted" style visibility management
|
|
17
|
+
class AccessControl < Valkyrie::Resource
|
|
18
|
+
##
|
|
19
|
+
# @!attribute [rw] access_to
|
|
20
|
+
# Supports query for ACLs at the resource level. Permissions should be
|
|
21
|
+
# grouped under an AccessControl with a matching `#access_to` so they can
|
|
22
|
+
# be retrieved in batch.
|
|
23
|
+
#
|
|
24
|
+
# @return [Valkyrie::ID] the id of the Resource these permissions apply to
|
|
25
|
+
# @!attribute [rw] permissions
|
|
26
|
+
# @return [Enumerable<Hyrax::Acl::Permission>]
|
|
27
|
+
attribute :access_to, Valkyrie::Types::ID
|
|
28
|
+
attribute :permissions, Valkyrie::Types::Set.of(Hyrax::Acl::Permission)
|
|
29
|
+
|
|
30
|
+
##
|
|
31
|
+
# A finder/factory method for getting an appropriate ACL for a given
|
|
32
|
+
# resource.
|
|
33
|
+
#
|
|
34
|
+
# @param resource [Valkyrie::Resource]
|
|
35
|
+
# @param query_service [#find_inverse_references_by]
|
|
36
|
+
#
|
|
37
|
+
# @return [AccessControl]
|
|
38
|
+
# @raise [ArgumentError] if the resource is not persisted
|
|
39
|
+
def self.for(resource:, query_service:)
|
|
40
|
+
Hyrax::Acl::CustomQueries::FindAccessControl.new(query_service: query_service).find_access_control_for(resource: resource)
|
|
41
|
+
rescue Valkyrie::Persistence::ObjectNotFoundError
|
|
42
|
+
new(access_to: resource.id, permissions: [])
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
module Acl
|
|
5
|
+
##
|
|
6
|
+
# A ChangeSet for Hyrax::Acl::AccessControl.
|
|
7
|
+
class AccessControlChangeSet < Valkyrie::ChangeSet
|
|
8
|
+
property :access_to, type: Valkyrie::Types::ID, default: nil
|
|
9
|
+
property :permissions, type: Valkyrie::Types::Set.of(Hyrax::Acl::Permission), default: nil
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
module Acl
|
|
5
|
+
##
|
|
6
|
+
# @api public
|
|
7
|
+
#
|
|
8
|
+
# ACLs for `Hyrax::Resource` models
|
|
9
|
+
#
|
|
10
|
+
# Allows managing `Hyrax::Permission` entries referring to a specific
|
|
11
|
+
# `Hyrax::Resource.
|
|
12
|
+
#
|
|
13
|
+
class AccessControlList
|
|
14
|
+
DISCOVER = :discover
|
|
15
|
+
EDIT = :edit
|
|
16
|
+
READ = :read
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
# @!attribute [rw] resource
|
|
20
|
+
# @return [Valkyrie::Resource]
|
|
21
|
+
# @!attribute [r] persister
|
|
22
|
+
# @return [#save]
|
|
23
|
+
# @!attribute [r] query_service
|
|
24
|
+
# @return [#find_inverse_references_by]
|
|
25
|
+
attr_reader :persister, :query_service
|
|
26
|
+
attr_accessor :resource
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# @param resource [Valkyrie::Resource]
|
|
30
|
+
# @param persister [#save] defaults to the configured Hyrax persister
|
|
31
|
+
# @param query_service [#find_inverse_references_by] defaults to the
|
|
32
|
+
# configured Hyrax query service
|
|
33
|
+
def initialize(resource:, persister:, query_service:)
|
|
34
|
+
self.resource = resource
|
|
35
|
+
@persister = persister
|
|
36
|
+
@query_service = query_service
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# @api public
|
|
41
|
+
#
|
|
42
|
+
# @param permission [Hyrax::Permission]
|
|
43
|
+
#
|
|
44
|
+
# @return [Boolean]
|
|
45
|
+
def <<(permission)
|
|
46
|
+
permission.access_to = resource.id
|
|
47
|
+
|
|
48
|
+
change_set.permissions += [permission]
|
|
49
|
+
|
|
50
|
+
true
|
|
51
|
+
end
|
|
52
|
+
alias add <<
|
|
53
|
+
|
|
54
|
+
##
|
|
55
|
+
# @api public
|
|
56
|
+
#
|
|
57
|
+
# @param permission [Hyrax::Permission]
|
|
58
|
+
#
|
|
59
|
+
# @return [Boolean]
|
|
60
|
+
def delete(permission)
|
|
61
|
+
change_set.permissions -= [permission]
|
|
62
|
+
|
|
63
|
+
true
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
##
|
|
67
|
+
# @api public
|
|
68
|
+
#
|
|
69
|
+
# @example
|
|
70
|
+
# user = User.find('user_id')
|
|
71
|
+
#
|
|
72
|
+
# acl.grant(:read).to(user)
|
|
73
|
+
def grant(mode)
|
|
74
|
+
ModeGrant.new(self, mode)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
##
|
|
78
|
+
# Discover grant
|
|
79
|
+
# @agent [Hyrax::Acl::Agent] agent
|
|
80
|
+
def has_discover?(agent:)
|
|
81
|
+
has_grant?(mode: DISCOVER, agent: agent)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
##
|
|
85
|
+
# Read grant
|
|
86
|
+
# @agent [Hyrax::Acl::Agent] agent
|
|
87
|
+
def has_read?(agent:)
|
|
88
|
+
has_grant?(mode: READ, agent: agent)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
##
|
|
92
|
+
# Edit grant
|
|
93
|
+
# @agent [Hyrax::Acl::Agent] agent
|
|
94
|
+
def has_edit?(agent:)
|
|
95
|
+
has_grant?(mode: EDIT, agent: agent)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
##
|
|
99
|
+
# Edit grant
|
|
100
|
+
# @agent [Hyrax::Acl::Agent] agent
|
|
101
|
+
def has_grant?(mode:, agent:)
|
|
102
|
+
permissions.any? do |permission|
|
|
103
|
+
permission.mode == mode && permission.agent == agent.agent_key
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
##
|
|
108
|
+
# @api public
|
|
109
|
+
#
|
|
110
|
+
# @return [Boolean]
|
|
111
|
+
def pending_changes?
|
|
112
|
+
change_set.changed?
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
##
|
|
116
|
+
# @api public
|
|
117
|
+
#
|
|
118
|
+
# @return [Set<Hyrax::Permission>]
|
|
119
|
+
def permissions
|
|
120
|
+
Set.new(change_set.permissions)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
##
|
|
124
|
+
# @api public
|
|
125
|
+
#
|
|
126
|
+
# @example
|
|
127
|
+
# user = User.find('user_id')
|
|
128
|
+
#
|
|
129
|
+
# acl.revoke(:read).from(user)
|
|
130
|
+
def revoke(mode)
|
|
131
|
+
ModeRevoke.new(self, mode)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
##
|
|
135
|
+
# @api public
|
|
136
|
+
#
|
|
137
|
+
# Saves the ACL for the resource, by saving each permission policy
|
|
138
|
+
#
|
|
139
|
+
# @yield [acl] gives self to the block only if the save is successful
|
|
140
|
+
# @return [Boolean]
|
|
141
|
+
def save
|
|
142
|
+
return true unless pending_changes?
|
|
143
|
+
|
|
144
|
+
change_set.sync
|
|
145
|
+
persister.save(resource: change_set.resource)
|
|
146
|
+
yield self if block_given?
|
|
147
|
+
@change_set = nil
|
|
148
|
+
|
|
149
|
+
true
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
private
|
|
153
|
+
|
|
154
|
+
##
|
|
155
|
+
# @api private
|
|
156
|
+
def access_control_model
|
|
157
|
+
AccessControl.for(resource: resource, query_service: query_service)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
##
|
|
161
|
+
# @api private
|
|
162
|
+
def change_set
|
|
163
|
+
@change_set ||= AccessControlChangeSet.new(access_control_model)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
##
|
|
167
|
+
# @abstract
|
|
168
|
+
# @api private
|
|
169
|
+
class ModeEditor
|
|
170
|
+
def initialize(acl, mode)
|
|
171
|
+
@acl = acl
|
|
172
|
+
@mode = mode.to_sym
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
private
|
|
176
|
+
|
|
177
|
+
##
|
|
178
|
+
# Returns the identifier used by ACLs to identify agents.
|
|
179
|
+
#
|
|
180
|
+
# This defaults to the `:agent_key`, but if that method doesn’t exist,
|
|
181
|
+
# `:user_key` will be used as a fallback.
|
|
182
|
+
def id_for(agent:)
|
|
183
|
+
key = agent.try(:agent_key) || agent.user_key
|
|
184
|
+
key.to_s
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
##
|
|
189
|
+
# @api private
|
|
190
|
+
#
|
|
191
|
+
# A short-term memory object for the permission granting DSL. Use with
|
|
192
|
+
# method chaining, as in: `acl.grant(:edit).to(user)`.
|
|
193
|
+
class ModeGrant < ModeEditor
|
|
194
|
+
##
|
|
195
|
+
# @api public
|
|
196
|
+
# @return [Hyrax::AccessControlList]
|
|
197
|
+
def to(user_or_group)
|
|
198
|
+
agent_id = id_for(agent: user_or_group)
|
|
199
|
+
|
|
200
|
+
@acl << Hyrax::Acl::Permission.new(access_to: @acl.resource.id, agent: agent_id, mode: @mode)
|
|
201
|
+
@acl
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
##
|
|
206
|
+
# @api private
|
|
207
|
+
#
|
|
208
|
+
# A short-term memory object for the permission revoking DSL. Use with
|
|
209
|
+
# method chaining, as in: `acl.revoke(:edit).from(user)`.
|
|
210
|
+
class ModeRevoke < ModeEditor
|
|
211
|
+
##
|
|
212
|
+
# @api public
|
|
213
|
+
# @return [Hyrax::AccessControlList]
|
|
214
|
+
def from(user_or_group)
|
|
215
|
+
permission_for_deletion = @acl.permissions.find do |p|
|
|
216
|
+
p.mode == @mode &&
|
|
217
|
+
p.agent.to_s == id_for(agent: user_or_group)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
@acl.delete(permission_for_deletion) if permission_for_deletion
|
|
221
|
+
@acl
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
module Acl
|
|
5
|
+
class Agent
|
|
6
|
+
attr_reader :name
|
|
7
|
+
|
|
8
|
+
def initialize(name)
|
|
9
|
+
@name = name
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# @return [String] a local identifier in ACL
|
|
14
|
+
# data
|
|
15
|
+
def agent_key
|
|
16
|
+
name
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Hyrax
|
|
3
|
+
module Acl
|
|
4
|
+
module CustomQueries
|
|
5
|
+
# @example
|
|
6
|
+
# Hyrax.custom_queries.find_access_control_for(resource: resource)
|
|
7
|
+
class FindAccessControl
|
|
8
|
+
def self.queries
|
|
9
|
+
[:find_access_control_for]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(query_service:)
|
|
13
|
+
@query_service = query_service
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
attr_reader :query_service
|
|
17
|
+
delegate :resource_factory, to: :query_service
|
|
18
|
+
|
|
19
|
+
def find_access_control_for(resource: )
|
|
20
|
+
query_service
|
|
21
|
+
.find_inverse_references_by(resource: resource, property: :access_to)
|
|
22
|
+
.find { |r| r.is_a?(Hyrax::Acl::AccessControl) } ||
|
|
23
|
+
raise(Valkyrie::Persistence::ObjectNotFoundError)
|
|
24
|
+
rescue ArgumentError # some adapters raise ArgumentError for missing resources
|
|
25
|
+
raise(Valkyrie::Persistence::ObjectNotFoundError)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'hyrax/acl/custom_queries/find_access_control'
|
|
4
|
+
|
|
5
|
+
module Hyrax
|
|
6
|
+
module Acl
|
|
7
|
+
##
|
|
8
|
+
# @see https://github.com/samvera/valkyrie/wiki/Queries#custom-queries
|
|
9
|
+
# @see https://github.com/samvera/hyrax/wiki/Hyrax-Valkyrie-Usage-Guide#custom-queriesy
|
|
10
|
+
module CustomQueries
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Hyrax
|
|
3
|
+
module Acl
|
|
4
|
+
class Group < Agent
|
|
5
|
+
DEFAULT_NAME_PREFIX = 'group/'
|
|
6
|
+
|
|
7
|
+
def self.name_prefix
|
|
8
|
+
DEFAULT_NAME_PREFIX
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# @return [Hyrax::Group]
|
|
13
|
+
def self.from_agent_key(key)
|
|
14
|
+
new(key.delete_prefix(name_prefix))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def initialize(name)
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# @return [String] a local identifier for this group; for use (e.g.) in ACL
|
|
23
|
+
# data
|
|
24
|
+
def agent_key
|
|
25
|
+
self.class.name_prefix + name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# @return [Boolean]
|
|
30
|
+
def ==(other)
|
|
31
|
+
other.class == self.class && other.name == name
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
module Acl
|
|
5
|
+
##
|
|
6
|
+
# Valkyrie native permissions (access policies) for Hyrax
|
|
7
|
+
#
|
|
8
|
+
# Permissions are persisted independently from `Hyrax::Resource`s (works,
|
|
9
|
+
# collections, file sets, etc...) since their scope is different. Access policies
|
|
10
|
+
# may be application-specific and tend to update more frequently than resource
|
|
11
|
+
# metadata. This approach also allows policies to be persisted using a
|
|
12
|
+
# different database or adapter than is used for curatorial objects.
|
|
13
|
+
class Permission < Valkyrie::Resource
|
|
14
|
+
include Dry::Equalizer(:access_to, :agent, :mode)
|
|
15
|
+
|
|
16
|
+
attribute :access_to, Valkyrie::Types::ID
|
|
17
|
+
attribute :agent, Valkyrie::Types::String
|
|
18
|
+
attribute :mode, Valkyrie::Types::Coercible::Symbol
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/hyrax/acl.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'valkyrie'
|
|
2
|
+
require 'hyrax/acl/agent'
|
|
3
|
+
require 'hyrax/acl/group'
|
|
4
|
+
require 'hyrax/acl/permission'
|
|
5
|
+
require 'hyrax/acl/access_control'
|
|
6
|
+
require 'hyrax/acl/custom_queries'
|
|
7
|
+
require 'hyrax/acl/access_control_change_set'
|
|
8
|
+
require 'hyrax/acl/access_control_list'
|
|
9
|
+
|
|
10
|
+
##
|
|
11
|
+
# Hyrax Access Control Lists
|
|
12
|
+
module Acl
|
|
13
|
+
end
|
data/lib/hyrax.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: hyrax-acl
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Project Surfliner
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2022-07-25 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: valkyrie
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rspec
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
description: Access Control List models and support for Hyrax
|
|
42
|
+
email:
|
|
43
|
+
- tomjohnson@ucsb.edu
|
|
44
|
+
executables: []
|
|
45
|
+
extensions: []
|
|
46
|
+
extra_rdoc_files: []
|
|
47
|
+
files:
|
|
48
|
+
- ".rspec"
|
|
49
|
+
- Gemfile
|
|
50
|
+
- Gemfile.lock
|
|
51
|
+
- README.md
|
|
52
|
+
- hyrax-acl.gemspec
|
|
53
|
+
- lib/hyrax.rb
|
|
54
|
+
- lib/hyrax/acl.rb
|
|
55
|
+
- lib/hyrax/acl/access_control.rb
|
|
56
|
+
- lib/hyrax/acl/access_control_change_set.rb
|
|
57
|
+
- lib/hyrax/acl/access_control_list.rb
|
|
58
|
+
- lib/hyrax/acl/agent.rb
|
|
59
|
+
- lib/hyrax/acl/custom_queries.rb
|
|
60
|
+
- lib/hyrax/acl/custom_queries/find_access_control.rb
|
|
61
|
+
- lib/hyrax/acl/group.rb
|
|
62
|
+
- lib/hyrax/acl/permission.rb
|
|
63
|
+
- lib/hyrax/acl/version.rb
|
|
64
|
+
homepage: http://github.com/samvera-labs/hyrax-acl
|
|
65
|
+
licenses:
|
|
66
|
+
- Apache-2.0
|
|
67
|
+
metadata:
|
|
68
|
+
rubygems_mfa_required: 'true'
|
|
69
|
+
post_install_message:
|
|
70
|
+
rdoc_options: []
|
|
71
|
+
require_paths:
|
|
72
|
+
- lib
|
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
|
+
requirements:
|
|
75
|
+
- - ">="
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '2.7'
|
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
requirements: []
|
|
84
|
+
rubygems_version: 3.1.4
|
|
85
|
+
signing_key:
|
|
86
|
+
specification_version: 4
|
|
87
|
+
summary: Hyrax Access Control List
|
|
88
|
+
test_files: []
|