Skip to content

Commit

Permalink
Merge pull request #257 from curationexperts/invoke-workflow-rebased
Browse files Browse the repository at this point in the history
Use mira_publication_workflow and hyrax actor stack for self-deposit contributions
  • Loading branch information
Thomas Johnson committed Sep 20, 2017
2 parents d65fd32 + d20f4e4 commit 2b7c8af
Show file tree
Hide file tree
Showing 16 changed files with 314 additions and 25 deletions.
6 changes: 5 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ Metrics/BlockLength:
Metrics/LineLength:
Exclude:
- 'spec/controllers/tufts/draft_controller_spec.rb'
Metrics/MethodLength:
Exclude:
- 'app/models/forms/contribution.rb'
RSpec/ExampleLength:
Exclude:
- 'spec/features/**/*'
Expand All @@ -31,8 +34,9 @@ RSpec/AnyInstance:
RSpec/MultipleExpectations:
Exclude:
- 'spec/controllers/contribute_controller_spec.rb'
- 'spec/lib/tufts/workflow_setup_spec.rb'
- 'spec/features/**/*'
- 'spec/lib/tufts/workflow_setup_spec.rb'
- 'spec/services/**/*'
Style/FileName:
Exclude:
- '**/Capfile'
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@ bundle install
bundle exec rails db:setup
bundle exec sidekiq -d -l tmp/sidekiq.log
# open a separate session and run bundle exec rails hydra:server
bundle exec rails hyrax:default_admin_set:create
```
Other services and settings required:
* MySQL
* Redis
* MySQL
* Redis
* Path to [FITS](https://projects.iq.harvard.edu/fits/downloads) in the [Hyrax initializer](https://github.com/curationexperts/epigaea/blob/master/config/initializers/hyrax.rb)
* sidekiq as queue adapter in [application.rb](https://github.com/curationexperts/epigaea/blob/master/config/): `config.active_job.queue_adapter = :sidekiq`

Expand Down
4 changes: 3 additions & 1 deletion app/controllers/contribute_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ def new
end

def create
@contribution = @deposit_type.contribution_class.new(params[:contribution].merge(deposit_type: @deposit_type))
@contribution = @deposit_type.contribution_class.new(
params[:contribution].merge(deposit_type: @deposit_type).merge(depositor: current_user.user_key)
)

if @contribution.save
flash[:notice] = "Your deposit has been submitted for approval."
Expand Down
32 changes: 24 additions & 8 deletions app/models/forms/contribution.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,44 @@ def persisted?
def tufts_pdf
return @tufts_pdf if @tufts_pdf
now = Time.zone.now

note = "#{creator} self-deposited on #{now.strftime('%Y-%m-%d at %H:%M:%S %Z')} using the Deposit Form for the Tufts Digital Library"
@tufts_pdf = Pdf.new(createdby: SELFDEP, contributor: [creator], title: [title],
steward: 'dca', displays_in: ['dl'],
publisher: ['Tufts University. Digital Collections and Archives.'],
rights_statement: ['http://dca.tufts.edu/ua/access/rights-creator.html'],
date_available: [now.to_s], date_uploaded: now.to_s, internal_note: note)

@tufts_pdf = Pdf.new(
createdby: SELFDEP,
depositor: @depositor,
visibility: Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC,
contributor: [creator],
title: [title],
steward: 'dca',
displays_in: ['dl'],
publisher: ['Tufts University. Digital Collections and Archives.'],
rights_statement: ['http://dca.tufts.edu/ua/access/rights-creator.html'],
date_available: [now.to_s],
date_uploaded: now.to_s,
internal_note: note
)
copy_attributes
user = User.find_by(email: @depositor)
current_ability = ::Ability.new(user)
uploaded_file = Hyrax::UploadedFile.create(user: user, file: @attachment)
attributes = { uploaded_files: [uploaded_file.id] }
env = Hyrax::Actors::Environment.new(@tufts_pdf, current_ability, attributes)
Hyrax::CurationConcern.actor.create(env)
@tufts_pdf
end

def initialize(data = {})
@deposit_type = data.delete(:deposit_type)
@depositor = data.delete(:depositor)
self.class.attributes.each do |attribute|
send("#{attribute}=", data[attribute])
end
end

def save
return false unless valid?
ArchivalStorageService.new(tufts_pdf, attachment).run
# Attaching file to work now handled by AttachFilesToWorkJob,
# called via the Hyrax actor stack, when @tufts_pdf is created.
# ArchivalStorageService.new(tufts_pdf, attachment).run
tufts_pdf.save!
tufts_pdf
end
Expand Down
27 changes: 27 additions & 0 deletions app/services/hyrax/workflow/mira_notification.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module Hyrax
module Workflow
class MiraNotification < AbstractNotification
# regardless of what is passed in, set the recipients according to this notification's requirements
def initialize(entity, comment, user, recipients)
super
@recipients = workflow_recipients
end

def workflow_recipients
raise NotImplementedError, "Implement workflow_recipients in a child class"
end

# The Users who have an admin role
# @return [<Array>::User] an Array of Hyrax::User objects
def admins
Role.where(name: 'admin').first_or_create.users.to_a
end

# The Hyrax::User who desposited the work
# @return [Hyrax::User]
def depositor
::User.find_by(email: document.depositor)
end
end
end
end
21 changes: 21 additions & 0 deletions app/services/hyrax/workflow/published_notification.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module Hyrax
module Workflow
# Notification of state change to "approved".
# Should notify users with the approving role for the work's AdminSet, plus super users.
class PublishedNotification < MiraNotification
def workflow_recipients
{ "to" => (admins << depositor) }
end

private

def subject
"Deposit #{title} has been published"
end

def message
"#{title} (#{link_to work_id, document_path}) has been published by #{user.display_name}. #{comment}"
end
end
end
end
19 changes: 19 additions & 0 deletions app/services/hyrax/workflow/self_deposit_notification.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module Hyrax
module Workflow
class SelfDepositNotification < MiraNotification
def workflow_recipients
{ "to" => (admins << depositor) }
end

private

def subject
"Deposit #{title} awaiting publication"
end

def message
"#{title} (#{link_to work_id, document_path}) has been deposited by #{depositor.display_name} (#{depositor.user_key}) and is awaiting publication."
end
end
end
end
21 changes: 21 additions & 0 deletions app/services/hyrax/workflow/unpublished_notification.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module Hyrax
module Workflow
# Notification of state change to "approved".
# Should notify users with the approving role for the work's AdminSet, plus super users.
class UnpublishedNotification < MiraNotification
def workflow_recipients
{ "to" => admins }
end

private

def subject
"Deposit #{title} has been unpublished"
end

def message
"#{title} (#{link_to work_id, document_path}) has been unpublished by #{user.display_name}. #{comment}"
end
end
end
end
6 changes: 3 additions & 3 deletions config/workflows/mira_publication_workflow.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"notifications": [
{
"notification_type": "email",
"name": "Hyrax::Workflow::PendingReviewNotification",
"name": "Hyrax::Workflow::SelfDepositNotification",
"to": ["publishing"]
}
],
Expand All @@ -27,7 +27,7 @@
"notifications": [
{
"notification_type": "email",
"name": "Hyrax::Workflow::ChangesRequiredNotification",
"name": "Hyrax::Workflow::UnpublishedNotification",
"to": ["publishing"]
}
],
Expand All @@ -41,7 +41,7 @@
"notifications": [
{
"notification_type": "email",
"name": "Hyrax::Workflow::DepositedNotification",
"name": "Hyrax::Workflow::PublishedNotification",
"to": ["publishing"]
}
],
Expand Down
4 changes: 3 additions & 1 deletion spec/factories/pdf.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
require 'ffaker'

FactoryGirl.define do
factory :pdf do
id { ActiveFedora::Noid::Service.new.mint }
title ['Test']
title [FFaker::Book.title]
visibility Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
end
end
3 changes: 2 additions & 1 deletion spec/features/batch_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'rails_helper'
require 'tufts/workflow_setup'
include Warden::Test::Helpers

RSpec.feature 'Create a Batch', :clean, js: true do
Expand All @@ -8,7 +9,7 @@
let(:user) { create(:admin) }

before do
AdminSet.find_or_create_default_admin_set_id
Tufts::WorkflowSetup.setup

objects.each do |obj|
obj.visibility = 'open'
Expand Down
42 changes: 42 additions & 0 deletions spec/features/fletcher_school_capstone_contribute_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Generated via
# `rails generate hyrax:work Pdf`
require 'rails_helper'
require 'ffaker'
require 'tufts/workflow_setup'
require 'import_export/deposit_type_importer.rb'
include Warden::Test::Helpers

# NOTE: If you generated more than one work, you have to set "js: true"
RSpec.feature 'Create a PDF', :clean, js: true do
context 'a logged in admin user' do
let(:user) { FactoryGirl.create(:user) }
let(:title) { FFaker::Movie.title }
before do
Tufts::WorkflowSetup.setup
importer = DepositTypeImporter.new('./config/deposit_type_seed.csv')
importer.import_from_csv
Pdf.delete_all
Hyrax::UploadedFile.delete_all
login_as user
end

scenario "a new user contributes a capstone project" do
visit '/contribute'
select 'Fletcher School Capstone Project', from: 'deposit_type'
click_button "Begin"
attach_file('contribution_attachment', File.absolute_path(file_fixture('pdf-sample.pdf')))
fill_in "Capstone project title", with: title
fill_in "Contributor", with: user.display_name
select 'Master of Arts', from: 'contribution_degree'
fill_in "Short description", with: FFaker::Lorem.paragraph
click_button "Agree & Deposit"
created_pdf = Pdf.last
expect(created_pdf.title.first).to eq title
expect(created_pdf.contributor.first).to eq user.display_name
expect(created_pdf.depositor).to eq user.user_key
expect(created_pdf.admin_set.title.first).to eq "Default Admin Set"
expect(created_pdf.active_workflow.name).to eq "mira_publication_workflow"
expect(created_pdf.visibility).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
end
end
end
20 changes: 13 additions & 7 deletions spec/features/publication_workflow_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
before do
allow(CharacterizeJob).to receive(:perform_later) # There is no fits installed on travis-ci
Tufts::WorkflowSetup.setup
publishing_user # Make sure publishing user exists before the work is submitted
current_ability = ::Ability.new(depositing_user)
attributes = {}
env = Hyrax::Actors::Environment.new(work, current_ability, attributes)
Expand Down Expand Up @@ -40,14 +41,13 @@
# Check notifications for depositing user
login_as depositing_user
visit("/notifications?locale=en")
expect(page).to have_content "Deposit needs review #{work.title.first} (#{work.id}) was deposited by #{depositing_user.email} and is awaiting approval"
expect(page).to have_content "#{work.title.first} (#{work.id}) has been deposited by #{depositing_user.display_name} (#{depositing_user.user_key}) and is awaiting publication."

# Check notifications for publishing user
logout
login_as publishing_user
visit("/notifications?locale=en")
# expect(page).to have_content "#{work.title.first} (#{work.id}) was deposited by #{depositing_user.display_name} and is awaiting approval."
# expect(page).to have_content "Deposit needs review #{work.title.first} (#{work.id}) was deposited by #{depositing_user.email} and is awaiting approval"
expect(page).to have_content "#{work.title.first} (#{work.id}) has been deposited by #{depositing_user.display_name} (#{depositing_user.user_key}) and is awaiting publication."

# Check workflow permissions for publishing user
available_workflow_actions = Hyrax::Workflow::PermissionQuery.scope_permitted_workflow_actions_available_for_current_state(
Expand All @@ -65,15 +65,15 @@
Hyrax::Workflow::WorkflowActionService.run(subject: subject, action: sipity_workflow_action, comment: "Approved in publication_workflow_spec.rb")
expect(work.to_sipity_entity.reload.workflow_state_name).to eq "published"

# # Check notifications for publishing user
# visit("/notifications?locale=en")
# expect(page).to have_content "#{etd.title.first} (#{etd.id}) has been approved by"
# Check notifications for publishing user
visit("/notifications?locale=en")
expect(page).to have_content "#{work.title.first} (#{work.id}) has been published by #{publishing_user.display_name}. Approved in publication_workflow_spec.rb"

# Check notifications for depositor again
logout
login_as depositing_user
visit("/notifications?locale=en")
expect(page).to have_content "#{work.title.first} (#{work.id}) was approved by #{publishing_user.email}. Approved in publication_workflow_spec.rb"
expect(page).to have_content "#{work.title.first} (#{work.id}) has been published by #{publishing_user.display_name}. Approved in publication_workflow_spec.rb"

# After publication, works are visible to the public
# Visit the ETD as a public user. It should be visible.
Expand All @@ -87,6 +87,12 @@
Hyrax::Workflow::WorkflowActionService.run(subject: subject, action: sipity_workflow_action, comment: "Unpublished in publication_workflow_spec.rb")
expect(work.to_sipity_entity.reload.workflow_state_name).to eq "unpublished"

# Check unpublished notifications for admin user
login_as publishing_user
visit("/notifications?locale=en")
expect(page).to have_content "#{work.title.first} (#{work.id}) has been unpublished by #{publishing_user.display_name}. Unpublished in publication_workflow_spec.rb"
logout

# After being unpublished, the work will no longer be visible to the public.
visit("/concern/images/#{work.id}")
expect(page).to have_content "The work is not currently available"
Expand Down
43 changes: 43 additions & 0 deletions spec/services/hyrax/workflow/published_notification_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
libdir = File.expand_path('../../../../', __FILE__)
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
require 'rails_helper'
require 'active_fedora/cleaner'
require 'tufts/workflow_setup'
require 'database_cleaner'

RSpec.describe Hyrax::Workflow::PublishedNotification do
before :all do
Tufts::WorkflowSetup.setup
end
let(:depositor) { FactoryGirl.create(:user) }
let(:admin) { FactoryGirl.create(:admin) }
let(:work) { FactoryGirl.create(:pdf, depositor: depositor.user_key) }
let(:ability) { ::Ability.new(depositor) }
let(:recipients) do
{ 'to' => [depositor] }
end
let(:notification) do
current_ability = ::Ability.new(depositor)
admin # ensure admin user exists
attributes = {}
env = Hyrax::Actors::Environment.new(work, current_ability, attributes)
Hyrax::CurationConcern.actor.create(env)
work_global_id = work.to_global_id.to_s
entity = Sipity::Entity.where(proxy_for_global_id: work_global_id).first
described_class.new(entity, '', depositor, recipients)
end
it "can instantiate" do
expect(notification).to be_instance_of(described_class)
end
it "can find depositor" do
expect(notification.depositor).to be_instance_of(::User)
expect(notification.depositor.email).to eq depositor.user_key
end
it "can find admins" do
expect(notification.admins).to be_instance_of(Array)
expect(notification.admins.pluck(:id)).to contain_exactly(admin.id)
end
it "sends notifications to the depositor, application admins and no one else" do
expect(notification.recipients["to"].pluck(:email)).to contain_exactly(depositor.user_key, admin.user_key)
end
end
Loading

0 comments on commit 2b7c8af

Please sign in to comment.