Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/api/v1/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
require 'v1/indexed_resources'
require 'v1/indexer'
require 'v1/envelope_communities'
require 'v1/containers'

module API
module V1
Expand Down Expand Up @@ -45,6 +46,7 @@ class Base < Grape::API
mount API::V1::Ctdl.api_class
mount API::V1::IndexedResources.api_class
mount API::V1::Indexer.api_class
mount API::V1::Containers.api_class

route_param :community_name do
mount API::V1::Resources.api_class
Expand All @@ -55,6 +57,7 @@ class Base < Grape::API
mount API::V1::Ctdl.api_class
mount API::V1::IndexedResources.api_class
mount API::V1::Indexer.api_class
mount API::V1::Containers.api_class
end

namespace :metadata do
Expand Down
52 changes: 52 additions & 0 deletions app/api/v1/containers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
require 'mountable_api'
require 'container_repository'
require 'helpers/shared_helpers'
require 'helpers/community_helpers'
require 'entities/envelope'

module API
module V1
# Implements the endpoints related to containers
class Containers < MountableAPI
mounted do # rubocop:todo Metrics/BlockLength
helpers CommunityHelpers
helpers SharedHelpers

resource :containers do
before do
authenticate!
end

route_param :container_ctid do
resource :resources do
before do
ctid = params[:container_ctid]&.downcase

@envelope = current_community
.envelopes
.containers
.find_sole_by(envelope_ceterms_ctid: ctid)

authorize @envelope, :update?
@repository = ContainerRepository.new(@envelope)
end

desc "Appends URIs to the container's ceterms:hasMember"
patch do
@repository.add_member_uri(JSON.parse(request.body.read))
present @envelope, with: API::Entities::Envelope
end

desc "Removes URIs from the container's ceterms:hasMember"
delete do
@repository.remove_member_uris(JSON.parse(request.body.read))
present @envelope, with: API::Entities::Envelope
end

end
end
end
end
end
end
end
2 changes: 2 additions & 0 deletions app/models/envelope.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class Envelope < ActiveRecord::Base
RESOURCE_PUBLISH_TYPES = %w[primary secondary].freeze
validates :resource_publish_type, inclusion: { in: RESOURCE_PUBLISH_TYPES, allow_blank: true }

scope :containers, -> { where(envelope_ctdl_type: CONTAINER_CTDL_TYPES) }
scope :not_deleted, -> { where(deleted_at: nil) }
scope :deleted, -> { where.not(deleted_at: nil) }
scope :ordered_by_date, -> { order(created_at: :desc) }
Expand All @@ -80,6 +81,7 @@ class Envelope < ActiveRecord::Base
end
}

CONTAINER_CTDL_TYPES = %w[ceterms:Collection].freeze
NOT_FOUND = 'Envelope not found'.freeze
DELETED = 'Envelope deleted'.freeze

Expand Down
6 changes: 1 addition & 5 deletions app/models/envelope_community.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,6 @@ def get_resource_type_from_values_map(cfg, envelope)
end
end

cfg['values_map'].fetch(key) do
raise MR::SchemaDoesNotExist,
"Cannot load json-schema. The property '#{cfg['property']}' " \
"has an invalid value '#{key}'"
end
cfg['values_map'][key]
end
end
37 changes: 37 additions & 0 deletions app/services/container_repository.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Manages subresources of a container
class ContainerRepository
attr_reader :envelope

delegate :processed_resource, to: :envelope

def initialize(envelope)
@envelope = envelope
end

def add_member_uri(uris)
existing_uris = container['ceterms:hasMember'] || []
container['ceterms:hasMember'] = (existing_uris + Array.wrap(uris)).uniq
update_envelope!
end

def remove_member_uris(uris)
existing_uris = container['ceterms:hasMember'] || []
container['ceterms:hasMember'] = existing_uris - Array.wrap(uris)
update_envelope!
end

def container
@container ||= graph.find { it['@type'] == 'ceterms:Collection' }
end

def graph
@graph ||= processed_resource['@graph']
end

def update_envelope!
envelope.update!(processed_resource:)
changed = envelope.previous_changes.any?
ExtractEnvelopeResourcesJob.perform_later(envelope.id) if changed
changed
end
end
2 changes: 2 additions & 0 deletions lib/swagger_docs.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require 'ctdl_query'
require 'swagger_docs/models'
require 'swagger_docs/sections/admin'
require 'swagger_docs/sections/containers'
require 'swagger_docs/sections/description_sets'
require 'swagger_docs/sections/envelopes'
require 'swagger_docs/sections/general'
Expand All @@ -18,6 +19,7 @@ class SwaggerDocs
include Models
include Sections::General
include Sections::Admin
include Sections::Containers
include Sections::DescriptionSets
include Sections::Envelopes
include Sections::Graphs
Expand Down
120 changes: 120 additions & 0 deletions lib/swagger_docs/sections/containers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
module MetadataRegistry
class SwaggerDocs
module Sections
# Swagger documentation for Containers API
module Containers
extend ActiveSupport::Concern

included do
swagger_path '/{community_name}/containers/{container_ctid}/resources' do
operation :patch do # rubocop:todo Metrics/BlockLength
key :operationId, 'patchApiContainerResources'
key :description, "Appends one or more URIs to the container's ceterms:hasMember"
key :consumes, ['application/json']
key :produces, ['application/json']
key :tags, ['Containers']

security

parameter community_name
parameter name: :container_ctid,
in: :path,
type: :string,
required: true,
description: 'CTID of the container'

parameter do
key :name, :uris
key :in, :body
key :description, "URI(s) to append to the container's ceterms:hasMember. " \
'Can be a single URI or an array of URIs. ' \
'Duplicates are ignored.'
key :required, true

schema do
key :type, :array
key :description, 'An array of resource URIs'
items do
key :type, :string
key :format, :uri
key :example, 'http://credentialengineregistry.org/resources/ce-abc123'
end
end
end

response 200 do
key :description, 'Successfully added theURI(s) to the container'
schema { key :$ref, :Envelope }
end

response 401 do
key :description, 'Unauthorized - authentication required'
end

response 403 do
key :description, 'Forbidden - insufficient permissions'
end

response 404 do
key :description, 'Container not found or not a collection type'
end
end

operation :delete do # rubocop:todo Metrics/BlockLength
key :operationId, 'deleteApiContainerResources'
key :description, "Removes one or more URIs from the container's ceterms:hasMember"
key :consumes, ['application/json']
key :produces, ['application/json']
key :tags, ['Containers']

security

parameter community_name
parameter name: :container_ctid,
in: :path,
type: :string,
required: true,
description: 'CTID of the container'

parameter do
key :name, :uris
key :in, :body
key :description, "URI(s) to remove from the container's ceterms:hasMember. " \
'Can be a single URI or an array of URIs.'
key :required, true

schema do
key :type, :array
key :description, 'An array of resource URIs'
items do
key :type, :string
key :format, :uri
key :example, 'http://credentialengineregistry.org/resources/ce-abc123'
end
end
end

response 200 do
key :description, 'Successfully removed the URI(s) from the container'
schema { key :$ref, :Envelope }
end

response 401 do
key :description, 'Unauthorized - authentication required'
end

response 403 do
key :description, 'Forbidden - insufficient permissions'
end

response 404 do
key :description, 'Container not found or not a collection type'
end
end
end

end
end
end
end
end
Loading
Loading