Skip to content

Commit

Permalink
Implement Change Manager from Scholar
Browse files Browse the repository at this point in the history
  • Loading branch information
bsp3ars committed Oct 5, 2018
1 parent 89ecc9a commit 78ce128
Show file tree
Hide file tree
Showing 32 changed files with 427 additions and 6 deletions.
4 changes: 4 additions & 0 deletions .rubocop.yml
Expand Up @@ -173,3 +173,7 @@ Metrics/CyclomaticComplexity:
Exclude:
- 'app/models/ability.rb'
- 'app/forms/hyrax/forms/batch_upload_form.rb'

Lint/HandleExceptions:
Exclude:
- 'app/controllers/concerns/scholar/works_controller_behavior.rb'
1 change: 1 addition & 0 deletions Gemfile
Expand Up @@ -44,6 +44,7 @@ gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

# gem 'clamav'
gem 'active_attr'
gem 'change_manager', git: "https://github.com/uclibs/change_manager.git", ref: '8d151d1123aa35658f061a63bc72435afdf0ec8a'
gem 'devise'
gem 'devise-guests', '~> 0.6'
gem 'devise-multi_auth', git: 'https://github.com/uclibs/devise-multi_auth', branch: 'rails-5-1'
Expand Down
10 changes: 10 additions & 0 deletions Gemfile.lock
Expand Up @@ -71,6 +71,15 @@ GIT
sass-rails
signet

GIT
remote: https://github.com/uclibs/change_manager.git
revision: 8d151d1123aa35658f061a63bc72435afdf0ec8a
ref: 8d151d1123aa35658f061a63bc72435afdf0ec8a
specs:
change_manager (1.0.0)
activejob
rails

GIT
remote: https://github.com/uclibs/devise-multi_auth
revision: 49073374277f94c3bb2e1cc654c8732da37ec4ce
Expand Down Expand Up @@ -921,6 +930,7 @@ DEPENDENCIES
byebug
capybara (~> 2.4, < 2.18.0)
capybara-maleficent (~> 0.2)
change_manager!
chromedriver-helper
coffee-rails (~> 4.2)
coveralls (~> 0.7.1)
Expand Down
23 changes: 23 additions & 0 deletions app/controllers/concerns/scholar/works_controller_behavior.rb
@@ -0,0 +1,23 @@
# frozen_string_literal: true
# Generated via
# `rails generate hyrax:work GenericWork`

module Scholar
module WorksControllerBehavior
include ChangeManager::ChangeManagerHelper

def create
super
# the to_s_u method must be implemented for every model
editors = params.to_unsafe_hash[curation_concern.class.to_s_u][:permissions_attributes]
queue_notifications_for_editors(editors) if editors
end

def update
super
# the to_s_u method must be implemented for every model
editors = params.to_unsafe_hash[curation_concern.class.to_s_u][:permissions_attributes]
queue_notifications_for_editors(editors) if editors
end
end
end
1 change: 1 addition & 0 deletions app/controllers/hyrax/articles_controller.rb
Expand Up @@ -7,6 +7,7 @@ module Hyrax
class ArticlesController < ApplicationController
# Adds Hyrax behaviors to the controller.
include Hyrax::WorksControllerBehavior
include Scholar::WorksControllerBehavior
include Hyrax::BreadcrumbsForWorks
self.curation_concern_type = ::Article

Expand Down
1 change: 1 addition & 0 deletions app/controllers/hyrax/datasets_controller.rb
Expand Up @@ -7,6 +7,7 @@ module Hyrax
class DatasetsController < ApplicationController
# Adds Hyrax behaviors to the controller.
include Hyrax::WorksControllerBehavior
include Scholar::WorksControllerBehavior
include Hyrax::BreadcrumbsForWorks
self.curation_concern_type = ::Dataset

Expand Down
35 changes: 35 additions & 0 deletions app/controllers/hyrax/depositors_controller.rb
@@ -0,0 +1,35 @@
# frozen_string_literal: true

require Hyrax::Engine.root.join('app/controllers/hyrax/depositors_controller.rb')
module Hyrax
class DepositorsController < ApplicationController
def destroy
grantor = authorize_and_return_grantor
grantee = ::User.from_url_component(params[:id])
send_removed_proxy_email(grantor, grantee) if grantor.can_receive_deposits_from.delete(grantee)
head :ok
end

def send_granted_proxy_email(grantor, grantee)
ChangeManager::EmailManager.queue_change(grantor, 'added_as_proxy', '', grantee)
rescue NotImplementedError # needed for specs and development environments
ChangeManager::EmailManager.skip_sidekiq_for_emails(grantor, 'added_as_proxy', '', grantee)
end

def send_removed_proxy_email(grantor, grantee)
ChangeManager::EmailManager.queue_change(grantor, 'removed_as_proxy', '', grantee)
rescue NotImplementedError # needed for specs and development environments
ChangeManager::EmailManager.skip_sidekiq_for_emails(grantor, 'removed_as_proxy', '', grantee)
end

private

def send_proxy_depositor_added_messages(grantor, grantee)
message_to_grantee = "#{grantor.name} has assigned you as a proxy depositor"
message_to_grantor = "You have assigned #{grantee.name} as a proxy depositor"
::User.batch_user.send_message(grantor, message_to_grantor, "Proxy Depositor Added")
::User.batch_user.send_message(grantee, message_to_grantee, "Proxy Depositor Added")
send_granted_proxy_email(grantor, grantee)
end
end
end
1 change: 1 addition & 0 deletions app/controllers/hyrax/documents_controller.rb
Expand Up @@ -7,6 +7,7 @@ module Hyrax
class DocumentsController < ApplicationController
# Adds Hyrax behaviors to the controller.
include Hyrax::WorksControllerBehavior
include Scholar::WorksControllerBehavior
include Hyrax::BreadcrumbsForWorks
self.curation_concern_type = ::Document

Expand Down
1 change: 1 addition & 0 deletions app/controllers/hyrax/etds_controller.rb
Expand Up @@ -7,6 +7,7 @@ module Hyrax
class EtdsController < ApplicationController
# Adds Hyrax behaviors to the controller.
include Hyrax::WorksControllerBehavior
include Scholar::WorksControllerBehavior
include Hyrax::BreadcrumbsForWorks
self.curation_concern_type = ::Etd

Expand Down
1 change: 1 addition & 0 deletions app/controllers/hyrax/generic_works_controller.rb
Expand Up @@ -7,6 +7,7 @@ module Hyrax
class GenericWorksController < ApplicationController
# Adds Hyrax behaviors to the controller.
include Hyrax::WorksControllerBehavior
include Scholar::WorksControllerBehavior
include Hyrax::BreadcrumbsForWorks
self.curation_concern_type = ::GenericWork

Expand Down
1 change: 1 addition & 0 deletions app/controllers/hyrax/images_controller.rb
Expand Up @@ -7,6 +7,7 @@ module Hyrax
class ImagesController < ApplicationController
# Adds Hyrax behaviors to the controller.
include Hyrax::WorksControllerBehavior
include Scholar::WorksControllerBehavior
include Hyrax::BreadcrumbsForWorks
self.curation_concern_type = ::Image

Expand Down
1 change: 1 addition & 0 deletions app/controllers/hyrax/media_controller.rb
Expand Up @@ -7,6 +7,7 @@ module Hyrax
class MediaController < ApplicationController
# Adds Hyrax behaviors to the controller.
include Hyrax::WorksControllerBehavior
include Scholar::WorksControllerBehavior
include Hyrax::BreadcrumbsForWorks
self.curation_concern_type = ::Medium
# Use this line if you want to use a custom presenter
Expand Down
1 change: 1 addition & 0 deletions app/controllers/hyrax/student_works_controller.rb
Expand Up @@ -7,6 +7,7 @@ module Hyrax
class StudentWorksController < ApplicationController
# Adds Hyrax behaviors to the controller.
include Hyrax::WorksControllerBehavior
include Scholar::WorksControllerBehavior
include Hyrax::BreadcrumbsForWorks
self.curation_concern_type = ::StudentWork

Expand Down
45 changes: 45 additions & 0 deletions app/helpers/change_manager/change_manager_helper.rb
@@ -0,0 +1,45 @@
# frozen_string_literal: true
# helper for the WorksControllerBehavior class
# cleaner to keep all change manager code in here
module ChangeManager
module ChangeManagerHelper
def queue_notifications_for_editors(editors)
editors.each do |editor_wrapper|
editor = editor_wrapper[1]
EmailManager.queue_change(curation_concern.depositor, 'added_as_editor', curation_concern.id, editor['name']) if new_editor? editor
# uncomment this once the `Ldp::Gone` error is resolved
# elsif removed_editor? editor
# EmailManager.queue_change(curation_concern.depositor, 'removed_as_editor', curation_concern.id, editor[:name])
# end
end
rescue NotImplementedError
editors.each do |editor_wrapper|
editor = editor_wrapper[1]
EmailManager.skip_sidekiq_for_emails(curation_concern.depositor, 'added_as_editor', curation_concern.id, editor['name']) if new_editor? editor
# uncomment this once the `Ldp::Gone` error is resolved
# elsif removed_editor? editor
# EmailManager.skip_sidekiq_for_emails(curation_concern.depositor, 'removed_as_editor', curation_concern.id, editor['name'])
# end
end
end

private

def new_editor?(editor)
edit_access?(editor) && name_key?(editor)
end

# implement once Ldp::Gone error is resolved
# def removed_editor?(_editor)
# false
# end

def name_key?(hash)
hash.key? 'name'
end

def edit_access?(hash)
hash.key?('access') && hash['access'] == 'edit'
end
end
end
12 changes: 12 additions & 0 deletions app/jobs/change_manager/process_change_job.rb
@@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'yaml'
module ChangeManager
class ProcessChangeJob < ActiveJob::Base
queue_as :change

def perform(change_id)
config_file ||= YAML.load_file(Rails.root.join('config', 'change_manager_config.yml'))
config_file['manager_class'].constantize.process_change(change_id)
end
end
end
8 changes: 3 additions & 5 deletions app/mailers/change_manager/scholar_notification_mailer.rb
@@ -1,20 +1,18 @@
# frozen_string_literal: true

###
# This mailer makes many assumptions as to the content contained in changes. Take care to ensure these assumptions are met
# or create your own mailer that extends ChangeManager::NotificationMailer
####

require 'yaml'

module ChangeManager
class ScholarNotificationMailer < ChangeManager::NotificationMailer
def notify_changes(changes)
@changes = changes
@change_types ||= YAML.load_file(Rails.root.join('path', 'to'))
subject = 'Changes to your ' + @change_types[changes.first.change_type]['print'] + ' status in ' + t('hyrax.product_name')
@change_types ||= YAML.load_file(Rails.root.join('config', 'change_types.yml'))
subject = 'Changes to your ' + @change_types[changes.first.change_type]['print'] + ' status in Scholar@UC.'
mail(to: changes.first.target,
from: t('hyrax.product_email'),
from: 'scholar@uc.edu',
subject: subject).deliver
end
end
Expand Down
14 changes: 14 additions & 0 deletions app/models/concerns/change_manager/comparison_concern.rb
@@ -0,0 +1,14 @@
# frozen_string_literal: true
module ChangeManager
module ComparisonConcern
extend ActiveSupport::Concern

def proxy_change?
change_type == 'added_as_proxy' || change_type == 'removed_as_proxy'
end

def editor_change?
change_type == 'added_as_editor' || change_type == 'removed_as_editor'
end
end
end
51 changes: 51 additions & 0 deletions app/services/change_manager/email_manager.rb
@@ -0,0 +1,51 @@
# frozen_string_literal: true
module ChangeManager
class EmailManager
extend ChangeManager::Manager

def self.queue_change(owner, change_type, context, target)
change_id = Change.new_change(owner, change_type, context, target)
ChangeManager::ProcessChangeJob.set(wait: 15.minutes).perform_later(change_id)
end

def self.skip_sidekiq_for_emails(owner, change_type, context, target)
# Note: For some reason, it duplicates the items in the final email, but only when not using sidekiq
change_id = Change.new_change(owner, change_type, context, target)
process_change change_id
end

def self.process_change(change_id)
change = Change.find change_id
return if change.cancelled?
verified_changes = process_changes_similar_to change
notify_target_of verified_changes unless verified_changes.empty?
true
end

def self.notify_target_of(changes)
grouped_changes = group_changes(changes)
if grouped_changes['proxies']
grouped_changes['proxies'].each(&:notify) if ChangeManager::ScholarNotificationMailer.notify_changes(grouped_changes['proxies']).deliver
end

return unless grouped_changes['editors']
grouped_changes['editors'].each(&:notify) if ChangeManager::ScholarNotificationMailer.notify_changes(grouped_changes['editors']).deliver
end

def self.group_changes(changes)
proxy_changes = []
editor_changes = []
changes.each do |change|
if change.proxy_change?
proxy_changes << change
elsif change.editor_change?
editor_changes << change
end
end
grouped_changes = {}
grouped_changes['proxies'] = proxy_changes unless proxy_changes.empty?
grouped_changes['editors'] = editor_changes unless editor_changes.empty?
grouped_changes
end
end
end
@@ -0,0 +1,14 @@
<%= User.find_by_email(@changes.first.owner).name %> has added or removed you as an editor to the following works in Scholar@UC:

<ul>
<% @changes.each do |change| %>
<% work_title = ActiveFedora::Base.find(change.context).title.first %>
<% work_url = File.join(Rails.configuration.application_root_url, 'show', change.context) %>
<li>
<%= @change_types[change.change_type]['human_readable'] %>
<%= link_to work_title, work_url %>
</li>
<% end %>
</ul>

An editor can modify all metadata for a work and upload/delete files for a work. If you feel that this was made in error, please contact the <a href="mailto:scholar@uc.edu">Scholar@UC</a> team.
@@ -0,0 +1,3 @@
<%= User.find_by_email(@changes.first.owner).name %> has <%= @change_types[@changes.first.change_type]['human_readable'] %>
you as a proxy in Scholar@UC. A proxy can create and upload files on behalf of another user as well as edit, or delete those
corresponding works and files. If you feel that this was made in error, <a href="mailto:scholar@uc.edu">Scholar@UC team</a>.
@@ -0,0 +1,12 @@
<p>Dear <%= User.find_by_email(@changes.first.target).name %>:</p>

<% if @changes.first.proxy_change? %>
<%= render 'proxy_changes' %>
<% elsif @changes.first.editor_change? %>
<%= render 'editor_changes' %>
<% end %>

<p>
Thanks,
Scholar@UC
</p>
1 change: 1 addition & 0 deletions config/change_manager_config.yml
@@ -0,0 +1 @@
manager_class: ChangeManager::EmailManager
24 changes: 24 additions & 0 deletions config/change_types.yml
@@ -0,0 +1,24 @@
added_as_proxy:
print: proxy
inverse: removed_as_proxy
human_readable: added
removed_as_proxy:
print: proxy
inverse: added_as_proxy
human_readable: removed
added_as_editor:
print: editor
inverse: removed_as_editor
human_readable: Added as an editor to
removed_as_editor:
print: editor
inverse: added_as_editor
human_readable: Removed as an editor from
embargo_set:
print: embargo
inverse: embargo_lifted
human_readable: An embargo has been set
embargo_lifted:
print: Emboargo lifted
inverse: embargo
human_readable: An embargo has been lifted
2 changes: 2 additions & 0 deletions config/initializers/change_manager_init.rb
@@ -0,0 +1,2 @@
# frozen_string_literal: true
ChangeManager::Change.send :include, ChangeManager::ComparisonConcern
1 change: 1 addition & 0 deletions config/sidekiq.yml
Expand Up @@ -4,3 +4,4 @@ max_retries: 3
- default
- ingest
- event
- change
13 changes: 13 additions & 0 deletions db/migrate/20181001000000_create_change_manager_changes.rb
@@ -0,0 +1,13 @@
class CreateChangeManagerChanges < ActiveRecord::Migration[5.1]
def change
create_table :change_manager_changes do |t|
t.string :change_type
t.boolean :cancelled
t.datetime :notified
t.string :owner
t.string :target
t.string :context
t.timestamps
end
end
end

0 comments on commit 78ce128

Please sign in to comment.