ddr-core 1.1.2 → 1.2.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/models/concerns/ddr/#search_builder_behavior.rb# +10 -0
- data/app/models/concerns/ddr/describable.rb +8 -12
- data/app/models/concerns/ddr/has_admin_metadata.rb +6 -0
- data/app/models/concerns/ddr/has_parent.rb +14 -2
- data/app/models/concerns/ddr/search_builder_behavior.rb~ +9 -0
- data/app/models/ddr/#admin_set.rb# +26 -0
- data/app/models/ddr/#auxiliary_resource_cache.rb# +34 -0
- data/app/models/ddr/auxiliary_resource.rb~ +13 -0
- data/app/models/ddr/cacheable_auxiliary_resource.rb~ +20 -0
- data/app/models/ddr/collection.rb +5 -4
- data/app/models/ddr/component.rb +8 -0
- data/app/models/ddr/resource.rb +4 -0
- data/config/locales/ddr-core.en.yml +2 -0
- data/lib/ddr/auth/#duke_person.rb# +9 -0
- data/lib/ddr/auth/ability_definitions/publication_ability_definitions.rb +7 -0
- data/lib/ddr/auth/ability_definitions/superuser_ability_definitions.rb +3 -0
- data/lib/ddr/auth/duke_directory.rb~ +7 -0
- data/lib/ddr/auth/effective_roles.rb +1 -1
- data/lib/ddr/auth/permissions.rb +14 -11
- data/lib/ddr/auth/role_based_access_controls_enforcement.rb +1 -1
- data/lib/ddr/auth/roles.rb +15 -3
- data/lib/ddr/auth/roles/role.rb +27 -24
- data/lib/ddr/auth/roles/role_types.rb +13 -6
- data/lib/ddr/core/version.rb +1 -1
- data/lib/ddr/index/csv_query_result.rb +27 -20
- data/lib/ddr/index/fields.rb +1 -0
- data/lib/ddr/vocab/asset.rb +4 -0
- data/lib/ddr/workflow.rb +1 -0
- metadata +15 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c58f60f94bc6a54ea670eb5a7a096e69221e5b8e6fce28191b939f283d4c3528
|
4
|
+
data.tar.gz: 170f607020dfabfa89c77c4a31b3daa10bc7d40bd06c251ff3e3d0a0372159e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ff5d87897742e3f736e3313a06145a6d378e168e72d6872effc563906370fe66865bf663027defe32041a45ab92910dab97e9d9a1ebd6d21bdf1d9b0b381b84
|
7
|
+
data.tar.gz: 48869cd2b81bd88378779ab319fb4a13407bc9060aa099b6b45d33469e8d6605af177aecff033b921f5588bca616f94e077ce75455d45ddba2a619fc7d0119a7
|
data/README.md
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
module Ddr
|
2
|
+
module SearchBuilderBehavior
|
3
|
+
|
4
|
+
def effective_role_filter(agents)
|
5
|
+
# https://lucene.apache.org/solr/guide/7_7/other-parsers.html#term-query-parser
|
6
|
+
"{!terms f=#{Ddr::Index::Fields::EFFECTIVE_ROLE} method=booleanQuery}#{agents.join(',')}"
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
end
|
@@ -15,6 +15,8 @@ module Ddr
|
|
15
15
|
term_names
|
16
16
|
end
|
17
17
|
|
18
|
+
# Dublin Core vocabulary comes from the rdf-vocab gem (https://github.com/ruby-rdf/rdf-vocab)
|
19
|
+
# DDR vocabulary is defined locally
|
18
20
|
def self.vocabularies
|
19
21
|
[RDF::Vocab::DC, Ddr::Vocab::DukeTerms].freeze
|
20
22
|
end
|
@@ -34,7 +36,11 @@ module Ddr
|
|
34
36
|
|
35
37
|
included do
|
36
38
|
Ddr::Describable.term_names.each do |term_name|
|
37
|
-
|
39
|
+
if term_name == :available # Intercept dcterms:available and set it to a single date so it can be used for embargoes
|
40
|
+
attribute term_name, Valkyrie::Types::DateTime.optional
|
41
|
+
else
|
42
|
+
attribute term_name, Valkyrie::Types::Set
|
43
|
+
end
|
38
44
|
end
|
39
45
|
end
|
40
46
|
|
@@ -53,7 +59,7 @@ module Ddr
|
|
53
59
|
arg = args.pop
|
54
60
|
terms = case arg.to_sym
|
55
61
|
when :empty
|
56
|
-
desc_metadata_terms.select { |t| values(t).empty? }
|
62
|
+
desc_metadata_terms.select { |t| values(t).nil? || values(t).empty? }
|
57
63
|
when :present
|
58
64
|
desc_metadata_terms.select { |t| values(t).present? }
|
59
65
|
when :defined_attributes
|
@@ -94,15 +100,5 @@ module Ddr
|
|
94
100
|
desc_metadata_terms.each { |t| set_desc_metadata_values(t, term_values_hash[t]) }
|
95
101
|
end
|
96
102
|
|
97
|
-
################
|
98
|
-
# I do not believe this method is needed any longer since I can't find any usage of it in ddr-models, ddr-batch,
|
99
|
-
# dul-hydra, ddr-public, or ddr-portals
|
100
|
-
################
|
101
|
-
# module ClassMethods
|
102
|
-
# def find_by_identifier(identifier)
|
103
|
-
# find(Ddr::Index::Fields::IDENTIFIER_ALL => identifier)
|
104
|
-
# end
|
105
|
-
# end
|
106
|
-
|
107
103
|
end
|
108
104
|
end
|
@@ -7,6 +7,7 @@ module Ddr
|
|
7
7
|
affiliation: Valkyrie::Types::Set,
|
8
8
|
aleph_id: Valkyrie::Types::Strict::String.optional,
|
9
9
|
aspace_id: Valkyrie::Types::Strict::String.optional,
|
10
|
+
contentdm_id: Valkyrie::Types::Strict::String.optional,
|
10
11
|
depositor: Valkyrie::Types::Strict::String.optional,
|
11
12
|
display_format: Valkyrie::Types::Strict::String.optional,
|
12
13
|
doi: Valkyrie::Types::Strict::String.optional,
|
@@ -54,6 +55,11 @@ module Ddr
|
|
54
55
|
workflow_state == Ddr::Workflow::UNPUBLISHED
|
55
56
|
end
|
56
57
|
|
58
|
+
# Usually won't be called directly. See `publishable?` on Resource and its derivatives
|
59
|
+
def nonpublishable?
|
60
|
+
workflow_state == Ddr::Workflow::NONPUBLISHABLE
|
61
|
+
end
|
62
|
+
|
57
63
|
def resource_roles
|
58
64
|
roles.select(&:in_resource_scope?)
|
59
65
|
end
|
@@ -7,12 +7,24 @@ module Ddr
|
|
7
7
|
attribute :parent_id, Valkyrie::Types::ID.optional
|
8
8
|
end
|
9
9
|
|
10
|
+
def has_parent?
|
11
|
+
parent_id.present?
|
12
|
+
end
|
13
|
+
|
10
14
|
def parent
|
11
|
-
Ddr.query_service.find_by(id: parent_id) if
|
15
|
+
Ddr.query_service.find_by(id: parent_id) if has_parent?
|
12
16
|
end
|
13
17
|
|
18
|
+
# Resources with parents (currently, Items and Components) are publishable only if they have not been marked
|
19
|
+
# nonpublishable and their parent is published
|
14
20
|
def publishable?
|
15
|
-
|
21
|
+
!nonpublishable? && parental_publication_guard
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def parental_publication_guard
|
27
|
+
parent.present? && parent.published?
|
16
28
|
end
|
17
29
|
|
18
30
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Ddr
|
2
|
+
class AdminSet < AuxiliaryResource
|
3
|
+
|
4
|
+
def self.call(obj)
|
5
|
+
find_by_code(obj.admin_set)
|
6
|
+
rescue ActiveResource::ResourceNotFound => e
|
7
|
+
raise Ddr::NotFoundError, e
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.find_by_code(code)
|
11
|
+
return unless code
|
12
|
+
new get(:find, code: code)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.keys
|
16
|
+
with_cache("keys") do
|
17
|
+
all.map(&:code)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
title
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'active_resource'
|
2
|
+
|
3
|
+
module Ddr
|
4
|
+
class AuxiliaryResourceCache < ActiveSupport::Cache::MemoryStore
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@_cache =
|
8
|
+
end
|
9
|
+
|
10
|
+
def with(key, &block)
|
11
|
+
begin
|
12
|
+
cache.set(key, block.call)
|
13
|
+
rescue ActiveResource::ServerError => e
|
14
|
+
if cache.key?(key)
|
15
|
+
Rails.logger.error(e)
|
16
|
+
cache.get(key)
|
17
|
+
else
|
18
|
+
raise
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def get(key)
|
26
|
+
@_cache[key]
|
27
|
+
end
|
28
|
+
|
29
|
+
def set(key, value)
|
30
|
+
@_cache[key] = value
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'active_resource'
|
2
|
+
|
3
|
+
module Ddr
|
4
|
+
#
|
5
|
+
# Abstract superclass for resources bound to ddr-aux API data
|
6
|
+
#
|
7
|
+
class AuxiliaryResource < ActiveResource::Base
|
8
|
+
|
9
|
+
# ActiveResource freezes `site` in subclasses
|
10
|
+
self.site = Ddr.ddr_aux_api_url
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Ddr
|
2
|
+
module CacheableAuxiliaryResource
|
3
|
+
|
4
|
+
def with_cache(key, &block)
|
5
|
+
block.call.tap { |value| cache.write(key, value) }
|
6
|
+
rescue ActiveResource::ServerError => e
|
7
|
+
if value = cache.fetch(key)
|
8
|
+
logger.error(e) if logger
|
9
|
+
value
|
10
|
+
else
|
11
|
+
raise
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def cache
|
16
|
+
@cache ||= ActiveSupport::Cache::MemoryStore.new
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -16,12 +16,13 @@ module Ddr
|
|
16
16
|
query.docs
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
# Collection resources are publishable unless they have been marked nonpublishable
|
20
|
+
def publishable?
|
21
|
+
!nonpublishable?
|
21
22
|
end
|
22
23
|
|
23
|
-
def
|
24
|
-
|
24
|
+
def targets
|
25
|
+
Ddr.query_service.find_inverse_references_by(resource: self, property: 'for_collection_id')
|
25
26
|
end
|
26
27
|
|
27
28
|
end
|
data/app/models/ddr/component.rb
CHANGED
data/app/models/ddr/resource.rb
CHANGED
@@ -90,6 +90,10 @@ module Ddr
|
|
90
90
|
send(f)&.file_identifier.present?
|
91
91
|
end
|
92
92
|
|
93
|
+
# By default, no resources are publishable. To enable publication of a particular class of resource, (1) include
|
94
|
+
# the `HasAdminMetadata` concern in the model class, which defines a `nonpublishable?` method which returns true
|
95
|
+
# if the workflow_state is "nonpublishable" and (2) override the `publishable?` method to provide the logic
|
96
|
+
# for determining if a particular resource is publishable.
|
93
97
|
def publishable?
|
94
98
|
false
|
95
99
|
end
|
@@ -2,6 +2,10 @@ module Ddr
|
|
2
2
|
module Auth
|
3
3
|
class PublicationAbilityDefinitions < AbilityDefinitions
|
4
4
|
|
5
|
+
# An object can't be published if it's already published or not publishable
|
6
|
+
# It can't be unpublished if it's already unpublished
|
7
|
+
# It can't be made nonpublishable if it's already published (must be unpublished
|
8
|
+
# first) or already nonpublishable
|
5
9
|
def call
|
6
10
|
cannot :publish, Ddr::Resource do |obj|
|
7
11
|
obj.published? || !obj.publishable?
|
@@ -9,6 +13,9 @@ module Ddr
|
|
9
13
|
cannot :unpublish, Ddr::Resource do |obj|
|
10
14
|
!obj.published?
|
11
15
|
end
|
16
|
+
cannot :make_nonpublishable, Ddr::Resource do |obj|
|
17
|
+
obj.published? || !obj.publishable?
|
18
|
+
end
|
12
19
|
end
|
13
20
|
|
14
21
|
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
module Ddr::Auth
|
2
2
|
class SuperuserAbilityDefinitions < AbilityDefinitions
|
3
3
|
|
4
|
+
# This bypasses all checks, including ones that look at whether an
|
5
|
+
# action is possible, not just allowed. So superusers may initiate
|
6
|
+
# actions which will fail.
|
4
7
|
def call
|
5
8
|
can :manage, :all
|
6
9
|
end
|
data/lib/ddr/auth/permissions.rb
CHANGED
@@ -1,18 +1,21 @@
|
|
1
1
|
module Ddr::Auth
|
2
2
|
class Permissions
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
4
|
+
DISCOVER = :discover
|
5
|
+
READ = :read
|
6
|
+
DOWNLOAD = :download
|
7
|
+
ADD_CHILDREN = :add_children
|
8
|
+
UPDATE = :update
|
9
|
+
REPLACE = :replace
|
10
|
+
ARRANGE = :arrange
|
11
|
+
PUBLISH = :publish
|
12
|
+
UNPUBLISH = :unpublish
|
13
|
+
MAKE_NONPUBLISHABLE = :make_nonpublishable
|
14
|
+
AUDIT = :audit
|
15
|
+
GRANT = :grant
|
14
16
|
|
15
|
-
ALL = [ READ, DOWNLOAD, ADD_CHILDREN, UPDATE,
|
17
|
+
ALL = [ DISCOVER, READ, DOWNLOAD, ADD_CHILDREN, UPDATE,
|
18
|
+
REPLACE, ARRANGE, PUBLISH, UNPUBLISH, MAKE_NONPUBLISHABLE, AUDIT, GRANT ]
|
16
19
|
|
17
20
|
end
|
18
21
|
end
|
data/lib/ddr/auth/roles.rb
CHANGED
@@ -10,18 +10,30 @@ module Ddr::Auth
|
|
10
10
|
|
11
11
|
RESOURCE_SCOPE = "resource".freeze
|
12
12
|
POLICY_SCOPE = "policy".freeze
|
13
|
-
SCOPES = [RESOURCE_SCOPE, POLICY_SCOPE].freeze
|
13
|
+
SCOPES = [ RESOURCE_SCOPE, POLICY_SCOPE ].freeze
|
14
|
+
|
15
|
+
ORDERED_ROLE_TYPES = [
|
16
|
+
CURATOR,
|
17
|
+
EDITOR,
|
18
|
+
METADATA_EDITOR,
|
19
|
+
CONTRIBUTOR,
|
20
|
+
DOWNLOADER,
|
21
|
+
VIEWER,
|
22
|
+
METADATA_VIEWER
|
23
|
+
]
|
14
24
|
|
15
25
|
class << self
|
16
|
-
|
17
26
|
def type_map
|
18
27
|
@type_map ||= role_types.map { |role_type| [role_type.to_s, role_type] }.to_h
|
19
28
|
end
|
20
29
|
|
21
30
|
def role_types
|
22
|
-
|
31
|
+
ORDERED_ROLE_TYPES
|
23
32
|
end
|
24
33
|
|
34
|
+
def titles
|
35
|
+
@titles ||= role_types.map(&:title)
|
36
|
+
end
|
25
37
|
end
|
26
38
|
|
27
39
|
end
|
data/lib/ddr/auth/roles/role.rb
CHANGED
@@ -8,35 +8,38 @@ module Ddr
|
|
8
8
|
|
9
9
|
DEFAULT_SCOPE = Roles::RESOURCE_SCOPE
|
10
10
|
|
11
|
-
ValidScope = Valkyrie::Types::
|
12
|
-
ValidRoleType = Valkyrie::Types::Strict::String.enum(*(Roles
|
11
|
+
ValidScope = Valkyrie::Types::Coercible::String.default(DEFAULT_SCOPE).enum(*(Roles::SCOPES))
|
12
|
+
ValidRoleType = Valkyrie::Types::Strict::String.enum(*(Roles.titles))
|
13
|
+
ValidAgent = Valkyrie::Types::Coercible::String.constrained(min_size: 1)
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
# @param args [Hash] the attributes
|
22
|
-
# @return [Role] the role
|
23
|
-
# @example
|
24
|
-
# Role.build type: "Curator", agent: "bob", scope: "resource"
|
25
|
-
def build(args={})
|
26
|
-
new.tap do |role|
|
27
|
-
args[:role_type] ||= args.delete(:type)
|
28
|
-
args[:agent] ||= nil # Triggers a constraint error
|
29
|
-
args[:agent] = args[:agent].to_s # Coerce Ddr::Auth:Group to string
|
30
|
-
|
31
|
-
args.each do |attr, val|
|
32
|
-
role.set_value(attr, val)
|
33
|
-
end
|
15
|
+
# Symbolize input keys
|
16
|
+
# https://dry-rb.org/gems/dry-struct/1.0/recipes/#symbolize-input-keys
|
17
|
+
transform_keys do |key|
|
18
|
+
_k = key.to_sym
|
19
|
+
# For backwards compat allow :type as an alias for :role_type
|
20
|
+
_k == :type ? :role_type : _k
|
21
|
+
end
|
34
22
|
|
35
|
-
|
23
|
+
# Make nils use default values
|
24
|
+
# https://dry-rb.org/gems/dry-struct/1.0/recipes/#resolving-default-values-on-code-nil-code
|
25
|
+
transform_types do |type|
|
26
|
+
if type.default?
|
27
|
+
type.constructor do |value|
|
28
|
+
value.nil? ? Dry::Types::Undefined : value
|
36
29
|
end
|
30
|
+
else
|
31
|
+
type
|
37
32
|
end
|
33
|
+
end
|
38
34
|
|
39
|
-
|
35
|
+
attribute :agent, ValidAgent
|
36
|
+
attribute :role_type, ValidRoleType
|
37
|
+
attribute :scope, ValidScope
|
38
|
+
|
39
|
+
# DEPRECATED: Use constructor
|
40
|
+
def self.build(args={})
|
41
|
+
new(args)
|
42
|
+
end
|
40
43
|
|
41
44
|
# Roles are considered equal (==) if they
|
42
45
|
# are of the same type and have the same agent and scope.
|
@@ -14,36 +14,43 @@ module Ddr
|
|
14
14
|
"Editor",
|
15
15
|
"The Editor role conveys reponsibility for managing the content, " \
|
16
16
|
"description and structural arrangement of a resource.",
|
17
|
-
[ Permissions::
|
18
|
-
Permissions::
|
17
|
+
[ Permissions::DISCOVER, Permissions::READ, Permissions::DOWNLOAD,
|
18
|
+
Permissions::ADD_CHILDREN, Permissions::UPDATE,
|
19
|
+
Permissions::REPLACE, Permissions::ARRANGE ]
|
19
20
|
)
|
20
21
|
|
21
22
|
METADATA_EDITOR = RoleType.new(
|
22
23
|
"MetadataEditor",
|
23
24
|
"The Metadata Editor role conveys responsibility for " \
|
24
25
|
"managing the description of a resource.",
|
25
|
-
[ Permissions::READ, Permissions::DOWNLOAD, Permissions::UPDATE ]
|
26
|
+
[ Permissions::DISCOVER, Permissions::READ, Permissions::DOWNLOAD, Permissions::UPDATE ]
|
26
27
|
)
|
27
28
|
|
28
29
|
CONTRIBUTOR = RoleType.new(
|
29
30
|
"Contributor",
|
30
31
|
"The Contributor role conveys responsibility for adding related " \
|
31
32
|
"resources to a resource, such as works to a collection.",
|
32
|
-
[ Permissions::READ, Permissions::ADD_CHILDREN ]
|
33
|
+
[ Permissions::DISCOVER, Permissions::READ, Permissions::ADD_CHILDREN ]
|
33
34
|
)
|
34
35
|
|
35
36
|
DOWNLOADER = RoleType.new(
|
36
37
|
"Downloader",
|
37
38
|
"The Downloader role conveys access to the \"master\" file " \
|
38
39
|
"(original content bitstream) of a resource.",
|
39
|
-
[ Permissions::READ, Permissions::DOWNLOAD ]
|
40
|
+
[ Permissions::DISCOVER, Permissions::READ, Permissions::DOWNLOAD ]
|
40
41
|
)
|
41
42
|
|
42
43
|
VIEWER = RoleType.new(
|
43
44
|
"Viewer",
|
44
45
|
"The Viewer role conveys access to the description and \"access\" " \
|
45
46
|
"files (e.g., derivative bitstreams) of a resource.",
|
46
|
-
[ Permissions::READ ]
|
47
|
+
[ Permissions::DISCOVER, Permissions::READ ]
|
48
|
+
)
|
49
|
+
|
50
|
+
METADATA_VIEWER = RoleType.new(
|
51
|
+
"MetadataViewer",
|
52
|
+
"The MetadataViewer role coveys access to the description of a resource.",
|
53
|
+
[ Permissions::DISCOVER ]
|
47
54
|
)
|
48
55
|
|
49
56
|
end
|
data/lib/ddr/core/version.rb
CHANGED
@@ -6,8 +6,35 @@ module Ddr::Index
|
|
6
6
|
MAX_ROWS = 10**8 # Just set to a really high number :)
|
7
7
|
CSV_MV_SEPARATOR = ";"
|
8
8
|
|
9
|
+
DEFAULT_CSV_OPTIONS = {
|
10
|
+
headers: :first_row,
|
11
|
+
return_headers: false,
|
12
|
+
write_headers: true,
|
13
|
+
converters: [
|
14
|
+
# convert semicolons
|
15
|
+
lambda { |f| f.gsub(/\\#{CSV_MV_SEPARATOR}/, CSV_MV_SEPARATOR) rescue f },
|
16
|
+
# convert escaped newlines
|
17
|
+
lambda { |f| f.gsub(/\\r/, "\r").gsub(/\\n/, "\n") rescue f }
|
18
|
+
],
|
19
|
+
}.freeze
|
20
|
+
|
9
21
|
delegate :headers, :to_s, :to_csv, to: :table
|
10
22
|
|
23
|
+
attr_reader :csv_opts
|
24
|
+
|
25
|
+
#
|
26
|
+
# See Ruby docs on CSV::new for details on available keys
|
27
|
+
# and values for the optional `csv_options' Hash parameter.
|
28
|
+
#
|
29
|
+
# N.B. If you want to *add* a converter and retain the
|
30
|
+
# default converters, append DEFAULT_CSV_OPTIONS[:converters]
|
31
|
+
# to your Array of converters.
|
32
|
+
#
|
33
|
+
def initialize(query, csv_opts: {})
|
34
|
+
super(query)
|
35
|
+
@csv_opts = DEFAULT_CSV_OPTIONS.merge(csv_opts)
|
36
|
+
end
|
37
|
+
|
11
38
|
def delete_empty_columns!
|
12
39
|
table.by_col!.delete_if { |c, vals| vals.all?(&:nil?) }
|
13
40
|
end
|
@@ -24,14 +51,6 @@ module Ddr::Index
|
|
24
51
|
@table ||= CSV.parse(data, csv_opts)
|
25
52
|
end
|
26
53
|
|
27
|
-
def csv_opts
|
28
|
-
{ headers: csv_headers,
|
29
|
-
converters: [convert_semicolons, convert_escaped_newlines],
|
30
|
-
return_headers: false,
|
31
|
-
write_headers: true,
|
32
|
-
}
|
33
|
-
end
|
34
|
-
|
35
54
|
def solr_csv_opts
|
36
55
|
{ "csv.mv.separator" => CSV_MV_SEPARATOR,
|
37
56
|
"csv.header" => solr_csv_header?,
|
@@ -44,10 +63,6 @@ module Ddr::Index
|
|
44
63
|
query.fields.map { |f| f.respond_to?(:heading) ? f.heading : f.to_s }
|
45
64
|
end
|
46
65
|
|
47
|
-
def csv_headers
|
48
|
-
:first_row
|
49
|
-
end
|
50
|
-
|
51
66
|
def solr_csv_header?
|
52
67
|
query.fields.empty?
|
53
68
|
end
|
@@ -72,13 +87,5 @@ module Ddr::Index
|
|
72
87
|
Connection.get("select", params: solr_csv_params)
|
73
88
|
end
|
74
89
|
|
75
|
-
def convert_semicolons
|
76
|
-
lambda { |f| f.gsub(/\\#{CSV_MV_SEPARATOR}/, CSV_MV_SEPARATOR) rescue f }
|
77
|
-
end
|
78
|
-
|
79
|
-
def convert_escaped_newlines
|
80
|
-
lambda { |f| f.gsub(/\\r/, "\r").gsub(/\\n/, "\n") rescue f }
|
81
|
-
end
|
82
|
-
|
83
90
|
end
|
84
91
|
end
|
data/lib/ddr/index/fields.rb
CHANGED
@@ -29,6 +29,7 @@ module Ddr::Index
|
|
29
29
|
CONTENT_CREATE_DATE = Field.new :content_create_date, :stored_sortable, type: :date
|
30
30
|
CONTENT_SIZE = Field.new :content_size, solr_name: "content_size_lsi"
|
31
31
|
CONTENT_SIZE_HUMAN = Field.new :content_size_human, :symbol
|
32
|
+
CONTENTDM_ID = Field.new :contentdm_id, :stored_sortable
|
32
33
|
CONTRIBUTOR_FACET = Field.new :contributor_facet, :facetable
|
33
34
|
CREATOR_FACET = Field.new :creator_facet, :facetable
|
34
35
|
DATE_FACET = Field.new :date_facet, :facetable
|
data/lib/ddr/vocab/asset.rb
CHANGED
@@ -47,5 +47,9 @@ module Ddr::Vocab
|
|
47
47
|
label: "Nested Path",
|
48
48
|
comment: "The nested/tree path to the object to be reflected in structural metadata."
|
49
49
|
|
50
|
+
property "contentdmId",
|
51
|
+
label: "CONTENTdm ID"
|
52
|
+
comment: "The CONTENTdm reference corresponding to the object."
|
53
|
+
|
50
54
|
end
|
51
55
|
end
|
data/lib/ddr/workflow.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ddr-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jim Coble
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2020-
|
14
|
+
date: 2020-06-10 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: activeresource
|
@@ -89,14 +89,14 @@ dependencies:
|
|
89
89
|
requirements:
|
90
90
|
- - "~>"
|
91
91
|
- !ruby/object:Gem::Version
|
92
|
-
version: 2.
|
92
|
+
version: 2.1.0
|
93
93
|
type: :runtime
|
94
94
|
prerelease: false
|
95
95
|
version_requirements: !ruby/object:Gem::Requirement
|
96
96
|
requirements:
|
97
97
|
- - "~>"
|
98
98
|
- !ruby/object:Gem::Version
|
99
|
-
version: 2.
|
99
|
+
version: 2.1.0
|
100
100
|
- !ruby/object:Gem::Dependency
|
101
101
|
name: grouper-rest-client
|
102
102
|
requirement: !ruby/object:Gem::Requirement
|
@@ -306,6 +306,7 @@ files:
|
|
306
306
|
- app/assets/config/ddr_core_manifest.js
|
307
307
|
- app/controllers/users/omniauth_callbacks_controller.rb
|
308
308
|
- app/controllers/users/sessions_controller.rb
|
309
|
+
- app/models/concerns/ddr/#search_builder_behavior.rb#
|
309
310
|
- app/models/concerns/ddr/captionable.rb
|
310
311
|
- app/models/concerns/ddr/describable.rb
|
311
312
|
- app/models/concerns/ddr/governable.rb
|
@@ -319,12 +320,17 @@ files:
|
|
319
320
|
- app/models/concerns/ddr/has_parent.rb
|
320
321
|
- app/models/concerns/ddr/has_struct_metadata.rb
|
321
322
|
- app/models/concerns/ddr/has_thumbnail.rb
|
323
|
+
- app/models/concerns/ddr/search_builder_behavior.rb~
|
322
324
|
- app/models/concerns/ddr/solr_document_behavior.rb
|
323
325
|
- app/models/concerns/ddr/streamable.rb
|
326
|
+
- app/models/ddr/#admin_set.rb#
|
327
|
+
- app/models/ddr/#auxiliary_resource_cache.rb#
|
324
328
|
- app/models/ddr/admin_set.rb
|
325
329
|
- app/models/ddr/alert.rb
|
326
330
|
- app/models/ddr/attachment.rb
|
327
331
|
- app/models/ddr/auxiliary_resource.rb
|
332
|
+
- app/models/ddr/auxiliary_resource.rb~
|
333
|
+
- app/models/ddr/cacheable_auxiliary_resource.rb~
|
328
334
|
- app/models/ddr/collection.rb
|
329
335
|
- app/models/ddr/component.rb
|
330
336
|
- app/models/ddr/contact.rb
|
@@ -345,6 +351,7 @@ files:
|
|
345
351
|
- db/migrate/20200207194453_add_default_to_lock_version.rb
|
346
352
|
- lib/ddr-core.rb
|
347
353
|
- lib/ddr/auth.rb
|
354
|
+
- lib/ddr/auth/#duke_person.rb#
|
348
355
|
- lib/ddr/auth/ability.rb
|
349
356
|
- lib/ddr/auth/ability_definitions.rb
|
350
357
|
- lib/ddr/auth/ability_definitions/admin_set_ability_definitions.rb
|
@@ -365,6 +372,7 @@ files:
|
|
365
372
|
- lib/ddr/auth/auth_context.rb
|
366
373
|
- lib/ddr/auth/auth_context_factory.rb
|
367
374
|
- lib/ddr/auth/detached_auth_context.rb
|
375
|
+
- lib/ddr/auth/duke_directory.rb~
|
368
376
|
- lib/ddr/auth/dynamic_groups.rb
|
369
377
|
- lib/ddr/auth/effective_permissions.rb
|
370
378
|
- lib/ddr/auth/effective_roles.rb
|
@@ -450,11 +458,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
450
458
|
version: '0'
|
451
459
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
452
460
|
requirements:
|
453
|
-
- - "
|
461
|
+
- - ">"
|
454
462
|
- !ruby/object:Gem::Version
|
455
|
-
version:
|
463
|
+
version: 1.3.1
|
456
464
|
requirements: []
|
457
|
-
rubygems_version: 3.0.
|
465
|
+
rubygems_version: 3.0.8
|
458
466
|
signing_key:
|
459
467
|
specification_version: 4
|
460
468
|
summary: Models used in the Duke Digital Repository
|