bulkrax 9.5.0 → 10.0.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/README.md +49 -0
- data/app/controllers/bulkrax/application_controller.rb +83 -0
- data/app/controllers/bulkrax/entries_controller.rb +16 -13
- data/app/controllers/bulkrax/exporters_controller.rb +21 -25
- data/app/controllers/bulkrax/guided_imports_controller.rb +4 -8
- data/app/controllers/bulkrax/importers_controller.rb +26 -29
- data/app/controllers/concerns/bulkrax/datatables_behavior.rb +18 -12
- data/app/controllers/concerns/bulkrax/importer_file_handler.rb +1 -1
- data/app/factories/bulkrax/object_factory.rb +2 -2
- data/app/factories/bulkrax/valkyrie_object_factory.rb +29 -17
- data/app/helpers/bulkrax/validation_helper.rb +1 -1
- data/app/jobs/bulkrax/create_relationships_job.rb +1 -1
- data/app/jobs/bulkrax/import_collection_job.rb +9 -2
- data/app/matchers/bulkrax/application_matcher.rb +5 -2
- data/app/models/bulkrax/csv_entry.rb +1 -1
- data/app/models/bulkrax/current.rb +7 -0
- data/app/models/bulkrax/export_scope.rb +21 -0
- data/app/models/bulkrax/exporter.rb +2 -2
- data/app/models/bulkrax/importer.rb +1 -1
- data/app/models/concerns/bulkrax/ability_behavior.rb +139 -0
- data/app/models/concerns/bulkrax/has_matchers.rb +15 -2
- data/app/models/concerns/bulkrax/import_behavior.rb +3 -3
- data/app/parsers/bulkrax/csv_parser.rb +13 -12
- data/app/parsers/bulkrax/oai_dc_parser.rb +1 -1
- data/app/parsers/bulkrax/parser_export_record_set.rb +26 -8
- data/app/parsers/concerns/bulkrax/csv_parser/csv_template_generation.rb +1 -1
- data/app/parsers/concerns/bulkrax/csv_parser/csv_validation.rb +1 -2
- data/app/parsers/concerns/bulkrax/csv_parser/csv_validation_helpers.rb +18 -1
- data/app/parsers/concerns/bulkrax/csv_parser/csv_validation_hierarchy.rb +2 -2
- data/app/search_builders/bulkrax/export_search_builder.rb +9 -0
- data/app/services/bulkrax/csv_template/column_builder.rb +2 -2
- data/app/services/bulkrax/csv_template/mapping_manager.rb +9 -7
- data/app/services/bulkrax/csv_template/schema_analyzer.rb +1 -5
- data/lib/bulkrax/engine.rb +1 -1
- data/lib/bulkrax/version.rb +1 -1
- data/lib/bulkrax.rb +76 -10
- data/lib/generators/bulkrax/install_generator.rb +22 -10
- data/lib/generators/bulkrax/templates/config/initializers/bulkrax.rb +1 -1
- metadata +33 -13
- data/lib/wings/custom_queries/find_by_source_identifier.rb +0 -41
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ae568e80c3ac44aeeefdcbea1810035b250ab070cd7d72b82481f8ee878cda54
|
|
4
|
+
data.tar.gz: 2b927f012dce82c3fc5c60dc23877bbae24ef986efec97ae6ff6a9acc89f3d3d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c198d55e37b8f4338a9ebe6a0042cada18f749f9dc0fead3fa9fd26b91f75a37a68f44a88e6a65e011c7c3a87183c77cf432a1e94d30027130ba6e2b090467f3
|
|
7
|
+
data.tar.gz: 9b72aaa5e796a76b804b011a532a91589486deee690488b9c514dc8e2ba5054e6a5a896387b30d2c3a6fbc8313ff4581ad4c473cc7c604166462e3cbfa4b1f8f
|
data/README.md
CHANGED
|
@@ -5,6 +5,25 @@ Bulkrax is a batteries included importer for Samvera applications. It currently
|
|
|
5
5
|
|
|
6
6
|
## Installation
|
|
7
7
|
|
|
8
|
+
### Rails compatibility
|
|
9
|
+
|
|
10
|
+
Existing Hyrax integration tests retain Rails 6.1 compatibility. Rails 8.1 is
|
|
11
|
+
tested independently with a minimal Rails application: engine boot, routes,
|
|
12
|
+
engine migrations, and persisted JSON/YAML serialization. This smoke coverage
|
|
13
|
+
unblocks a subsequent Hyrax upgrade; it does **not** claim that current Hyrax
|
|
14
|
+
releases support Rails 8.1, or exercise repository-backed import/export workflows.
|
|
15
|
+
|
|
16
|
+
Run the standalone smoke suite from the Bulkrax checkout with a separate bundle:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
BULKRAX_WITH_HYRAX=false RAILS_GEM_VERSION='~> 8.1.0' BUNDLE_PATH=vendor/rails81 bundle install
|
|
20
|
+
BULKRAX_WITH_HYRAX=false RAILS_GEM_VERSION='~> 8.1.0' BUNDLE_PATH=vendor/rails81 bundle exec rspec spec/rails_compat
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Hyrax remains enabled by default for the existing integration suite. Resolve the
|
|
24
|
+
bundle again when switching modes; do not reuse a frozen lockfile from the other
|
|
25
|
+
mode. Rails 8.1 requires Ruby 3.2 or newer and SQLite 2.1 or newer for this smoke app.
|
|
26
|
+
|
|
8
27
|
### Install Generator
|
|
9
28
|
|
|
10
29
|
Add this line to your application's Gemfile:
|
|
@@ -24,6 +43,36 @@ $ rails db:migrate
|
|
|
24
43
|
|
|
25
44
|
If using Sidekiq, set up queues for `import` and `export`.
|
|
26
45
|
|
|
46
|
+
### Permissions
|
|
47
|
+
|
|
48
|
+
Add Bulkrax's rules to your application's `app/models/ability.rb`:
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
include Bulkrax::AbilityBehavior
|
|
52
|
+
self.ability_logic += [:bulkrax_default_abilities]
|
|
53
|
+
|
|
54
|
+
def can_import_works?
|
|
55
|
+
can_create_any_work?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def can_export_works?
|
|
59
|
+
can_create_any_work?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def can_admin_importers?
|
|
63
|
+
current_user.admin?
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def can_admin_exporters?
|
|
67
|
+
current_user.admin?
|
|
68
|
+
end
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Replace the example predicates with your application's policy. By default, all
|
|
72
|
+
four return `false`; permitted users manage only their own importers and
|
|
73
|
+
exporters, while the admin predicates grant access to all records. Ensure
|
|
74
|
+
existing importers and exporters have an owner (`user_id`).
|
|
75
|
+
|
|
27
76
|
### Bundle errors on ARM
|
|
28
77
|
|
|
29
78
|
If posix-spawn is failing to bundle on an ARM based processor, try the following
|
|
@@ -4,5 +4,88 @@ module Bulkrax
|
|
|
4
4
|
class ApplicationController < ::ApplicationController
|
|
5
5
|
helper Rails.application.class.helpers
|
|
6
6
|
protect_from_forgery with: :exception
|
|
7
|
+
|
|
8
|
+
# Rescue CanCan::AccessDenied in all Bulkrax controllers. HTML requests are
|
|
9
|
+
# redirected to the host-app root with an alert; JSON requests receive a 403
|
|
10
|
+
# response. Defining the handler here (rather than in individual controllers)
|
|
11
|
+
# keeps error handling in one place and consistent across all resources.
|
|
12
|
+
rescue_from CanCan::AccessDenied do |exception|
|
|
13
|
+
respond_to do |format|
|
|
14
|
+
format.html do
|
|
15
|
+
flash[:alert] = exception.message
|
|
16
|
+
redirect_to main_app.root_path
|
|
17
|
+
end
|
|
18
|
+
format.json { render json: { error: exception.message }, status: :forbidden }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
protected
|
|
23
|
+
|
|
24
|
+
# Single auth before_action for ImportersController and ExportersController.
|
|
25
|
+
# Authenticates the request, then loads and authorizes the record targeted
|
|
26
|
+
# by the current action, assigning it to @importer / @exporter (derived
|
|
27
|
+
# from +klass+).
|
|
28
|
+
#
|
|
29
|
+
# * Authentication: API requests (see Bulkrax::API) use the token;
|
|
30
|
+
# everything else uses authenticate_user!.
|
|
31
|
+
# * new/create: build a new record (from +<name>_params+ on create) and
|
|
32
|
+
# authorize it. Skipped for API requests, which validate params and build
|
|
33
|
+
# the record inside the action.
|
|
34
|
+
# * Member actions: find by :id or :<name>_id (e.g. continue, download,
|
|
35
|
+
# entry_table) and authorize action_name. Custom actions resolve through
|
|
36
|
+
# the alias_action mappings in Bulkrax::AbilityBehavior (e.g. :export_errors ->
|
|
37
|
+
# :read, :continue -> :update).
|
|
38
|
+
# * Browser collection actions (no id param, e.g. index, *_table): check
|
|
39
|
+
# the controller-supplied capability predicate. The action scopes records
|
|
40
|
+
# with accessible_by after authorization. API collection actions remain
|
|
41
|
+
# compatible until token-to-user wiring is available.
|
|
42
|
+
#
|
|
43
|
+
# @param klass [Class] Bulkrax::Importer or Bulkrax::Exporter
|
|
44
|
+
# @param collection_ability [Symbol] ability predicate for collection actions
|
|
45
|
+
def authenticate_and_authorize!(klass, collection_ability)
|
|
46
|
+
return unless authenticate_request!
|
|
47
|
+
|
|
48
|
+
name = klass.model_name.element
|
|
49
|
+
record = case action_name
|
|
50
|
+
when 'new', 'create'
|
|
51
|
+
return if api_request?
|
|
52
|
+
klass.new(action_name == 'create' ? send(:"#{name}_params") : {})
|
|
53
|
+
else
|
|
54
|
+
id = params[:id] || params[:"#{name}_id"]
|
|
55
|
+
return if id.blank? && api_request?
|
|
56
|
+
return authorize_collection!(collection_ability) if id.blank?
|
|
57
|
+
klass.find(id)
|
|
58
|
+
end
|
|
59
|
+
instance_variable_set(:"@#{name}", record)
|
|
60
|
+
|
|
61
|
+
# TODO(#1237): API requests have no current_user until the token is
|
|
62
|
+
# resolved to a user, so API actions addressed by :id (and entry_table)
|
|
63
|
+
# skip authorization to keep existing consumers working. Other
|
|
64
|
+
# :<name>_id actions are authorized.
|
|
65
|
+
return if api_request? && (params[:id].present? || action_name == 'entry_table')
|
|
66
|
+
|
|
67
|
+
authorize! action_name.to_sym, record
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def authorize_collection!(ability_method)
|
|
73
|
+
return if current_ability.public_send(ability_method)
|
|
74
|
+
|
|
75
|
+
raise CanCan::AccessDenied, 'Not authorized'
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Overridden by Bulkrax::API in controllers that accept token-authenticated
|
|
79
|
+
# JSON requests.
|
|
80
|
+
def api_request?
|
|
81
|
+
false
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Returns false when authentication rendered or redirected, so the caller
|
|
85
|
+
# can halt.
|
|
86
|
+
def authenticate_request!
|
|
87
|
+
api_request? ? token_authenticate! : authenticate_user!
|
|
88
|
+
!performed?
|
|
89
|
+
end
|
|
7
90
|
end
|
|
8
91
|
end
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module Bulkrax
|
|
4
4
|
class EntriesController < ApplicationController
|
|
5
|
-
include Hyrax::ThemedLayoutController if
|
|
5
|
+
include Hyrax::ThemedLayoutController if Bulkrax.hyrax_loaded?
|
|
6
6
|
before_action :authenticate_user!
|
|
7
|
-
|
|
8
|
-
with_themed_layout 'dashboard' if defined?(::Hyrax)
|
|
7
|
+
with_themed_layout 'dashboard' if Bulkrax.hyrax_loaded?
|
|
9
8
|
|
|
10
9
|
def show
|
|
11
10
|
if params[:importer_id].present?
|
|
@@ -17,6 +16,8 @@ module Bulkrax
|
|
|
17
16
|
|
|
18
17
|
def update
|
|
19
18
|
@entry = Entry.find(params[:id])
|
|
19
|
+
authorize! :update, @entry
|
|
20
|
+
|
|
20
21
|
type = case @entry.type.downcase
|
|
21
22
|
when /fileset/
|
|
22
23
|
'file_set'
|
|
@@ -25,8 +26,8 @@ module Bulkrax
|
|
|
25
26
|
else
|
|
26
27
|
'work'
|
|
27
28
|
end
|
|
28
|
-
item = @entry.importerexporter
|
|
29
29
|
# do not run counters as it loads the whole parser
|
|
30
|
+
item = @entry.importerexporter
|
|
30
31
|
current_run = item.current_run(skip_counts: true)
|
|
31
32
|
@entry.set_status_info('Pending', current_run)
|
|
32
33
|
ScheduleRelationshipsJob.set(wait: 5.minutes).perform_later(importer_id: @entry.importer.id)
|
|
@@ -44,6 +45,9 @@ module Bulkrax
|
|
|
44
45
|
|
|
45
46
|
def destroy
|
|
46
47
|
@entry = Entry.find(params[:id])
|
|
48
|
+
authorize! :destroy, @entry
|
|
49
|
+
|
|
50
|
+
item = @entry.importerexporter
|
|
47
51
|
@status = ""
|
|
48
52
|
begin
|
|
49
53
|
work = @entry.factory&.find
|
|
@@ -59,7 +63,6 @@ module Bulkrax
|
|
|
59
63
|
@status = "Error: #{e.message}"
|
|
60
64
|
end
|
|
61
65
|
|
|
62
|
-
item = @entry.importerexporter
|
|
63
66
|
entry_path = item.class.to_s.include?('Importer') ? bulkrax.importer_entry_path(item.id, @entry.id) : bulkrax.exporter_entry_path(item.id, @entry.id)
|
|
64
67
|
|
|
65
68
|
redirect_back fallback_location: entry_path, notice: @status
|
|
@@ -70,9 +73,11 @@ module Bulkrax
|
|
|
70
73
|
# GET /importers/1/entries/1
|
|
71
74
|
def show_importer
|
|
72
75
|
@importer = Importer.find(params[:importer_id])
|
|
73
|
-
|
|
76
|
+
authorize! :read, @importer
|
|
77
|
+
@entry = @importer.entries.find(params[:id])
|
|
78
|
+
authorize! :read, @entry
|
|
74
79
|
|
|
75
|
-
return unless
|
|
80
|
+
return unless Bulkrax.hyrax_loaded?
|
|
76
81
|
add_breadcrumb t(:'hyrax.controls.home'), main_app.root_path
|
|
77
82
|
add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
|
|
78
83
|
add_breadcrumb t(:'bulkrax.headings.importers'), bulkrax.importers_path
|
|
@@ -83,18 +88,16 @@ module Bulkrax
|
|
|
83
88
|
# GET /exporters/1/entries/1
|
|
84
89
|
def show_exporter
|
|
85
90
|
@exporter = Exporter.find(params[:exporter_id])
|
|
86
|
-
|
|
91
|
+
authorize! :read, @exporter
|
|
92
|
+
@entry = @exporter.entries.find(params[:id])
|
|
93
|
+
authorize! :read, @entry
|
|
87
94
|
|
|
88
|
-
return unless
|
|
95
|
+
return unless Bulkrax.hyrax_loaded?
|
|
89
96
|
add_breadcrumb t(:'hyrax.controls.home'), main_app.root_path
|
|
90
97
|
add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
|
|
91
98
|
add_breadcrumb t(:'bulkrax.headings.exporters'), bulkrax.exporters_path
|
|
92
99
|
add_breadcrumb @exporter.name, bulkrax.exporter_path(@exporter.id)
|
|
93
100
|
add_breadcrumb @entry.id
|
|
94
101
|
end
|
|
95
|
-
|
|
96
|
-
def check_permissions
|
|
97
|
-
raise CanCan::AccessDenied unless current_ability.can_import_works? || current_ability.can_export_works?
|
|
98
|
-
end
|
|
99
102
|
end
|
|
100
103
|
end
|
|
@@ -2,33 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
module Bulkrax
|
|
4
4
|
class ExportersController < ApplicationController
|
|
5
|
-
include Hyrax::ThemedLayoutController if
|
|
5
|
+
include Hyrax::ThemedLayoutController if Bulkrax.hyrax_loaded?
|
|
6
6
|
include Bulkrax::DownloadBehavior
|
|
7
7
|
include Bulkrax::DatatablesBehavior
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
before_action
|
|
11
|
-
|
|
8
|
+
|
|
9
|
+
# Authentication, record loading and authorization for every action.
|
|
10
|
+
before_action(except: [:download]) { authenticate_and_authorize!(Bulkrax::Exporter, :can_export_works?) }
|
|
11
|
+
|
|
12
|
+
with_themed_layout 'dashboard' if Bulkrax.hyrax_loaded?
|
|
12
13
|
|
|
13
14
|
# GET /exporters
|
|
14
15
|
def index
|
|
15
16
|
# NOTE: We're paginating this in the browser.
|
|
16
|
-
@exporters = Exporter.order(created_at: :desc)
|
|
17
|
+
@exporters = Exporter.accessible_by(current_ability).order(created_at: :desc)
|
|
17
18
|
|
|
18
|
-
add_exporter_breadcrumbs if
|
|
19
|
+
add_exporter_breadcrumbs if Bulkrax.hyrax_loaded?
|
|
19
20
|
end
|
|
20
21
|
|
|
21
22
|
def exporter_table
|
|
22
|
-
@exporters = Exporter.
|
|
23
|
+
@exporters = Exporter.accessible_by(current_ability)
|
|
23
24
|
@exporters = @exporters.where(exporter_table_search) if exporter_table_search.present?
|
|
25
|
+
# Count the filtered relation before applying pagination so the UI receives
|
|
26
|
+
# the total number of matching exporters, not just the total number of exporters.
|
|
27
|
+
filtered_count = @exporters.count
|
|
28
|
+
@exporters = @exporters.order(table_order).page(table_page).per(table_per_page)
|
|
24
29
|
respond_to do |format|
|
|
25
|
-
format.json { render json: format_exporters(@exporters) }
|
|
30
|
+
format.json { render json: format_exporters(@exporters, filtered_count) }
|
|
26
31
|
end
|
|
27
32
|
end
|
|
28
33
|
|
|
29
34
|
# GET /exporters/1
|
|
30
35
|
def show
|
|
31
|
-
if
|
|
36
|
+
if Bulkrax.hyrax_loaded?
|
|
32
37
|
add_exporter_breadcrumbs
|
|
33
38
|
add_breadcrumb @exporter.name
|
|
34
39
|
end
|
|
@@ -45,15 +50,14 @@ module Bulkrax
|
|
|
45
50
|
|
|
46
51
|
# GET /exporters/new
|
|
47
52
|
def new
|
|
48
|
-
|
|
49
|
-
return unless defined?(::Hyrax)
|
|
53
|
+
return unless Bulkrax.hyrax_loaded?
|
|
50
54
|
add_exporter_breadcrumbs
|
|
51
55
|
add_breadcrumb t(:'bulkrax.headings.new_exporter')
|
|
52
56
|
end
|
|
53
57
|
|
|
54
58
|
# GET /exporters/1/edit
|
|
55
59
|
def edit
|
|
56
|
-
if
|
|
60
|
+
if Bulkrax.hyrax_loaded?
|
|
57
61
|
add_exporter_breadcrumbs
|
|
58
62
|
add_breadcrumb @exporter.name, bulkrax.exporter_path(@exporter.id)
|
|
59
63
|
add_breadcrumb t(:'bulkrax.headings.edit_exporter')
|
|
@@ -65,7 +69,7 @@ module Bulkrax
|
|
|
65
69
|
|
|
66
70
|
# POST /exporters
|
|
67
71
|
def create
|
|
68
|
-
@exporter =
|
|
72
|
+
@exporter.user_id = current_user.id
|
|
69
73
|
field_mapping_params
|
|
70
74
|
|
|
71
75
|
if @exporter.save
|
|
@@ -107,25 +111,21 @@ module Bulkrax
|
|
|
107
111
|
# GET /exporters/1/download
|
|
108
112
|
def download
|
|
109
113
|
@exporter = Exporter.find(params[:exporter_id])
|
|
114
|
+
authorize! :read, @exporter
|
|
110
115
|
send_content
|
|
111
116
|
end
|
|
112
117
|
|
|
113
118
|
private
|
|
114
119
|
|
|
115
|
-
# Use callbacks to share common setup or constraints between actions.
|
|
116
|
-
def set_exporter
|
|
117
|
-
@exporter = Exporter.find(params[:id] || params[:exporter_id])
|
|
118
|
-
end
|
|
119
|
-
|
|
120
120
|
# Only allow a trusted parameters through.
|
|
121
121
|
def exporter_params
|
|
122
122
|
params[:exporter][:export_source] = params[:exporter]["export_source_#{params[:exporter][:export_from]}".to_sym]
|
|
123
123
|
if params[:exporter][:date_filter] == "1"
|
|
124
|
-
params.fetch(:exporter).permit(:name, :
|
|
124
|
+
params.fetch(:exporter).permit(:name, :export_source, :export_from, :export_type, :generated_metadata,
|
|
125
125
|
:include_thumbnails, :parser_klass, :limit, :start_date, :finish_date, :work_visibility,
|
|
126
126
|
:workflow_status, field_mapping: {})
|
|
127
127
|
else
|
|
128
|
-
params.fetch(:exporter).permit(:name, :
|
|
128
|
+
params.fetch(:exporter).permit(:name, :export_source, :export_from, :export_type, :generated_metadata,
|
|
129
129
|
:include_thumbnails, :parser_klass, :limit, :work_visibility, :workflow_status,
|
|
130
130
|
field_mapping: {}).merge(start_date: nil, finish_date: nil)
|
|
131
131
|
end
|
|
@@ -149,9 +149,5 @@ module Bulkrax
|
|
|
149
149
|
def file_path
|
|
150
150
|
"#{@exporter.exporter_export_zip_path}/#{params['exporter']['exporter_export_zip_files']}"
|
|
151
151
|
end
|
|
152
|
-
|
|
153
|
-
def check_permissions
|
|
154
|
-
raise CanCan::AccessDenied unless current_ability.can_export_works?
|
|
155
|
-
end
|
|
156
152
|
end
|
|
157
153
|
end
|
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
module Bulkrax
|
|
4
4
|
class GuidedImportsController < ::Bulkrax::ApplicationController
|
|
5
|
-
include Hyrax::ThemedLayoutController if
|
|
5
|
+
include Hyrax::ThemedLayoutController if Bulkrax.hyrax_loaded?
|
|
6
6
|
include Bulkrax::GuidedImportDemoScenarios if Bulkrax.config.guided_import_demo_scenarios_enabled
|
|
7
7
|
include Bulkrax::ImporterFileHandler
|
|
8
8
|
helper Bulkrax::ImportersHelper
|
|
9
9
|
|
|
10
10
|
before_action :authenticate_user!
|
|
11
|
-
before_action :
|
|
12
|
-
with_themed_layout 'dashboard' if
|
|
11
|
+
before_action { authorize! :create, Bulkrax::Importer }
|
|
12
|
+
with_themed_layout 'dashboard' if Bulkrax.hyrax_loaded?
|
|
13
13
|
|
|
14
14
|
# trigger form to allow upload
|
|
15
15
|
def new
|
|
16
16
|
@importer = Importer.new
|
|
17
|
-
return unless
|
|
17
|
+
return unless Bulkrax.hyrax_loaded?
|
|
18
18
|
add_importer_breadcrumbs
|
|
19
19
|
add_breadcrumb I18n.t('bulkrax.importer.guided_import.breadcrumb')
|
|
20
20
|
end
|
|
@@ -169,9 +169,5 @@ module Bulkrax
|
|
|
169
169
|
add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
|
|
170
170
|
add_breadcrumb t(:'bulkrax.headings.importers'), bulkrax.importers_path
|
|
171
171
|
end
|
|
172
|
-
|
|
173
|
-
def check_permissions
|
|
174
|
-
raise CanCan::AccessDenied unless current_ability.can_import_works?
|
|
175
|
-
end
|
|
176
172
|
end
|
|
177
173
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Bulkrax
|
|
4
4
|
# rubocop:disable Metrics/ClassLength
|
|
5
5
|
class ImportersController < ::Bulkrax::ApplicationController
|
|
6
|
-
include Hyrax::ThemedLayoutController if
|
|
6
|
+
include Hyrax::ThemedLayoutController if Bulkrax.hyrax_loaded?
|
|
7
7
|
include Bulkrax::DownloadBehavior
|
|
8
8
|
include Bulkrax::API
|
|
9
9
|
include Bulkrax::DatatablesBehavior
|
|
@@ -11,29 +11,39 @@ module Bulkrax
|
|
|
11
11
|
include Bulkrax::ImporterFileHandler
|
|
12
12
|
|
|
13
13
|
protect_from_forgery unless: -> { api_request? }
|
|
14
|
-
|
|
15
|
-
before_action
|
|
16
|
-
|
|
17
|
-
before_action :set_importer, only: [:show, :entry_table, :edit, :update, :destroy, :original_file]
|
|
18
|
-
with_themed_layout 'dashboard' if defined?(::Hyrax)
|
|
14
|
+
# Authentication, record loading and authorization for every action.
|
|
15
|
+
before_action { authenticate_and_authorize!(Bulkrax::Importer, :can_import_works?) }
|
|
16
|
+
with_themed_layout 'dashboard' if Bulkrax.hyrax_loaded?
|
|
19
17
|
|
|
20
18
|
# GET /importers
|
|
21
19
|
def index
|
|
22
20
|
# NOTE: We're paginating this in the browser.
|
|
23
21
|
if api_request?
|
|
22
|
+
# TODO(#1237): Scope API index by token owner once token-to-user wiring
|
|
23
|
+
# is in place. Until then, API clients see all importers
|
|
24
|
+
# to preserve backward-compatibility with existing API consumers.
|
|
24
25
|
@importers = Importer.order(created_at: :desc).all
|
|
25
26
|
json_response('index')
|
|
26
|
-
elsif
|
|
27
|
+
elsif Bulkrax.hyrax_loaded?
|
|
27
28
|
add_importer_breadcrumbs
|
|
28
29
|
end
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
def importer_table
|
|
32
33
|
order = table_order.presence || Arel.sql('last_imported_at DESC NULLS LAST')
|
|
33
|
-
|
|
34
|
+
# TODO(#1237): API requests bypass ownership scoping here too.
|
|
35
|
+
@importers = if api_request?
|
|
36
|
+
Importer.all
|
|
37
|
+
else
|
|
38
|
+
Importer.accessible_by(current_ability)
|
|
39
|
+
end
|
|
34
40
|
@importers = @importers.where(importer_table_search) if importer_table_search.present?
|
|
41
|
+
# Count the filtered relation before applying pagination so the UI receives
|
|
42
|
+
# the total number of matching importers, not just the total number of importers.
|
|
43
|
+
filtered_count = @importers.count
|
|
44
|
+
@importers = @importers.order(order).page(table_page).per(table_per_page)
|
|
35
45
|
respond_to do |format|
|
|
36
|
-
format.json { render json: format_importers(@importers) }
|
|
46
|
+
format.json { render json: format_importers(@importers, filtered_count) }
|
|
37
47
|
end
|
|
38
48
|
end
|
|
39
49
|
|
|
@@ -41,7 +51,7 @@ module Bulkrax
|
|
|
41
51
|
def show
|
|
42
52
|
if api_request?
|
|
43
53
|
json_response('show')
|
|
44
|
-
elsif
|
|
54
|
+
elsif Bulkrax.hyrax_loaded?
|
|
45
55
|
add_importer_breadcrumbs
|
|
46
56
|
add_breadcrumb @importer.name
|
|
47
57
|
end
|
|
@@ -58,10 +68,9 @@ module Bulkrax
|
|
|
58
68
|
|
|
59
69
|
# GET /importers/new
|
|
60
70
|
def new
|
|
61
|
-
@importer = Importer.new
|
|
62
71
|
if api_request?
|
|
63
72
|
json_response('new')
|
|
64
|
-
elsif
|
|
73
|
+
elsif Bulkrax.hyrax_loaded?
|
|
65
74
|
add_importer_breadcrumbs
|
|
66
75
|
add_breadcrumb t(:'bulkrax.headings.new_importer')
|
|
67
76
|
end
|
|
@@ -81,7 +90,7 @@ module Bulkrax
|
|
|
81
90
|
def edit
|
|
82
91
|
if api_request?
|
|
83
92
|
json_response('edit')
|
|
84
|
-
elsif
|
|
93
|
+
elsif Bulkrax.hyrax_loaded?
|
|
85
94
|
add_importer_breadcrumbs
|
|
86
95
|
add_breadcrumb @importer.name, bulkrax.importer_path(@importer.id)
|
|
87
96
|
add_breadcrumb t(:'bulkrax.headings.edit_importer')
|
|
@@ -95,12 +104,14 @@ module Bulkrax
|
|
|
95
104
|
# rubocop:disable Style/IfInsideElse
|
|
96
105
|
if api_request?
|
|
97
106
|
return return_json_response unless valid_create_params?
|
|
107
|
+
# authenticate_and_authorize! doesn't build for API requests; build it here
|
|
108
|
+
@importer ||= Importer.new(importer_params)
|
|
98
109
|
end
|
|
110
|
+
@importer.user_id = current_user.id
|
|
99
111
|
uploads = uploaded_files_scope
|
|
100
112
|
file = file_param
|
|
101
113
|
cloud_files = cloud_params
|
|
102
114
|
|
|
103
|
-
@importer = Importer.new(importer_params)
|
|
104
115
|
field_mapping_params
|
|
105
116
|
@importer.validate_only = true if params[:commit] == 'Create and Validate'
|
|
106
117
|
# the following line is needed to handle updating remote files of a FileSet
|
|
@@ -177,7 +188,6 @@ module Bulkrax
|
|
|
177
188
|
|
|
178
189
|
# PUT /importers/1
|
|
179
190
|
def continue
|
|
180
|
-
@importer = Importer.find(params[:importer_id])
|
|
181
191
|
params[:importer] = { name: @importer.name }
|
|
182
192
|
@importer.validate_only = false
|
|
183
193
|
update
|
|
@@ -185,8 +195,7 @@ module Bulkrax
|
|
|
185
195
|
|
|
186
196
|
# GET /importer/1/upload_corrected_entries
|
|
187
197
|
def upload_corrected_entries
|
|
188
|
-
|
|
189
|
-
return unless defined?(::Hyrax)
|
|
198
|
+
return unless Bulkrax.hyrax_loaded?
|
|
190
199
|
add_breadcrumb t(:'hyrax.controls.home'), main_app.root_path
|
|
191
200
|
add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
|
|
192
201
|
add_breadcrumb t(:'bulkrax.headings.importers'), bulkrax.importers_path
|
|
@@ -197,7 +206,6 @@ module Bulkrax
|
|
|
197
206
|
# POST /importer/1/upload_corrected_entries_file
|
|
198
207
|
def upload_corrected_entries_file
|
|
199
208
|
file = params[:importer][:parser_fields].delete(:file)
|
|
200
|
-
@importer = Importer.find(params[:importer_id])
|
|
201
209
|
if file.present?
|
|
202
210
|
@importer[:parser_fields]['partial_import_file_path'] = @importer.parser.write_partial_import_file(file)
|
|
203
211
|
@importer.save
|
|
@@ -242,18 +250,12 @@ module Bulkrax
|
|
|
242
250
|
|
|
243
251
|
# GET /importers/1/export_errors
|
|
244
252
|
def export_errors
|
|
245
|
-
@importer = Importer.find(params[:importer_id])
|
|
246
253
|
@importer.write_errored_entries_file
|
|
247
254
|
send_content
|
|
248
255
|
end
|
|
249
256
|
|
|
250
257
|
private
|
|
251
258
|
|
|
252
|
-
# Use callbacks to share common setup or constraints between actions.
|
|
253
|
-
def set_importer
|
|
254
|
-
@importer = Importer.find(params[:id] || params[:importer_id])
|
|
255
|
-
end
|
|
256
|
-
|
|
257
259
|
def importable_params
|
|
258
260
|
params.except(:selected_files)
|
|
259
261
|
end
|
|
@@ -267,7 +269,6 @@ module Bulkrax
|
|
|
267
269
|
importable_params.require(:importer).permit(
|
|
268
270
|
:name,
|
|
269
271
|
:admin_set_id,
|
|
270
|
-
:user_id,
|
|
271
272
|
:frequency,
|
|
272
273
|
:parser_klass,
|
|
273
274
|
:limit,
|
|
@@ -365,10 +366,6 @@ module Bulkrax
|
|
|
365
366
|
end
|
|
366
367
|
@importer.save
|
|
367
368
|
end
|
|
368
|
-
|
|
369
|
-
def check_permissions
|
|
370
|
-
raise CanCan::AccessDenied unless current_ability.can_import_works?
|
|
371
|
-
end
|
|
372
369
|
end
|
|
373
370
|
# rubocop:enable Metrics/ClassLength
|
|
374
371
|
end
|
|
@@ -83,7 +83,7 @@ module Bulkrax
|
|
|
83
83
|
@exporter_table_search
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
def format_importers(importers)
|
|
86
|
+
def format_importers(importers, filtered_count = Bulkrax::Importer.accessible_by(current_ability).count)
|
|
87
87
|
result = importers.map do |i|
|
|
88
88
|
{
|
|
89
89
|
name: view_context.link_to(i.name, view_context.importer_path(i)),
|
|
@@ -102,12 +102,12 @@ module Bulkrax
|
|
|
102
102
|
end
|
|
103
103
|
{
|
|
104
104
|
data: result,
|
|
105
|
-
recordsTotal: Bulkrax::Importer.count,
|
|
106
|
-
recordsFiltered:
|
|
105
|
+
recordsTotal: api_request? ? Bulkrax::Importer.count : Bulkrax::Importer.accessible_by(current_ability).count,
|
|
106
|
+
recordsFiltered: filtered_count
|
|
107
107
|
}
|
|
108
108
|
end
|
|
109
109
|
|
|
110
|
-
def format_exporters(exporters)
|
|
110
|
+
def format_exporters(exporters, filtered_count = Bulkrax::Exporter.accessible_by(current_ability).count)
|
|
111
111
|
result = exporters.map do |e|
|
|
112
112
|
{
|
|
113
113
|
name: view_context.link_to(e.name, view_context.exporter_path(e)),
|
|
@@ -119,8 +119,8 @@ module Bulkrax
|
|
|
119
119
|
end
|
|
120
120
|
{
|
|
121
121
|
data: result,
|
|
122
|
-
recordsTotal: Bulkrax::Exporter.count,
|
|
123
|
-
recordsFiltered:
|
|
122
|
+
recordsTotal: Bulkrax::Exporter.accessible_by(current_ability).count,
|
|
123
|
+
recordsFiltered: filtered_count
|
|
124
124
|
}
|
|
125
125
|
end
|
|
126
126
|
|
|
@@ -146,8 +146,10 @@ module Bulkrax
|
|
|
146
146
|
def entry_util_links(e, item)
|
|
147
147
|
links = []
|
|
148
148
|
links << view_context.link_to(view_context.raw('<span class="fa fa-info-circle"></span>'), view_context.item_entry_path(item, e))
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
if can?(:update, item)
|
|
150
|
+
links << "<a class='fa fa-repeat' data-toggle='modal' data-target='#bulkraxItemModal' data-entry-id='#{e.id}'></a>" if view_context.an_importer?(item)
|
|
151
|
+
links << view_context.link_to(view_context.raw('<span class="fa fa-trash"></span>'), view_context.item_entry_path(item, e), method: :delete, data: { confirm: 'This will delete the entry and any work associated with it. Are you sure?' })
|
|
152
|
+
end
|
|
151
153
|
links.join(" ")
|
|
152
154
|
end
|
|
153
155
|
|
|
@@ -166,16 +168,20 @@ module Bulkrax
|
|
|
166
168
|
def importer_util_links(i)
|
|
167
169
|
links = []
|
|
168
170
|
links << view_context.link_to(view_context.raw('<span class="fa fa-info-circle"></span>'), importer_path(i))
|
|
169
|
-
|
|
170
|
-
|
|
171
|
+
if can?(:update, i)
|
|
172
|
+
links << view_context.link_to(view_context.raw('<span class="fa fa-pencil"></span>'), edit_importer_path(i))
|
|
173
|
+
links << view_context.link_to(view_context.raw('<span class="fa fa-remove"></span>'), i, method: :delete, data: { confirm: 'Are you sure?' })
|
|
174
|
+
end
|
|
171
175
|
links.join(" ")
|
|
172
176
|
end
|
|
173
177
|
|
|
174
178
|
def exporter_util_links(i)
|
|
175
179
|
links = []
|
|
176
180
|
links << view_context.link_to(view_context.raw('<span class="fa fa-info-circle"></span>'), exporter_path(i))
|
|
177
|
-
|
|
178
|
-
|
|
181
|
+
if can?(:update, i)
|
|
182
|
+
links << view_context.link_to(view_context.raw('<span class="fa fa-pencil"></span>'), edit_exporter_path(i), data: { turbolinks: false })
|
|
183
|
+
links << view_context.link_to(view_context.raw('<span class="fa fa-remove"></span>'), i, method: :delete, data: { confirm: 'Are you sure?' })
|
|
184
|
+
end
|
|
179
185
|
links.join(" ")
|
|
180
186
|
end
|
|
181
187
|
|
|
@@ -168,8 +168,8 @@ module Bulkrax
|
|
|
168
168
|
end
|
|
169
169
|
|
|
170
170
|
def self.solr_name(field_name)
|
|
171
|
-
if defined?(Hyrax)
|
|
172
|
-
Hyrax.index_field_mapper.solr_name(field_name)
|
|
171
|
+
if defined?(Hyrax) && Hyrax.respond_to?(:config) && Hyrax.config.respond_to?(:index_field_mapper)
|
|
172
|
+
Hyrax.config.index_field_mapper.solr_name(field_name)
|
|
173
173
|
else
|
|
174
174
|
ActiveFedora.index_field_mapper.solr_name(field_name)
|
|
175
175
|
end
|