blacklight-access_controls 0.5.1 → 0.6.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/.gitignore +1 -0
- data/.rspec +2 -0
- data/.rubocop.yml +15 -0
- data/.rubocop_todo.yml +156 -0
- data/Rakefile +14 -7
- data/VERSION +1 -1
- data/blacklight-access_controls.gemspec +2 -0
- data/lib/blacklight/access_controls/ability.rb +3 -5
- data/lib/blacklight/access_controls/catalog.rb +5 -8
- data/lib/blacklight/access_controls/config.rb +6 -8
- data/lib/blacklight/access_controls/enforcement.rb +45 -51
- data/lib/blacklight/access_controls/permissions_cache.rb +2 -4
- data/lib/blacklight/access_controls/permissions_query.rb +8 -8
- data/lib/blacklight/access_controls/user.rb +0 -1
- data/lib/blacklight-access_controls.rb +1 -2
- data/lib/generators/blacklight/ability.rb +0 -1
- data/lib/generators/blacklight/access_controls_generator.rb +7 -11
- data/lib/generators/blacklight/blacklight_access_controls.rb +1 -1
- data/spec/support/solr_support.rb +0 -2
- data/spec/test_app_templates/lib/generators/test_app_generator.rb +2 -3
- data/spec/unit/ability_spec.rb +28 -32
- data/spec/unit/catalog_spec.rb +1 -4
- data/spec/unit/config_spec.rb +6 -9
- data/spec/unit/enforcement_spec.rb +72 -98
- metadata +33 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1e7cd1735e1adbfc7b730e61d0b6deb065ef3d6c
|
|
4
|
+
data.tar.gz: d1d6ad746309d9c725eee9afee7a5d2000cfa262
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 79b64f8758122bb057404ececc2322b8eb5b25511d96ad5a937234259860e1959dc45f79fbbef8c1f3ad4423e6fc81543363a78bf2ce780b8514d672d2e4fa64
|
|
7
|
+
data.tar.gz: 8b0e425f6f6f93e3087803a25b00212ece6dcb1d240cc5abd7d2004198f44183e3017c4b4702449fd56a15622327b0f92414349563344c960319579bbbdd6ae3
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# This configuration was generated by
|
|
2
|
+
# `rubocop --auto-gen-config`
|
|
3
|
+
# on 2016-08-24 16:11:34 -0700 using RuboCop version 0.42.0.
|
|
4
|
+
# The point is for the user to remove these configuration records
|
|
5
|
+
# one by one as the offenses are removed from the code base.
|
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
|
8
|
+
|
|
9
|
+
# Manually added to prevent `unrecognized cop` warnings during execution.
|
|
10
|
+
require: rubocop-rspec
|
|
11
|
+
|
|
12
|
+
# Offense count: 4
|
|
13
|
+
Metrics/AbcSize:
|
|
14
|
+
Max: 18
|
|
15
|
+
|
|
16
|
+
# Offense count: 1
|
|
17
|
+
# Configuration parameters: CountComments.
|
|
18
|
+
Metrics/ModuleLength:
|
|
19
|
+
Max: 120
|
|
20
|
+
|
|
21
|
+
# Offense count: 7
|
|
22
|
+
# Configuration parameters: SkipBlocks.
|
|
23
|
+
RSpec/DescribedClass:
|
|
24
|
+
Exclude:
|
|
25
|
+
- 'spec/unit/ability_spec.rb'
|
|
26
|
+
|
|
27
|
+
# Offense count: 1
|
|
28
|
+
# Configuration parameters: Max.
|
|
29
|
+
RSpec/ExampleLength:
|
|
30
|
+
Exclude:
|
|
31
|
+
- 'spec/unit/ability_spec.rb'
|
|
32
|
+
|
|
33
|
+
# Offense count: 3
|
|
34
|
+
# Configuration parameters: CustomTransform.
|
|
35
|
+
RSpec/FilePath:
|
|
36
|
+
Exclude:
|
|
37
|
+
- 'spec/unit/catalog_spec.rb'
|
|
38
|
+
- 'spec/unit/config_spec.rb'
|
|
39
|
+
- 'spec/unit/enforcement_spec.rb'
|
|
40
|
+
|
|
41
|
+
# Offense count: 17
|
|
42
|
+
# Configuration parameters: AssignmentOnly.
|
|
43
|
+
RSpec/InstanceVariable:
|
|
44
|
+
Exclude:
|
|
45
|
+
- 'spec/unit/enforcement_spec.rb'
|
|
46
|
+
|
|
47
|
+
# Offense count: 23
|
|
48
|
+
RSpec/LeadingSubject:
|
|
49
|
+
Exclude:
|
|
50
|
+
- 'spec/unit/ability_spec.rb'
|
|
51
|
+
- 'spec/unit/enforcement_spec.rb'
|
|
52
|
+
|
|
53
|
+
# Offense count: 7
|
|
54
|
+
RSpec/MultipleExpectations:
|
|
55
|
+
Max: 6
|
|
56
|
+
|
|
57
|
+
# Offense count: 24
|
|
58
|
+
RSpec/NamedSubject:
|
|
59
|
+
Exclude:
|
|
60
|
+
- 'spec/unit/ability_spec.rb'
|
|
61
|
+
- 'spec/unit/catalog_spec.rb'
|
|
62
|
+
- 'spec/unit/config_spec.rb'
|
|
63
|
+
- 'spec/unit/enforcement_spec.rb'
|
|
64
|
+
|
|
65
|
+
# Offense count: 30
|
|
66
|
+
# Configuration parameters: MaxNesting.
|
|
67
|
+
RSpec/NestedGroups:
|
|
68
|
+
Exclude:
|
|
69
|
+
- 'spec/unit/ability_spec.rb'
|
|
70
|
+
- 'spec/unit/catalog_spec.rb'
|
|
71
|
+
- 'spec/unit/enforcement_spec.rb'
|
|
72
|
+
|
|
73
|
+
# Offense count: 2
|
|
74
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
75
|
+
# SupportedStyles: not_to, to_not
|
|
76
|
+
RSpec/NotToNot:
|
|
77
|
+
Exclude:
|
|
78
|
+
- 'spec/unit/catalog_spec.rb'
|
|
79
|
+
- 'spec/unit/enforcement_spec.rb'
|
|
80
|
+
|
|
81
|
+
# Offense count: 1
|
|
82
|
+
# Configuration parameters: IgnoreSymbolicNames.
|
|
83
|
+
RSpec/VerifiedDoubles:
|
|
84
|
+
Exclude:
|
|
85
|
+
- 'spec/unit/ability_spec.rb'
|
|
86
|
+
|
|
87
|
+
# Offense count: 5
|
|
88
|
+
# Cop supports --auto-correct.
|
|
89
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
|
90
|
+
# SupportedStyles: with_first_parameter, with_fixed_indentation
|
|
91
|
+
Style/AlignParameters:
|
|
92
|
+
Exclude:
|
|
93
|
+
- 'lib/generators/blacklight/access_controls_generator.rb'
|
|
94
|
+
|
|
95
|
+
# Offense count: 6
|
|
96
|
+
# Cop supports --auto-correct.
|
|
97
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles, ProceduralMethods, FunctionalMethods, IgnoredMethods.
|
|
98
|
+
# SupportedStyles: line_count_based, semantic, braces_for_chaining
|
|
99
|
+
# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
|
|
100
|
+
# FunctionalMethods: let, let!, subject, watch
|
|
101
|
+
# IgnoredMethods: lambda, proc, it
|
|
102
|
+
Style/BlockDelimiters:
|
|
103
|
+
Exclude:
|
|
104
|
+
- 'spec/unit/ability_spec.rb'
|
|
105
|
+
|
|
106
|
+
# Offense count: 3
|
|
107
|
+
# Cop supports --auto-correct.
|
|
108
|
+
Style/BlockEndNewline:
|
|
109
|
+
Exclude:
|
|
110
|
+
- 'spec/unit/ability_spec.rb'
|
|
111
|
+
|
|
112
|
+
# Offense count: 3
|
|
113
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
114
|
+
# SupportedStyles: nested, compact
|
|
115
|
+
Style/ClassAndModuleChildren:
|
|
116
|
+
Exclude:
|
|
117
|
+
- 'lib/blacklight-access_controls.rb'
|
|
118
|
+
- 'lib/blacklight/access_controls/permissions_cache.rb'
|
|
119
|
+
- 'lib/blacklight/access_controls/permissions_query.rb'
|
|
120
|
+
|
|
121
|
+
# Offense count: 12
|
|
122
|
+
Style/Documentation:
|
|
123
|
+
Exclude:
|
|
124
|
+
- 'spec/**/*'
|
|
125
|
+
- 'test/**/*'
|
|
126
|
+
- 'lib/blacklight-access_controls.rb'
|
|
127
|
+
- 'lib/blacklight/access_controls.rb'
|
|
128
|
+
- 'lib/blacklight/access_controls/ability.rb'
|
|
129
|
+
- 'lib/blacklight/access_controls/catalog.rb'
|
|
130
|
+
- 'lib/blacklight/access_controls/config.rb'
|
|
131
|
+
- 'lib/blacklight/access_controls/enforcement.rb'
|
|
132
|
+
- 'lib/blacklight/access_controls/permissions_cache.rb'
|
|
133
|
+
- 'lib/blacklight/access_controls/permissions_query.rb'
|
|
134
|
+
- 'lib/blacklight/access_controls/user.rb'
|
|
135
|
+
- 'lib/generators/blacklight/ability.rb'
|
|
136
|
+
- 'lib/generators/blacklight/access_controls_generator.rb'
|
|
137
|
+
|
|
138
|
+
# Offense count: 1
|
|
139
|
+
# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts.
|
|
140
|
+
Style/FileName:
|
|
141
|
+
Exclude:
|
|
142
|
+
- 'lib/blacklight-access_controls.rb'
|
|
143
|
+
|
|
144
|
+
# Offense count: 3
|
|
145
|
+
# Cop supports --auto-correct.
|
|
146
|
+
Style/MultilineBlockLayout:
|
|
147
|
+
Exclude:
|
|
148
|
+
- 'spec/unit/ability_spec.rb'
|
|
149
|
+
|
|
150
|
+
# Offense count: 6
|
|
151
|
+
# Cop supports --auto-correct.
|
|
152
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes.
|
|
153
|
+
# SupportedStyles: slashes, percent_r, mixed
|
|
154
|
+
Style/RegexpLiteral:
|
|
155
|
+
Exclude:
|
|
156
|
+
- 'spec/unit/enforcement_spec.rb'
|
data/Rakefile
CHANGED
|
@@ -7,6 +7,7 @@ end
|
|
|
7
7
|
|
|
8
8
|
Bundler::GemHelper.install_tasks
|
|
9
9
|
|
|
10
|
+
require 'rubocop/rake_task'
|
|
10
11
|
require 'solr_wrapper'
|
|
11
12
|
require 'solr_wrapper/rake_task'
|
|
12
13
|
require 'engine_cart/rake_task'
|
|
@@ -17,27 +18,33 @@ RSpec::Core::RakeTask.new(:spec)
|
|
|
17
18
|
task default: 'ci'
|
|
18
19
|
|
|
19
20
|
def solr_config_dir
|
|
20
|
-
File.join(File.expand_path(File.dirname(__FILE__)),
|
|
21
|
+
File.join(File.expand_path(File.dirname(__FILE__)), 'solr_conf', 'conf')
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
namespace :solr do
|
|
24
25
|
desc 'Configure solr cores'
|
|
25
26
|
task :config do
|
|
26
27
|
SolrWrapper.wrap do |solr|
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
solr.create(name: 'development', dir: solr_config_dir)
|
|
29
|
+
solr.create(name: 'test', dir: solr_config_dir)
|
|
29
30
|
end
|
|
30
31
|
end
|
|
31
32
|
|
|
32
|
-
desc
|
|
33
|
+
desc 'Run test suite (with solr wrapper)'
|
|
33
34
|
task :spec do
|
|
34
35
|
SolrWrapper.wrap do |solr|
|
|
35
|
-
solr.with_collection(name:'test', dir: solr_config_dir) do |collection_name|
|
|
36
|
+
solr.with_collection(name: 'test', dir: solr_config_dir) do # |collection_name|
|
|
36
37
|
Rake::Task['spec'].invoke
|
|
37
38
|
end
|
|
38
39
|
end
|
|
39
40
|
end
|
|
40
41
|
end
|
|
41
42
|
|
|
42
|
-
desc
|
|
43
|
-
task ci: ['engine_cart:generate', 'solr:spec']
|
|
43
|
+
desc 'Run CI build'
|
|
44
|
+
task ci: ['rubocop', 'engine_cart:generate', 'solr:spec']
|
|
45
|
+
|
|
46
|
+
desc 'Run style checker'
|
|
47
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
|
48
|
+
task.requires << 'rubocop-rspec'
|
|
49
|
+
task.fail_on_error = true
|
|
50
|
+
end
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.6.0
|
|
@@ -27,4 +27,6 @@ Gem::Specification.new do |gem|
|
|
|
27
27
|
gem.add_development_dependency "solr_wrapper"
|
|
28
28
|
gem.add_development_dependency "factory_girl_rails", "~> 4.0"
|
|
29
29
|
gem.add_development_dependency "database_cleaner"
|
|
30
|
+
gem.add_development_dependency 'rubocop'
|
|
31
|
+
gem.add_development_dependency 'rubocop-rspec'
|
|
30
32
|
end
|
|
@@ -17,7 +17,7 @@ module Blacklight
|
|
|
17
17
|
self.ability_logic = [:discover_permissions, :read_permissions, :download_permissions]
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def initialize(user, options={})
|
|
20
|
+
def initialize(user, options = {})
|
|
21
21
|
@current_user = user || guest_user
|
|
22
22
|
@options = options
|
|
23
23
|
@cache = Blacklight::AccessControls::PermissionsCache.new
|
|
@@ -36,8 +36,8 @@ module Blacklight
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def grant_permissions
|
|
39
|
-
Rails.logger.debug(
|
|
40
|
-
|
|
39
|
+
Rails.logger.debug('Usergroups are ' + user_groups.inspect)
|
|
40
|
+
ability_logic.each do |method|
|
|
41
41
|
send(method)
|
|
42
42
|
end
|
|
43
43
|
end
|
|
@@ -161,7 +161,6 @@ module Blacklight
|
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
module ClassMethods
|
|
164
|
-
|
|
165
164
|
def discover_group_field
|
|
166
165
|
Blacklight::AccessControls.config.discover_group_field
|
|
167
166
|
end
|
|
@@ -185,7 +184,6 @@ module Blacklight
|
|
|
185
184
|
def download_user_field
|
|
186
185
|
Blacklight::AccessControls.config.download_user_field
|
|
187
186
|
end
|
|
188
|
-
|
|
189
187
|
end
|
|
190
188
|
end
|
|
191
189
|
end
|
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# This is behavior for the catalog controller.
|
|
3
|
-
|
|
4
2
|
module Blacklight
|
|
5
3
|
module AccessControls
|
|
4
|
+
# This is behavior for the catalog controller.
|
|
6
5
|
module Catalog
|
|
7
6
|
extend ActiveSupport::Concern
|
|
8
7
|
|
|
9
|
-
# Controller "before" filter for enforcing access controls
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
def enforce_show_permissions(opts={})
|
|
8
|
+
# Controller "before" filter for enforcing access controls on show actions.
|
|
9
|
+
# @param [Hash] _opts (optional, not currently used)
|
|
10
|
+
def enforce_show_permissions(_opts = {})
|
|
13
11
|
permissions = current_ability.permissions_doc(params[:id])
|
|
14
12
|
unless can? :read, permissions
|
|
15
|
-
raise Blacklight::AccessControls::AccessDenied.new(
|
|
13
|
+
raise Blacklight::AccessControls::AccessDenied.new('You do not have sufficient access privileges to read this document, which has been marked private.', :read, params[:id])
|
|
16
14
|
end
|
|
17
15
|
permissions
|
|
18
16
|
end
|
|
19
|
-
|
|
20
17
|
end
|
|
21
18
|
end
|
|
22
19
|
end
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
module Blacklight
|
|
3
3
|
module AccessControls
|
|
4
4
|
class Config
|
|
5
|
-
|
|
6
5
|
def initialize
|
|
7
6
|
@user_model = default_user_model
|
|
8
7
|
|
|
@@ -26,29 +25,28 @@ module Blacklight
|
|
|
26
25
|
end
|
|
27
26
|
|
|
28
27
|
def default_discover_group_field
|
|
29
|
-
|
|
28
|
+
'discover_access_group_ssim'
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
def default_discover_user_field
|
|
33
|
-
|
|
32
|
+
'discover_access_person_ssim'
|
|
34
33
|
end
|
|
35
34
|
|
|
36
35
|
def default_read_group_field
|
|
37
|
-
|
|
36
|
+
'read_access_group_ssim'
|
|
38
37
|
end
|
|
39
38
|
|
|
40
39
|
def default_read_user_field
|
|
41
|
-
|
|
40
|
+
'read_access_person_ssim'
|
|
42
41
|
end
|
|
43
42
|
|
|
44
43
|
def default_download_group_field
|
|
45
|
-
|
|
44
|
+
'download_access_group_ssim'
|
|
46
45
|
end
|
|
47
46
|
|
|
48
47
|
def default_download_user_field
|
|
49
|
-
|
|
48
|
+
'download_access_person_ssim'
|
|
50
49
|
end
|
|
51
|
-
|
|
52
50
|
end
|
|
53
51
|
end
|
|
54
52
|
end
|
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module Blacklight
|
|
3
3
|
module AccessControls
|
|
4
|
+
# Attributes and methods used to restrict access via Solr.
|
|
5
|
+
#
|
|
6
|
+
# Note: solr_access_filters_logic is an Array of Symbols.
|
|
7
|
+
# It sets defaults. Each symbol identifies a _method_ that must be in
|
|
8
|
+
# this class, taking two parameters (permission_types, ability).
|
|
9
|
+
# Can be changed in local apps or by plugins, e.g.:
|
|
10
|
+
# CatalogController.include ModuleDefiningNewMethod
|
|
11
|
+
# CatalogController.solr_access_filters_logic += [:new_method]
|
|
12
|
+
# CatalogController.solr_access_filters_logic.delete(:we_dont_want)
|
|
4
13
|
module Enforcement
|
|
5
14
|
extend ActiveSupport::Concern
|
|
6
15
|
|
|
7
16
|
included do
|
|
8
17
|
extend Deprecation
|
|
9
|
-
attr_writer :current_ability
|
|
18
|
+
attr_writer :current_ability, :discovery_permissions
|
|
10
19
|
deprecation_deprecate :current_ability=
|
|
11
20
|
|
|
12
21
|
class_attribute :solr_access_filters_logic
|
|
22
|
+
alias_method :add_access_controls_to_solr_params, :apply_gated_discovery
|
|
13
23
|
|
|
14
|
-
# Set defaults. Each symbol identifies a _method_ that must be in
|
|
15
|
-
# this class, taking one parameter (permission_types)
|
|
16
|
-
# Can be changed in local apps or by plugins, eg:
|
|
17
|
-
# CatalogController.include ModuleDefiningNewMethod
|
|
18
|
-
# CatalogController.solr_access_filters_logic += [:new_method]
|
|
19
|
-
# CatalogController.solr_access_filters_logic.delete(:we_dont_want)
|
|
20
24
|
self.solr_access_filters_logic = [:apply_group_permissions, :apply_user_permissions]
|
|
21
25
|
|
|
22
26
|
# Apply appropriate access controls to all solr queries
|
|
@@ -25,71 +29,61 @@ module Blacklight
|
|
|
25
29
|
|
|
26
30
|
delegate :current_ability, to: :scope
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
# Grant access based on user id & group
|
|
34
|
-
solr_access_filters_logic.each do |method_name|
|
|
35
|
-
user_access_filters += send(method_name, permission_types, ability)
|
|
36
|
-
end
|
|
37
|
-
user_access_filters
|
|
32
|
+
# Which permission levels (logical OR) will grant you the ability to discover documents in a search.
|
|
33
|
+
# Override this method if you want it to be something other than the default, or hit the setter
|
|
34
|
+
def discovery_permissions
|
|
35
|
+
@discovery_permissions ||= %w(discover read)
|
|
38
36
|
end
|
|
39
37
|
|
|
40
|
-
|
|
41
|
-
# Solr query modifications
|
|
42
|
-
#
|
|
38
|
+
protected
|
|
43
39
|
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def add_access_controls_to_solr_params(solr_parameters)
|
|
49
|
-
apply_gated_discovery(solr_parameters)
|
|
40
|
+
# Grant access based on user id & group
|
|
41
|
+
# @return [Array{Array{String}}]
|
|
42
|
+
def gated_discovery_filters(permission_types = discovery_permissions, ability = current_ability)
|
|
43
|
+
solr_access_filters_logic.map { |method| send(method, permission_types, ability).reject(&:blank?) }.reject(&:empty?)
|
|
50
44
|
end
|
|
51
45
|
|
|
52
|
-
|
|
53
|
-
# Override this method if you want it to be something other than the default
|
|
54
|
-
def discovery_permissions
|
|
55
|
-
@discovery_permissions ||= ["discover","read"]
|
|
56
|
-
end
|
|
57
|
-
def discovery_permissions= (permissions)
|
|
58
|
-
@discovery_permissions = permissions
|
|
59
|
-
end
|
|
46
|
+
### Solr query modifications
|
|
60
47
|
|
|
61
|
-
# Controller
|
|
62
|
-
#
|
|
48
|
+
# Controller before_filter that sets up access-controlled lucene query to provide gated discovery behavior.
|
|
49
|
+
# Set solr_parameters to enforce appropriate permissions.
|
|
50
|
+
# @param [Hash{Object}] solr_parameters the current solr parameters, to be modified herein!
|
|
51
|
+
# @note Applies a lucene filter query to the solr :fq parameter for gated discovery.
|
|
63
52
|
def apply_gated_discovery(solr_parameters)
|
|
64
53
|
solr_parameters[:fq] ||= []
|
|
65
|
-
solr_parameters[:fq] << gated_discovery_filters.join(
|
|
66
|
-
Rails.logger.debug("Solr parameters: #{
|
|
54
|
+
solr_parameters[:fq] << gated_discovery_filters.reject(&:blank?).join(' OR ')
|
|
55
|
+
Rails.logger.debug("Solr parameters: #{solr_parameters.inspect}")
|
|
67
56
|
end
|
|
68
57
|
|
|
58
|
+
# For groups
|
|
59
|
+
# @return [Array{String}] values are lucence syntax term queries suitable for :fq
|
|
60
|
+
# @example
|
|
61
|
+
# [ "({!terms f=discover_access_group_ssim}public,faculty,africana-faculty,registered)",
|
|
62
|
+
# "({!terms f=read_access_group_ssim}public,faculty,africana-faculty,registered)" ]
|
|
69
63
|
def apply_group_permissions(permission_types, ability = current_ability)
|
|
70
|
-
|
|
64
|
+
groups = ability.user_groups
|
|
65
|
+
return [] if groups.empty?
|
|
71
66
|
permission_types.map do |type|
|
|
72
67
|
field = solr_field_for(type, 'group')
|
|
73
|
-
groups
|
|
74
|
-
# The parens are required to properly OR the cases together.
|
|
75
|
-
"({!terms f=#{field}}#{groups.join(',')})"
|
|
68
|
+
"({!terms f=#{field}}#{groups.join(',')})" # parens required to properly OR the clauses together.
|
|
76
69
|
end
|
|
77
70
|
end
|
|
78
71
|
|
|
72
|
+
# For individual user access
|
|
73
|
+
# @return [Array{String}] values are lucence syntax term queries suitable for :fq
|
|
74
|
+
# @example ['discover_access_person_ssim:user_1@abc.com', 'read_access_person_ssim:user_1@abc.com']
|
|
79
75
|
def apply_user_permissions(permission_types, ability = current_ability)
|
|
80
|
-
# for individual user access
|
|
81
|
-
user_access_filters = []
|
|
82
76
|
user = ability.current_user
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
end
|
|
77
|
+
return [] unless user && user.user_key.present?
|
|
78
|
+
permission_types.map do |type|
|
|
79
|
+
escape_filter(solr_field_for(type, 'user'), user.user_key)
|
|
87
80
|
end
|
|
88
|
-
user_access_filters
|
|
89
81
|
end
|
|
90
82
|
|
|
91
|
-
#
|
|
92
|
-
# e.g. "
|
|
83
|
+
# @param [#to_s] permission_type a single value, e.g. "read" or "discover"
|
|
84
|
+
# @param [#to_s] permission_category a single value, e.g. "group" or "person"
|
|
85
|
+
# @return [String] name of the solr field for this type of permission
|
|
86
|
+
# @example return values: "read_access_group_ssim" or "discover_access_person_ssim"
|
|
93
87
|
def solr_field_for(permission_type, permission_category)
|
|
94
88
|
method_name = "#{permission_type}_#{permission_category}_field".to_sym
|
|
95
89
|
Blacklight::AccessControls.config.send(method_name)
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
class Blacklight::AccessControls::PermissionsCache
|
|
3
|
-
|
|
4
3
|
def initialize
|
|
5
|
-
clear
|
|
4
|
+
clear
|
|
6
5
|
end
|
|
7
6
|
|
|
8
7
|
def get(pid)
|
|
@@ -10,11 +9,10 @@ class Blacklight::AccessControls::PermissionsCache
|
|
|
10
9
|
end
|
|
11
10
|
|
|
12
11
|
def put(pid, doc)
|
|
13
|
-
@cache[pid] = doc
|
|
12
|
+
@cache[pid] = doc
|
|
14
13
|
end
|
|
15
14
|
|
|
16
15
|
def clear
|
|
17
16
|
@cache = {}
|
|
18
17
|
end
|
|
19
|
-
|
|
20
18
|
end
|
|
@@ -23,13 +23,13 @@ module Blacklight::AccessControls
|
|
|
23
23
|
# Modeled on Blacklight::SolrHelper.get_permissions_solr_response_for_doc_id
|
|
24
24
|
# @param [String] id of the documetn to retrieve
|
|
25
25
|
# @param [Hash] extra_controller_params (optional)
|
|
26
|
-
def get_permissions_solr_response_for_doc_id(id=nil, extra_controller_params={})
|
|
27
|
-
raise Blacklight::Exceptions::InvalidSolrID
|
|
26
|
+
def get_permissions_solr_response_for_doc_id(id = nil, extra_controller_params = {})
|
|
27
|
+
raise Blacklight::Exceptions::InvalidSolrID, 'The application is trying to retrieve permissions without specifying an asset id' if id.nil?
|
|
28
28
|
solr_opts = permissions_solr_doc_params(id).merge(extra_controller_params)
|
|
29
|
-
response = Blacklight.default_index.connection.get('select', :
|
|
29
|
+
response = Blacklight.default_index.connection.get('select', params: solr_opts)
|
|
30
30
|
solr_response = Blacklight::Solr::Response.new(response, solr_opts)
|
|
31
31
|
|
|
32
|
-
raise Blacklight::Exceptions::InvalidSolrID
|
|
32
|
+
raise Blacklight::Exceptions::InvalidSolrID, "The solr permissions search handler didn't return anything for id \"#{id}\"" if solr_response.docs.empty?
|
|
33
33
|
permissions_document_class.new(solr_response.docs.first, solr_response)
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -42,13 +42,13 @@ module Blacklight::AccessControls
|
|
|
42
42
|
# This method is primary called by the get_permissions_solr_response_for_doc_id method.
|
|
43
43
|
# Modeled on Blacklight::SolrHelper.solr_doc_params
|
|
44
44
|
# @param [String] id of the documetn to retrieve
|
|
45
|
-
def permissions_solr_doc_params(id=nil)
|
|
45
|
+
def permissions_solr_doc_params(id = nil)
|
|
46
46
|
id ||= params[:id]
|
|
47
47
|
# just to be consistent with the other solr param methods:
|
|
48
48
|
{
|
|
49
|
-
:
|
|
50
|
-
:
|
|
49
|
+
qt: :permissions,
|
|
50
|
+
id: id # this assumes the document request handler will map the 'id' param to the unique key field
|
|
51
51
|
}
|
|
52
52
|
end
|
|
53
|
-
end
|
|
53
|
+
end
|
|
54
54
|
end
|
|
@@ -13,12 +13,11 @@ module Blacklight::AccessControls
|
|
|
13
13
|
yield @config if block_given?
|
|
14
14
|
@config
|
|
15
15
|
end
|
|
16
|
-
alias
|
|
16
|
+
alias config configure
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
# This error is raised when a user isn't allowed to access a given controller action.
|
|
20
20
|
# This usually happens within a call to Enforcement#enforce_access_controls but can be
|
|
21
21
|
# raised manually.
|
|
22
22
|
class AccessDenied < ::CanCan::AccessDenied; end
|
|
23
|
-
|
|
24
23
|
end
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module Blacklight
|
|
3
3
|
class AccessControlsGenerator < Rails::Generators::Base
|
|
4
|
-
|
|
5
4
|
desc "This generator makes the following changes to your application:
|
|
6
5
|
|
|
7
6
|
1. Includes Blacklight::AccessControls::User in the User class.
|
|
@@ -9,21 +8,19 @@ module Blacklight
|
|
|
9
8
|
3. Adds access controls to CatalogController.
|
|
10
9
|
4. Adds Ability class."
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
source_root File.expand_path("..", __FILE__)
|
|
11
|
+
source_root File.expand_path('..', __FILE__)
|
|
14
12
|
|
|
15
13
|
class_option :user_model, aliases: '-m',
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
type: :string, default: 'User',
|
|
15
|
+
desc: 'What is your user model called?'
|
|
18
16
|
|
|
19
17
|
class_option :search_builders, aliases: '-b', type: :array,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
default: Array(File.join('app', 'models', 'search_builder.rb')),
|
|
19
|
+
desc: 'The path(s) to your search builder model(s)'
|
|
23
20
|
|
|
24
21
|
def add_access_controls_to_user
|
|
25
22
|
say_status('status', 'ADDING ACCESS CONTROLS TO USER MODEL', :yellow)
|
|
26
|
-
insert_into_file File.join('app','models', "#{options[:user_model].underscore}.rb"),
|
|
23
|
+
insert_into_file File.join('app', 'models', "#{options[:user_model].underscore}.rb"),
|
|
27
24
|
" include Blacklight::AccessControls::User\n\n",
|
|
28
25
|
after: "include Blacklight::User\n"
|
|
29
26
|
end
|
|
@@ -44,7 +41,7 @@ module Blacklight
|
|
|
44
41
|
include Blacklight::AccessControls::Catalog
|
|
45
42
|
|
|
46
43
|
# Apply the blacklight-access_controls
|
|
47
|
-
|
|
44
|
+
before_action :enforce_show_permissions, only: :show
|
|
48
45
|
|
|
49
46
|
EOS
|
|
50
47
|
|
|
@@ -61,6 +58,5 @@ module Blacklight
|
|
|
61
58
|
say_status('status', 'ADDING BLACKLIGHT ACCESS CONTROLS CONFIGURATION', :yellow)
|
|
62
59
|
copy_file 'blacklight_access_controls.rb', 'config/initializers/blacklight_access_controls.rb'
|
|
63
60
|
end
|
|
64
|
-
|
|
65
61
|
end
|
|
66
62
|
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
require 'rails/generators'
|
|
3
3
|
|
|
4
4
|
class TestAppGenerator < Rails::Generators::Base
|
|
5
|
-
source_root File.expand_path(
|
|
5
|
+
source_root File.expand_path('../../../../spec/test_app_templates', __FILE__)
|
|
6
6
|
|
|
7
7
|
# if you need to generate any additional configuration
|
|
8
8
|
# into the test app, this generator will be run immediately
|
|
@@ -10,7 +10,7 @@ class TestAppGenerator < Rails::Generators::Base
|
|
|
10
10
|
|
|
11
11
|
def generate_blacklight
|
|
12
12
|
say_status('status', 'GENERATING BLACKLIGHT', :yellow)
|
|
13
|
-
generate
|
|
13
|
+
generate 'blacklight:install', '--devise'
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def configure_blacklight
|
|
@@ -22,5 +22,4 @@ class TestAppGenerator < Rails::Generators::Base
|
|
|
22
22
|
def run_access_controls_generator
|
|
23
23
|
generate 'blacklight:access_controls'
|
|
24
24
|
end
|
|
25
|
-
|
|
26
25
|
end
|
data/spec/unit/ability_spec.rb
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require 'spec_helper'
|
|
3
2
|
require 'cancan/matchers'
|
|
4
3
|
|
|
5
4
|
describe Ability do
|
|
6
5
|
let(:ability) { Ability.new(user) }
|
|
7
6
|
|
|
8
|
-
describe
|
|
7
|
+
describe 'class methods' do
|
|
9
8
|
it 'has keys for access control fields' do
|
|
10
9
|
expect(Ability.read_group_field).to eq 'read_access_group_ssim'
|
|
11
10
|
expect(Ability.read_user_field).to eq 'read_access_person_ssim'
|
|
@@ -16,11 +15,11 @@ describe Ability do
|
|
|
16
15
|
end
|
|
17
16
|
end
|
|
18
17
|
|
|
19
|
-
describe
|
|
18
|
+
describe 'Given an asset that has been made publicly discoverable' do
|
|
20
19
|
let(:asset) { SolrDocument.new(id: 'public_discovery',
|
|
21
|
-
|
|
20
|
+
discover_access_group_ssim: ['public']) }
|
|
22
21
|
|
|
23
|
-
context
|
|
22
|
+
context 'Then a not-signed-in user' do
|
|
24
23
|
let(:user) { nil }
|
|
25
24
|
subject { ability }
|
|
26
25
|
|
|
@@ -29,7 +28,7 @@ describe Ability do
|
|
|
29
28
|
it { should_not be_able_to(:download, asset) }
|
|
30
29
|
end
|
|
31
30
|
|
|
32
|
-
context
|
|
31
|
+
context 'Then a registered user' do
|
|
33
32
|
let(:user) { create(:user) }
|
|
34
33
|
subject { ability }
|
|
35
34
|
|
|
@@ -54,11 +53,11 @@ describe Ability do
|
|
|
54
53
|
end
|
|
55
54
|
end
|
|
56
55
|
|
|
57
|
-
describe
|
|
56
|
+
describe 'Given an asset that has been made publicly readable' do
|
|
58
57
|
let(:asset) { SolrDocument.new(id: 'public_read',
|
|
59
|
-
|
|
58
|
+
read_access_group_ssim: ['public']) }
|
|
60
59
|
|
|
61
|
-
context
|
|
60
|
+
context 'Then a not-signed-in user' do
|
|
62
61
|
let(:user) { nil }
|
|
63
62
|
subject { ability }
|
|
64
63
|
|
|
@@ -67,7 +66,7 @@ describe Ability do
|
|
|
67
66
|
it { should_not be_able_to(:download, asset) }
|
|
68
67
|
end
|
|
69
68
|
|
|
70
|
-
context
|
|
69
|
+
context 'Then a registered user' do
|
|
71
70
|
let(:user) { create(:user) }
|
|
72
71
|
subject { ability }
|
|
73
72
|
|
|
@@ -92,12 +91,12 @@ describe Ability do
|
|
|
92
91
|
end
|
|
93
92
|
end
|
|
94
93
|
|
|
95
|
-
describe
|
|
94
|
+
describe 'Given an asset that has been made publicly downloadable' do
|
|
96
95
|
let(:id) { 'public_download' }
|
|
97
96
|
let(:asset) { SolrDocument.new(id: id,
|
|
98
|
-
|
|
97
|
+
download_access_group_ssim: ['public']) }
|
|
99
98
|
|
|
100
|
-
context
|
|
99
|
+
context 'Then a not-signed-in user' do
|
|
101
100
|
let(:user) { nil }
|
|
102
101
|
subject { ability }
|
|
103
102
|
|
|
@@ -106,7 +105,7 @@ describe Ability do
|
|
|
106
105
|
it { should be_able_to(:download, asset) }
|
|
107
106
|
end
|
|
108
107
|
|
|
109
|
-
context
|
|
108
|
+
context 'Then a registered user' do
|
|
110
109
|
let(:user) { create(:user) }
|
|
111
110
|
subject { ability }
|
|
112
111
|
|
|
@@ -131,12 +130,11 @@ describe Ability do
|
|
|
131
130
|
end
|
|
132
131
|
end
|
|
133
132
|
|
|
134
|
-
|
|
135
|
-
describe "Given an asset to which a specific user has discovery access" do
|
|
133
|
+
describe 'Given an asset to which a specific user has discovery access' do
|
|
136
134
|
let(:user_with_access) { create(:user) }
|
|
137
135
|
let(:asset) { SolrDocument.new(id: 'user_disco', discover_access_person_ssim: [user_with_access.email]) }
|
|
138
136
|
|
|
139
|
-
context
|
|
137
|
+
context 'Then a not-signed-in user' do
|
|
140
138
|
let(:user) { nil }
|
|
141
139
|
subject { ability }
|
|
142
140
|
|
|
@@ -145,7 +143,7 @@ describe Ability do
|
|
|
145
143
|
it { should_not be_able_to(:download, asset) }
|
|
146
144
|
end
|
|
147
145
|
|
|
148
|
-
context
|
|
146
|
+
context 'Then a different registered user' do
|
|
149
147
|
let(:user) { create(:user) }
|
|
150
148
|
subject { ability }
|
|
151
149
|
|
|
@@ -154,7 +152,7 @@ describe Ability do
|
|
|
154
152
|
it { should_not be_able_to(:download, asset) }
|
|
155
153
|
end
|
|
156
154
|
|
|
157
|
-
context
|
|
155
|
+
context 'Then that user' do
|
|
158
156
|
let(:user) { user_with_access }
|
|
159
157
|
subject { ability }
|
|
160
158
|
|
|
@@ -164,11 +162,11 @@ describe Ability do
|
|
|
164
162
|
end
|
|
165
163
|
end
|
|
166
164
|
|
|
167
|
-
describe
|
|
165
|
+
describe 'Given an asset to which a specific user has read access' do
|
|
168
166
|
let(:user_with_access) { create(:user) }
|
|
169
167
|
let(:asset) { SolrDocument.new(id: 'user_read', read_access_person_ssim: [user_with_access.email]) }
|
|
170
168
|
|
|
171
|
-
context
|
|
169
|
+
context 'Then a not-signed-in user' do
|
|
172
170
|
let(:user) { nil }
|
|
173
171
|
subject { ability }
|
|
174
172
|
|
|
@@ -177,7 +175,7 @@ describe Ability do
|
|
|
177
175
|
it { should_not be_able_to(:download, asset) }
|
|
178
176
|
end
|
|
179
177
|
|
|
180
|
-
context
|
|
178
|
+
context 'Then a different registered user' do
|
|
181
179
|
let(:user) { create(:user) }
|
|
182
180
|
subject { ability }
|
|
183
181
|
|
|
@@ -186,7 +184,7 @@ describe Ability do
|
|
|
186
184
|
it { should_not be_able_to(:download, asset) }
|
|
187
185
|
end
|
|
188
186
|
|
|
189
|
-
context
|
|
187
|
+
context 'Then that user' do
|
|
190
188
|
let(:user) { user_with_access }
|
|
191
189
|
subject { ability }
|
|
192
190
|
|
|
@@ -196,11 +194,11 @@ describe Ability do
|
|
|
196
194
|
end
|
|
197
195
|
end
|
|
198
196
|
|
|
199
|
-
describe
|
|
197
|
+
describe 'Given an asset to which a specific user has download access' do
|
|
200
198
|
let(:user_with_access) { create(:user) }
|
|
201
199
|
let(:asset) { SolrDocument.new(id: 'user_read', download_access_person_ssim: [user_with_access.email]) }
|
|
202
200
|
|
|
203
|
-
context
|
|
201
|
+
context 'Then a not-signed-in user' do
|
|
204
202
|
let(:user) { nil }
|
|
205
203
|
subject { ability }
|
|
206
204
|
|
|
@@ -209,7 +207,7 @@ describe Ability do
|
|
|
209
207
|
it { should_not be_able_to(:download, asset) }
|
|
210
208
|
end
|
|
211
209
|
|
|
212
|
-
context
|
|
210
|
+
context 'Then a different registered user' do
|
|
213
211
|
let(:user) { create(:user) }
|
|
214
212
|
subject { ability }
|
|
215
213
|
|
|
@@ -218,7 +216,7 @@ describe Ability do
|
|
|
218
216
|
it { should_not be_able_to(:download, asset) }
|
|
219
217
|
end
|
|
220
218
|
|
|
221
|
-
context
|
|
219
|
+
context 'Then that user' do
|
|
222
220
|
let(:user) { user_with_access }
|
|
223
221
|
subject { ability }
|
|
224
222
|
|
|
@@ -228,7 +226,6 @@ describe Ability do
|
|
|
228
226
|
end
|
|
229
227
|
end
|
|
230
228
|
|
|
231
|
-
|
|
232
229
|
describe '.user_class' do
|
|
233
230
|
subject { Blacklight::AccessControls::Ability.user_class }
|
|
234
231
|
it { is_expected.to eq User }
|
|
@@ -258,19 +255,19 @@ describe Ability do
|
|
|
258
255
|
end
|
|
259
256
|
|
|
260
257
|
context 'a user with groups' do
|
|
261
|
-
let(:user) { double(groups:
|
|
258
|
+
let(:user) { double(groups: %w(group1 group2), new_record?: false) }
|
|
262
259
|
it { is_expected.to include('group1', 'group2') }
|
|
263
260
|
end
|
|
264
261
|
end
|
|
265
262
|
|
|
266
|
-
describe
|
|
263
|
+
describe 'with a custom method' do
|
|
267
264
|
let(:user) { create(:user) }
|
|
268
265
|
subject { MyAbility.new(user) }
|
|
269
266
|
|
|
270
267
|
before do
|
|
271
268
|
class MyAbility
|
|
272
269
|
include Blacklight::AccessControls::Ability
|
|
273
|
-
self.ability_logic +=[:setup_my_permissions]
|
|
270
|
+
self.ability_logic += [:setup_my_permissions]
|
|
274
271
|
|
|
275
272
|
def setup_my_permissions
|
|
276
273
|
can :accept, SolrDocument
|
|
@@ -285,5 +282,4 @@ describe Ability do
|
|
|
285
282
|
# Make sure it called the custom method
|
|
286
283
|
it { should be_able_to(:accept, SolrDocument) }
|
|
287
284
|
end
|
|
288
|
-
|
|
289
285
|
end
|
data/spec/unit/catalog_spec.rb
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require 'spec_helper'
|
|
3
|
-
|
|
4
2
|
describe Blacklight::AccessControls::Catalog do
|
|
5
3
|
let(:controller) { CatalogController.new }
|
|
6
4
|
|
|
7
5
|
describe '#enforce_show_permissions' do
|
|
8
6
|
subject { controller.send(:enforce_show_permissions) }
|
|
9
|
-
let(:params) {{ id: doc.id }}
|
|
7
|
+
let(:params) { { id: doc.id } }
|
|
10
8
|
|
|
11
9
|
before do
|
|
12
10
|
allow(controller).to receive(:current_user).and_return(user)
|
|
@@ -38,5 +36,4 @@ describe Blacklight::AccessControls::Catalog do
|
|
|
38
36
|
end
|
|
39
37
|
end
|
|
40
38
|
end
|
|
41
|
-
|
|
42
39
|
end
|
data/spec/unit/config_spec.rb
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require 'spec_helper'
|
|
3
|
-
|
|
4
2
|
describe Blacklight::AccessControls::Config do
|
|
5
3
|
let(:config) { described_class.new }
|
|
6
4
|
|
|
@@ -19,7 +17,7 @@ describe Blacklight::AccessControls::Config do
|
|
|
19
17
|
subject { config.discover_group_field }
|
|
20
18
|
|
|
21
19
|
it 'has a default value' do
|
|
22
|
-
expect(subject).to eq
|
|
20
|
+
expect(subject).to eq 'discover_access_group_ssim'
|
|
23
21
|
end
|
|
24
22
|
|
|
25
23
|
it 'can be set to a non-default value' do
|
|
@@ -32,7 +30,7 @@ describe Blacklight::AccessControls::Config do
|
|
|
32
30
|
subject { config.discover_user_field }
|
|
33
31
|
|
|
34
32
|
it 'has a default value' do
|
|
35
|
-
expect(subject).to eq
|
|
33
|
+
expect(subject).to eq 'discover_access_person_ssim'
|
|
36
34
|
end
|
|
37
35
|
|
|
38
36
|
it 'can be set to a non-default value' do
|
|
@@ -45,7 +43,7 @@ describe Blacklight::AccessControls::Config do
|
|
|
45
43
|
subject { config.read_group_field }
|
|
46
44
|
|
|
47
45
|
it 'has a default value' do
|
|
48
|
-
expect(subject).to eq
|
|
46
|
+
expect(subject).to eq 'read_access_group_ssim'
|
|
49
47
|
end
|
|
50
48
|
|
|
51
49
|
it 'can be set to a non-default value' do
|
|
@@ -58,7 +56,7 @@ describe Blacklight::AccessControls::Config do
|
|
|
58
56
|
subject { config.read_user_field }
|
|
59
57
|
|
|
60
58
|
it 'has a default value' do
|
|
61
|
-
expect(subject).to eq
|
|
59
|
+
expect(subject).to eq 'read_access_person_ssim'
|
|
62
60
|
end
|
|
63
61
|
|
|
64
62
|
it 'can be set to a non-default value' do
|
|
@@ -71,7 +69,7 @@ describe Blacklight::AccessControls::Config do
|
|
|
71
69
|
subject { config.download_group_field }
|
|
72
70
|
|
|
73
71
|
it 'has a default value' do
|
|
74
|
-
expect(subject).to eq
|
|
72
|
+
expect(subject).to eq 'download_access_group_ssim'
|
|
75
73
|
end
|
|
76
74
|
|
|
77
75
|
it 'can be set to a non-default value' do
|
|
@@ -84,7 +82,7 @@ describe Blacklight::AccessControls::Config do
|
|
|
84
82
|
subject { config.download_user_field }
|
|
85
83
|
|
|
86
84
|
it 'has a default value' do
|
|
87
|
-
expect(subject).to eq
|
|
85
|
+
expect(subject).to eq 'download_access_person_ssim'
|
|
88
86
|
end
|
|
89
87
|
|
|
90
88
|
it 'can be set to a non-default value' do
|
|
@@ -92,5 +90,4 @@ describe Blacklight::AccessControls::Config do
|
|
|
92
90
|
expect(subject).to eq 'something else'
|
|
93
91
|
end
|
|
94
92
|
end
|
|
95
|
-
|
|
96
93
|
end
|
|
@@ -1,147 +1,121 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
2
|
+
class MyController # < ApplicationController
|
|
3
|
+
include Blacklight::AccessControls::Enforcement
|
|
4
|
+
end
|
|
3
5
|
|
|
4
6
|
describe Blacklight::AccessControls::Enforcement do
|
|
5
|
-
let(:controller)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
let(:controller) do
|
|
8
|
+
c = MyController.new
|
|
9
|
+
allow(c).to receive(:current_ability).and_return(ability)
|
|
10
|
+
c
|
|
11
|
+
end
|
|
10
12
|
let(:user) { User.new }
|
|
11
13
|
let(:ability) { Ability.new(user) }
|
|
14
|
+
subject { controller }
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
describe '#discovery_permissions' do
|
|
17
|
+
it 'has defaults' do
|
|
18
|
+
expect(subject.discovery_permissions).to eq %w(discover read)
|
|
19
|
+
end
|
|
14
20
|
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
it 'does getter/setter' do
|
|
22
|
+
subject.discovery_permissions = %w(discover read frobnicate)
|
|
23
|
+
expect(subject.discovery_permissions).to eq %w(discover read frobnicate)
|
|
24
|
+
subject.discovery_permissions << 'zazzo'
|
|
25
|
+
expect(subject.discovery_permissions).to eq %w(discover read frobnicate zazzo)
|
|
26
|
+
end
|
|
17
27
|
end
|
|
18
28
|
|
|
19
|
-
describe
|
|
20
|
-
|
|
21
|
-
|
|
29
|
+
describe '#apply_gated_discovery' do
|
|
30
|
+
let(:fq_first) do
|
|
31
|
+
solr_parameters = {}
|
|
32
|
+
subject.send(:apply_gated_discovery, solr_parameters)
|
|
33
|
+
solr_parameters[:fq].first
|
|
22
34
|
end
|
|
23
35
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
36
|
+
# rubocop:disable RSpec/MessageExpectation
|
|
37
|
+
describe 'logger' do
|
|
38
|
+
# Expectation will be triggered by Ability class (that calls Rails.logger.debug earlier). So we double Ability to avoid false positive.
|
|
39
|
+
let(:ability) { instance_double(Ability, user_groups: [], current_user: user) }
|
|
40
|
+
it 'is called with debug' do
|
|
41
|
+
expect(Rails.logger).to receive(:debug).with(/^Solr parameters/)
|
|
42
|
+
controller.send(:apply_gated_discovery, {})
|
|
27
43
|
end
|
|
44
|
+
end
|
|
28
45
|
|
|
46
|
+
context 'Given I am not logged in' do
|
|
29
47
|
it "Then I should be treated as a member of the 'public' group" do
|
|
30
|
-
expect(
|
|
48
|
+
expect(fq_first).to eq '({!terms f=discover_access_group_ssim}public) OR ({!terms f=read_access_group_ssim}public)'
|
|
31
49
|
end
|
|
32
50
|
|
|
33
51
|
it "Then I should not be treated as a member of the 'registered' group" do
|
|
34
|
-
expect(
|
|
52
|
+
expect(fq_first).to_not match(/registered/)
|
|
35
53
|
end
|
|
36
54
|
end
|
|
37
55
|
|
|
38
|
-
context
|
|
56
|
+
context 'Given I am a registered user' do
|
|
57
|
+
let(:groups) { %w(faculty africana-faculty) }
|
|
39
58
|
let(:user) do
|
|
40
59
|
create(:user).tap do |u|
|
|
41
|
-
allow(u).to receive(:groups) {
|
|
60
|
+
allow(u).to receive(:groups) { groups }
|
|
42
61
|
end
|
|
43
62
|
end
|
|
44
63
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
it "searches for my groups" do
|
|
50
|
-
expect(@solr_parameters[:fq].first).to match(%r{\{!terms f=discover_access_group_ssim\}public,faculty,africana-faculty,registered})
|
|
51
|
-
expect(@solr_parameters[:fq].first).to match(%r{\{!terms f=read_access_group_ssim\}public,faculty,africana-faculty,registered})
|
|
64
|
+
it 'searches for my user key in discover and read fields' do
|
|
65
|
+
expect(fq_first).to match(/discover_access_person_ssim\:#{user.user_key}/)
|
|
66
|
+
expect(fq_first).to match(/read_access_person_ssim\:#{user.user_key}/)
|
|
52
67
|
end
|
|
53
68
|
|
|
54
|
-
it
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
describe "#except" do
|
|
63
|
-
let(:user) { build(:user) }
|
|
64
|
-
let(:ability) { Ability.new(user) }
|
|
65
|
-
subject { search_builder.except('foo') }
|
|
66
|
-
|
|
67
|
-
it "keeps the current_ability set" do
|
|
68
|
-
expect(subject.current_ability).to eq ability
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
describe "#append" do
|
|
73
|
-
let(:user) { build(:user) }
|
|
74
|
-
let(:ability) { Ability.new(user) }
|
|
75
|
-
subject { search_builder.append('foo') }
|
|
76
|
-
|
|
77
|
-
it "keeps the current_ability set" do
|
|
78
|
-
expect(subject.current_ability).to eq ability
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
describe "apply_gated_discovery" do
|
|
83
|
-
let(:user) do
|
|
84
|
-
create(:user).tap do |u|
|
|
85
|
-
allow(u).to receive(:groups) { groups }
|
|
69
|
+
it 'searches for my groups' do
|
|
70
|
+
expect(fq_first).to match(%r{\{!terms f=discover_access_group_ssim\}public,faculty,africana-faculty,registered})
|
|
71
|
+
expect(fq_first).to match(%r{\{!terms f=read_access_group_ssim\}public,faculty,africana-faculty,registered})
|
|
86
72
|
end
|
|
87
|
-
end
|
|
88
|
-
let(:groups) { ["archivist","researcher"] }
|
|
89
|
-
|
|
90
|
-
before do
|
|
91
|
-
@solr_parameters = {}
|
|
92
|
-
subject.send(:apply_gated_discovery, @solr_parameters)
|
|
93
|
-
end
|
|
94
73
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
expect(
|
|
74
|
+
it 'does not build empty clauses' do
|
|
75
|
+
expect(controller).to receive(:apply_user_permissions).and_return(['({!terms f=discover_access_group_ssim}public,faculty,africana-faculty,registered)', '', nil])
|
|
76
|
+
expect(fq_first).not_to match(/ OR $/) # i.e. doesn't end w/ empty
|
|
98
77
|
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
it "queries roles the user is a member of checking against the discover, read fields" do
|
|
102
|
-
expect(@solr_parameters[:fq].first).to match(%r{\{!terms f=discover_access_group_ssim\}public,archivist,researcher,registered})
|
|
103
|
-
expect(@solr_parameters[:fq].first).to match(%r{\{!terms f=read_access_group_ssim\}public,archivist,researcher,registered})
|
|
104
|
-
end
|
|
105
78
|
|
|
106
|
-
|
|
107
|
-
|
|
79
|
+
context 'slashes in the group names' do
|
|
80
|
+
let(:groups) { ['abc/123', 'cde/567'] }
|
|
108
81
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
82
|
+
it 'does not escape slashes' do
|
|
83
|
+
expect(fq_first).to match(%r{\{!terms f=discover_access_group_ssim\}public,abc/123,cde/567,registered})
|
|
84
|
+
expect(fq_first).to match(%r{\{!terms f=read_access_group_ssim\}public,abc/123,cde/567,registered})
|
|
85
|
+
end
|
|
112
86
|
end
|
|
113
|
-
end
|
|
114
87
|
|
|
115
|
-
|
|
116
|
-
|
|
88
|
+
context 'spaces in the group names' do
|
|
89
|
+
let(:groups) { ['abc 123', 'cd/e 567'] }
|
|
117
90
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
91
|
+
it 'does not escape spaces in group names' do
|
|
92
|
+
expect(fq_first).to match(%r{\{!terms f=discover_access_group_ssim\}public,abc 123,cd/e 567,registered})
|
|
93
|
+
expect(fq_first).to match(%r{\{!terms f=read_access_group_ssim\}public,abc 123,cd/e 567,registered})
|
|
94
|
+
end
|
|
121
95
|
end
|
|
122
|
-
end
|
|
123
96
|
|
|
124
|
-
|
|
125
|
-
|
|
97
|
+
context 'colons in the groups names' do
|
|
98
|
+
let(:groups) { ['abc:123', 'cde:567'] }
|
|
126
99
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
100
|
+
it 'does not escape colons' do
|
|
101
|
+
expect(fq_first).to match(%r{\{!terms f=discover_access_group_ssim\}public,abc:123,cde:567,registered})
|
|
102
|
+
expect(fq_first).to match(%r{\{!terms f=read_access_group_ssim\}public,abc:123,cde:567,registered})
|
|
103
|
+
end
|
|
130
104
|
end
|
|
131
105
|
end
|
|
132
106
|
end
|
|
133
107
|
|
|
134
|
-
describe
|
|
135
|
-
describe
|
|
136
|
-
it
|
|
137
|
-
expect(subject.send(:apply_user_permissions,
|
|
108
|
+
describe '#apply_user_permissions' do
|
|
109
|
+
describe 'when the user is a guest user (user key nil)' do
|
|
110
|
+
it 'does not create filters' do
|
|
111
|
+
expect(subject.send(:apply_user_permissions, %w(discover read))).to eq []
|
|
138
112
|
end
|
|
139
113
|
end
|
|
140
114
|
|
|
141
|
-
describe
|
|
115
|
+
describe 'when the user is a guest user (user key empty string)' do
|
|
142
116
|
let(:user) { User.new(email: '') }
|
|
143
|
-
it
|
|
144
|
-
expect(subject.send(:apply_user_permissions,
|
|
117
|
+
it 'does not create filters' do
|
|
118
|
+
expect(subject.send(:apply_user_permissions, %w(discover read))).to eq []
|
|
145
119
|
end
|
|
146
120
|
end
|
|
147
121
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: blacklight-access_controls
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chris Beer
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date: 2016-
|
|
14
|
+
date: 2016-09-01 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: cancancan
|
|
@@ -139,6 +139,34 @@ dependencies:
|
|
|
139
139
|
- - ">="
|
|
140
140
|
- !ruby/object:Gem::Version
|
|
141
141
|
version: '0'
|
|
142
|
+
- !ruby/object:Gem::Dependency
|
|
143
|
+
name: rubocop
|
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
|
145
|
+
requirements:
|
|
146
|
+
- - ">="
|
|
147
|
+
- !ruby/object:Gem::Version
|
|
148
|
+
version: '0'
|
|
149
|
+
type: :development
|
|
150
|
+
prerelease: false
|
|
151
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
152
|
+
requirements:
|
|
153
|
+
- - ">="
|
|
154
|
+
- !ruby/object:Gem::Version
|
|
155
|
+
version: '0'
|
|
156
|
+
- !ruby/object:Gem::Dependency
|
|
157
|
+
name: rubocop-rspec
|
|
158
|
+
requirement: !ruby/object:Gem::Requirement
|
|
159
|
+
requirements:
|
|
160
|
+
- - ">="
|
|
161
|
+
- !ruby/object:Gem::Version
|
|
162
|
+
version: '0'
|
|
163
|
+
type: :development
|
|
164
|
+
prerelease: false
|
|
165
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
166
|
+
requirements:
|
|
167
|
+
- - ">="
|
|
168
|
+
- !ruby/object:Gem::Version
|
|
169
|
+
version: '0'
|
|
142
170
|
description: Access controls for blacklight-based applications
|
|
143
171
|
email:
|
|
144
172
|
- blacklight-development@googlegroups.com
|
|
@@ -147,6 +175,9 @@ extensions: []
|
|
|
147
175
|
extra_rdoc_files: []
|
|
148
176
|
files:
|
|
149
177
|
- ".gitignore"
|
|
178
|
+
- ".rspec"
|
|
179
|
+
- ".rubocop.yml"
|
|
180
|
+
- ".rubocop_todo.yml"
|
|
150
181
|
- ".travis.yml"
|
|
151
182
|
- Gemfile
|
|
152
183
|
- README.textile
|