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

pulibrary / pdc_describe / 5db21940-59bd-4742-a25d-02e5e58d6646

pending completion
5db21940-59bd-4742-a25d-02e5e58d6646

Pull #1014

circleci

Carolyn Cole
Creating a folder in Amazon so the curators do not need to do it by hand fixes #1001
Pull Request #1014: Creating a folder in Amazon so the curators do not need to do it by hand

3 of 3 new or added lines in 2 files covered. (100.0%)

1703 of 1872 relevant lines covered (90.97%)

80.56 hits per line

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

79.34
/app/controllers/works_controller.rb
1
# frozen_string_literal: true
2

3
require "nokogiri"
1✔
4
require "open-uri"
1✔
5

6
# rubocop:disable Metrics/ClassLength
7
class WorksController < ApplicationController
1✔
8
  include ERB::Util
1✔
9
  around_action :rescue_aasm_error, only: [:approve, :withdraw, :resubmit, :validate, :create]
1✔
10

11
  skip_before_action :authenticate_user!
1✔
12
  before_action :authenticate_user!, unless: :public_request?
1✔
13

14
  ##
15
  # Public requests are requests that do not require authentication.
16
  # This is to enable PDC Discovery to index approved content via the RSS feed and
17
  # .json calls to individual works without needing to log in as a user.
18
  # Note that only approved works can be fetched for indexing.
19
  def public_request?
1✔
20
    return true if action_name == "index" && request.format.symbol == :rss
51✔
21
    return true if action_name == "show" && request.format.symbol == :json && Work.find(params[:id]).state == "approved"
50✔
22
    false
50✔
23
  end
24

25
  def index
1✔
26
    @works = Work.all
3✔
27
    respond_to do |format|
3✔
28
      format.html
3✔
29
      format.rss { render layout: false }
4✔
30
    end
31
  end
32

33
  # Renders the "step 0" information page before creating a new dataset
34
  def new
1✔
35
    if wizard_mode?
2✔
36
      render "new_submission"
1✔
37
    else
38
      @work = Work.new(created_by_user_id: current_user.id, collection: current_user.default_collection)
1✔
39
    end
40
  end
41

42
  def create
1✔
43
    @work = Work.new(created_by_user_id: current_user.id, collection_id: params_collection_id, user_entered_doi: params["doi"].present?)
2✔
44
    @work.resource = FormToResourceService.convert(params, @work)
2✔
45
    if @work.valid?
2✔
46
      @work.draft!(current_user)
2✔
47
      redirect_to work_url(@work), notice: "Work was successfully created."
2✔
48
    else
49
      render :new, status: :unprocessable_entity
×
50
    end
51
  end
52

53
  # Creates the new dataset
54
  def new_submission
1✔
55
    default_collection_id = current_user.default_collection.id
1✔
56
    work = Work.new(created_by_user_id: current_user.id, collection_id: default_collection_id)
1✔
57
    work.resource = FormToResourceService.convert(params, work)
1✔
58
    work.draft!(current_user)
1✔
59
    redirect_to edit_work_path(work, wizard: true)
1✔
60
  end
61

62
  ##
63
  # Show the information for the dataset with the given id
64
  # When requested as .json, return the internal json resource
65
  def show
1✔
66
    @work = Work.find(params[:id])
4✔
67
    @changes =  WorkActivity.changes_for_work(@work.id)
4✔
68
    @messages = WorkActivity.messages_for_work(@work.id)
4✔
69

70
    respond_to do |format|
4✔
71
      format.html do
4✔
72
        # Ensure that the Work belongs to a Collection
73
        @collection = @work.collection
4✔
74
        raise(Work::InvalidCollectionError, "The Work #{@work.id} does not belong to any Collection") unless @collection
4✔
75

76
        @can_curate = current_user.can_admin?(@collection)
4✔
77
        @work.mark_new_notifications_as_read(current_user.id)
4✔
78
      end
79
      format.json { render json: @work.to_json }
4✔
80
    end
81
  end
82

83
  def file_list
1✔
84
    @work = Work.find(params[:id])
3✔
85
    render json: @work.pre_curation_uploads_fast
3✔
86
  end
87

88
  def resolve_doi
1✔
89
    @work = Work.find_by_doi(params[:doi])
3✔
90
    redirect_to @work
2✔
91
  end
92

93
  def resolve_ark
1✔
94
    @work = Work.find_by_ark(params[:ark])
3✔
95
    redirect_to @work
2✔
96
  end
97

98
  # GET /works/1/edit
99
  def edit
1✔
100
    @work = Work.find(params[:id])
3✔
101
    if current_user && @work.editable_by?(current_user)
3✔
102
      if @work.approved? && !@work.administered_by?(current_user)
2✔
103
        Honeybadger.notify("Can not edit work: #{@work.id} is approved but #{current_user} is not admin")
1✔
104
        redirect_to root_path, notice: I18n.t("works.uneditable.approved")
1✔
105
      else
106
        @uploads = @work.uploads
1✔
107
        @wizard_mode = wizard_mode?
1✔
108
        render "edit"
1✔
109
      end
110
    else
111
      Honeybadger.notify("Can not edit work: #{@work.id} is not editable by #{current_user}")
1✔
112
      redirect_to root_path, notice: I18n.t("works.uneditable.privs")
1✔
113
    end
114
  end
115

116
  def update
1✔
117
    @work = Work.find(params[:id])
6✔
118
    if current_user.blank? || !@work.editable_by?(current_user)
6✔
119
      Honeybadger.notify("Can not update work: #{@work.id} is not editable by #{current_user}")
×
120
      redirect_to root_path, notice: I18n.t("works.uneditable.privs")
×
121
    elsif !@work.editable_in_current_state?(current_user)
6✔
122
      Honeybadger.notify("Can not update work: #{@work.id} is not editable in current state by #{current_user}")
×
123
      redirect_to root_path, notice: I18n.t("works.uneditable.approved")
×
124
    else
125
      update_work
6✔
126
    end
127
  end
128

129
  # Prompt to select how to submit their files
130
  def attachment_select
1✔
131
    @work = Work.find(params[:id])
1✔
132
    @wizard_mode = true
1✔
133
  end
134

135
  # User selected a specific way to submit their files
136
  def attachment_selected
1✔
137
    @work = Work.find(params[:id])
×
138
    @wizard_mode = true
×
139
    @work.files_location = params["attachment_type"]
×
140
    @work.save!
×
141

142
    # create a directory for the work if the curator will need to move files by hand
143
    @work.s3_query_service.create_directory if @work.files_location != "file_upload"
×
144

145
    next_url = case @work.files_location
×
146
               when "file_upload"
147
                 work_file_upload_url(@work)
×
148
               when "file_cluster"
149
                 work_file_cluster_url(@work)
×
150
               else
151
                 work_file_other_url(@work)
×
152
               end
153
    redirect_to next_url
×
154
  end
155

156
  # Allow user to upload files directly
157
  def file_upload
1✔
158
    @work = Work.find(params[:id])
1✔
159
  end
160

161
  def file_uploaded
1✔
162
    @work = Work.find(params[:id])
3✔
163
    if pre_curation_uploads_param
3✔
164
      @work.pre_curation_uploads.attach(pre_curation_uploads_param)
2✔
165
      @work.save!
1✔
166
    end
167

168
    redirect_to(work_review_path)
2✔
169
  rescue StandardError => active_storage_error
170
    Rails.logger.error("Failed to attach the file uploads for the work #{@work.doi}: #{active_storage_error}")
1✔
171
    flash[:notice] = "Failed to attach the file uploads for the work #{@work.doi}: #{active_storage_error}. Please contact rdss@princeton.edu for assistance."
1✔
172

173
    redirect_to work_file_upload_path(@work)
1✔
174
  end
175

176
  # Allow user to indicate where their files are located in the PUL Research Cluster
177
  def file_cluster
1✔
178
    @work = Work.find(params[:id])
1✔
179
  end
180

181
  # Allow user to indicate where their files are located in the WWW
182
  def file_other
1✔
183
    @work = Work.find(params[:id])
1✔
184
  end
185

186
  def review
1✔
187
    @work = Work.find(params[:id])
1✔
188
    if request.method == "POST"
1✔
189
      @work.location_notes = params["location_notes"]
1✔
190
      @work.save!
1✔
191
    end
192
  end
193

194
  def validate
1✔
195
    @work = Work.find(params[:id])
×
196
    @work.submission_notes = params["submission_notes"]
×
197
    @uploads = @work.uploads
×
198
    @wizard_mode = true
×
199
    @work.complete_submission!(current_user)
×
200
    redirect_to user_url(current_user)
×
201
  end
202

203
  def approve
1✔
204
    @work = Work.find(params[:id])
×
205
    @work.approve!(current_user)
×
206
    redirect_to work_path(@work)
×
207
  end
208

209
  def withdraw
1✔
210
    @work = Work.find(params[:id])
2✔
211
    @work.withdraw!(current_user)
2✔
212
    redirect_to work_path(@work)
1✔
213
  end
214

215
  def resubmit
1✔
216
    @work = Work.find(params[:id])
2✔
217
    @work.resubmit!(current_user)
2✔
218
    redirect_to work_path(@work)
1✔
219
  end
220

221
  def assign_curator
1✔
222
    work = Work.find(params[:id])
3✔
223
    work.change_curator(params[:uid], current_user)
3✔
224
    if work.errors.count > 0
2✔
225
      render json: { errors: work.errors.map(&:type) }, status: :bad_request
×
226
    else
227
      render json: {}
2✔
228
    end
229
  rescue => ex
230
    Rails.logger.error("Error changing curator for work: #{work.id}. Exception: #{ex.message}")
1✔
231
    render json: { errors: ["Cannot save dataset"] }, status: :bad_request
1✔
232
  end
233

234
  def add_message
1✔
235
    work = Work.find(params[:id])
2✔
236
    if params["new-message"].present?
2✔
237
      new_message_param = params["new-message"]
2✔
238
      sanitized_new_message = html_escape(new_message_param)
2✔
239

240
      work.add_message(sanitized_new_message, current_user.id)
2✔
241
    end
242
    redirect_to work_path(id: params[:id])
2✔
243
  end
244

245
  def add_provenance_note
1✔
246
    work = Work.find(params[:id])
×
247
    if params["new-provenance-note"].present?
×
248
      new_date = params["new-provenance-date"]
×
249
      new_note = html_escape(params["new-provenance-note"])
×
250

251
      work.add_provenance_note(new_date, new_note, current_user.id)
×
252
    end
253
    redirect_to work_path(id: params[:id])
×
254
  end
255

256
  # Outputs the Datacite XML representation of the work
257
  def datacite
1✔
258
    work = Work.find(params[:id])
1✔
259
    render xml: work.to_xml
1✔
260
  end
261

262
  def datacite_validate
1✔
263
    @errors = []
×
264
    @work = Work.find(params[:id])
×
265
    datacite_xml = Nokogiri::XML(@work.to_xml)
×
266
    schema_location = Rails.root.join("config", "schema")
×
267
    Dir.chdir(schema_location) do
×
268
      xsd = Nokogiri::XML::Schema(File.read("datacite_4_4.xsd"))
×
269
      xsd.validate(datacite_xml).each do |error|
×
270
        @errors << error
×
271
      end
272
    end
273
  end
274

275
  private
1✔
276

277
    def work_params
1✔
278
      params[:work] || params
6✔
279
    end
280

281
    def patch_params
1✔
282
      return {} unless params.key?(:patch)
8✔
283

284
      params[:patch]
6✔
285
    end
286

287
    def pre_curation_uploads_param
1✔
288
      return if patch_params.nil?
4✔
289

290
      patch_params[:pre_curation_uploads]
4✔
291
    end
292

293
    def rescue_aasm_error
1✔
294
      yield
6✔
295
    rescue AASM::InvalidTransition => error
296
      message = error.message
2✔
297
      if @work.errors.count > 0
2✔
298
        message = @work.errors.to_a.join(", ")
×
299
      end
300
      Honeybadger.notify("Invalid #{@work.current_transition}: #{error.message} errors: #{message}")
2✔
301
      @errors = ["Cannot #{@work.current_transition}: #{message}"]
2✔
302
      render error_action, status: :unprocessable_entity
2✔
303
    end
304

305
    def error_action
1✔
306
      if action_name == "create"
2✔
307
        :new
×
308
      elsif action_name == "validate"
2✔
309
        :edit
×
310
      else
311
        :show
2✔
312
      end
313
    end
314

315
    def wizard_mode?
1✔
316
      params[:wizard] == "true"
9✔
317
    end
318

319
    def update_work
1✔
320
      @wizard_mode = wizard_mode?
6✔
321
      upload_service = WorkUploadsEditService.new(@work, current_user)
6✔
322
      if @work.approved?
6✔
323
        upload_keys = work_params[:deleted_uploads] || []
2✔
324
        deleted_uploads = upload_service.find_post_curation_uploads(upload_keys: upload_keys)
2✔
325

326
        return head(:forbidden) unless deleted_uploads.empty?
2✔
327
      else
328
        @work = upload_service.update_precurated_file_list(work_params)
4✔
329
      end
330

331
      process_updates
5✔
332
    end
333

334
    def update_params
1✔
335
      {
336
        collection_id: params_collection_id,
10✔
337
        resource: FormToResourceService.convert(params, @work)
338
      }
339
    end
340

341
    def process_updates
1✔
342
      resource_before = @work.resource
5✔
343
      if @work.update(update_params)
5✔
344

345
        resource_compare = ResourceCompareService.new(resource_before, update_params[:resource])
5✔
346
        @work.log_changes(resource_compare, current_user.id)
5✔
347

348
        if @wizard_mode
5✔
349
          redirect_to work_attachment_select_url(@work)
1✔
350
        else
351
          redirect_to work_url(@work), notice: "Work was successfully updated."
4✔
352
        end
353
      else
354
        @uploads = @work.uploads
×
355
        render :edit, status: :unprocessable_entity
×
356
      end
357
    end
358

359
    def params_collection_id
1✔
360
      # Do not allow a nil for the collection id
361
      @params_collection_id ||= begin
12✔
362
        collection_id = params[:collection_id]
6✔
363
        if collection_id.blank?
6✔
364
          collection_id = current_user.default_collection.id
1✔
365
          Honeybadger.notify("We got a nil collection as part of the parameters #{params} #{request}")
1✔
366
        end
367
        collection_id
6✔
368
      end
369
    end
370
end
371
# rubocop:enable Metrics/ClassLength
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

© 2025 Coveralls, Inc