blacklight-access_controls 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|