• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

curationexperts / laevigata / 8087b51d-407b-477d-8eec-438dc461fd38

02 Jul 2025 04:57AM UTC coverage: 97.424%. Remained the same
8087b51d-407b-477d-8eec-438dc461fd38

push

circleci

mark-dce
Speed up AttachFilesToWorkJob test

**ISSUE**
The test was creating a new ETD and file, and then running the
job for each example, and then only reading the results. I.E. we
were running expensive setup multiple times with no variation and
only reading (not modifying or acting on) the output.

**RESOLUTION**
Doing the setup and running the job only once reduces the test
time by over 30% (avg 27.9s down to avg 9.8s).

2837 of 2912 relevant lines covered (97.42%)

51.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/lib/workflow_setup.rb
1
# Set up the AdminSets and Workflow for Laevigata
2
require File.expand_path('../../config/environment', __FILE__)
4✔
3
require 'yaml'
4✔
4

5
# Set up the application's initial state: load required roles, create required AdminSets, load appropriate users and workflows
6
class WorkflowSetup
4✔
7
  include SemanticLogger::Loggable
4✔
8

9
  attr_reader :admin_set_owner
4✔
10
  attr_reader :admin_sets_config
4✔
11
  attr_accessor :superusers_config
4✔
12
  ADMIN_SET_OWNER = "admin_set_owner".freeze
4✔
13
  NOTIFICATION_OWNER = "notification_owner".freeze
4✔
14
  DEFAULT_SUPERUSERS_CONFIG = "#{::Rails.root}/config/emory/superusers.yml".freeze
4✔
15
  DEFAULT_ADMIN_SETS_CONFIG = "#{::Rails.root}/config/emory/admin_sets.yml".freeze
4✔
16

17
  # Set up the parameters for
18
  # @param [String] superusers_config a file containing the email addresses of the application's superusers
19
  # @param [String] config_file_dir the directory where the config files reside
20
  # @param [String] schools_config
21
  # @param [String] log_location where should the log files write? Default is STDOUT. /dev/null is also an option for CI builds
22
  def initialize(superusers_config = DEFAULT_SUPERUSERS_CONFIG, admin_sets_config = DEFAULT_ADMIN_SETS_CONFIG, _log_location = STDOUT)
4✔
23
    raise "File #{superusers_config} does not exist" unless File.exist?(superusers_config)
68✔
24
    @superusers_config = YAML.safe_load(File.read(superusers_config))
68✔
25
    raise "File #{admin_sets_config} does not exist" unless File.exist?(admin_sets_config)
68✔
26
    @admin_sets_config = YAML.safe_load(File.read(admin_sets_config))
68✔
27
    logger.info "Initializing new workflow setup with superusers file #{superusers_config} and admin_sets_config files from #{admin_sets_config}"
68✔
28
    Hyrax::RoleRegistry.new.persist_registered_roles! # Ensure we have a managing and a depositing role
68✔
29
    @admin_set_owner = make_superuser(ADMIN_SET_OWNER)
68✔
30
  end
31

32
  # Load the superusers
33
  # Make an AdminSet for each school, with the proper workflow
34
  # Allow any registered user to deposit into any of the AdminSets
35
  # Give superusers every available role in all workflows in all AdminSets
36
  def setup
4✔
37
    make_notification_owner
46✔
38
    load_superusers
46✔
39
    admin_sets.each do |as|
46✔
40
      logger.debug "Attempting to make admin set for #{as}"
54✔
41
      make_admin_set_from_config(as)
54✔
42
    end
43
    load_workflows
46✔
44
    everyone_can_deposit_everywhere
46✔
45
    give_superusers_superpowers
46✔
46
  end
47

48
  # A ::User to own notifications
49
  def make_notification_owner
4✔
50
    u = ::User.find_or_create_by(uid: NOTIFICATION_OWNER)
47✔
51
    u.ppid = NOTIFICATION_OWNER
47✔
52
    u.display_name = "ETD Notification System"
47✔
53
    u.save
47✔
54
  end
55

56
  # Make an AdminSet and assign it a one step mediated deposit workflow
57
  # @param [String] admin_set_title The title of the admin set to create
58
  # @param [String] workflow_name The name of the mediated deposit workflow to enable
59
  def make_mediated_deposit_admin_set(admin_set_title, workflow_name = "emory_one_step_approval")
4✔
60
    a = make_admin_set(admin_set_title)
62✔
61
    activate_mediated_deposit(a, workflow_name)
62✔
62
    a
62✔
63
  end
64

65
  # Given an admin set and a role, return relevant Array of Sipity::Users for the
66
  # currently active workflow
67
  # @param [AdminSet] admin_set
68
  # @param [String|Sipity::Role] role e.g., "approving" "depositing" "managing"
69
  # @return [Array<Sipity::Agent>] An array of Sipity::Agent objects
70
  def users_in_role(admin_set, role)
4✔
71
    return [] unless admin_set.permission_template.available_workflows.exists?(active: true)
231✔
72

73
    role     = Sipity::Role.find_by!(name: role) unless role.is_a?(Sipity::Role)
231✔
74
    workflow = admin_set.permission_template.available_workflows.find_by(active: true)
231✔
75
    wf_role  = Sipity::WorkflowRole.find_by(workflow: workflow, role_id: role)
231✔
76
    return [] unless wf_role
231✔
77

78
    Sipity::Agent.where(id: wf_role.workflow_responsibilities.pluck(:agent_id),
231✔
79
                        proxy_for_type: 'User').to_a
80
  end
81

82
  # Read a config file to figure out what workflow to enable and how to grant approving_role
83
  # @param [String] admin_set_title
84
  # @return [AdminSet]
85
  def make_admin_set_from_config(admin_set_title)
4✔
86
    config = admin_set_config(admin_set_title)
59✔
87
    config["workflow"] || config["workflow"] = "emory_one_step_approval"
59✔
88
    admin_set = make_mediated_deposit_admin_set(admin_set_title, config["workflow"])
59✔
89
    approving_users = []
59✔
90
    config["approving"].each do |approver_uid|
59✔
91
      u = ::User.find_or_create_by(uid: approver_uid)
108✔
92
      u.password = "123456" if set_default_password?
108✔
93
      u.provider = "shibboleth"
108✔
94
      u.ppid = approver_uid # temporary ppid, will get replaced when user signs in with shibboleth
108✔
95
      u.save
108✔
96
      approving_users << u.to_sipity_agent
108✔
97
    end
98
    approval_role = Sipity::Role.find_by!(name: 'approving')
59✔
99
    workflow = admin_set.active_workflow
59✔
100
    workflow.update_responsibilities(role: approval_role, agents: (approving_users.concat users_in_role(admin_set, "approving")))
59✔
101
    if workflow.workflow_roles.map { |workflow_role| workflow_role.role.name }.include?("reviewing")
295✔
102
      reviewing_role = Sipity::Role.find_by!(name: 'reviewing')
59✔
103
      workflow.update_responsibilities(role: reviewing_role, agents: (approving_users.concat users_in_role(admin_set, "reviewing")))
59✔
104
    end
105
    admin_set
59✔
106
  end
107

108
  # Create the admin role, or find it if it exists already
109
  # @return [Role] the admin Role
110
  def admin_role
4✔
111
    Role.find_or_create_by(name: "admin")
1,185✔
112
  end
113

114
  # Load the superusers from a config file
115
  def load_superusers
4✔
116
    admin_role.users = [] # Remove all the admin users every time you reload
57✔
117
    admin_role.save
57✔
118
    @superusers_config["superusers"].each_key do |provider|
57✔
119
      @superusers_config["superusers"][provider].each do |s|
114✔
120
        make_superuser(s, provider)
171✔
121
      end
122
    end
123
  end
124

125
  # Make a superuser
126
  # @param [String] the uid of the superuser
127
  # @return [User] the superuser who was just created
128
  def make_superuser(uid, provider = "database")
4✔
129
    logger.debug "Making superuser #{uid}"
245✔
130
    admin_user = ::User.find_or_create_by(uid: uid)
245✔
131
    admin_user.password = "123456" if set_default_password?
245✔
132
    admin_user.ppid = uid # temporary ppid, will get replaced when user signs in with shibboleth
245✔
133
    admin_user.provider = provider
245✔
134
    admin_user.save
245✔
135
    admin_role.users << admin_user
245✔
136
    admin_role.save
245✔
137
    admin_user
245✔
138
  end
139

140
  # Don't set default passwords in production mode
141
  def set_default_password?
4✔
142
    AuthConfig.use_database_auth? && !Rails.env.production?
353✔
143
  end
144

145
  # return an array of all current superusers
146
  # @return [Array(User)]
147
  def superusers
4✔
148
    raise "No superusers are defined" unless admin_role.users.count > 0
289✔
149
    admin_role.users
289✔
150
  end
151

152
  # Allow anyone with a registered account to deposit into any of the AdminSets
153
  def everyone_can_deposit_everywhere
4✔
154
    AdminSet.all.each do |admin_set|
47✔
155
      next if Hyrax::PermissionTemplateAccess
55✔
156
                .find_by(permission_template_id: admin_set.permission_template.id,
157
                         agent_id:   'registered',
158
                         access:     'deposit',
159
                         agent_type: 'group')
160

161
      admin_set.permission_template.access_grants.create(agent_type: 'group', agent_id: 'registered', access: 'deposit')
55✔
162
      deposit = Sipity::Role.find_by!(name: 'depositing')
55✔
163
      admin_set.permission_template.available_workflows.each do |workflow|
55✔
164
        workflow.update_responsibilities(role: deposit, agents: Hyrax::Group.new('registered'))
110✔
165
      end
166
    end
167
  end
168

169
  # Give superusers the managing role in all AdminSets
170
  # Also give them all workflow roles for all AdminSets
171
  def give_superusers_superpowers
4✔
172
    logger.info "Giving superuser powers to #{superusers.pluck(:ppid)}"
48✔
173
    give_superusers_managing_role
48✔
174
    give_superusers_workflow_roles
48✔
175
  end
176

177
  def superusers_as_sipity_agents
4✔
178
    superusers.map(&:to_sipity_agent)
224✔
179
  end
180

181
  # Give all superusers the managing role all workflows
182
  def give_superusers_managing_role
4✔
183
    AdminSet.all.each do |admin_set|
48✔
184
      admin_set.permission_template.available_workflows.each do |workflow| # .where(active: true) ?
56✔
185
        workflow.update_responsibilities(role: Sipity::Role.where(name: "managing").first, agents: superusers_as_sipity_agents)
112✔
186
      end
187
    end
188
  end
189

190
  def give_superusers_workflow_roles
4✔
191
    AdminSet.all.each do |admin_set|
48✔
192
      admin_set.permission_template.available_workflows.where(active: true).each do |workflow|
56✔
193
        workflow_roles = Sipity::WorkflowRole.where(workflow_id: workflow.id)
56✔
194
        workflow_roles.each do |workflow_role|
56✔
195
          workflow_role_name = Sipity::Role.where(id: workflow_role.role_id).first.name
224✔
196
          next if workflow_role_name == "depositing" || workflow_role_name == "managing"
224✔
197
          union_of_users = superusers_as_sipity_agents.concat(users_in_role(admin_set, workflow_role_name)).uniq
112✔
198
          logger.debug "Granting #{workflow_role_name} to #{union_of_users.map { |u| User.where(id: u.proxy_for_id).first.ppid }.to_sentence}"
760✔
199
          workflow.update_responsibilities(role: Sipity::Role.where(id: workflow_role.role_id), agents: union_of_users)
112✔
200
        end
201
      end
202
    end
203
  end
204

205
  # Make an AdminSet with the given title, belonging to the @admin_set_owner
206
  # @return [AdminSet] the admin set that was just created, or the one that existed already
207
  def make_admin_set(admin_set_title)
4✔
208
    if AdminSet.where(title_sim: admin_set_title).count > 0
66✔
209
      logger.debug "AdminSet #{admin_set_title} already exists."
1✔
210
      return AdminSet.where(title_sim: admin_set_title).first
1✔
211
    end
212
    a = AdminSet.create(title: [admin_set_title])
65✔
213
    Hyrax::AdminSetCreateService.call(admin_set: a, creating_user: @admin_set_owner)
65✔
214
    a
65✔
215
  end
216

217
  # Load the workflows from config/workflows
218
  # Does the same thing as `bin/rails hyrax:workflow:load`
219
  # Note: You MUST create an AdminSet (and its associated PermissionTemplate first)
220
  # If you think you have the right AdminSet, but workflows won't load, check that
221
  # the permission templates didn't get wiped from the database somehow
222
  def load_workflows
4✔
223
    raise "Can't load workflows without a Permission Template. Do you need to make an AdminSet first?" if Hyrax::PermissionTemplate.all.empty?
46✔
224
    Hyrax::Workflow::WorkflowImporter.load_workflows(logger: logger)
46✔
225
    errors = Hyrax::Workflow::WorkflowImporter.load_errors
46✔
226
    abort("Failed to process all workflows:\n  #{errors.join('\n  ')}") unless errors.empty?
46✔
227
  end
228

229
  # Activate a mediated deposit workflow for the given admin_set.
230
  # Default is emory_one_step_approval, but a different value can be passed in.
231
  # The activate! method will DEactivate it if it was already active, so be careful.
232
  # @return [Boolean] true if successful
233
  def activate_mediated_deposit(admin_set, workflow_name = "emory_one_step_approval")
4✔
234
    osmd = admin_set.permission_template.available_workflows.where(name: workflow_name).first
63✔
235
    if osmd.active == true
63✔
236
      logger.debug "AdminSet #{admin_set.title.first} already had workflow #{admin_set.permission_template.available_workflows.where(active: true).first.name}. Not making any changes."
47✔
237
      return true
47✔
238
    end
239
    Sipity::Workflow.activate!(
16✔
240
      permission_template: admin_set.permission_template,
241
      workflow_id: osmd.id
242
    )
243
    logger.debug "AdminSet #{admin_set.title.first} has workflow #{admin_set.permission_template.available_workflows.where(active: true).first.name}"
16✔
244
    true
16✔
245
  end
246

247
  # Return an array of AdminSets that should be set up for the initial workflow
248
  # @return [Array(String)]
249
  def admin_sets
4✔
250
    @admin_sets_config.keys
54✔
251
  end
252

253
  # Given the name of a school, read its config into a Hash
254
  # @param [String] the name of an admin_set
255
  # @return [Hash] a Hash containing approvers and (optionally) workflow for this school
256
  def admin_set_config(school_name)
4✔
257
    raise "Couldn't find expected config for #{school_name}" unless @admin_sets_config[school_name]
61✔
258
    @admin_sets_config[school_name]
60✔
259
  end
260
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc