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

pulibrary / pdc_describe / 7031ff5b-e2d7-4285-af8b-e7b55adfc48a

pending completion
7031ff5b-e2d7-4285-af8b-e7b55adfc48a

Pull #899

circleci

mccalluc
Finish removal of explicit if-then in js
Pull Request #899: Move messages up to sidebar on the right which can be toggled

1623 of 1788 relevant lines covered (90.77%)

105.5 hits per line

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

74.04
/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
157✔
21
    return true if action_name == "show" && request.format.symbol == :json && Work.find(params[:id]).state == "approved"
157✔
22
    false
157✔
23
  end
24

25
  def index
1✔
26
    @works = Work.all
×
27
    respond_to do |format|
×
28
      format.html
×
29
      format.rss { render layout: false }
×
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?
12✔
36
      render "new_submission"
4✔
37
    else
38
      @work = Work.new(created_by_user_id: current_user.id, collection: current_user.default_collection)
8✔
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?)
11✔
44
    @work.resource = FormToResourceService.convert(params, @work)
11✔
45
    if @work.valid?
11✔
46
      @work.draft!(current_user)
9✔
47
      redirect_to work_url(@work), notice: "Work was successfully created."
8✔
48
    else
49
      render :new, status: :unprocessable_entity
2✔
50
    end
51
  end
52

53
  # Creates the new dataset
54
  def new_submission
1✔
55
    default_collection_id = current_user.default_collection.id
4✔
56
    work = Work.new(created_by_user_id: current_user.id, collection_id: default_collection_id)
4✔
57
    work.resource = FormToResourceService.convert(params, work)
4✔
58
    work.draft!(current_user)
4✔
59
    redirect_to edit_work_path(work, wizard: true)
4✔
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])
48✔
67
    # check if anything was added in S3 since we last viewed this object
68
    @work.attach_s3_resources
48✔
69
    @changes =  WorkActivity.changes_for_work(@work.id)
48✔
70
    @messages = WorkActivity.messages_for_work(@work.id)
48✔
71

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

78
        @can_curate = current_user.can_admin?(@collection)
47✔
79
        @work.mark_new_notifications_as_read(current_user.id)
47✔
80
      end
81
      format.json { render json: @work.to_json }
48✔
82
    end
83
  end
84

85
  def resolve_doi
1✔
86
    @work = Work.find_by_doi(params[:doi])
×
87
    redirect_to @work
×
88
  end
89

90
  def resolve_ark
1✔
91
    @work = Work.find_by_ark(params[:ark])
×
92
    redirect_to @work
×
93
  end
94

95
  # GET /works/1/edit
96
  def edit
1✔
97
    @work = Work.find(params[:id])
23✔
98
    if current_user && @work.editable_by?(current_user)
23✔
99
      if @work.approved? && !@work.administered_by?(current_user)
21✔
100
        redirect_to root_path, notice: I18n.t("works.approved.uneditable")
×
101
      else
102
        @uploads = @work.uploads
21✔
103
        @wizard_mode = wizard_mode?
21✔
104
        render "edit"
21✔
105
      end
106
    else
107
      Rails.logger.warn("Unauthorized attempt to edit work #{@work.id} by user #{current_user.uid}")
2✔
108
      redirect_to root_path
2✔
109
    end
110
  end
111

112
  def update
1✔
113
    @work = Work.find(params[:id])
14✔
114
    if current_user.blank? || !@work.editable_by?(current_user)
14✔
115
      Rails.logger.warn("Unauthorized attempt to update work #{@work.id} by user #{current_user.uid}")
×
116
      redirect_to root_path
×
117
    elsif @work.approved? && @work.submitted_by?(current_user)
14✔
118
      redirect_to root_path, notice: I18n.t("works.approved.uneditable")
×
119
    else
120
      update_work
14✔
121
    end
122
  end
123

124
  # Prompt to select how to submit their files
125
  def attachment_select
1✔
126
    @work = Work.find(params[:id])
5✔
127
    @wizard_mode = true
5✔
128
  end
129

130
  # User selected a specific way to submit their files
131
  def attachment_selected
1✔
132
    @work = Work.find(params[:id])
5✔
133
    @wizard_mode = true
5✔
134
    @work.files_location = params["attachment_type"]
5✔
135
    @work.save!
5✔
136
    next_url = case @work.files_location
5✔
137
               when "file_upload"
138
                 work_file_upload_url(@work)
2✔
139
               when "file_cluster"
140
                 work_file_cluster_url(@work)
×
141
               else
142
                 work_file_other_url(@work)
3✔
143
               end
144
    redirect_to next_url
5✔
145
  end
146

147
  # Allow user to upload files directly
148
  def file_upload
1✔
149
    @work = Work.find(params[:id])
2✔
150
  end
151

152
  def file_uploaded
1✔
153
    @work = Work.find(params[:id])
2✔
154
    if pre_curation_uploads_param
2✔
155
      @work.pre_curation_uploads.attach(pre_curation_uploads_param)
1✔
156
      @work.save!
1✔
157
    end
158

159
    redirect_to(work_review_path)
2✔
160
  rescue StandardError => active_storage_error
161
    Rails.logger.error("Failed to attach the file uploads for the work #{@work.doi}: #{active_storage_error}")
×
162
    flash[:notice] = "Failed to attach the file uploads for the work #{@work.doi}: #{active_storage_error}. Please contact rdss@princeton.edu for assistance."
×
163

164
    redirect_to work_file_upload_path(@work)
×
165
  end
166

167
  # Allow user to indicate where their files are located in the PUL Research Cluster
168
  def file_cluster
1✔
169
    @work = Work.find(params[:id])
×
170
  end
171

172
  # Allow user to indicate where their files are located in the WWW
173
  def file_other
1✔
174
    @work = Work.find(params[:id])
3✔
175
  end
176

177
  def review
1✔
178
    @work = Work.find(params[:id])
5✔
179
    if request.method == "POST"
5✔
180
      @work.location_notes = params["location_notes"]
3✔
181
      @work.save!
3✔
182
    end
183
  end
184

185
  def validate
1✔
186
    @work = Work.find(params[:id])
13✔
187
    @work.submission_notes = params["submission_notes"]
13✔
188
    @uploads = @work.uploads
13✔
189
    @wizard_mode = true
13✔
190
    @work.complete_submission!(current_user)
13✔
191
    redirect_to user_url(current_user)
12✔
192
  end
193

194
  def approve
1✔
195
    @work = Work.find(params[:id])
3✔
196
    @work.approve!(current_user)
3✔
197
    redirect_to work_path(@work)
3✔
198
  end
199

200
  def withdraw
1✔
201
    @work = Work.find(params[:id])
×
202
    @work.withdraw!(current_user)
×
203
    redirect_to work_path(@work)
×
204
  end
205

206
  def resubmit
1✔
207
    @work = Work.find(params[:id])
×
208
    @work.resubmit!(current_user)
×
209
    redirect_to work_path(@work)
×
210
  end
211

212
  def assign_curator
1✔
213
    work = Work.find(params[:id])
×
214
    work.change_curator(params[:uid], current_user)
×
215
    if work.errors.count > 0
×
216
      render json: { errors: work.errors.map(&:type) }, status: :bad_request
×
217
    else
218
      render json: {}
×
219
    end
220
  rescue => ex
221
    Rails.logger.error("Error changing curator for work: #{work.id}. Exception: #{ex.message}")
×
222
    render json: { errors: ["Cannot save dataset"] }, status: :bad_request
×
223
  end
224

225
  def add_message
1✔
226
    work = Work.find(params[:id])
4✔
227
    if params["new-message"].present?
4✔
228
      new_message_param = params["new-message"]
4✔
229
      sanitized_new_message = html_escape(new_message_param)
4✔
230

231
      work.add_message(sanitized_new_message, current_user.id)
4✔
232
    end
233
    redirect_to work_path(id: params[:id])
4✔
234
  end
235

236
  def add_provenance_note
1✔
237
    work = Work.find(params[:id])
×
238
    if params["new-provenance-note"].present?
×
239
      new_date = params["new-provenance-date"]
×
240
      new_note = html_escape(params["new-provenance-note"])
×
241

242
      work.add_provenance_note(new_date, new_note, current_user.id)
×
243
    end
244
    redirect_to work_path(id: params[:id])
×
245
  end
246

247
  # Outputs the Datacite XML representation of the work
248
  def datacite
1✔
249
    work = Work.find(params[:id])
×
250
    render xml: work.to_xml
×
251
  end
252

253
  def datacite_validate
1✔
254
    @errors = []
×
255
    @work = Work.find(params[:id])
×
256
    datacite_xml = Nokogiri::XML(@work.to_xml)
×
257
    schema_location = Rails.root.join("config", "schema")
×
258
    Dir.chdir(schema_location) do
×
259
      xsd = Nokogiri::XML::Schema(File.read("datacite_4_4.xsd"))
×
260
      xsd.validate(datacite_xml).each do |error|
×
261
        @errors << error
×
262
      end
263
    end
264
  end
265

266
  private
1✔
267

268
    def work_params
1✔
269
      params[:work] || params
14✔
270
    end
271

272
    def patch_params
1✔
273
      return {} unless params.key?(:patch)
6✔
274

275
      params[:patch]
4✔
276
    end
277

278
    def pre_curation_uploads_param
1✔
279
      return if patch_params.nil?
3✔
280

281
      patch_params[:pre_curation_uploads]
3✔
282
    end
283

284
    def rescue_aasm_error
1✔
285
      yield
27✔
286
    rescue AASM::InvalidTransition => error
287
      message = error.message
2✔
288
      if @work.errors.count > 0
2✔
289
        message = @work.errors.to_a.join(", ")
2✔
290
      end
291
      logger.warn("Invalid #{@work.current_transition}: #{error.message} errors: #{message}")
2✔
292
      @errors = ["Cannot #{@work.current_transition}: #{message}"]
2✔
293
      render error_action, status: :unprocessable_entity
2✔
294
    end
295

296
    def error_action
1✔
297
      if action_name == "create"
2✔
298
        :new
1✔
299
      elsif action_name == "validate"
1✔
300
        :edit
1✔
301
      else
302
        :show
×
303
      end
304
    end
305

306
    def wizard_mode?
1✔
307
      params[:wizard] == "true"
47✔
308
    end
309

310
    def update_work
1✔
311
      @wizard_mode = wizard_mode?
14✔
312
      upload_service = WorkUploadsEditService.new(@work, current_user)
14✔
313
      if @work.approved?
14✔
314
        upload_keys = work_params[:deleted_uploads] || []
×
315
        deleted_uploads = upload_service.find_post_curation_uploads(upload_keys: upload_keys)
×
316

317
        return head(:forbidden) unless deleted_uploads.empty?
×
318
      else
319
        @work = upload_service.update_precurated_file_list(work_params)
14✔
320
      end
321

322
      process_updates
14✔
323
    end
324

325
    def update_params
1✔
326
      {
327
        collection_id: params_collection_id,
28✔
328
        resource: FormToResourceService.convert(params, @work)
329
      }
330
    end
331

332
    def process_updates
1✔
333
      resource_before = @work.resource
14✔
334
      if @work.update(update_params)
14✔
335

336
        resource_compare = ResourceCompareService.new(resource_before, update_params[:resource])
14✔
337
        @work.log_changes(resource_compare, current_user.id)
14✔
338

339
        if @wizard_mode
14✔
340
          redirect_to work_attachment_select_url(@work)
5✔
341
        else
342
          redirect_to work_url(@work), notice: "Work was successfully updated."
9✔
343
        end
344
      else
345
        @uploads = @work.uploads
×
346
        render :edit, status: :unprocessable_entity
×
347
      end
348
    end
349

350
    def params_collection_id
1✔
351
      # Do not allow a nil for the collection id
352
      @params_collection_id ||= begin
39✔
353
        collection_id = params[:collection_id]
25✔
354
        if collection_id.blank?
25✔
355
          collection_id = current_user.default_collection.id
×
356
          Honeybadger.notify("We got a nil collection as part of the parameters #{params} #{request}")
×
357
        end
358
        collection_id
25✔
359
      end
360
    end
361
end
362
# 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