Skip to content

Commit

Permalink
Add an API endpoint for handling legacy metadata
Browse files Browse the repository at this point in the history
This can be used by accessionWF robots so they don't need to make Fedora calls
  • Loading branch information
jcoyne committed Nov 8, 2019
1 parent 1983a09 commit a67faaf
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .rubocop.yml
@@ -1,3 +1,4 @@

inherit_from: .rubocop_todo.yml

require:
Expand All @@ -14,6 +15,9 @@ AllCops:
Rails:
Enabled: true

Lint/AssignmentInCondition:
Enabled: false

Lint/UnusedMethodArgument:
AllowUnusedKeywordArguments: true

Expand Down
20 changes: 20 additions & 0 deletions app/controllers/metadata_controller.rb
Expand Up @@ -13,4 +13,24 @@ def descriptive
service = PublicDescMetadataService.new(@item)
render xml: service
end

# This supports the Legacy Fedora 3 data model. This is used by the accessionWF.
def update_legacy_metadata
datastream_names = { descriptive: 'descMetadata',
technical: 'technicalMetadata',
content: 'contentMetadata',
rights: 'rightsMetadata' }

datastream_names.each do |section, datastream_name|
next unless values = params[section]

update_datastream_if_newer(datastream: @item.datastreams[datastream_name],
updated: Time.zone.parse(values[:updated]),
content: values[:content])
end

@item.save!
end

delegate :update_datastream_if_newer, to: LegacyMetadataService
end
15 changes: 15 additions & 0 deletions app/services/legacy_metadata_service.rb
@@ -0,0 +1,15 @@
# frozen_string_literal: true

# Operations on the legacy Fedora 3 metadata.
# This is used by the accessionWF
class LegacyMetadataService
# If the updated value is newer than then createDate of the datastream, then update it.
def self.update_datastream_if_newer(datastream:, updated:, content:)
datastream.content = content if !datastream.createDate || updated > datastream.createDate
return if !datastream.createDate || updated > datastream.createDate

Honeybadger.notify("Found #{datasteam.pid}/#{datastream.dsid} that had a create " \
"date (#{datastream.createDate}) after the file was modified (#{updated}). " \
'Doing an experiment to see if this ever happens.')
end
end
1 change: 1 addition & 0 deletions config/routes.rb
Expand Up @@ -56,6 +56,7 @@

resources :metadata, only: [] do
collection do
patch 'legacy', action: :update_legacy_metadata
get 'dublin_core'
get 'descriptive'
end
Expand Down
66 changes: 66 additions & 0 deletions openapi.json
Expand Up @@ -787,6 +787,41 @@
]
}
},
"/objects/{object_id}/metadata/legacy": {
"post": {
"tags": [
"objects"
],
"summary": "Update the legacy (datastream) metadata for the object",
"description": "",
"operationId": "metadata#update_legacy_metadata",
"responses": {
"200": {
"description": "OK"
}
},
"parameters": [
{
"name": "object_id",
"in": "path",
"description": "ID of object",
"required": true,
"schema": {
"$ref": "#/components/schemas/Druid"
}
},
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateLegacyMetadata"
}
}
}
}
}
},
"/objects/{object_id}/metadata/dublin_core": {
"get": {
"tags": [
Expand Down Expand Up @@ -1244,6 +1279,37 @@
}
}
}
},
"UpdateLegacyMetadata": {
"properties": {
"descriptive": {
"$ref": "#/components/schemas/LegacyDatastream"
},
"rights": {
"$ref": "#/components/schemas/LegacyDatastream"
},
"content": {
"$ref": "#/components/schemas/LegacyDatastream"
},
"technical": {
"$ref": "#/components/schemas/LegacyDatastream"
},
}
},
"LegacyDatastream": {
"properties": {
"updated": {
"type": "string",
"format": "date-time",
"description": "The date the xml was produced. This may be used to see if the server wants to accept this or if it already has a more recent version."

},
"content": {
"type": "string",
"description": "The XML datastream content",
"example": "<xmlDatastream>...</xmlDatastream>"
}
}
}
},
"securitySchemes": {
Expand Down
62 changes: 62 additions & 0 deletions spec/requests/legacy_metadata_update_spec.rb
@@ -0,0 +1,62 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe 'Update the legacy (datastream) metadata' do
let(:work) { instance_double(Dor::Item, pid: 'druid:bc123df4567', datastreams: datastreams, save!: nil) }
let(:create_date) { Time.zone.parse('2019-08-09T19:18:15Z') }
let(:descMetadata) { instance_double(Dor::DescMetadataDS, createDate: create_date) }
let(:rightsMetadata) { instance_double(Dor::RightsMetadataDS, createDate: create_date) }
let(:technicalMetadata) { instance_double(Dor::TechnicalMetadataDS, createDate: create_date) }
let(:contentMetadata) { instance_double(Dor::ContentMetadataDS, createDate: create_date) }

let(:datastreams) do
{
'descMetadata' => descMetadata,
'rightsMetadata' => rightsMetadata,
'technicalMetadata' => technicalMetadata,
'contentMetadata' => contentMetadata
}
end

context 'when update is successful' do
before do
allow(Dor).to receive(:find).and_return(work)
allow(LegacyMetadataService).to receive(:update_datastream_if_newer)
end

let(:data) do
<<~JSON
{
"descriptive": {
"updated": "2019-11-08T15:15:43Z",
"content": "<descMetadata></descMetadata>"
},
"rights": {
"updated": "2019-11-08T15:15:43Z",
"content": "<rightsMetadata></rightsMetadata>"
}
}
JSON
end

it 'updates the object datastreams' do
patch "/v1/objects/#{work.pid}/metadata/legacy",
params: data,
headers: { 'Authorization' => "Bearer #{jwt}", 'CONTENT_TYPE' => 'application/json' }
expect(response).to have_http_status(:no_content)

expect(LegacyMetadataService).to have_received(:update_datastream_if_newer)
.with(datastream: descMetadata,
updated: Time.zone.parse('2019-11-08T15:15:43Z'),
content: '<descMetadata></descMetadata>')

expect(LegacyMetadataService).to have_received(:update_datastream_if_newer)
.with(datastream: rightsMetadata,
updated: Time.zone.parse('2019-11-08T15:15:43Z'),
content: '<rightsMetadata></rightsMetadata>')

expect(work).to have_received(:save!)
end
end
end
31 changes: 31 additions & 0 deletions spec/services/legacy_metadata_service_spec.rb
@@ -0,0 +1,31 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe LegacyMetadataService do
describe '.update_datastream_if_newer' do
subject(:update) { described_class.update_datastream_if_newer(datastream: datastream, updated: updated, content: content) }

let(:updated) { Time.zone.parse('2019-08-09T19:18:15Z') }
let(:content) { '<descMetadata><foo/></descMetadata>' }
let(:datastream) { instance_double(Dor::DescMetadataDS, createDate: create_date, :content= => nil) }

context 'with a new datastream' do
let(:create_date) { nil }

it 'updates the content' do
update
expect(datastream).to have_received(:content=).with(content)
end
end

context 'with a datastream that is older than the content' do
let(:create_date) { Time.zone.parse('2019-07-09T19:18:15Z') }

it 'updates the content' do
update
expect(datastream).to have_received(:content=).with(content)
end
end
end
end

0 comments on commit a67faaf

Please sign in to comment.