Skip to content

Commit

Permalink
Merge pull request #1200 from sul-dlss/pass-cocina
Browse files Browse the repository at this point in the history
[refactor] Pass only cocina to StacksFile and StorageRoot
  • Loading branch information
jcoyne committed Jul 1, 2024
2 parents 9c96336 + 5a70fb4 commit f5b6be2
Show file tree
Hide file tree
Showing 25 changed files with 81 additions and 44 deletions.
2 changes: 1 addition & 1 deletion app/controllers/file_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def cache_headers
end

def current_file
@file ||= StacksFile.new(id: params[:id], file_name: params[:file_name], cocina:)
@file ||= StacksFile.new(file_name: params[:file_name], cocina:)
end

def cocina
Expand Down
7 changes: 5 additions & 2 deletions app/controllers/iiif/auth/v2/probe_service_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ def show # rubocop:disable Metrics:AbcSize
stacks_uri = params[:id] # this is a fully qualified URI to the resource on the stacks that the user is requesting access to
parsed_uri = parse_uri(stacks_uri)

file = StacksFile.new(id: parsed_uri[:druid], file_name: parsed_uri[:file_name], cocina: Cocina.find(parsed_uri[:druid]))

json = { '@context': 'http://iiif.io/api/auth/2/context.json', type: 'AuthProbeResult2' }
begin
file = StacksFile.new(file_name: parsed_uri[:file_name], cocina: Cocina.find(parsed_uri[:druid]))
rescue Purl::Exception
return render json: json.merge(status: 404, note: { en: ["Unable to find #{parsed_uri[:druid]}"] })
end

if !file.valid?
json[:status] = 400
Expand Down
1 change: 0 additions & 1 deletion app/controllers/iiif_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ def canonical_url

def stacks_file
StacksFile.new(
id: identifier_params[:id],
file_name: "#{identifier_params[:file_name]}.jp2",
cocina: Cocina.find(identifier_params[:id])
)
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/legacy_image_service_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def load_image
end

def stacks_file
StacksFile.new(id:, file_name:, cocina: Cocina.find(id))
StacksFile.new(file_name:, cocina: Cocina.find(id))
end

def iiif_params
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/media_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def load_media
end

def stacks_file
StacksFile.new(id: params[:id], file_name: params[:file_name], cocina: Cocina.find(params[:id]))
StacksFile.new(file_name: params[:file_name], cocina: Cocina.find(params[:id]))
end

def current_media
Expand Down
6 changes: 5 additions & 1 deletion app/models/cocina.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ def initialize(data)

attr_accessor :data

def druid
@druid ||= data.fetch('externalIdentifier').delete_prefix('druid:')
end

def find_file(file_name)
file_sets = data.dig('structural', 'contains')
raise(ActionController::MissingFile, "File not found '#{file_name}'") unless file_sets # Trap for Collections
Expand Down Expand Up @@ -61,7 +65,7 @@ def files(&)
def files_from_json
data.dig('structural', 'contains').each do |fileset|
fileset.dig('structural', 'contains').each do |file|
file = StacksFile.new(id: data.fetch('externalIdentifier').delete_prefix('druid:'), file_name: file['filename'], cocina: self)
file = StacksFile.new(file_name: file['filename'], cocina: self)
yield file
end
end
Expand Down
11 changes: 7 additions & 4 deletions app/models/stacks_file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
class StacksFile
include ActiveModel::Validations

def initialize(id:, file_name:, cocina:)
@id = id
def initialize(file_name:, cocina:)
@file_name = file_name
@cocina = cocina
end

attr_reader :id, :file_name, :cocina
attr_reader :file_name, :cocina

def id
cocina.druid
end

validates :id, format: { with: StorageRoot::DRUID_PARTS_PATTERN }

Expand Down Expand Up @@ -42,7 +45,7 @@ def treeified_path
end

def storage_root
@storage_root ||= StorageRoot.new(druid: id, file_name:)
@storage_root ||= StorageRoot.new(cocina:, file_name:)
end

def stacks_rights
Expand Down
2 changes: 2 additions & 0 deletions app/models/stacks_rights.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
class StacksRights
attr_reader :cocina_file, :cocina

# @param [String] file_name
# @param [Cocina] cocina
def initialize(file_name:, cocina:)
@cocina = cocina
@cocina_file = cocina.find_file(file_name)
Expand Down
15 changes: 11 additions & 4 deletions app/models/storage_root.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@
class StorageRoot
DRUID_PARTS_PATTERN = /\A([b-df-hjkmnp-tv-z]{2})([0-9]{3})([b-df-hjkmnp-tv-z]{2})([0-9]{4})\z/i

def initialize(druid:, file_name:)
@druid = druid
@druid_parts = druid.match(DRUID_PARTS_PATTERN)
# @param [String] file_name
# @param [Cocina] cocina
def initialize(file_name:, cocina:)
@file_name = file_name
@cocina = cocina
end

delegate :druid, to: :cocina

def druid_parts
@druid_parts ||= druid.match(DRUID_PARTS_PATTERN)
end

def absolute_path
Expand All @@ -28,7 +35,7 @@ def treeified_id

private

attr_reader :druid, :druid_parts, :file_name
attr_reader :cocina, :file_name

def path_finder
@path_finder ||= path_finder_class.new(treeified_id:, druid:, file_name:)
Expand Down
7 changes: 4 additions & 3 deletions spec/abilities/cocina_ability_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

let(:public_json) do
{
'externalIdentifier' => 'yx350pf4616',
'structural' => {
'contains' => [
{
Expand Down Expand Up @@ -56,13 +57,13 @@

let(:cocina) { Cocina.new(public_json) }
let(:file) do
StacksFile.new(id: 'xxxxxxx', file_name: 'file.csv', cocina:)
StacksFile.new(file_name: 'file.csv', cocina:)
end
let(:image) do
StacksImage.new(stacks_file: StacksFile.new(id: 'yx350pf4616', file_name: 'image.jpg', cocina:))
StacksImage.new(stacks_file: StacksFile.new(file_name: 'image.jpg', cocina:))
end
let(:media) do
StacksMediaStream.new(stacks_file: StacksFile.new(id: 'xxxxxxx', file_name: 'movie.mp4', cocina:))
StacksMediaStream.new(stacks_file: StacksFile.new(file_name: 'movie.mp4', cocina:))
end

let(:thumbnail_transformation) { IIIF::Image::OptionDecoder.decode(region: 'full', size: '!400,400') }
Expand Down
1 change: 1 addition & 0 deletions spec/controllers/file_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

let(:public_json) do
{
'externalIdentifier' => druid,
'structural' => {
'contains' => [
{
Expand Down
2 changes: 1 addition & 1 deletion spec/models/iiif_image_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
let(:druid) { 'nr349ct7889' }
let(:file_name) { 'image.jp2' }
let(:transformation) { IIIF::Image::Transformation.new(size: 'full', region: 'full') }
let(:stacks_file) { StacksFile.new(id: druid, file_name:, cocina: Cocina.new({})) }
let(:stacks_file) { StacksFile.new(file_name:, cocina: Cocina.new({ "externalIdentifier" => druid })) }
let(:instance) { described_class.new(stacks_file:, base_uri:, transformation:) }

describe "#remote_id" do
Expand Down
6 changes: 3 additions & 3 deletions spec/models/projection_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@
describe '#response' do
let(:druid) { 'nr349ct7889' }
let(:file_name) { 'image.jp2' }
let(:cocina) { Cocina.new({}) }
let(:cocina) { Cocina.new({ 'externalIdentifier' => druid }) }

context 'for an image' do
let(:image) { StacksImage.new(stacks_file: StacksFile.new(id: druid, file_name:, cocina:)) }
let(:image) { StacksImage.new(stacks_file: StacksFile.new(file_name:, cocina:)) }

subject(:projection) { described_class.new(image, transformation) }

Expand Down Expand Up @@ -130,7 +130,7 @@
end

context 'for a restricted image' do
let(:image) { RestrictedImage.new(stacks_file: StacksFile.new(id: druid, file_name:, cocina:)) }
let(:image) { RestrictedImage.new(stacks_file: StacksFile.new(file_name:, cocina:)) }

subject(:projection) { described_class.new(image, transformation) }

Expand Down
5 changes: 3 additions & 2 deletions spec/models/stacks_file_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
RSpec.describe StacksFile do
let(:druid) { 'nr349ct7889' }
let(:file_name) { 'image.jp2' }
let(:instance) { described_class.new(id: druid, file_name:, cocina: Cocina.new({})) }
let(:cocina) { Cocina.new({ 'externalIdentifier' => druid }) }
let(:instance) { described_class.new(file_name:, cocina:) }
let(:path) { storage_root.absolute_path }
let(:storage_root) { StorageRoot.new(druid:, file_name:) }
let(:storage_root) { StorageRoot.new(cocina:, file_name:) }

describe '#path' do
subject { instance.path }
Expand Down
2 changes: 1 addition & 1 deletion spec/models/stacks_image_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

describe "#info_service" do
subject { instance.send(:info_service) }
let(:stacks_file) { StacksFile.new(id: 'nr349ct7889', file_name: 'image.jp2', cocina: Cocina.new({})) }
let(:stacks_file) { StacksFile.new(file_name: 'image.jp2', cocina: Cocina.new({ 'externalIdentifier' => 'nr349ct7889' })) }
let(:instance) { described_class.new(stacks_file:) }

it { is_expected.to be_a IiifMetadataService }
Expand Down
6 changes: 4 additions & 2 deletions spec/requests/file_auth_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
let(:druid) { 'nr349ct7889' }
let(:file_name) { 'image.jp2' }
let(:path) { storage_root.absolute_path }
let(:storage_root) { StorageRoot.new(druid:, file_name:) }
let(:storage_root) { StorageRoot.new(cocina:, file_name:) }
let(:perms) { nil }
let(:stacks_file) { StacksFile.new(id: druid, file_name:, cocina:) }
let(:stacks_file) { StacksFile.new(file_name:, cocina:) }
let(:cocina) { Cocina.new(public_json) }

before do
Expand All @@ -26,6 +26,7 @@
context 'stanford only (no location qualifications)' do
let(:public_json) do
{
'externalIdentifier' => druid,
'structural' => {
'contains' => [
{
Expand Down Expand Up @@ -69,6 +70,7 @@
context 'not stanford qualified in any way' do
let(:public_json) do
{
'externalIdentifier' => druid,
'structural' => {
'contains' => [
{
Expand Down
2 changes: 2 additions & 0 deletions spec/requests/file_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
let(:file_name) { 'image.jp2' }
let(:public_json) do
{
'externalIdentifier' => druid,
'structural' => {
'contains' => [
{
Expand Down Expand Up @@ -44,6 +45,7 @@
let(:file_name) { 'path/to/image.jp2' }
let(:public_json) do
{
'externalIdentifier' => druid,
'structural' => {
'contains' => [
{
Expand Down
21 changes: 10 additions & 11 deletions spec/requests/iiif/auth/v2/probe_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
let(:file_name) { 'image.jp2' }
let(:stacks_uri) { "https://stacks-uat.stanford.edu/file/druid:#{id}/#{URI.encode_uri_component(file_name)}" }
let(:stacks_uri_param) { URI.encode_uri_component(stacks_uri) }
let(:public_json) { '{}' }
let(:public_json) { { "externalIdentifier" => "druid:nr349ct7889" } }

# NOTE: For any unauthorized responses, the status from the service is OK...the access status of the resource is in the response body

Expand Down Expand Up @@ -46,14 +46,15 @@
let(:id) { '111' }

before do
allow(Cocina).to receive(:find).and_raise(Purl::Exception)
get "/iiif/auth/v2/probe?id=#{stacks_uri_param}"
end

it 'returns a success response' do
expect(response).to have_http_status :ok
expect(response.parsed_body).to eq("@context" => "http://iiif.io/api/auth/2/context.json",
"note" => { "en" => ["Id is invalid"] },
"status" => 400,
"note" => { "en" => ["Unable to find 111"] },
"status" => 404,
"type" => "AuthProbeResult2")
end
end
Expand All @@ -73,6 +74,7 @@
context 'when the user has access to the resource because it is world accessible' do
let(:public_json) do
{
"externalIdentifier" => "druid:nr349ct7889",
'structural' => {
'contains' => [
{
Expand Down Expand Up @@ -100,9 +102,6 @@
context 'when druid has a prefix' do
it 'returns a success response' do
expect(response).to have_http_status :ok
# Ensure the druid doesn't have a prefix:
expect(StacksFile).to have_received(:new).with(hash_including(id: "nr349ct7889"))

expect(response.parsed_body).to include({
"@context" => "http://iiif.io/api/auth/2/context.json",
"type" => "AuthProbeResult2",
Expand All @@ -116,9 +115,6 @@

it 'returns a success response' do
expect(response).to have_http_status :ok
# Ensure the druid doesn't have a prefix:
expect(StacksFile).to have_received(:new).with(hash_including(id: "nr349ct7889"))

expect(response.parsed_body).to include({
"@context" => "http://iiif.io/api/auth/2/context.json",
"type" => "AuthProbeResult2",
Expand All @@ -145,6 +141,7 @@
let(:file_name) { 'SC0193_1982-013_b06_f01_1981-09-29.mp4' }
let(:public_json) do
{
"externalIdentifier" => "druid:nr349ct7889",
'structural' => {
'contains' => [
{
Expand Down Expand Up @@ -183,8 +180,6 @@
end

context 'when the requested file does not exist' do
let(:public_json) { {} }

before do
allow_any_instance_of(StacksFile).to receive(:readable?).and_return(nil)
get "/iiif/auth/v2/probe?id=#{stacks_uri_param}"
Expand All @@ -203,6 +198,7 @@
context 'when a Stanford only resource' do
let(:public_json) do
{
"externalIdentifier" => "druid:nr349ct7889",
'structural' => {
'contains' => [
{
Expand Down Expand Up @@ -283,6 +279,7 @@
context 'when the user does not have access to a location restricted resource' do
let(:public_json) do
{
"externalIdentifier" => "druid:nr349ct7889",
'structural' => {
'contains' => [
{
Expand Down Expand Up @@ -346,6 +343,7 @@
context 'when the user does not have access to a stanford restricted embargoed resource' do
let(:public_json) do
{
"externalIdentifier" => "druid:nr349ct7889",
'access' => {
'embargo' => {
"releaseDate" => Time.parse('2099-05-15').getlocal.as_json
Expand Down Expand Up @@ -393,6 +391,7 @@
context 'when the user does not have access to an embargoed resource' do
let(:public_json) do
{
"externalIdentifier" => "druid:nr349ct7889",
'access' => {
'embargo' => {
"releaseDate" => Time.parse('2099-05-15').getlocal.as_json
Expand Down
Loading

0 comments on commit f5b6be2

Please sign in to comment.