ddr-core 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +12 -0
  3. data/README.md +27 -0
  4. data/Rakefile +30 -0
  5. data/app/assets/config/ddr_core_manifest.js +0 -0
  6. data/app/controllers/users/omniauth_callbacks_controller.rb +11 -0
  7. data/app/controllers/users/sessions_controller.rb +15 -0
  8. data/app/models/concerns/ddr/captionable.rb +25 -0
  9. data/app/models/concerns/ddr/describable.rb +108 -0
  10. data/app/models/concerns/ddr/governable.rb +25 -0
  11. data/app/models/concerns/ddr/has_admin_metadata.rb +141 -0
  12. data/app/models/concerns/ddr/has_attachments.rb +10 -0
  13. data/app/models/concerns/ddr/has_children.rb +10 -0
  14. data/app/models/concerns/ddr/has_content.rb +132 -0
  15. data/app/models/concerns/ddr/has_extracted_text.rb +10 -0
  16. data/app/models/concerns/ddr/has_intermediate_file.rb +25 -0
  17. data/app/models/concerns/ddr/has_multires_image.rb +14 -0
  18. data/app/models/concerns/ddr/has_parent.rb +18 -0
  19. data/app/models/concerns/ddr/has_struct_metadata.rb +21 -0
  20. data/app/models/concerns/ddr/has_thumbnail.rb +33 -0
  21. data/app/models/concerns/ddr/solr_document_behavior.rb +429 -0
  22. data/app/models/concerns/ddr/streamable.rb +25 -0
  23. data/app/models/ddr/admin_set.rb +28 -0
  24. data/app/models/ddr/attachment.rb +14 -0
  25. data/app/models/ddr/collection.rb +28 -0
  26. data/app/models/ddr/component.rb +31 -0
  27. data/app/models/ddr/contact.rb +23 -0
  28. data/app/models/ddr/digest.rb +8 -0
  29. data/app/models/ddr/file.rb +40 -0
  30. data/app/models/ddr/item.rb +36 -0
  31. data/app/models/ddr/language.rb +31 -0
  32. data/app/models/ddr/media_type.rb +22 -0
  33. data/app/models/ddr/resource.rb +94 -0
  34. data/app/models/ddr/rights_statement.rb +25 -0
  35. data/app/models/ddr/target.rb +17 -0
  36. data/config/initializers/devise.rb +262 -0
  37. data/config/locales/ddr-core.en.yml +85 -0
  38. data/config/routes.rb +3 -0
  39. data/db/migrate/20141104181418_create_users.rb +34 -0
  40. data/db/migrate/20141107124012_add_columns_to_user.rb +46 -0
  41. data/lib/ddr-core.rb +1 -0
  42. data/lib/ddr/auth.rb +80 -0
  43. data/lib/ddr/auth/ability.rb +18 -0
  44. data/lib/ddr/auth/ability_definitions.rb +26 -0
  45. data/lib/ddr/auth/ability_definitions/admin_set_ability_definitions.rb +9 -0
  46. data/lib/ddr/auth/ability_definitions/alias_ability_definitions.rb +23 -0
  47. data/lib/ddr/auth/ability_definitions/attachment_ability_definitions.rb +13 -0
  48. data/lib/ddr/auth/ability_definitions/collection_ability_definitions.rb +28 -0
  49. data/lib/ddr/auth/ability_definitions/component_ability_definitions.rb +13 -0
  50. data/lib/ddr/auth/ability_definitions/item_ability_definitions.rb +13 -0
  51. data/lib/ddr/auth/ability_definitions/lock_ability_definitions.rb +13 -0
  52. data/lib/ddr/auth/ability_definitions/publication_ability_definitions.rb +16 -0
  53. data/lib/ddr/auth/ability_definitions/role_based_ability_definitions.rb +39 -0
  54. data/lib/ddr/auth/ability_definitions/superuser_ability_definitions.rb +9 -0
  55. data/lib/ddr/auth/ability_factory.rb +10 -0
  56. data/lib/ddr/auth/abstract_ability.rb +48 -0
  57. data/lib/ddr/auth/affiliation.rb +14 -0
  58. data/lib/ddr/auth/affiliation_groups.rb +20 -0
  59. data/lib/ddr/auth/anonymous_ability.rb +7 -0
  60. data/lib/ddr/auth/auth_context.rb +109 -0
  61. data/lib/ddr/auth/auth_context_factory.rb +13 -0
  62. data/lib/ddr/auth/detached_auth_context.rb +19 -0
  63. data/lib/ddr/auth/dynamic_groups.rb +13 -0
  64. data/lib/ddr/auth/effective_permissions.rb +12 -0
  65. data/lib/ddr/auth/effective_roles.rb +9 -0
  66. data/lib/ddr/auth/failure_app.rb +16 -0
  67. data/lib/ddr/auth/group.rb +40 -0
  68. data/lib/ddr/auth/grouper_gateway.rb +70 -0
  69. data/lib/ddr/auth/groups.rb +32 -0
  70. data/lib/ddr/auth/ldap_gateway.rb +74 -0
  71. data/lib/ddr/auth/permissions.rb +18 -0
  72. data/lib/ddr/auth/remote_groups.rb +14 -0
  73. data/lib/ddr/auth/role_based_access_controls_enforcement.rb +56 -0
  74. data/lib/ddr/auth/roles.rb +28 -0
  75. data/lib/ddr/auth/roles/role.rb +121 -0
  76. data/lib/ddr/auth/roles/role_type.rb +23 -0
  77. data/lib/ddr/auth/roles/role_types.rb +52 -0
  78. data/lib/ddr/auth/superuser_ability.rb +7 -0
  79. data/lib/ddr/auth/test_helpers.rb +22 -0
  80. data/lib/ddr/auth/user.rb +54 -0
  81. data/lib/ddr/auth/web_auth_context.rb +29 -0
  82. data/lib/ddr/core.rb +110 -0
  83. data/lib/ddr/core/engine.rb +8 -0
  84. data/lib/ddr/core/version.rb +5 -0
  85. data/lib/ddr/error.rb +16 -0
  86. data/lib/ddr/files.rb +13 -0
  87. data/lib/ddr/fits.rb +189 -0
  88. data/lib/ddr/index.rb +29 -0
  89. data/lib/ddr/index/abstract_query_result.rb +22 -0
  90. data/lib/ddr/index/connection.rb +38 -0
  91. data/lib/ddr/index/csv_query_result.rb +84 -0
  92. data/lib/ddr/index/document_builder.rb +9 -0
  93. data/lib/ddr/index/field.rb +35 -0
  94. data/lib/ddr/index/field_attribute.rb +22 -0
  95. data/lib/ddr/index/fields.rb +154 -0
  96. data/lib/ddr/index/filter.rb +139 -0
  97. data/lib/ddr/index/query.rb +82 -0
  98. data/lib/ddr/index/query_builder.rb +185 -0
  99. data/lib/ddr/index/query_clause.rb +112 -0
  100. data/lib/ddr/index/query_params.rb +40 -0
  101. data/lib/ddr/index/query_result.rb +102 -0
  102. data/lib/ddr/index/response.rb +30 -0
  103. data/lib/ddr/index/sort_order.rb +28 -0
  104. data/lib/ddr/index/unique_key_field.rb +12 -0
  105. data/lib/ddr/managers.rb +9 -0
  106. data/lib/ddr/managers/manager.rb +13 -0
  107. data/lib/ddr/managers/technical_metadata_manager.rb +141 -0
  108. data/lib/ddr/structure.rb +188 -0
  109. data/lib/ddr/structures/agent.rb +49 -0
  110. data/lib/ddr/structures/component_type_term.rb +29 -0
  111. data/lib/ddr/structures/div.rb +64 -0
  112. data/lib/ddr/structures/f_locat.rb +54 -0
  113. data/lib/ddr/structures/file.rb +52 -0
  114. data/lib/ddr/structures/file_grp.rb +35 -0
  115. data/lib/ddr/structures/file_sec.rb +22 -0
  116. data/lib/ddr/structures/fptr.rb +31 -0
  117. data/lib/ddr/structures/mets_hdr.rb +37 -0
  118. data/lib/ddr/structures/mptr.rb +49 -0
  119. data/lib/ddr/structures/struct_map.rb +40 -0
  120. data/lib/ddr/utils.rb +185 -0
  121. data/lib/ddr/vocab.rb +22 -0
  122. data/lib/ddr/vocab/asset.rb +51 -0
  123. data/lib/ddr/vocab/contact.rb +9 -0
  124. data/lib/ddr/vocab/display.rb +9 -0
  125. data/lib/ddr/vocab/duke_terms.rb +13 -0
  126. data/lib/ddr/vocab/rdf_vocabulary_parser.rb +43 -0
  127. data/lib/ddr/vocab/roles.rb +25 -0
  128. data/lib/ddr/vocab/sources/duketerms.rdf +870 -0
  129. data/lib/ddr/vocab/vocabulary.rb +37 -0
  130. data/lib/ddr/workflow.rb +8 -0
  131. data/lib/tasks/ddr/core_tasks.rake +4 -0
  132. metadata +428 -0
@@ -0,0 +1,85 @@
1
+ en:
2
+ ddr:
3
+ core:
4
+ errors:
5
+ incorrect_resource_class: "%{subject} must be a %{resource_class}"
6
+ index:
7
+ fields:
8
+ aleph_id:
9
+ label: "Aleph ID"
10
+ aspace_id:
11
+ label: "ArchivesSpace ID"
12
+ common_model_name:
13
+ label: "Common Model Name"
14
+ doi:
15
+ label: DOI
16
+ ead_id:
17
+ label: "EAD ID"
18
+ id:
19
+ label: ID
20
+ heading: id
21
+ local_id:
22
+ label: "Local ID"
23
+ permanent_id:
24
+ label: "Permanent ID"
25
+ permanent_url:
26
+ label: "Permanent URL"
27
+ resource_model:
28
+ label: Model
29
+ heading: model
30
+ streamable_media_url:
31
+ label: "Streamable Media URL"
32
+ created_at:
33
+ label: "Creation Date"
34
+ heading: creation_date
35
+ updated_at:
36
+ label: "Modification Date"
37
+ heading: modification_date
38
+ techmd_color_space:
39
+ label: "Color Space"
40
+ heading: color_space
41
+ techmd_creating_application:
42
+ label: "Creating Application"
43
+ heading: creating_application
44
+ techmd_creation_time:
45
+ label: "Creation Time"
46
+ heading: creation_time
47
+ techmd_file_size:
48
+ label: "File Size"
49
+ heading: "file_size"
50
+ techmd_fits_version:
51
+ label: "FITS Version"
52
+ heading: fits_version
53
+ techmd_fits_datetime:
54
+ label: "FITS Run At"
55
+ heading: fits_datetime
56
+ techmd_format_label:
57
+ label: "Format Label"
58
+ heading: format_label
59
+ techmd_format_version:
60
+ label: "Format Version"
61
+ heading: format_version
62
+ techmd_image_height:
63
+ label: "Image Height"
64
+ heading: image_height
65
+ techmd_image_width:
66
+ label: "Image Width"
67
+ heading: image_width
68
+ techmd_md5:
69
+ label: MD5
70
+ heading: md5
71
+ techmd_media_type:
72
+ label: "Media Type"
73
+ heading: media_type
74
+ techmd_modification_time:
75
+ label: "Modification Time"
76
+ heading: modification_time
77
+ techmd_pronom_identifier:
78
+ label: "PRONOM Unique ID"
79
+ heading: "pronom_uid"
80
+ techmd_valid:
81
+ label: Valid
82
+ heading: valid
83
+ techmd_well_formed:
84
+ label: "Well-formed"
85
+ heading: well_formed
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks", sessions: "users/sessions" }
3
+ end
@@ -0,0 +1,34 @@
1
+ class CreateUsers < ActiveRecord::Migration[4.2]
2
+ def up
3
+ unless table_exists?("users")
4
+ create_table "users" do |t|
5
+ t.string "email", default: "", null: false
6
+ t.string "encrypted_password", default: "", null: false
7
+ t.string "reset_password_token"
8
+ t.datetime "reset_password_sent_at"
9
+ t.datetime "remember_created_at"
10
+ t.integer "sign_in_count", default: 0
11
+ t.datetime "current_sign_in_at"
12
+ t.datetime "last_sign_in_at"
13
+ t.string "current_sign_in_ip"
14
+ t.string "last_sign_in_ip"
15
+ t.datetime "created_at", null: false
16
+ t.datetime "updated_at", null: false
17
+ t.string "username", default: "", null: false
18
+ t.string "first_name"
19
+ t.string "middle_name"
20
+ t.string "nickname"
21
+ t.string "last_name"
22
+ t.string "display_name"
23
+ end
24
+
25
+ add_index "users", ["email"], name: "index_users_on_email"
26
+ add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
27
+ add_index "users", ["username"], name: "index_users_on_username", unique: true
28
+ end
29
+ end
30
+
31
+ def down
32
+ raise ActiveRecord::IrreversibleMigration
33
+ end
34
+ end
@@ -0,0 +1,46 @@
1
+ class AddColumnsToUser < ActiveRecord::Migration[4.2]
2
+ def up
3
+ if table_exists?("users")
4
+ unless column_exists?("users", "username")
5
+ add_column "users", "username", :string, default: "", null: false
6
+ end
7
+ unless column_exists?("users", "first_name")
8
+ add_column "users", "first_name", :string
9
+ end
10
+ unless column_exists?("users", "middle_name")
11
+ add_column "users", "middle_name", :string
12
+ end
13
+ unless column_exists?("users", "nickname")
14
+ add_column "users", "nickname", :string
15
+ end
16
+ unless column_exists?("users", "last_name")
17
+ add_column "users", "last_name", :string
18
+ end
19
+ unless column_exists?("users", "display_name")
20
+ add_column "users", "display_name", :string
21
+ end
22
+
23
+ # If the email index exists and is set such that email must be unique (which is the initial
24
+ # setting typically set by Devise(?)), remove and we'll re-add it as non-unique below.
25
+ if index_exists?("users", ["email"])
26
+ if index_exists?("users", ["email"], unique: true)
27
+ remove_index "users", ["email"]
28
+ end
29
+ end
30
+
31
+ # Either the email index didn't exist when we started or, more likely, we removed above
32
+ # because it existed but required email to be unique.
33
+ unless index_exists?("users", ["email"])
34
+ add_index "users", ["email"], name: "index_users_on_email"
35
+ end
36
+
37
+ unless index_exists?("users", ["username"])
38
+ add_index "users", ["username"], name: "index_users_on_username", unique: true
39
+ end
40
+ end
41
+ end
42
+
43
+ def down
44
+ raise ActiveRecord::IrreversibleMigration
45
+ end
46
+ end
@@ -0,0 +1 @@
1
+ require 'ddr/core'
@@ -0,0 +1,80 @@
1
+ module Ddr
2
+ module Auth
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :Ability
6
+ autoload :AbilityDefinitions
7
+ autoload :AbilityFactory
8
+ autoload :AbstractAbility
9
+ autoload :Affiliation
10
+ autoload :AffiliationGroups
11
+ autoload :AnonymousAbility
12
+ autoload :AuthContext
13
+ autoload :AuthContextFactory
14
+ autoload :DetachedAuthContext
15
+ autoload :DynamicGroups
16
+ autoload :EffectivePermissions
17
+ autoload :EffectiveRoles
18
+ autoload :FailureApp
19
+ autoload :Group
20
+ autoload :GrouperGateway
21
+ autoload :Groups
22
+ autoload :LdapGateway
23
+ autoload :Permissions
24
+ autoload :RemoteGroups
25
+ autoload :RoleBasedAccessControlsEnforcement
26
+ autoload :Roles
27
+ autoload :SuperuserAbility
28
+ autoload :User
29
+ autoload :WebAuthContext
30
+
31
+ autoload_under 'ability_definitions' do
32
+ autoload :AdminSetAbilityDefinitions
33
+ autoload :AliasAbilityDefinitions
34
+ autoload :AttachmentAbilityDefinitions
35
+ autoload :CollectionAbilityDefinitions
36
+ autoload :ComponentAbilityDefinitions
37
+ autoload :ItemAbilityDefinitions
38
+ autoload :PublicationAbilityDefinitions
39
+ autoload :LockAbilityDefinitions
40
+ autoload :RoleBasedAbilityDefinitions
41
+ autoload :SuperuserAbilityDefinitions
42
+ end
43
+
44
+ # Name of group whose members are authorized to act as superuser
45
+ mattr_accessor :superuser_group
46
+
47
+ # Name of group whose members are authorized to create Collections
48
+ mattr_accessor :collection_creators_group
49
+
50
+ # Name of group whose members are authorized to act as a metadata manager
51
+ mattr_accessor :metadata_managers_group
52
+
53
+ # Whether to require Shibboleth authentication
54
+ mattr_accessor :require_shib_user_authn do
55
+ false
56
+ end
57
+
58
+ # Grouper gateway implementation
59
+ mattr_accessor :grouper_gateway do
60
+ GrouperGateway
61
+ end
62
+
63
+ # LDAP gateway implementation
64
+ mattr_accessor :ldap_gateway do
65
+ LdapGateway
66
+ end
67
+
68
+ mattr_accessor :default_ability do
69
+ "::Ability"
70
+ end
71
+
72
+ def self.repository_group_filter
73
+ if filter = ENV["REPOSITORY_GROUP_FILTER"]
74
+ return filter
75
+ end
76
+ raise Ddr::Error, "The \"REPOSITORY_GROUP_FILTER\" environment variable is not set."
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,18 @@
1
+ module Ddr
2
+ module Auth
3
+ class Ability < AbstractAbility
4
+
5
+ self.ability_definitions = [ AliasAbilityDefinitions,
6
+ CollectionAbilityDefinitions,
7
+ ItemAbilityDefinitions,
8
+ ComponentAbilityDefinitions,
9
+ AttachmentAbilityDefinitions,
10
+ RoleBasedAbilityDefinitions,
11
+ PublicationAbilityDefinitions,
12
+ LockAbilityDefinitions,
13
+ AdminSetAbilityDefinitions,
14
+ ]
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ require "delegate"
2
+
3
+ module Ddr
4
+ module Auth
5
+ #
6
+ # A class which applies ability definitions to the delegated ability class
7
+ # when `#call` is invoked.
8
+ #
9
+ # @abstract
10
+ #
11
+ class AbilityDefinitions < SimpleDelegator
12
+
13
+ # Applies ability definitions to the ability and return it
14
+ def self.call(ability)
15
+ new(ability).call
16
+ ability
17
+ end
18
+
19
+ # Applies abilities definitions with `can` and `cannot`.
20
+ def call
21
+ raise NotImplementedError, "Subclasses must implement `#call`."
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ module Ddr::Auth
2
+ class AdminSetAbilityDefinitions < AbilityDefinitions
3
+
4
+ def call
5
+ can :export, Ddr::AdminSet if metadata_manager?
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ module Ddr
2
+ module Auth
3
+ class AliasAbilityDefinitions < AbilityDefinitions
4
+
5
+ FILE_REQUIRES_DOWNLOAD = %i( content extracted_text )
6
+ DEFAULT_FILE_PERMISSION = :read
7
+
8
+ DOWNLOAD_ALIASES = Ddr::Resource::FILE_FIELDS.each_with_object({}) do |field, memo|
9
+ action = [ :download, field ].join('_').to_sym # e.g., :download_content
10
+ memo[action] = FILE_REQUIRES_DOWNLOAD.include?(field) ? :download : DEFAULT_FILE_PERMISSION
11
+ end
12
+
13
+ def call
14
+ alias_action :upload, to: :replace
15
+ alias_action :add_attachment, to: :add_children
16
+ DOWNLOAD_ALIASES.each do |action, permission|
17
+ alias_action action, to: permission
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ module Ddr
2
+ module Auth
3
+ class AttachmentAbilityDefinitions < AbilityDefinitions
4
+
5
+ def call
6
+ can :create, Ddr::Attachment do |obj|
7
+ obj.attached_to.present? && can?(:add_attachment, obj.attached_to)
8
+ end
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,28 @@
1
+ module Ddr
2
+ module Auth
3
+ class CollectionAbilityDefinitions < AbilityDefinitions
4
+
5
+ def call
6
+ if member_of? Ddr::Auth.collection_creators_group
7
+ can :create, Ddr::Collection
8
+ end
9
+ can :export, Ddr::Collection do |obj|
10
+ has_policy_permission?(obj, Permissions::READ)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def policy_permissions(obj)
17
+ obj.policy_roles
18
+ .select { |r| agents.include?(r.agent) }
19
+ .map(&:permissions).flatten.uniq
20
+ end
21
+
22
+ def has_policy_permission?(obj, perm)
23
+ policy_permissions(obj).include?(perm)
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ module Ddr
2
+ module Auth
3
+ class ComponentAbilityDefinitions < AbilityDefinitions
4
+
5
+ def call
6
+ can :create, Ddr::Component do |obj|
7
+ obj.parent.present? && can?(:add_children, obj.parent)
8
+ end
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Ddr
2
+ module Auth
3
+ class ItemAbilityDefinitions < AbilityDefinitions
4
+
5
+ def call
6
+ can :create, Ddr::Item do |obj|
7
+ obj.parent.present? && can?(:add_children, obj.parent)
8
+ end
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Ddr
2
+ module Auth
3
+ class LockAbilityDefinitions < AbilityDefinitions
4
+
5
+ DENIED_WHEN_LOCKED = [ :add_children, :update, :replace, :arrange, :grant ]
6
+
7
+ def call
8
+ cannot DENIED_WHEN_LOCKED, Ddr::Resource, :locked? => true
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ module Ddr
2
+ module Auth
3
+ class PublicationAbilityDefinitions < AbilityDefinitions
4
+
5
+ def call
6
+ cannot :publish, Ddr::Resource do |obj|
7
+ obj.published? || !obj.publishable?
8
+ end
9
+ cannot :unpublish, Ddr::Resource do |obj|
10
+ !obj.published?
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module Ddr
2
+ module Auth
3
+ class RoleBasedAbilityDefinitions < AbilityDefinitions
4
+
5
+ def call
6
+ Permissions::ALL.each do |permission|
7
+ can permission, [ Ddr::Resource, ::SolrDocument, String ] do |obj|
8
+ has_permission? permission, obj
9
+ end
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def has_permission?(permission, object_or_id)
16
+ permissions(object_or_id).include? permission
17
+ end
18
+
19
+ def permissions(object_or_id)
20
+ case object_or_id
21
+ when Ddr::Resource, ::SolrDocument
22
+ cached_permissions(object_or_id.id) do
23
+ object_or_id.effective_permissions(agents)
24
+ end
25
+ when String
26
+ cached_permissions(object_or_id) do
27
+ doc = ::SolrDocument.find(object_or_id) # raises SolrDocument::NotFound
28
+ doc.effective_permissions(agents)
29
+ end
30
+ end
31
+ end
32
+
33
+ def cached_permissions(pid, &block)
34
+ cache[pid] ||= block.call
35
+ end
36
+
37
+ end
38
+ end
39
+ end