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

pulibrary / pdc_describe / b5634745-8cc5-4baf-9ca5-04e96eef6e71

14 Jan 2025 06:38PM UTC coverage: 95.976% (-0.1%) from 96.113%
b5634745-8cc5-4baf-9ca5-04e96eef6e71

Pull #2010

circleci

hectorcorrea
Troubleshooting issue 2009
Pull Request #2010: Troubleshooting file upload issue

1 of 6 new or added lines in 2 files covered. (16.67%)

3339 of 3479 relevant lines covered (95.98%)

405.03 hits per line

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

85.45
/app/controllers/works_wizard_controller.rb
1
# frozen_string_literal: true
2

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

6
# Controller to handle wizard Mode when editing an work
7
#
8
# The wizard flow is shown in the [mermaid diagram here](https://github.com/pulibrary/pdc_describe/blob/main/docs/wizard_flow.md).
9

10
class WorksWizardController < ApplicationController
2✔
11
  include ERB::Util
2✔
12
  around_action :rescue_aasm_error, only: [:validate, :new_submission_save]
2✔
13

14
  before_action :load_work, only: [:edit_wizard, :update_wizard, :attachment_select, :attachment_selected,
2✔
15
                                   :file_upload, :file_uploaded, :file_other, :review, :validate,
16
                                   :readme_select, :readme_uploaded, :readme_uploaded_payload]
17

18
  # GET /works/1/edit-wizard
19
  def edit_wizard
2✔
20
    @wizard_mode = true
28✔
21
    if validate_modification_permissions(work: @work,
28✔
22
                                         uneditable_message: "Can not edit work: #{@work.id} is not editable by #{current_user.uid}",
23
                                         current_state_message: "Can not edit work: #{@work.id} is not editable in current state by #{current_user.uid}")
24

25
      prepare_decorators_for_work_form(@work)
26✔
26
    end
27
  end
28

29
  # PATCH /works/1/update-wizard
30
  def update_wizard
2✔
31
    edit_helper(:edit_wizard, work_update_additional_path(@work))
24✔
32
  end
33

34
  # Prompt to select how to submit their files
35
  # GET /works/1/attachment_select
36
  def attachment_select; end
2✔
37

38
  # User selected a specific way to submit their files
39
  # POST /works/1/attachment_selected
40
  def attachment_selected
2✔
41
    @work.files_location = params["attachment_type"]
30✔
42
    @work.save!
30✔
43

44
    # create a directory for the work if the curator will need to move files by hand
45
    @work.s3_query_service.create_directory if @work.files_location != "file_upload"
30✔
46

47
    if params[:save_only] == "true"
30✔
48
      render :attachment_select
8✔
49
    else
50
      redirect_to file_location_url
22✔
51
    end
52
  end
53

54
  # Allow user to upload files directly
55
  # GET /works/1/file_upload
56
  def file_upload
2✔
57
    @work_decorator = WorkDecorator.new(@work, current_user)
16✔
58
  end
59

60
  # POST /works/1/upload-files-wizard (called via Uppy)
61
  def upload_files
2✔
62
    @work = Work.find(params[:id])
×
63
    upload_service = WorkUploadsEditService.new(@work, current_user)
×
64
    upload_service.update_precurated_file_list(params["files"], [])
×
65
  rescue => ex
NEW
66
    error_message = "Failed to upload file, URL: #{request.url}: #{ex}"
×
NEW
67
    Rails.logger.error(error_message)
×
NEW
68
    Honeybadger.notify(error_message)
×
NEW
69
    flash[:notice] = "Failed to upload file, work: #{@work&.doi}: #{ex}. Please contact rdss@princeton.edu for assistance."
×
NEW
70
    redirect_to work_file_upload_path(@work)
×
71
  end
72

73
  # POST /works/1/file_upload
74
  def file_uploaded
2✔
75
    upload_service = WorkUploadsEditService.new(@work, current_user)
20✔
76
    # By the time we hit this endpoint files have been uploaded by Uppy submmitting POST requests
77
    # to /works/1/upload-files-wizard therefore we only need to delete files here and update the upload snapshot.
78
    @work = upload_service.snapshot_uppy_and_delete_files(deleted_files_param)
20✔
79

80
    prepare_decorators_for_work_form(@work)
18✔
81
    if params[:save_only] == "true"
18✔
82
      render :file_upload
4✔
83
    else
84
      redirect_to(work_review_path)
14✔
85
    end
86
  rescue => ex
87
    # Notice that we log the URL (rather than @work.doi) because sometimes we are getting a nil @work.
88
    # The URL will include the ID and might help us troubleshoot the issue further if it happens again.
89
    # See https://github.com/pulibrary/pdc_describe/issues/1801
90
    error_message = "Failed to update work snapshot, URL: #{request.url}: #{ex}"
2✔
91
    Rails.logger.error(error_message)
2✔
92
    Honeybadger.notify(error_message)
2✔
93
    flash[:notice] = "Failed to update work snapshot, work: #{@work&.doi}: #{ex}. Please contact rdss@princeton.edu for assistance."
2✔
94

95
    redirect_to work_file_upload_path(@work)
2✔
96
  end
97

98
  # Allow user to indicate where their files are located in the WWW
99
  # GET /works/1/file_other
100
  def file_other; end
2✔
101

102
  # GET /works/1/review
103
  # POST /works/1/review
104
  def review
2✔
105
    if request.method == "POST" || request.method == "PATCH"
30✔
106
      @work.location_notes = params["location_notes"]
14✔
107
      @work.save!
14✔
108
      if params[:save_only] == "true"
14✔
109
        render :file_other
4✔
110
      end
111
    end
112
  end
113

114
  # Validates that the work is ready to be approved
115
  # POST /works/1/validate-wizard
116
  # PATCH /works/1/validate-wizard
117
  def validate
2✔
118
    @work.submission_notes = params["submission_notes"]
24✔
119

120
    if params[:save_only] == "true"
24✔
121
      @work.save
4✔
122
      render :review
4✔
123
    else
124
      @work.complete_submission!(current_user)
20✔
125
      redirect_to work_complete_path(@work.id)
14✔
126
    end
127
  end
128

129
  # Show the user the form to select a readme
130
  # GET /works/1/readme_select
131
  def readme_select
2✔
132
    readme = Readme.new(@work, current_user)
28✔
133
    @readme = readme.file_name
28✔
134
  end
135

136
  # Hit when the user clicks "Save" or "Next" on the README upload process.
137
  # Notice that this does not really uploads the file, that happens in readme_uploaded_payload.
138
  # PATCH /works/1/readme_uploaded
139
  def readme_uploaded
2✔
140
    readme = Readme.new(@work, current_user)
24✔
141
    if params[:save_only] == "true"
24✔
142
      @readme = readme.file_name
4✔
143
      render :readme_select
4✔
144
    else
145
      redirect_to work_attachment_select_url(@work)
20✔
146
    end
147
  end
148

149
  def files_param
2✔
150
    params["files"]
12✔
151
  end
152

153
  # Uploads the README file, called by Uppy.
154
  # POST /works/1/readme-uploaded-payload
155
  def readme_uploaded_payload
2✔
156
    raise StandardError("Only one README file can be uploaded.") if files_param.empty?
4✔
157
    raise StandardError("Only one README file can be uploaded.") if files_param.length > 1
4✔
158

159
    readme_file = files_param.first
4✔
160
    readme = Readme.new(@work, current_user)
4✔
161

162
    readme_error = readme.attach(readme_file)
4✔
163
    if readme_error.nil?
4✔
164
      render plain: readme.file_name
2✔
165
    else
166
      # Tell Uppy there was an error uploading the README
167
      render plain: readme.file_name, status: :internal_server_error
2✔
168
    end
169
  end
170

171
  def file_location_url
2✔
172
    WorkMetadataService.file_location_url(@work)
48✔
173
  end
174
  helper_method :file_location_url
2✔
175

176
  private
2✔
177

178
    def edit_helper(view_name, redirect_url)
2✔
179
      if validate_modification_permissions(work: @work,
44✔
180
                                           uneditable_message: "Can not update work: #{@work.id} is not editable by #{current_user.uid}",
181
                                           current_state_message: "Can not update work: #{@work.id} is not editable in current state by #{current_user.uid}")
182
        prepare_decorators_for_work_form(@work)
44✔
183
        if WorkCompareService.update_work(work: @work, update_params:, current_user:)
44✔
184
          if params[:save_only] == "true"
42✔
185
            render view_name
6✔
186
          else
187
            redirect_to redirect_url
36✔
188
          end
189
        else
190
          # return 200 so the loadbalancer doesn't capture the error
191
          render view_name
2✔
192
        end
193
      end
194
    end
195

196
    def load_work
2✔
197
      @work = Work.find(params[:id])
308✔
198
    end
199

200
    # @note No testing coverage but not a route, not called
201
    def patch_params
2✔
202
      return {} unless params.key?(:patch)
×
203

204
      params[:patch]
×
205
    end
206

207
    # @note No testing coverage but not a route, not called
208
    def pre_curation_uploads_param
2✔
209
      return if patch_params.nil?
×
210

211
      patch_params[:pre_curation_uploads]
×
212
    end
213

214
    def deleted_files_param
2✔
215
      deleted_count = (params.dig("work", "deleted_files_count") || "0").to_i
20✔
216
      (1..deleted_count).map { |i| params.dig("work", "deleted_file_#{i}") }.select(&:present?)
26✔
217
    end
218

219
    # @note No testing coverage but not a route, not called
220
    def readme_file_param
2✔
221
      return if patch_params.nil?
×
222

223
      patch_params[:readme_file]
×
224
    end
225

226
    def rescue_aasm_error
2✔
227
      super
24✔
228
    rescue StandardError => generic_error
229
      redirect_to root_url, notice: "We apologize, an error was encountered: #{generic_error.message}. Please contact the PDC Describe administrators."
×
230
    end
231

232
    def redirect_aasm_error(transition_error_message)
2✔
233
      if @work.persisted?
6✔
234
        redirect_to edit_work_wizard_path(id: @work.id), notice: transition_error_message, params:
6✔
235
      else
236
        redirect_to work_create_new_submission_path(@work), notice: transition_error_message, params:
×
237
      end
238
    end
239
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

© 2025 Coveralls, Inc