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

pulibrary / pdc_describe / 95ff1d10-5774-4415-8b66-ffb4f4f58024

pending completion
95ff1d10-5774-4415-8b66-ffb4f4f58024

Pull #725

circleci

Carolyn Cole
Updating manifest not to include the javascript for edit This seems to do nothing, so I am removing it
Pull Request #725: Updating manifest not to include the javascript for edit

1638 of 1684 relevant lines covered (97.27%)

102.75 hits per line

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

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

25
  def index
1✔
26
    @works = Work.all
4✔
27
    respond_to do |format|
4✔
28
      format.html
4✔
29
      format.rss { render layout: false }
6✔
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?
20✔
36
      render "new_submission"
8✔
37
    else
38
      @work = Work.new(created_by_user_id: current_user.id, collection: current_user.default_collection)
12✔
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])
38✔
67
    # check if anything was added in S3 since we last viewed this object
68
    @work.attach_s3_resources
38✔
69
    respond_to do |format|
38✔
70
      format.html do
38✔
71
        # Ensure that the Work belongs to a Collection
72
        @collection = @work.collection
36✔
73
        raise(Work::InvalidCollectionError, "The Work #{@work.id} does not belong to any Collection") unless @collection
36✔
74

75
        @can_curate = current_user.can_admin?(@collection)
35✔
76
        @work.mark_new_notifications_as_read(current_user.id)
35✔
77
      end
78
      format.json { render json: @work.resource }
40✔
79
    end
80
  end
81

82
  def resolve_doi
1✔
83
    @work = Work.find_by_doi(params[:doi])
2✔
84
    redirect_to @work
2✔
85
  end
86

87
  def resolve_ark
1✔
88
    @work = Work.find_by_ark(params[:ark])
2✔
89
    redirect_to @work
2✔
90
  end
91

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

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

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

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

144
  # Allow user to upload files directly
145
  def file_upload
1✔
146
    @work = Work.find(params[:id])
1✔
147
  end
148

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

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

161
    redirect_to work_file_upload_path(@work)
1✔
162
  end
163

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

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

174
  def review
1✔
175
    @work = Work.find(params[:id])
1✔
176
    if request.method == "POST"
1✔
177
      @work.location_notes = params["location_notes"]
1✔
178
      @work.save!
1✔
179
    end
180
  end
181

182
  def validate
1✔
183
    @work = Work.find(params[:id])
2✔
184
    @work.submission_notes = params["submission_notes"]
2✔
185
    @uploads = @work.uploads
2✔
186
    @wizard_mode = true
2✔
187
    @work.complete_submission!(current_user)
2✔
188
    redirect_to user_url(current_user)
1✔
189
  end
190

191
  def approve
1✔
192
    @work = Work.find(params[:id])
10✔
193
    @work.approve!(current_user)
10✔
194
    redirect_to work_path(@work)
6✔
195
  end
196

197
  def withdraw
1✔
198
    @work = Work.find(params[:id])
2✔
199
    @work.withdraw!(current_user)
2✔
200
    redirect_to work_path(@work)
1✔
201
  end
202

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

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

222
  def add_comment
1✔
223
    work = Work.find(params[:id])
2✔
224
    if params["new-comment"].present?
2✔
225
      new_comment_param = params["new-comment"]
2✔
226
      sanitized_new_comment = html_escape(new_comment_param)
2✔
227

228
      work.add_comment(sanitized_new_comment, current_user.id)
2✔
229
    end
230
    redirect_to work_path(id: params[:id])
2✔
231
  end
232

233
  # Outputs the Datacite XML representation of the work
234
  def datacite
1✔
235
    work = Work.find(params[:id])
2✔
236
    render xml: work.to_xml
2✔
237
  end
238

239
  def datacite_validate
1✔
240
    @errors = []
1✔
241
    @work = Work.find(params[:id])
1✔
242
    datacite_xml = Nokogiri::XML(@work.to_xml)
1✔
243
    schema_location = Rails.root.join("config", "schema")
1✔
244
    Dir.chdir(schema_location) do
1✔
245
      xsd = Nokogiri::XML::Schema(File.read("datacite_4_4.xsd"))
1✔
246
      xsd.validate(datacite_xml).each do |error|
1✔
247
        @errors << error
1✔
248
      end
249
    end
250
  end
251

252
  private
1✔
253

254
    def work_params
1✔
255
      params[:work] || params
19✔
256
    end
257

258
    def patch_params
1✔
259
      return {} unless params.key?(:patch)
8✔
260

261
      params[:patch]
6✔
262
    end
263

264
    def pre_curation_uploads_param
1✔
265
      return if patch_params.nil?
4✔
266

267
      patch_params[:pre_curation_uploads]
4✔
268
    end
269

270
    def rescue_aasm_error
1✔
271
      yield
18✔
272
    rescue AASM::InvalidTransition => error
273
      message = error.message
7✔
274
      if @work.errors.count > 0
7✔
275
        message = @work.errors.to_a.join(", ")
4✔
276
      end
277
      logger.warn("Invalid #{@work.current_transition}: #{error.message} errors: #{message}")
7✔
278
      @errors = ["Cannot #{@work.current_transition}: #{message}"]
7✔
279
      render error_action, status: :unprocessable_entity
7✔
280
    end
281

282
    def error_action
1✔
283
      if action_name == "create"
7✔
284
        :new
×
285
      elsif action_name == "validate"
7✔
286
        :edit
1✔
287
      else
288
        :show
6✔
289
      end
290
    end
291

292
    def wizard_mode?
1✔
293
      params[:wizard] == "true"
68✔
294
    end
295

296
    def update_work
1✔
297
      @wizard_mode = wizard_mode?
19✔
298
      upload_service = WorkUploadsEditService.new(@work, current_user)
19✔
299
      if @work.approved?
19✔
300
        upload_keys = work_params[:deleted_uploads] || []
4✔
301
        deleted_uploads = upload_service.find_post_curation_uploads(upload_keys: upload_keys)
4✔
302

303
        return head(:forbidden) unless deleted_uploads.empty?
4✔
304
      else
305
        @work = upload_service.update_precurated_file_list(work_params)
15✔
306
      end
307

308
      process_updates
18✔
309
    end
310

311
    def update_params
1✔
312
      {
313
        collection_id: params_collection_id,
34✔
314
        resource: FormToResourceService.convert(params, @work)
315
      }
316
    end
317

318
    def process_updates
1✔
319
      resource_before = @work.resource
18✔
320
      if @work.update(update_params)
18✔
321

322
        resource_compare = ResourceCompareService.new(resource_before, update_params[:resource])
16✔
323
        @work.log_changes(resource_compare, current_user.id)
16✔
324

325
        if @wizard_mode
16✔
326
          redirect_to work_attachment_select_url(@work)
1✔
327
        else
328
          redirect_to work_url(@work), notice: "Work was successfully updated."
15✔
329
        end
330
      else
331
        @uploads = @work.uploads
2✔
332
        render :edit, status: :unprocessable_entity
2✔
333
      end
334
    end
335

336
    def params_collection_id
1✔
337
      # Do not allow a nil for the collection id
338
      @params_collection_id ||= begin
36✔
339
        collection_id = params[:collection_id]
19✔
340
        if collection_id.blank?
19✔
341
          collection_id = current_user.default_collection.id
2✔
342
          Honeybadger.notify("We got a nil collection as part of the parameters #{params} #{request}")
2✔
343
        end
344
        collection_id
19✔
345
      end
346
    end
347
end
348
# 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