Skip to content

Commit

Permalink
Merge pull request #1659 from psu-libraries/1656-delete-work-webhook
Browse files Browse the repository at this point in the history
1656 delete work webhook
  • Loading branch information
EricDurante authored Jan 21, 2025
2 parents 48b8558 + 0ed8bd9 commit 43abf32
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 44 deletions.
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ jobs:
POSTGRES_PASSWORD: scholarsphere
POSTGRES_DB: scholarsphere
POSTGRES_HOST: 127.0.0.1
RMD_HOST: https://metadata.libraries.psu.edu
steps:
- browser-tools/install-browser-tools
- checkout
Expand Down
10 changes: 9 additions & 1 deletion .envrc.sample
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@ export POSTGRES_PORT=
export DIRECTORY_SERVICE_ENDPOINT=
export PSU_ID_OAUTH_CLIENT_ID=
export PSU_ID_OAUTH_CLIENT_SECRET=
export PSU_ID_OAUTH_ENDPOINT=
export PSU_ID_OAUTH_ENDPOINT=
export DATACITE_ENDPOINT=
export DATACITE_PASSWORD=
export DATACITE_PREFIX=
export DATACITE_PUBLISHER=
export DATACITE_USERNAME=
export RMD_API_KEY=
export RMD_WEBHOOK_SECRET=
export RMD_HOST=
9 changes: 9 additions & 0 deletions app/jobs/work_removed_webhook_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

class WorkRemovedWebhookJob < ApplicationJob
queue_as :webhooks

def perform(work_uuid)
WorkRemovedWebhook.new(work_uuid).notify
end
end
6 changes: 6 additions & 0 deletions app/models/work.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ class Work < ApplicationRecord
include GeneratedUuids
include ThumbnailSelections

after_destroy :notify_work_deleted

fields_with_dois :doi, :latest_published_version_dois

delegate :email, :display_name, to: :depositor
Expand Down Expand Up @@ -293,4 +295,8 @@ def embargoed_until_is_valid_date
nil
end
end

def notify_work_deleted
WorkRemovedWebhookJob.perform_later(uuid)
end
end
5 changes: 5 additions & 0 deletions app/models/work_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ def label(id)
end

event :withdraw do
after_commit do
if work.withdrawn?
WorkRemovedWebhookJob.perform_later(work.uuid)
end
end
transitions from: :published, to: :withdrawn
end

Expand Down
2 changes: 1 addition & 1 deletion app/services/rmd_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def endpoint
end

def rmd_host
'https://metadata.libraries.psu.edu'
ENV['RMD_HOST']
end

def api_key
Expand Down
20 changes: 20 additions & 0 deletions app/services/work_removed_webhook.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

class WorkRemovedWebhook
def initialize(work_uuid)
@work_uuid = work_uuid
end

def notify
conn = Faraday.new(
url: ENV['RMD_HOST'],
headers: { 'X-API-KEY' => ENV['RMD_WEBHOOK_SECRET'] }
)

conn.post('/webhooks/scholarsphere_events', publication_url: "https://scholarsphere.psu.edu/resources/#{work_uuid}")
end

private

attr_reader :work_uuid
end
19 changes: 19 additions & 0 deletions spec/jobs/work_removed_webhook_job_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe WorkRemovedWebhookJob do
let(:webhook) { instance_double WorkRemovedWebhook, notify: nil }

before do
allow(WorkRemovedWebhook).to receive(:new).with('abc123').and_return(webhook)
end

describe '#perform' do
it 'triggers a work removed webhook' do
described_class.perform_now('abc123')

expect(webhook).to have_received(:notify)
end
end
end
68 changes: 41 additions & 27 deletions spec/models/work_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require 'rails_helper'

RSpec.describe Work, type: :model do
RSpec.describe Work do
it { is_expected.to delegate_method(:email).to(:depositor) }
it { is_expected.to delegate_method(:display_name).to(:depositor) }
it { is_expected.to delegate_method(:has_publisher_doi?).to(:latest_version) }
Expand All @@ -20,12 +20,12 @@
it_behaves_like 'a resource that can provide all DOIs in', [:doi, :latest_published_version_dois]

it_behaves_like 'a resource with a thumbnail url' do
let!(:work) { create :work, versions_count: 2 }
let!(:work) { create(:work, versions_count: 2) }
let(:resource) { work }
end

it_behaves_like 'a resource with a thumbnail selection' do
let!(:work) { create :work, versions_count: 2 }
let!(:work) { create(:work, versions_count: 2) }
let(:resource) { work }
end

Expand Down Expand Up @@ -90,17 +90,31 @@
end
end

describe 'lifecycle callbacks' do
describe 'destroying a work' do
let!(:work) { create(:work) }

before { allow(WorkRemovedWebhookJob).to receive(:perform_later) }

it 'enqueues a notification job' do
work.destroy!

expect(WorkRemovedWebhookJob).to have_received(:perform_later).with(work.uuid)
end
end
end

describe '.recently_published' do
let(:wv1) { build :work_version, :published, work: nil, sent_for_curation_at: nil }
let(:work1) { create :work, versions: [wv1] }
let(:wv1) { build(:work_version, :published, work: nil, sent_for_curation_at: nil) }
let(:work1) { create(:work, versions: [wv1]) }

let(:wv2) { build :work_version, :published, work: nil, sent_for_curation_at: Time.now }
let(:work2) { create :work, versions: [wv2] }
let(:wv2) { build(:work_version, :published, work: nil, sent_for_curation_at: Time.now) }
let(:work2) { create(:work, versions: [wv2]) }

let(:wv4) { build :work_version, work: nil, aasm_state: 'draft' }
let(:work3) { create :work, versions: [wv4] }
let(:wv4) { build(:work_version, work: nil, aasm_state: 'draft') }
let(:work3) { create(:work, versions: [wv4]) }

let(:work4) { create :work }
let(:work4) { create(:work) }

it 'returns works with a published WorkVersion that has not been sent for curation' do
expect(described_class.recently_published).to match_array([work1])
Expand Down Expand Up @@ -357,15 +371,15 @@
end

describe 'version accessors' do
let(:draft) { build :work_version, :draft, title: 'Draft', work: nil, created_at: 1.day.ago, version_number: 3 }
let(:v2) { build :work_version, :published, title: 'Published v2', work: nil, created_at: 2.days.ago, version_number: 2 }
let(:v1) { build :work_version, :published, title: 'Published v1', work: nil, created_at: 3.days.ago, version_number: 1 }
let(:withdrawn) { build :work_version, :withdrawn, work: nil, created_at: 3.days.ago, version_number: 1 }
let(:draft) { build(:work_version, :draft, title: 'Draft', work: nil, created_at: 1.day.ago, version_number: 3) }
let(:v2) { build(:work_version, :published, title: 'Published v2', work: nil, created_at: 2.days.ago, version_number: 2) }
let(:v1) { build(:work_version, :published, title: 'Published v1', work: nil, created_at: 3.days.ago, version_number: 1) }
let(:withdrawn) { build(:work_version, :withdrawn, work: nil, created_at: 3.days.ago, version_number: 1) }

before { work.reload }

context 'with draft, published, and withdrawn versions' do
subject(:work) { create :work, versions: [draft, v2, withdrawn] }
subject(:work) { create(:work, versions: [draft, v2, withdrawn]) }

it { is_expected.not_to be_withdrawn }

Expand All @@ -377,7 +391,7 @@
end

context 'with draft and published versions' do
subject(:work) { create :work, versions: [draft, v2, v1] }
subject(:work) { create(:work, versions: [draft, v2, v1]) }

it { is_expected.not_to be_withdrawn }

Expand All @@ -389,7 +403,7 @@
end

context 'with draft and withdrawn versions' do
subject(:work) { create :work, versions: [draft, withdrawn] }
subject(:work) { create(:work, versions: [draft, withdrawn]) }

it { is_expected.to be_withdrawn }

Expand All @@ -401,7 +415,7 @@
end

context 'with published and withdrawn versions' do
subject(:work) { create :work, versions: [v2, withdrawn] }
subject(:work) { create(:work, versions: [v2, withdrawn]) }

it { is_expected.not_to be_withdrawn }

Expand All @@ -413,7 +427,7 @@
end

context 'with only published versions' do
subject(:work) { create :work, versions: [v2, v1] }
subject(:work) { create(:work, versions: [v2, v1]) }

it { is_expected.not_to be_withdrawn }

Expand All @@ -425,7 +439,7 @@
end

context 'with only a draft version' do
subject(:work) { create :work, versions: [draft] }
subject(:work) { create(:work, versions: [draft]) }

it { is_expected.not_to be_withdrawn }

Expand All @@ -437,7 +451,7 @@
end

context 'with only a withdrawn version' do
subject(:work) { create :work, versions: [withdrawn] }
subject(:work) { create(:work, versions: [withdrawn]) }

it { is_expected.to be_withdrawn }

Expand Down Expand Up @@ -656,7 +670,7 @@
end

describe '#stats' do
subject(:work) { create :work, versions_count: 3, has_draft: true }
subject(:work) { create(:work, versions_count: 3, has_draft: true) }

before { allow(AggregateViewStatistics).to receive(:call).and_return(:returned_stats) }

Expand All @@ -668,11 +682,11 @@

describe '#thumbnail_urls' do
let(:mock_attacher) { instance_double FileUploader::Attacher }
let!(:work) { create :work, versions_count: 2 }
let!(:work) { create(:work, versions_count: 2) }

context "when work's latest_published_version has multiple file_resources with thumbnail urls" do
before do
work.latest_published_version.file_resources << (create :file_resource)
work.latest_published_version.file_resources << (create(:file_resource))
work.save
allow(mock_attacher).to receive(:url).with(:thumbnail).and_return 'url.com/path/file'
end
Expand All @@ -687,11 +701,11 @@
end

describe '#latest_published_version_dois' do
let!(:work) { create :work }
let!(:work) { create(:work) }
let(:work_version) do
create :work_version, :published,
create(:work_version, :published,
doi: '10.26207/utaj-jfhi',
identifier: '10.26207/xyz-lmno'
identifier: '10.26207/xyz-lmno')
end

before do
Expand Down
Loading

0 comments on commit 43abf32

Please sign in to comment.