geoblacklight 6.0.0.pre.beta.1 → 6.0.0.pre.beta.2
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/.github/workflows/ruby.yml +14 -3
- data/app/components/geoblacklight/iiif_drag_drop_component.html.erb +1 -1
- data/app/components/geoblacklight/login_link_component.html.erb +1 -1
- data/app/components/geoblacklight/login_link_component.rb +17 -1
- data/app/controllers/relations_controller.rb +2 -0
- data/app/controllers/viewer_record_controller.rb +2 -0
- data/app/helpers/geoblacklight_helper.rb +5 -1
- data/app/javascript/geoblacklight/core.js +0 -2
- data/config/importmap.rb +4 -4
- data/lib/generators/geoblacklight/install_generator.rb +3 -6
- data/lib/generators/geoblacklight/templates/settings.yml +1 -25
- data/lib/geoblacklight/configuration/settings_builder.rb +0 -2
- data/lib/geoblacklight/configuration.rb +1 -19
- data/lib/geoblacklight/version.rb +1 -1
- data/lib/geoblacklight.rb +0 -1
- data/spec/components/geoblacklight/document/sidebar_component_spec.rb +1 -1
- data/spec/components/geoblacklight/document_component_spec.rb +1 -1
- data/spec/components/geoblacklight/item_map_viewer_component_spec.rb +31 -0
- data/spec/components/geoblacklight/login_link_component_spec.rb +20 -12
- data/spec/factories/user.rb +6 -1
- data/spec/features/axe_spec.rb +1 -0
- data/spec/features/restricted_viewer_spec.rb +1 -3
- data/spec/features/sign_in_spec.rb +26 -0
- data/spec/requests/bookmarks_spec.rb +1 -0
- data/spec/requests/viewer_record_spec.rb +1 -3
- data/spec/requests/viewer_requests_spec.rb +3 -5
- data/spec/spec_helper.rb +6 -1
- data/spec/support/authentication.rb +37 -0
- data/spec/support/features/session_helpers.rb +15 -13
- data/spec/test_app_templates/lib/generators/test_app_generator.rb +1 -1
- data/template.rb +1 -1
- metadata +5 -11
- data/app/controllers/wms_controller.rb +0 -17
- data/app/javascript/geoblacklight/initializers/tooltips.js +0 -51
- data/lib/geoblacklight/routes/wms.rb +0 -15
- data/lib/geoblacklight/wms_layer/feature_info_response.rb +0 -37
- data/lib/geoblacklight/wms_layer.rb +0 -34
- data/spec/controllers/wms_controller_spec.rb +0 -34
- data/spec/lib/geoblacklight/wms_layer/feature_info_response_spec.rb +0 -54
- data/spec/lib/geoblacklight/wms_layer_spec.rb +0 -115
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 321f6ba33268ae5d69c4ab0030a91515ac2e5f84805fb4b6d11044692d1a9f15
|
|
4
|
+
data.tar.gz: 4c95b22d126e274ba26fd6402dbe1174c2a4f865e94ef85c6d35451b72683c27
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4b1303681dee3d6ed7c82f00f30d16ee0e12e4f0b8430fd26f0be02416f060ed538976ada2f6b86595ceeec2ce99853f2e812df65347c5e5cfd5994bc43fb459
|
|
7
|
+
data.tar.gz: b1e70fddc4c7f4d5b423b6e5dee103171386b38668ad0aca54bf1718eeec88e17a2e37ae2319854ffc26d41ca069b0693d0f05459560f6e1a4010c0fc4f5b440
|
data/.github/workflows/ruby.yml
CHANGED
|
@@ -51,9 +51,19 @@ jobs:
|
|
|
51
51
|
strategy:
|
|
52
52
|
matrix:
|
|
53
53
|
ruby_version: ["3.3", "3.4", "4.0"]
|
|
54
|
-
rails_version: ["8.1.
|
|
54
|
+
rails_version: ["8.1.4"]
|
|
55
|
+
auth: ["devise"]
|
|
56
|
+
include:
|
|
57
|
+
- ruby_version: "4.0"
|
|
58
|
+
rails_version: "8.1.4"
|
|
59
|
+
auth: "rails"
|
|
60
|
+
blacklight_install_options: "--authentication --skip-solr"
|
|
61
|
+
- ruby_version: "4.0"
|
|
62
|
+
rails_version: "8.1.4"
|
|
63
|
+
auth: "no"
|
|
64
|
+
blacklight_install_options: "--skip-solr"
|
|
55
65
|
|
|
56
|
-
name: test ruby ${{ matrix.ruby_version }} / rails ${{ matrix.rails_version }}
|
|
66
|
+
name: test ruby ${{ matrix.ruby_version }} / rails ${{ matrix.rails_version }} / ${{ matrix.auth }} auth
|
|
57
67
|
steps:
|
|
58
68
|
- uses: actions/checkout@v7
|
|
59
69
|
- name: Set up Ruby
|
|
@@ -71,9 +81,10 @@ jobs:
|
|
|
71
81
|
BUNDLE_FORCE_RUBY_PLATFORM: true
|
|
72
82
|
RAILS_VERSION: ${{ matrix.rails_version }}
|
|
73
83
|
SOLR_URL: http://solr:SolrRocks@localhost:8983/solr/blacklight-core
|
|
84
|
+
BLACKLIGHT_INSTALL_OPTIONS: ${{ matrix.blacklight_install_options }}
|
|
74
85
|
- name: Upload coverage artifacts
|
|
75
86
|
if: always()
|
|
76
87
|
uses: actions/upload-artifact@v7
|
|
77
88
|
with:
|
|
78
|
-
name: "coverage-${{ matrix.ruby_version }}-${{ matrix.rails_version }}"
|
|
89
|
+
name: "coverage-${{ matrix.ruby_version }}-${{ matrix.rails_version }}-${{ matrix.auth }}-auth"
|
|
79
90
|
path: coverage/
|
|
@@ -10,8 +10,24 @@ module Geoblacklight
|
|
|
10
10
|
super()
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
def before_render
|
|
14
|
+
store_return_location if render?
|
|
15
|
+
end
|
|
16
|
+
|
|
13
17
|
def render?
|
|
14
|
-
document.restricted? &&
|
|
18
|
+
document.restricted? &&
|
|
19
|
+
document.same_institution? &&
|
|
20
|
+
helpers.blacklight_login_path.present? &&
|
|
21
|
+
!helpers.current_user_signed_in?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
# Bring the user back to this record once they've signed in, for either
|
|
27
|
+
# Devise or Rails auth.
|
|
28
|
+
def store_return_location
|
|
29
|
+
controller.store_location_for(:user, request.original_url) if controller.respond_to?(:store_location_for)
|
|
30
|
+
controller.send(:store_location_for_rails_authentication)
|
|
15
31
|
end
|
|
16
32
|
end
|
|
17
33
|
end
|
|
@@ -5,6 +5,8 @@ class RelationsController < ApplicationController
|
|
|
5
5
|
|
|
6
6
|
copy_blacklight_config_from(CatalogController)
|
|
7
7
|
|
|
8
|
+
allow_unauthenticated_access raise: false if respond_to?(:allow_unauthenticated_access)
|
|
9
|
+
|
|
8
10
|
def index
|
|
9
11
|
@relations = Geoblacklight::Relations::RelationResponse.new(params[:id], repository)
|
|
10
12
|
render layout: !(request.xhr? || request.headers["Turbo-Frame"].present?)
|
|
@@ -6,6 +6,8 @@ class ViewerRecordController < ApplicationController
|
|
|
6
6
|
|
|
7
7
|
copy_blacklight_config_from(CatalogController)
|
|
8
8
|
|
|
9
|
+
allow_unauthenticated_access raise: false if respond_to?(:allow_unauthenticated_access)
|
|
10
|
+
|
|
9
11
|
rescue_from Blacklight::Exceptions::RecordNotFound do
|
|
10
12
|
head :not_found
|
|
11
13
|
end
|
|
@@ -24,7 +24,11 @@ module GeoblacklightHelper
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def document_available?(document)
|
|
27
|
-
document.public? || (document.same_institution? &&
|
|
27
|
+
document.public? || (document.same_institution? && current_user_signed_in?)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def current_user_signed_in?
|
|
31
|
+
controller.respond_to?(:current_user) && current_user.present?
|
|
28
32
|
end
|
|
29
33
|
|
|
30
34
|
# If you turn off dark mode support, Geoblacklight will display in light mode,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// Initializers
|
|
2
|
-
import initializeTooltips from "geoblacklight/initializers/tooltips"
|
|
3
2
|
import initializeTruncation from "geoblacklight/initializers/truncation"
|
|
4
3
|
import initializeFieldTruncation from "geoblacklight/initializers/field_truncation"
|
|
5
4
|
import initializeMetadataDownload from "geoblacklight/initializers/metadata_download"
|
|
@@ -41,7 +40,6 @@ Geoblacklight.listeners().forEach((listener) =>
|
|
|
41
40
|
)
|
|
42
41
|
|
|
43
42
|
// Register our initializers
|
|
44
|
-
Geoblacklight.onLoad(initializeTooltips)
|
|
45
43
|
Geoblacklight.onLoad(initializeTruncation)
|
|
46
44
|
Geoblacklight.onLoad(initializeFieldTruncation)
|
|
47
45
|
Geoblacklight.onLoad(initializeMetadataDownload)
|
data/config/importmap.rb
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
# OGM viewer components: the previewer, the map of where a set of records is, and the map of where
|
|
4
4
|
# one of them is
|
|
5
|
-
pin "ogm-viewer", to: "https://unpkg.com/ogm-viewer@1.
|
|
6
|
-
pin "ogm-overview", to: "https://unpkg.com/ogm-viewer@1.
|
|
7
|
-
pin "ogm-locator", to: "https://unpkg.com/ogm-viewer@1.
|
|
5
|
+
pin "ogm-viewer", to: "https://unpkg.com/ogm-viewer@1.4.0/dist/components/ogm-viewer.js"
|
|
6
|
+
pin "ogm-overview", to: "https://unpkg.com/ogm-viewer@1.4.0/dist/components/ogm-overview.js"
|
|
7
|
+
pin "ogm-locator", to: "https://unpkg.com/ogm-viewer@1.4.0/dist/components/ogm-locator.js"
|
|
8
8
|
|
|
9
9
|
# OGM viewer library, used for constructing the location previewers handed to the results map.
|
|
10
10
|
# Not preloaded because only the pages with that map want it; loaded dynamically there.
|
|
11
|
-
pin "ogm-viewer/lib", to: "https://unpkg.com/ogm-viewer@1.
|
|
11
|
+
pin "ogm-viewer/lib", to: "https://unpkg.com/ogm-viewer@1.4.0/dist/components/index.js", preload: false
|
|
12
12
|
|
|
13
13
|
# Geoblacklight
|
|
14
14
|
pin_all_from Geoblacklight::Engine.root.join("app", "javascript", "geoblacklight"), under: "geoblacklight"
|
|
@@ -22,7 +22,8 @@ module Geoblacklight
|
|
|
22
22
|
|
|
23
23
|
def raise_unpermitted_params
|
|
24
24
|
inject_into_file "config/environments/test.rb",
|
|
25
|
-
"config.action_controller.action_on_unpermitted_parameters = :raise\n"
|
|
25
|
+
"config.action_controller.action_on_unpermitted_parameters = :raise\n" \
|
|
26
|
+
"config.action_controller.always_permitted_parameters = %w[controller action commit]\n", before: /^end/
|
|
26
27
|
end
|
|
27
28
|
|
|
28
29
|
def mount_geoblacklight_engine
|
|
@@ -35,10 +36,6 @@ module Geoblacklight
|
|
|
35
36
|
resources :solr_documents, only: [:show], path: '/catalog', controller: 'catalog' do
|
|
36
37
|
concerns :gbl_exportable
|
|
37
38
|
end
|
|
38
|
-
concern :gbl_wms, Geoblacklight::Routes::Wms.new
|
|
39
|
-
namespace :wms do
|
|
40
|
-
concerns :gbl_wms
|
|
41
|
-
end
|
|
42
39
|
ROUTES
|
|
43
40
|
|
|
44
41
|
inject_into_file "config/routes.rb", routes, before: /^end/
|
|
@@ -58,7 +55,7 @@ module Geoblacklight
|
|
|
58
55
|
end
|
|
59
56
|
|
|
60
57
|
def add_rsolr_gem
|
|
61
|
-
gem "rsolr", ">= 1.0", "<
|
|
58
|
+
gem "rsolr", ">= 1.0", "< 4"
|
|
62
59
|
end
|
|
63
60
|
|
|
64
61
|
def docker_compose
|
|
@@ -33,9 +33,7 @@
|
|
|
33
33
|
# homepage_map_geom: null
|
|
34
34
|
# # homepage_map_geom: '{"type":"Polygon","coordinates":[[[-73.58,42.93],[-73.58,41.20],[-69.90,41.20],[-69.90,42.93]]]}'
|
|
35
35
|
|
|
36
|
-
# # Non-search-field GeoBlacklight application permitted params
|
|
37
|
-
# # Values are left mixed-case on purpose: the uppercase symbols are WMS/OGC
|
|
38
|
-
# # request parameter names (BBOX, WIDTH, etc.) and must match what clients send.
|
|
36
|
+
# # Non-search-field GeoBlacklight application permitted params
|
|
39
37
|
# gbl_params:
|
|
40
38
|
# - :bbox
|
|
41
39
|
# - :email
|
|
@@ -45,14 +43,6 @@
|
|
|
45
43
|
# - :logo
|
|
46
44
|
# - :provider
|
|
47
45
|
# - :type
|
|
48
|
-
# - :BBOX
|
|
49
|
-
# - :HEIGHT
|
|
50
|
-
# - :LAYERS
|
|
51
|
-
# - :QUERY_LAYERS
|
|
52
|
-
# - :URL
|
|
53
|
-
# - :WIDTH
|
|
54
|
-
# - :X
|
|
55
|
-
# - :Y
|
|
56
46
|
|
|
57
47
|
# # Solr field mappings
|
|
58
48
|
# fields:
|
|
@@ -109,9 +99,6 @@
|
|
|
109
99
|
# - "iso19139"
|
|
110
100
|
# - "html"
|
|
111
101
|
|
|
112
|
-
# # (For WMS inspection) timeout and open_timeout parameters for Faraday
|
|
113
|
-
# timeout_wms: 4
|
|
114
|
-
|
|
115
102
|
# # Web services shown in tool panel
|
|
116
103
|
# webservices_shown:
|
|
117
104
|
# - "wms"
|
|
@@ -210,17 +197,6 @@
|
|
|
210
197
|
# label: geoblacklight.relations.version_of_descendants
|
|
211
198
|
# query_type: descendants
|
|
212
199
|
|
|
213
|
-
# # WMS Parameters. Keys are OGC WMS request parameter names and are sent to
|
|
214
|
-
# # remote WMS servers, so they are intentionally left uppercase.
|
|
215
|
-
# wms_params:
|
|
216
|
-
# SERVICE: "WMS"
|
|
217
|
-
# VERSION: "1.1.1"
|
|
218
|
-
# REQUEST: "GetFeatureInfo"
|
|
219
|
-
# STYLES: ""
|
|
220
|
-
# SRS: "EPSG:4326"
|
|
221
|
-
# EXCEPTIONS: "application/json"
|
|
222
|
-
# INFO_FORMAT: "application/json"
|
|
223
|
-
|
|
224
200
|
# iiif_drag_drop_link: "@manifest?manifest=@manifest"
|
|
225
201
|
|
|
226
202
|
# # Toggle thumbnail images in the search results (index) view
|
|
@@ -26,8 +26,6 @@ module Geoblacklight
|
|
|
26
26
|
assign(config, :webservices_shown, settings.WEBSERVICES_SHOWN)
|
|
27
27
|
assign(config, :relationships_shown, build_relationships)
|
|
28
28
|
assign(config, :gbl_params, settings.GBL_PARAMS)
|
|
29
|
-
assign(config, :wms_params, settings.WMS_PARAMS&.to_h)
|
|
30
|
-
assign(config, :timeout_wms, settings.TIMEOUT_WMS)
|
|
31
29
|
assign(config, :restricted_origins, settings.restricted_origins)
|
|
32
30
|
|
|
33
31
|
build_fields(config)
|
|
@@ -15,9 +15,6 @@ module Geoblacklight
|
|
|
15
15
|
# Institution deployed at
|
|
16
16
|
attribute :institution, :string, default: "Stanford"
|
|
17
17
|
|
|
18
|
-
# (For WMS inspection) timeout and open_timeout parameters for Faraday
|
|
19
|
-
attribute :timeout_wms, :integer, default: 4
|
|
20
|
-
|
|
21
18
|
# Services the item viewer should send cookies to when previewing restricted data a reader is
|
|
22
19
|
# allowed at, as URL prefixes - usually just the service's origin, e.g.
|
|
23
20
|
# config.restricted_origins = ["https://geoserver-restricted.example.edu/"]
|
|
@@ -34,9 +31,6 @@ module Geoblacklight
|
|
|
34
31
|
# Non-search-field GeoBlacklight application permitted params
|
|
35
32
|
attr_accessor :gbl_params # typed as Array
|
|
36
33
|
|
|
37
|
-
# WMS Parameters
|
|
38
|
-
attr_accessor :wms_params # typed as Hash
|
|
39
|
-
|
|
40
34
|
attribute :iiif_drag_drop_link, :string, default: "@manifest?manifest=@manifest"
|
|
41
35
|
|
|
42
36
|
# Toggle thumbnail images in the search results (index) view
|
|
@@ -71,19 +65,7 @@ module Geoblacklight
|
|
|
71
65
|
def initialize
|
|
72
66
|
super
|
|
73
67
|
@relationships_shown = RelationshipsConfig.new
|
|
74
|
-
@gbl_params = [
|
|
75
|
-
:bbox, :email, :file, :format, :id, :logo, :provider, :type,
|
|
76
|
-
:BBOX, :HEIGHT, :LAYERS, :QUERY_LAYERS, :URL, :WIDTH, :X, :Y
|
|
77
|
-
]
|
|
78
|
-
@wms_params = {
|
|
79
|
-
SERVICE: "WMS",
|
|
80
|
-
VERSION: "1.1.1",
|
|
81
|
-
REQUEST: "GetFeatureInfo",
|
|
82
|
-
STYLES: "",
|
|
83
|
-
SRS: "EPSG:4326",
|
|
84
|
-
EXCEPTIONS: "application/json",
|
|
85
|
-
INFO_FORMAT: "application/json"
|
|
86
|
-
}
|
|
68
|
+
@gbl_params = [:bbox, :email, :file, :format, :id, :logo, :provider, :type]
|
|
87
69
|
|
|
88
70
|
@restricted_origins = []
|
|
89
71
|
|
data/lib/geoblacklight.rb
CHANGED
|
@@ -17,7 +17,7 @@ RSpec.describe Geoblacklight::Document::SidebarComponent, type: :component do
|
|
|
17
17
|
allow_any_instance_of(Blacklight::DocumentHelperBehavior).to receive(:current_bookmarks).and_return([])
|
|
18
18
|
|
|
19
19
|
with_controller_class(CatalogController) do
|
|
20
|
-
allow(vc_test_controller).to receive_messages(current_or_guest_user:
|
|
20
|
+
allow(vc_test_controller).to receive_messages(current_or_guest_user: nil)
|
|
21
21
|
render_inline(component)
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -20,7 +20,7 @@ RSpec.describe Geoblacklight::DocumentComponent, type: :component do
|
|
|
20
20
|
|
|
21
21
|
before do
|
|
22
22
|
vc_test_controller.action_name = "show"
|
|
23
|
-
allow(vc_test_controller).to receive_messages(view_context: view_context, current_or_guest_user:
|
|
23
|
+
allow(vc_test_controller).to receive_messages(view_context: view_context, current_or_guest_user: nil, blacklight_config: blacklight_config)
|
|
24
24
|
allow(view_context).to receive_messages(search_session: {}, current_search_session: nil, current_bookmarks: [])
|
|
25
25
|
render_inline(component)
|
|
26
26
|
end
|
|
@@ -45,6 +45,37 @@ RSpec.describe Geoblacklight::ItemMapViewerComponent, type: :component do
|
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
describe "restricted origins in reference URLs" do
|
|
49
|
+
# Restricted, and provided by this app's own institution
|
|
50
|
+
let(:document) { SolrDocument.new(JSON.parse(read_fixture("solr_documents/actual-raster1.json"))) }
|
|
51
|
+
|
|
52
|
+
before do
|
|
53
|
+
allow(Geoblacklight.configuration).to receive(:restricted_origins).and_return(["https://stacks.stanford.edu/"])
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "when signed in" do
|
|
57
|
+
before do
|
|
58
|
+
allow(vc_test_controller).to receive(:current_user).and_return(instance_double(ActiveRecord::Base))
|
|
59
|
+
render_inline(described_class.new(document: document))
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "sends them to the viewer as a separate data param" do
|
|
63
|
+
expect(page).to have_css('ogm-viewer[data-restricted-origins=\'["https://stacks.stanford.edu/"]\']')
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "when not signed in" do
|
|
68
|
+
before do
|
|
69
|
+
allow(vc_test_controller).to receive(:current_user).and_return(nil)
|
|
70
|
+
render_inline(described_class.new(document: document))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "does not send them to the viewer" do
|
|
74
|
+
expect(page).to have_css("ogm-viewer:not([data-restricted-origins])")
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
48
79
|
context "with an oembed record" do
|
|
49
80
|
let(:document) { SolrDocument.new(JSON.parse(read_fixture("solr_documents/oembed.json"))) }
|
|
50
81
|
|
|
@@ -3,26 +3,34 @@
|
|
|
3
3
|
require "spec_helper"
|
|
4
4
|
|
|
5
5
|
RSpec.describe Geoblacklight::LoginLinkComponent, type: :component do
|
|
6
|
-
let(:document) { instance_double(SolrDocument, id: 123) }
|
|
6
|
+
let(:document) { instance_double(SolrDocument, id: 123, restricted?: true, same_institution?: true) }
|
|
7
|
+
let(:login_path) { "/login" }
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
allow(document).to receive(:same_institution?).and_return(true)
|
|
13
|
-
end
|
|
9
|
+
before do
|
|
10
|
+
allow(vc_test_controller).to receive(:blacklight_login_path).and_return(login_path)
|
|
11
|
+
allow(vc_test_controller).to receive(:current_user).and_return(nil)
|
|
12
|
+
end
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
context "when the document is restricted to this institution and no one is signed in" do
|
|
15
|
+
it "links to the sign-in page" do
|
|
16
16
|
render_inline(described_class.new(document: document))
|
|
17
|
-
expect(page).to
|
|
17
|
+
expect(page).to have_link(I18n.t("geoblacklight.tools.login_to_view"), href: login_path)
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
context "when
|
|
21
|
+
context "when signed in" do
|
|
22
22
|
before do
|
|
23
|
-
allow(
|
|
24
|
-
|
|
23
|
+
allow(vc_test_controller).to receive(:current_user).and_return(instance_double(ActiveRecord::Base))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "does not render anything" do
|
|
27
|
+
render_inline(described_class.new(document: document))
|
|
28
|
+
expect(page).not_to have_text(I18n.t("geoblacklight.tools.login_to_view"))
|
|
25
29
|
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context "when the app has no authentication" do
|
|
33
|
+
let(:login_path) { nil }
|
|
26
34
|
|
|
27
35
|
it "does not render anything" do
|
|
28
36
|
render_inline(described_class.new(document: document))
|
data/spec/factories/user.rb
CHANGED
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
FactoryBot.define do
|
|
4
4
|
factory :user do
|
|
5
|
-
|
|
5
|
+
# Rails' built-in authentication calls the column email_address, where Devise calls it email
|
|
6
|
+
if AuthenticationHelpers.provider == :rails
|
|
7
|
+
sequence(:email_address) { |n| "user#{n}@example.com" }
|
|
8
|
+
else
|
|
9
|
+
sequence(:email) { |n| "user#{n}@example.com" }
|
|
10
|
+
end
|
|
6
11
|
password { "password" }
|
|
7
12
|
password_confirmation { "password" }
|
|
8
13
|
end
|
data/spec/features/axe_spec.rb
CHANGED
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
require "spec_helper"
|
|
4
4
|
|
|
5
5
|
RSpec.feature "Restricted item viewer", js: true do
|
|
6
|
-
scenario "
|
|
6
|
+
scenario "shows where the layer is rather than failing to load it" do
|
|
7
7
|
visit solr_document_path("stanford-dp018hs9766")
|
|
8
8
|
|
|
9
|
-
expect(page).to have_link("Login to View and Download")
|
|
10
|
-
|
|
11
9
|
# The viewer was handed a record with no service references, so the only preview it can offer
|
|
12
10
|
# is the record's own extent
|
|
13
11
|
previews = find("ogm-viewer").shadow_root.find("ogm-previews", visible: :all)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
RSpec.feature "Signing in to see a restricted record" do
|
|
6
|
+
let(:restricted) { "stanford-dp018hs9766" }
|
|
7
|
+
|
|
8
|
+
scenario "brings the reader back to the record once they're signed in" do
|
|
9
|
+
skip_without_authentication
|
|
10
|
+
visit solr_document_path(restricted)
|
|
11
|
+
click_link "Login to View and Download"
|
|
12
|
+
fill_in_sign_in_form FactoryBot.create(:user)
|
|
13
|
+
|
|
14
|
+
expect(page).to have_current_path(solr_document_path(restricted))
|
|
15
|
+
expect(page).to have_link "Log Out"
|
|
16
|
+
expect(page).to have_no_link "Login to View and Download"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
scenario "is not offered when the app has no authentication" do
|
|
20
|
+
skip "the test app has authentication" if AuthenticationHelpers.provider
|
|
21
|
+
visit solr_document_path(restricted)
|
|
22
|
+
|
|
23
|
+
expect(page).to have_css "h1", text: "Elkhorn Slough"
|
|
24
|
+
expect(page).to have_no_link "Login to View and Download"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
require "spec_helper"
|
|
4
4
|
|
|
5
5
|
RSpec.describe "Viewer record", type: :request do
|
|
6
|
-
include Devise::Test::IntegrationHelpers
|
|
7
|
-
|
|
8
6
|
let(:references) { JSON.parse(response.parsed_body[Geoblacklight.configuration.fields.references]) }
|
|
9
7
|
|
|
10
8
|
# Restricted, and provided by this app's own institution, so signing in makes the difference
|
|
@@ -19,7 +17,7 @@ RSpec.describe "Viewer record", type: :request do
|
|
|
19
17
|
end
|
|
20
18
|
|
|
21
19
|
it "hands over the same record once that reader signs in" do
|
|
22
|
-
sign_in
|
|
20
|
+
sign_in
|
|
23
21
|
get viewer_solr_document_path(restricted)
|
|
24
22
|
|
|
25
23
|
expect(references.keys).to include("https://github.com/cogeotiff/cog-spec", "http://schema.org/downloadUrl")
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
require "spec_helper"
|
|
4
4
|
|
|
5
5
|
RSpec.describe "Viewer requests", type: :request do
|
|
6
|
-
include Devise::Test::IntegrationHelpers
|
|
7
|
-
|
|
8
6
|
let(:origins) { ["https://stacks.stanford.edu/"] }
|
|
9
7
|
|
|
10
8
|
# Restricted, and provided by this app's own institution, so signing in makes the difference
|
|
@@ -22,7 +20,7 @@ RSpec.describe "Viewer requests", type: :request do
|
|
|
22
20
|
end
|
|
23
21
|
|
|
24
22
|
it "names the services a signed-in reader's requests need to carry cookies to" do
|
|
25
|
-
sign_in
|
|
23
|
+
sign_in
|
|
26
24
|
get solr_document_path(restricted)
|
|
27
25
|
|
|
28
26
|
expect(JSON.parse(restricted_origins)).to eq origins
|
|
@@ -35,7 +33,7 @@ RSpec.describe "Viewer requests", type: :request do
|
|
|
35
33
|
end
|
|
36
34
|
|
|
37
35
|
it "names none for a public record, which has nothing that needs authorizing" do
|
|
38
|
-
sign_in
|
|
36
|
+
sign_in
|
|
39
37
|
get solr_document_path("berkeley-s7pq31")
|
|
40
38
|
|
|
41
39
|
expect(restricted_origins).to be_nil
|
|
@@ -45,7 +43,7 @@ RSpec.describe "Viewer requests", type: :request do
|
|
|
45
43
|
let(:origins) { [] }
|
|
46
44
|
|
|
47
45
|
it "names none" do
|
|
48
|
-
sign_in
|
|
46
|
+
sign_in
|
|
49
47
|
get solr_document_path(restricted)
|
|
50
48
|
|
|
51
49
|
expect(restricted_origins).to be_nil
|
data/spec/spec_helper.rb
CHANGED
|
@@ -44,6 +44,11 @@ Capybara.register_driver :chrome_headless do |app|
|
|
|
44
44
|
options.add_argument("--disable-gpu")
|
|
45
45
|
options.add_argument("--no-sandbox")
|
|
46
46
|
options.add_argument("--window-size=1280,1024")
|
|
47
|
+
# Scroll without animating. Bootstrap puts `scroll-behavior: smooth` on :root, so when
|
|
48
|
+
# ChromeDriver sets scrollTop to bring an element into view before clicking it, the page only
|
|
49
|
+
# starts to move and ChromeDriver reads back the element's old, off-screen position. The click
|
|
50
|
+
# then fails and is left to Capybara's retry, which a busy page can outlast.
|
|
51
|
+
options.add_argument("--disable-smooth-scrolling")
|
|
47
52
|
# Software WebGL, which the viewer and the overview map both need: they draw with MapLibre, and
|
|
48
53
|
# headless Chrome has no GPU to give them. SwiftShader is Chrome's own CPU renderer, and since
|
|
49
54
|
# Chrome 128 it has to be asked for by name before WebGL will fall back to it at all.
|
|
@@ -77,6 +82,6 @@ RSpec.configure do |config|
|
|
|
77
82
|
|
|
78
83
|
config.use_transactional_fixtures = true
|
|
79
84
|
|
|
80
|
-
config.include Devise::Test::ControllerHelpers, type: :controller
|
|
85
|
+
config.include Devise::Test::ControllerHelpers, type: :controller if defined?(Devise)
|
|
81
86
|
config.include ViewComponent::TestHelpers, type: :component
|
|
82
87
|
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# The app can be generated using Devise auth, Rails auth, or no auth. These
|
|
4
|
+
# are for signing in and/or skipping tests depending on which is the case.
|
|
5
|
+
module AuthenticationHelpers
|
|
6
|
+
# :devise, :rails, or nil if the app has no authentication
|
|
7
|
+
def self.provider
|
|
8
|
+
if defined?(Devise)
|
|
9
|
+
:devise
|
|
10
|
+
elsif ApplicationController.respond_to?(:allow_unauthenticated_access)
|
|
11
|
+
:rails
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def skip_without_authentication
|
|
16
|
+
skip "the test app has no authentication" unless AuthenticationHelpers.provider
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
module Requests
|
|
20
|
+
# Sign a new user in by posting the sign-in form
|
|
21
|
+
def sign_in
|
|
22
|
+
skip_without_authentication
|
|
23
|
+
user = FactoryBot.create(:user)
|
|
24
|
+
|
|
25
|
+
if AuthenticationHelpers.provider == :devise
|
|
26
|
+
post user_session_path, params: {user: {email: user.email, password: user.password}}
|
|
27
|
+
else
|
|
28
|
+
post session_path, params: {email_address: user.email_address, password: user.password}
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
RSpec.configure do |config|
|
|
35
|
+
config.include AuthenticationHelpers
|
|
36
|
+
config.include AuthenticationHelpers::Requests, type: :request
|
|
37
|
+
end
|
|
@@ -2,24 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
module Features
|
|
4
4
|
module SessionHelpers
|
|
5
|
-
def sign_up_with(email, password)
|
|
6
|
-
visit new_user_registration_path
|
|
7
|
-
fill_in "Email", with: email
|
|
8
|
-
fill_in "Password", with: password
|
|
9
|
-
click_button "Sign up"
|
|
10
|
-
end
|
|
11
|
-
|
|
12
5
|
def sign_in
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
fill_in "user_email", with: user.email
|
|
17
|
-
fill_in "user_password", with: user.password
|
|
18
|
-
click_button "Log in"
|
|
6
|
+
skip_without_authentication
|
|
7
|
+
visit (AuthenticationHelpers.provider == :devise) ? new_user_session_path : new_session_path
|
|
8
|
+
fill_in_sign_in_form FactoryBot.create(:user)
|
|
19
9
|
# Wait for the persistent "Log Out" nav link rather than the one-shot
|
|
20
10
|
# "Signed in successfully." flash, which can render and then become
|
|
21
11
|
# non-visible before Capybara's default wait time elapses.
|
|
22
12
|
expect(page).to have_link "Log Out"
|
|
23
13
|
end
|
|
14
|
+
|
|
15
|
+
def fill_in_sign_in_form(user)
|
|
16
|
+
if AuthenticationHelpers.provider == :devise
|
|
17
|
+
fill_in "user_email", with: user.email
|
|
18
|
+
fill_in "user_password", with: user.password
|
|
19
|
+
click_button "Log in"
|
|
20
|
+
else
|
|
21
|
+
fill_in "email_address", with: user.email_address
|
|
22
|
+
fill_in "password", with: user.password
|
|
23
|
+
click_button "Sign in"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
24
26
|
end
|
|
25
27
|
end
|
|
@@ -16,7 +16,7 @@ class TestAppGenerator < Rails::Generators::Base
|
|
|
16
16
|
# Install blacklight
|
|
17
17
|
def run_blacklight_generator
|
|
18
18
|
say_status("warning", "GENERATING BL", :yellow)
|
|
19
|
-
generate "blacklight:install", "
|
|
19
|
+
generate "blacklight:install", ENV["BLACKLIGHT_INSTALL_OPTIONS"].presence || "--devise --skip-solr"
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
# Install geoblacklight
|
data/template.rb
CHANGED
|
@@ -10,7 +10,7 @@ end
|
|
|
10
10
|
run "bundle install"
|
|
11
11
|
|
|
12
12
|
after_bundle do
|
|
13
|
-
generate "blacklight:install", ENV
|
|
13
|
+
generate "blacklight:install", ENV["BLACKLIGHT_INSTALL_OPTIONS"].presence || "--devise --skip-solr"
|
|
14
14
|
generate "geoblacklight:install"
|
|
15
15
|
rails_command "db:migrate"
|
|
16
16
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: geoblacklight
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.0.0.pre.beta.
|
|
4
|
+
version: 6.0.0.pre.beta.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mike Graves
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
- Jack Reed
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date:
|
|
13
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: rails
|
|
@@ -492,7 +492,6 @@ files:
|
|
|
492
492
|
- app/components/geoblacklight/web_services_wms_component.rb
|
|
493
493
|
- app/controllers/relations_controller.rb
|
|
494
494
|
- app/controllers/viewer_record_controller.rb
|
|
495
|
-
- app/controllers/wms_controller.rb
|
|
496
495
|
- app/helpers/geoblacklight_helper.rb
|
|
497
496
|
- app/javascript/geoblacklight/controllers/clipboard_controller.js
|
|
498
497
|
- app/javascript/geoblacklight/controllers/oembed_viewer_controller.js
|
|
@@ -501,7 +500,6 @@ files:
|
|
|
501
500
|
- app/javascript/geoblacklight/index.js
|
|
502
501
|
- app/javascript/geoblacklight/initializers/field_truncation.js
|
|
503
502
|
- app/javascript/geoblacklight/initializers/metadata_download.js
|
|
504
|
-
- app/javascript/geoblacklight/initializers/tooltips.js
|
|
505
503
|
- app/javascript/geoblacklight/initializers/truncation.js
|
|
506
504
|
- app/javascript/geoblacklight/initializers/viewer_requests.js
|
|
507
505
|
- app/javascript/geoblacklight/initializers/viewer_theme.js
|
|
@@ -570,11 +568,8 @@ files:
|
|
|
570
568
|
- lib/geoblacklight/relations/relation_response.rb
|
|
571
569
|
- lib/geoblacklight/routes.rb
|
|
572
570
|
- lib/geoblacklight/routes/exportable.rb
|
|
573
|
-
- lib/geoblacklight/routes/wms.rb
|
|
574
571
|
- lib/geoblacklight/version.rb
|
|
575
572
|
- lib/geoblacklight/viewer_record.rb
|
|
576
|
-
- lib/geoblacklight/wms_layer.rb
|
|
577
|
-
- lib/geoblacklight/wms_layer/feature_info_response.rb
|
|
578
573
|
- lib/tasks/geoblacklight.rake
|
|
579
574
|
- lib/tasks/solr.rb
|
|
580
575
|
- package.json
|
|
@@ -617,7 +612,6 @@ files:
|
|
|
617
612
|
- spec/components/geoblacklight/web_services_component_spec.rb
|
|
618
613
|
- spec/controllers/catalog_controller_spec.rb
|
|
619
614
|
- spec/controllers/relations_controller_spec.rb
|
|
620
|
-
- spec/controllers/wms_controller_spec.rb
|
|
621
615
|
- spec/factories/user.rb
|
|
622
616
|
- spec/features/axe_spec.rb
|
|
623
617
|
- spec/features/citations_spec.rb
|
|
@@ -630,6 +624,7 @@ files:
|
|
|
630
624
|
- spec/features/restricted_viewer_spec.rb
|
|
631
625
|
- spec/features/search_results_map_spec.rb
|
|
632
626
|
- spec/features/search_spec.rb
|
|
627
|
+
- spec/features/sign_in_spec.rb
|
|
633
628
|
- spec/features/sms_spec.rb
|
|
634
629
|
- spec/features/tilejson_spec.rb
|
|
635
630
|
- spec/features/tms_spec.rb
|
|
@@ -732,8 +727,6 @@ files:
|
|
|
732
727
|
- spec/lib/geoblacklight/relations/descendants_spec.rb
|
|
733
728
|
- spec/lib/geoblacklight/relations/relation_response_spec.rb
|
|
734
729
|
- spec/lib/geoblacklight/viewer_record_spec.rb
|
|
735
|
-
- spec/lib/geoblacklight/wms_layer/feature_info_response_spec.rb
|
|
736
|
-
- spec/lib/geoblacklight/wms_layer_spec.rb
|
|
737
730
|
- spec/models/concerns/geoblacklight/bbox_filter_field_spec.rb
|
|
738
731
|
- spec/models/concerns/geoblacklight/bbox_filter_query_spec.rb
|
|
739
732
|
- spec/models/concerns/geoblacklight/solr_document/citation_spec.rb
|
|
@@ -760,6 +753,7 @@ files:
|
|
|
760
753
|
- spec/solr_config_spec.rb
|
|
761
754
|
- spec/solr_fixtures_spec.rb
|
|
762
755
|
- spec/spec_helper.rb
|
|
756
|
+
- spec/support/authentication.rb
|
|
763
757
|
- spec/support/features.rb
|
|
764
758
|
- spec/support/features/map_helpers.rb
|
|
765
759
|
- spec/support/features/session_helpers.rb
|
|
@@ -785,7 +779,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
785
779
|
- !ruby/object:Gem::Version
|
|
786
780
|
version: 2.5.2
|
|
787
781
|
requirements: []
|
|
788
|
-
rubygems_version:
|
|
782
|
+
rubygems_version: 4.0.3
|
|
789
783
|
specification_version: 4
|
|
790
784
|
summary: A discovery platform for geospatial holdings
|
|
791
785
|
test_files: []
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
class WmsController < ApplicationController
|
|
4
|
-
def handle
|
|
5
|
-
response = Geoblacklight::WmsLayer.new(wms_params).feature_info
|
|
6
|
-
|
|
7
|
-
respond_to do |format|
|
|
8
|
-
format.json { render json: response }
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
private
|
|
13
|
-
|
|
14
|
-
def wms_params
|
|
15
|
-
params.permit(Geoblacklight.configuration.gbl_params)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { Tooltip } from "bootstrap"
|
|
2
|
-
|
|
3
|
-
export default function initializeTooltips() {
|
|
4
|
-
document.body.addEventListener(
|
|
5
|
-
"mouseenter",
|
|
6
|
-
(event) => {
|
|
7
|
-
if (event.target.closest(".blacklight-icons.svg_tooltip svg")) {
|
|
8
|
-
const svgElement = event.target.closest(".blacklight-icons.svg_tooltip svg")
|
|
9
|
-
const svgTitleElement = svgElement.querySelector("title")
|
|
10
|
-
const titleText = svgTitleElement ? svgTitleElement.textContent : ""
|
|
11
|
-
|
|
12
|
-
if (titleText !== undefined && titleText !== "") {
|
|
13
|
-
// Initialize Bootstrap tooltip with native JavaScript
|
|
14
|
-
const tooltip = new Tooltip(svgElement, {
|
|
15
|
-
placement: "bottom",
|
|
16
|
-
title: titleText,
|
|
17
|
-
})
|
|
18
|
-
tooltip.show()
|
|
19
|
-
|
|
20
|
-
// Store the original title in the data-original-title attribute
|
|
21
|
-
// and remove the title element to prevent it from interfering with Bootstrap's tooltip.
|
|
22
|
-
svgElement.setAttribute("data-original-title", titleText)
|
|
23
|
-
svgTitleElement.remove()
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
true,
|
|
28
|
-
) // Use capture to ensure the event is caught as it bubbles up
|
|
29
|
-
|
|
30
|
-
document.body.addEventListener(
|
|
31
|
-
"mouseleave",
|
|
32
|
-
(event) => {
|
|
33
|
-
if (event.target.closest(".blacklight-icons.svg_tooltip svg")) {
|
|
34
|
-
const svgElement = event.target.closest(".blacklight-icons.svg_tooltip svg")
|
|
35
|
-
const originalTitle = svgElement.getAttribute("data-original-title")
|
|
36
|
-
|
|
37
|
-
if (originalTitle !== undefined && originalTitle !== "") {
|
|
38
|
-
// Restore the SVG title element from data-original-title
|
|
39
|
-
const newTitleElement = document.createElement("title")
|
|
40
|
-
newTitleElement.textContent = originalTitle
|
|
41
|
-
svgElement.prepend(newTitleElement)
|
|
42
|
-
svgElement.setAttribute("data-original-title", "")
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Remove tooltips
|
|
47
|
-
document.querySelectorAll(".tooltip").forEach((elem) => elem.remove())
|
|
48
|
-
},
|
|
49
|
-
true,
|
|
50
|
-
) // Use capture to ensure the event is caught as it bubbles up
|
|
51
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Geoblacklight
|
|
4
|
-
class FeatureInfoResponse
|
|
5
|
-
def initialize(response)
|
|
6
|
-
@response = response
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def check
|
|
10
|
-
if error?
|
|
11
|
-
@response
|
|
12
|
-
else
|
|
13
|
-
format
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def format
|
|
18
|
-
JSON.parse(@response.body)
|
|
19
|
-
rescue
|
|
20
|
-
page = Nokogiri::HTML(@response.body)
|
|
21
|
-
properties = {}
|
|
22
|
-
values = {}
|
|
23
|
-
page.css("td").each_with_index do |td, index|
|
|
24
|
-
values[index] = td.text
|
|
25
|
-
end
|
|
26
|
-
page.css("th").each_with_index do |th, index|
|
|
27
|
-
properties[th.text] = values[index] unless index >= values.keys.count
|
|
28
|
-
end
|
|
29
|
-
{features: [{properties: properties, isHTML: true}]}
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def error?
|
|
33
|
-
@response[:error] ||
|
|
34
|
-
@response.headers["content-type"].slice(0, 9) == "text/xml"
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Geoblacklight
|
|
4
|
-
class WmsLayer
|
|
5
|
-
def initialize(params)
|
|
6
|
-
@params = params.to_h.merge(Geoblacklight.configuration.wms_params)
|
|
7
|
-
@response = Geoblacklight::FeatureInfoResponse.new(request_response)
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def url
|
|
11
|
-
@params["URL"]
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def search_params
|
|
15
|
-
@params.except("URL")
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def feature_info
|
|
19
|
-
@response.check
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def request_response
|
|
23
|
-
conn = Faraday.new(url: url)
|
|
24
|
-
conn.get do |request|
|
|
25
|
-
request.params = search_params
|
|
26
|
-
request.options.timeout = Geoblacklight.configuration.timeout_wms
|
|
27
|
-
request.options.open_timeout = Geoblacklight.configuration.timeout_wms
|
|
28
|
-
end
|
|
29
|
-
rescue Faraday::ConnectionFailed, Faraday::TimeoutError => error
|
|
30
|
-
Geoblacklight.logger.error error.inspect
|
|
31
|
-
{error: error.inspect}
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "spec_helper"
|
|
4
|
-
|
|
5
|
-
RSpec.describe WmsController, type: :controller do
|
|
6
|
-
let(:wms_layer) { instance_double(Geoblacklight::WmsLayer) }
|
|
7
|
-
let(:feature_info) { {values: ["fid", "layer:example"]} }
|
|
8
|
-
let(:params) do
|
|
9
|
-
{"format" => "json", "URL" => "http://www.example.com/", "LAYERS" => "layer:example",
|
|
10
|
-
"BBOX" => "-74, 40, -68, 43", "WIDTH" => "500", "HEIGHT" => "400",
|
|
11
|
-
"QUERY_LAYERS" => "layer:example", "X" => "277", "Y" => "195"}
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
before do
|
|
15
|
-
allow(Geoblacklight::WmsLayer).to receive(:new).and_return(wms_layer)
|
|
16
|
-
allow(wms_layer).to receive(:feature_info).and_return(feature_info)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
describe "#handle" do
|
|
20
|
-
it "returns feature info as json" do
|
|
21
|
-
get :handle, params: params
|
|
22
|
-
expect(response.body).to eq(feature_info.to_json)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
describe "#wms_params" do
|
|
27
|
-
let(:wms_params) { controller.instance_eval { wms_params } }
|
|
28
|
-
|
|
29
|
-
it "returns only permitted params" do
|
|
30
|
-
get :handle, params: params
|
|
31
|
-
expect(wms_params.to_h).to eq(params)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "spec_helper"
|
|
4
|
-
|
|
5
|
-
RSpec.describe Geoblacklight::FeatureInfoResponse do
|
|
6
|
-
let(:response) { described_class.new(OpenStruct.new(body: "<html><body><table><th>Header1</th><th>Header2</th><td>value1</td><td>value2</td></body></html>", headers: {"content-type" => "all good"})) }
|
|
7
|
-
let(:response_multiple_features) { described_class.new(OpenStruct.new(body: "<html><body><table><th>Header1</th><th>Header2</th><tr><td>value1</td><td>value2</td></tr><tr><td>value3</td><td>value4</td></tr></body></html>", headers: {"content-type" => "all good"})) }
|
|
8
|
-
let(:error_response) { described_class.new(error: "bad stuff") }
|
|
9
|
-
let(:content_response) { described_class.new(OpenStruct.new(headers: {"content-type" => "text/xml"})) }
|
|
10
|
-
|
|
11
|
-
describe "#initialize" do
|
|
12
|
-
it "initializes as a FeatureInfoResponse type" do
|
|
13
|
-
expect(response).to be_an described_class
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
describe "#error?" do
|
|
18
|
-
it "if no error" do
|
|
19
|
-
expect(response.error?).to be_falsey
|
|
20
|
-
end
|
|
21
|
-
it "if error key is present" do
|
|
22
|
-
expect(error_response.error?).to be_truthy
|
|
23
|
-
end
|
|
24
|
-
it "if content-type header is text/xml" do
|
|
25
|
-
expect(content_response.error?).to be_truthy
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
describe "#format" do
|
|
30
|
-
it "returns a formated response" do
|
|
31
|
-
expect(response.format).not_to be_nil
|
|
32
|
-
expect(response.format[:features][0][:properties].keys.length).to eq 2
|
|
33
|
-
expect(response.format[:features][0][:isHTML]).to be true
|
|
34
|
-
expect(response.format[:features][0][:properties]["Header1"]).to eq "value1"
|
|
35
|
-
expect(response.format[:features][0][:properties]["Header2"]).to eq "value2"
|
|
36
|
-
end
|
|
37
|
-
it "returns a formated response when multiple features are retrieved" do
|
|
38
|
-
expect(response_multiple_features.format).not_to be_nil
|
|
39
|
-
expect(response.format[:features][0][:properties].keys.length).to eq 2
|
|
40
|
-
expect(response.format[:features][0][:isHTML]).to be true
|
|
41
|
-
expect(response.format[:features][0][:properties]["Header1"]).to eq "value1"
|
|
42
|
-
expect(response.format[:features][0][:properties]["Header2"]).to eq "value2"
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
describe "#check" do
|
|
47
|
-
it "returns a formated response if no errors" do
|
|
48
|
-
expect(response.check).to eq response.format
|
|
49
|
-
end
|
|
50
|
-
it "returns the unformated response if there are errors" do
|
|
51
|
-
expect(error_response.check).to eq error_response.instance_variable_get(:@response)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "spec_helper"
|
|
4
|
-
|
|
5
|
-
RSpec.describe Geoblacklight::WmsLayer do
|
|
6
|
-
let(:wms_layer) { described_class.new(params) }
|
|
7
|
-
let(:rails_4_params) { {"URL" => "http://www.example.com/", "X" => "277"} }
|
|
8
|
-
let(:rails_5_params) { instance_double(ActionController::Parameters) }
|
|
9
|
-
|
|
10
|
-
before do
|
|
11
|
-
allow(rails_5_params).to receive(:to_h).and_return("URL" => "http://www.example.com/", "X" => "277")
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
describe "#initialize" do
|
|
15
|
-
let(:params) { rails_4_params }
|
|
16
|
-
|
|
17
|
-
it "initializes as a WmsLayer object" do
|
|
18
|
-
expect(wms_layer).to be_an described_class
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
describe "#url" do
|
|
23
|
-
context "when running on rails 4" do
|
|
24
|
-
let(:params) { rails_4_params }
|
|
25
|
-
|
|
26
|
-
it "returns the correct URL parameter" do
|
|
27
|
-
expect(wms_layer.url).to eq("http://www.example.com/")
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
context "when running on rails 5" do
|
|
32
|
-
let(:params) { rails_5_params }
|
|
33
|
-
|
|
34
|
-
it "returns the correct URL parameter" do
|
|
35
|
-
expect(wms_layer.url).to eq("http://www.example.com/")
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
describe "#search_params" do
|
|
41
|
-
context "when running on rails 4" do
|
|
42
|
-
let(:params) { rails_4_params }
|
|
43
|
-
|
|
44
|
-
it "returns all params except URL plus default params" do
|
|
45
|
-
expect(wms_layer.search_params.length).to eq 8
|
|
46
|
-
expect(wms_layer.search_params).not_to include "URL" => "http://www.example.com/"
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
context "when running on rails 5" do
|
|
51
|
-
let(:params) { rails_5_params }
|
|
52
|
-
|
|
53
|
-
it "returns all params except URL plus default params" do
|
|
54
|
-
expect(wms_layer.search_params.length).to eq 8
|
|
55
|
-
expect(wms_layer.search_params).not_to include "URL" => "http://www.example.com/"
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
describe "#feature_info" do
|
|
61
|
-
let(:response) { instance_double(Geoblacklight::FeatureInfoResponse) }
|
|
62
|
-
let(:params) { rails_4_params }
|
|
63
|
-
|
|
64
|
-
before do
|
|
65
|
-
allow(Geoblacklight::FeatureInfoResponse).to receive(:new).and_return(response)
|
|
66
|
-
allow(response).to receive(:check)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
it "returns the response from the FeatureInfoResponse object" do
|
|
70
|
-
expect(wms_layer.feature_info).to eq(response.check)
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
describe "#request_response" do
|
|
75
|
-
subject(:wms_layer) { described_class.new(params) }
|
|
76
|
-
let(:params) { rails_4_params }
|
|
77
|
-
let(:connection) { instance_double(Faraday::Connection) }
|
|
78
|
-
let(:response) { instance_double(Faraday::Response) }
|
|
79
|
-
|
|
80
|
-
before do
|
|
81
|
-
allow(Faraday).to receive(:new).and_return(connection)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
it "returns a Faraday object" do
|
|
85
|
-
allow(connection).to receive(:get).and_return(response)
|
|
86
|
-
expect(wms_layer.request_response).to eq(response)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
context "when the HTTP connection fails" do
|
|
90
|
-
before do
|
|
91
|
-
allow(Geoblacklight.logger).to receive(:error).with("#<Faraday::ConnectionFailed wrapped=#<StandardError: test connection error>>")
|
|
92
|
-
allow(connection).to receive(:get).and_raise(Faraday::ConnectionFailed.new(StandardError.new("test connection error")))
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
it "logs the Faraday error" do
|
|
96
|
-
expect(Geoblacklight.logger).to receive(:error).exactly(3).times
|
|
97
|
-
expect(wms_layer.request_response).to be_a Hash
|
|
98
|
-
expect(wms_layer.request_response).to include(error: "#<Faraday::ConnectionFailed wrapped=#<StandardError: test connection error>>")
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
context "when the HTTP connection times out" do
|
|
103
|
-
before do
|
|
104
|
-
allow(Geoblacklight.logger).to receive(:error).with("#<Faraday::TimeoutError #<Faraday::TimeoutError: timeout>>")
|
|
105
|
-
allow(connection).to receive(:get).and_raise(Faraday::TimeoutError)
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
it "logs the Faraday error" do
|
|
109
|
-
expect(Geoblacklight.logger).to receive(:error).exactly(3).times
|
|
110
|
-
expect(wms_layer.request_response).to be_a Hash
|
|
111
|
-
expect(wms_layer.request_response).to include(error: "#<Faraday::TimeoutError #<Faraday::TimeoutError: timeout>>")
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|