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

pulibrary / pdc_describe / b3a0c557-c65c-42fe-965a-932c42e16649

17 Apr 2024 08:14PM UTC coverage: 95.535% (-0.1%) from 95.648%
b3a0c557-c65c-42fe-965a-932c42e16649

Pull #1768

circleci

hectorcorrea
Added validation to make sure the README file selected is indeed a readme file.
Pull Request #1768: Handles the upload of the README with new file uploader

10 of 10 new or added lines in 1 file covered. (100.0%)

4 existing lines in 1 file now uncovered.

3274 of 3427 relevant lines covered (95.54%)

208.52 hits per line

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

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

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

6
# Controller to handle wizard Mode when editing an work
7
#
8
# The wizard flow is as follows:
9
# new_submission -> new_submission_save -> edit_wizard -> update_wizard -> update_additional -> update_additional_save ->readme_select -> readme_uploaded -> attachment_select ->
10
#     attachment_selected -> file_other ->                  review -> validate -> [ work controller ] show & file_list
11
#                         \> file_upload -> file_uploaded -^
12

13
class WorksWizardController < ApplicationController
1✔
14
  include ERB::Util
1✔
15
  around_action :rescue_aasm_error, only: [:validate, :new_submission_save]
1✔
16

17
  before_action :load_work, only: [:edit_wizard, :update_wizard, :attachment_select, :attachment_selected,
1✔
18
                                   :file_upload, :file_uploaded, :file_other, :review, :validate,
19
                                   :readme_select, :readme_uploaded, :readme_uploaded_payload]
20

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

28
      prepare_decorators_for_work_form(@work)
14✔
29
    end
30
  end
31

32
  # PATCH /works/1/update-wizard
33
  def update_wizard
1✔
34
    edit_helper(:edit_wizard, work_update_additional_path(@work))
14✔
35
  end
36

37
  # Prompt to select how to submit their files
38
  # GET /works/1/attachment_select
39
  def attachment_select; end
1✔
40

41
  # User selected a specific way to submit their files
42
  # POST /works/1/attachment_selected
43
  def attachment_selected
1✔
44
    @work.files_location = params["attachment_type"]
15✔
45
    @work.save!
15✔
46

47
    # create a directory for the work if the curator will need to move files by hand
48
    @work.s3_query_service.create_directory if @work.files_location != "file_upload"
15✔
49

50
    if params[:save_only] == "true"
15✔
51
      render :attachment_select
4✔
52
    else
53
      redirect_to file_location_url
11✔
54
    end
55
  end
56

57
  # Allow user to upload files directly
58
  # GET /works/1/file_upload
59
  def file_upload
1✔
60
    @work_decorator = WorkDecorator.new(@work, current_user)
8✔
61
  end
62

63
  # POST /works/1/upload-files-wizard (called via Uppy)
64
  # this puts the files into AWS, but does not capture anything in the Upload Snapshot.  THat occurs when the user hits next
65
  def upload_files
1✔
66
    @work = Work.find(params[:id])
×
67
    params["files"].each { |file| upload_file(file) }
×
68
  end
69

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

77
    prepare_decorators_for_work_form(@work)
9✔
78
    if params[:save_only] == "true"
9✔
79
      render :file_upload
2✔
80
    else
81
      redirect_to(work_review_path)
7✔
82
    end
83
  rescue StandardError => active_storage_error
84
    Rails.logger.error("Failed to attach the file uploads for the work #{@work.doi}: #{active_storage_error}")
1✔
85
    flash[:notice] = "Failed to attach the file uploads for the work #{@work.doi}: #{active_storage_error}. Please contact rdss@princeton.edu for assistance."
1✔
86

87
    redirect_to work_file_upload_path(@work)
1✔
88
  end
89

90
  # Allow user to indicate where their files are located in the WWW
91
  # GET /works/1/file_other
92
  def file_other; end
1✔
93

94
  # GET /works/1/review
95
  # POST /works/1/review
96
  def review
1✔
97
    if request.method == "POST" || request.method == "PATCH"
13✔
98
      @work.location_notes = params["location_notes"]
7✔
99
      @work.save!
7✔
100
      if params[:save_only] == "true"
7✔
101
        render :file_other
2✔
102
      end
103
    end
104
  end
105

106
  # Validates that the work is ready to be approved
107
  # GET /works/1/validate
108
  def validate
1✔
109
    @work.submission_notes = params["submission_notes"]
33✔
110
    if params[:save_only] == "true"
33✔
111
      @work.save
2✔
112
      render :review
2✔
113
    else
114
      @work.complete_submission!(current_user)
31✔
115
      redirect_to user_url(current_user)
30✔
116
    end
117
  end
118

119
  # Show the user the form to select a readme
120
  # GET /works/1/readme_select
121
  def readme_select
1✔
122
    readme = Readme.new(@work, current_user)
16✔
123
    @readme = readme.file_name
16✔
124
  end
125

126
  # Hit when the user clicks "Save" or "Next" on the README upload process.
127
  # Notice that this does not really uploads the file, that happens in readme_uploaded_payload.
128
  # PATCH /works/1/readme_uploaded
129
  def readme_uploaded
1✔
130
    readme = Readme.new(@work, current_user)
12✔
131
    if params[:save_only] == "true"
12✔
132
      @readme = readme.file_name
2✔
133
      render :readme_select
2✔
134
    else
135
      redirect_to work_attachment_select_url(@work)
10✔
136
    end
137
  end
138

139
  # Uploads the README file, called by Uppy.
140
  # POST /works/1/readme-uploaded-payload
141
  def readme_uploaded_payload
1✔
142
    readme = Readme.new(@work, current_user)
2✔
143
    readme_file = params["files"].first
2✔
144
    readme_error = readme.attach(readme_file)
2✔
145
    if readme_error.nil?
2✔
146
      render plain: readme.file_name
1✔
147
    else
148
      # Tell Uppy there was an error uploading the README
149
      render plain: readme.file_name, status: :internal_server_error
1✔
150
    end
151
  end
152

153
  def file_location_url
1✔
154
    WorkMetadataService.file_location_url(@work)
22✔
155
  end
156
  helper_method :file_location_url
1✔
157

158
  private
1✔
159

160
    def edit_helper(view_name, redirect_url)
1✔
161
      if validate_modification_permissions(work: @work,
26✔
162
                                           uneditable_message: "Can not update work: #{@work.id} is not editable by #{current_user.uid}",
163
                                           current_state_message: "Can not update work: #{@work.id} is not editable in current state by #{current_user.uid}")
164
        prepare_decorators_for_work_form(@work)
26✔
165
        if WorkCompareService.update_work(work: @work, update_params:, current_user:)
26✔
166
          if params[:save_only] == "true"
25✔
167
            render view_name
3✔
168
          else
169
            redirect_to redirect_url
22✔
170
          end
171
        else
172
          render view_name, status: :unprocessable_entity
1✔
173
        end
174
      end
175
    end
176

177
    def load_work
1✔
178
      @work = Work.find(params[:id])
181✔
179
    end
180

181
    def patch_params
1✔
UNCOV
182
      return {} unless params.key?(:patch)
×
183

UNCOV
184
      params[:patch]
×
185
    end
186

187
    def pre_curation_uploads_param
1✔
188
      return if patch_params.nil?
×
189

190
      patch_params[:pre_curation_uploads]
×
191
    end
192

193
    def deleted_files_param
1✔
194
      deleted_count = (params.dig("work", "deleted_files_count") || "0").to_i
10✔
195
      (1..deleted_count).map { |i| params.dig("work", "deleted_file_#{i}") }.select(&:present?)
13✔
196
    end
197

198
    def readme_file_param
1✔
UNCOV
199
      return if patch_params.nil?
×
200

UNCOV
201
      patch_params[:readme_file]
×
202
    end
203

204
    def rescue_aasm_error
1✔
205
      super
33✔
206
    rescue StandardError => generic_error
207
      redirect_to root_url, notice: "We apologize, an error was encountered: #{generic_error.message}. Please contact the PDC Describe administrators."
×
208
    end
209

210
    def redirect_aasm_error(transition_error_message)
1✔
211
      if @work.persisted?
1✔
212
        redirect_to edit_work_wizard_path(id: @work.id), notice: transition_error_message, params:
1✔
213
      else
214
        redirect_to work_create_new_submission_path(@work), notice: transition_error_message, params:
×
215
      end
216
    end
217

218
    def upload_file(file)
1✔
219
      key = @work.s3_query_service.upload_file(io: file.to_io, filename: file.original_filename, size: file.size)
×
220
      if key.blank?
×
221
        # TODO: Can we tell uppy there was a failure instead of just logging the error here
222
        #  you can render json: {}, status: 500 but how do you tell one file failed instead of all of them
223
        Rails.logger.error("Error uploading #{file.original_filename} to work #{@work.id}")
×
224
        Honeybadger.notify("Error uploading #{file.original_filename} to work #{@work.id}")
×
225
      end
226
    end
227
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