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

pulibrary / tigerdata-app / 8104a809-ff43-45c7-a383-49e5e81ab55c

24 Jul 2025 09:27PM UTC coverage: 64.93%. First build
8104a809-ff43-45c7-a383-49e5e81ab55c

Pull #1640

circleci

web-flow
Merge branch 'main' into projects_controller_spec
Pull Request #1640: Refactored code that produces the XML representation

4 of 18 branches covered (22.22%)

14 of 16 new or added lines in 3 files covered. (87.5%)

2568 of 3955 relevant lines covered (64.93%)

304.2 hits per line

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

83.24
/app/controllers/projects_controller.rb
1
# frozen_string_literal: true
2
class ProjectsController < ApplicationController
1✔
3

4
  before_action :set_breadcrumbs
1✔
5
  before_action :authenticate_user!
1✔
6

7
  def new
1✔
8
    add_breadcrumb("New Project Request")
16✔
9
    return build_new_project if current_user.eligible_sponsor?
16✔
10

11
    redirect_to dashboard_path
2✔
12
  end
13

14
  def project_params
1✔
15
    params.dup
×
16
  end
17

18
  def create
1✔
19
    metadata_params = params.dup
12✔
20
    metadata_params[:status] = Project::PENDING_STATUS
12✔
21
    metadata_params[:created_by] = current_user.uid
12✔
22
    metadata_params[:created_on] = Time.current.in_time_zone("America/New_York").iso8601
12✔
23
    project_metadata = ProjectMetadata.new_from_params(metadata_params)
12✔
24

25
    build_new_project # calling private method to build a new project and set a class variable @project
12✔
26
    project.create!(initial_metadata: project_metadata, user: current_user)
12✔
27
    if project.metadata_model.project_id != nil
12✔
28
      begin
29
        mailer = TigerdataMailer.with(project_id: project.id)
12✔
30
        message_delivery = mailer.project_creation
12✔
31
        message_delivery.deliver_later
12✔
32

33
        redirect_to project_confirmation_path(project)
11✔
34
      rescue StandardError => mailer_error
35
        raise(TigerData::MailerError, mailer_error)
2✔
36
      end
37
    else
38
      render :new
×
39
    end
40
  rescue TigerData::MailerError => mailer_error
41
    logger_message = "Error encountered creating the project #{project.id} as user #{current_user.email}"
2✔
42
    Rails.logger.error(logger_message)
2✔
43
    honeybadger_context = {
44
      current_user_email: current_user.email,
2✔
45
      project_id: project.id,
46
      project_metadata: project.metadata
47
    }
48
    Honeybadger.notify(mailer_error, context: honeybadger_context)
2✔
49

50
    error_message = "We are sorry, while the project was successfully created, an error was encountered which prevents the delivery of an e-mail message confirming this. Please know that this error has been logged, and shall be reviewed by members of RDSS."
2✔
51
    flash[:notice] = error_message
2✔
52

53
    render :new
2✔
54
  rescue StandardError => error
55
    logger_message = if project.persisted?
×
56
                      "Error encountered creating the project #{project.id} as user #{current_user.email}"
×
57
                     else
58
                      "Error encountered creating the project #{metadata_params[:title]} as user #{current_user.email}"
×
59
                     end
60
    Rails.logger.error(logger_message)
×
61
    honeybadger_context = {
62
      current_user_email: current_user.email,
×
63
      project_id: project.id,
64
      project_metadata: project.metadata
65
    }
66
    Honeybadger.notify(error, context: honeybadger_context)
×
67

68
    error_message = "We are sorry, the project was not successfully created, and an error was encountered which prevents the delivery of an e-mail message confirming this. Please know that this error has been logged, and shall be reviewed by members of RDSS promptly."
×
69

70
    flash[:notice] = error_message
×
71
    render :new
×
72
  end
73

74
  def details
1✔
75
    return if project.blank?
31✔
76

77
    add_breadcrumb(project.title, project_path)
30✔
78
    add_breadcrumb("Details")
30✔
79

80
    @departments = project.departments.join(", ")
30✔
81
    @project_metadata = project.metadata_model
30✔
82

83
    @data_sponsor = User.find_by(uid: @project_metadata.data_sponsor)
30✔
84
    @data_manager = User.find_by(uid: @project_metadata.data_manager)
30✔
85

86
    read_only_uids = @project_metadata.ro_users
30✔
87
    data_read_only_users = read_only_uids.map { |uid| ReadOnlyUser.find_by(uid:) }.reject(&:blank?)
46✔
88

89
    read_write_uids = @project_metadata.rw_users
30✔
90
    data_read_write_users = read_write_uids.map { |uid| User.find_by(uid:) }.reject(&:blank?)
42✔
91

92
    unsorted_data_users = data_read_only_users + data_read_write_users
30✔
93
    sorted_data_users = unsorted_data_users.sort_by { |u| u.family_name || u.uid }
58✔
94
    @data_users = sorted_data_users.uniq { |u| u.uid }
50✔
95
    user_model_names = @data_users.map(&:display_name_safe)
30✔
96
    @data_user_names = user_model_names.join(", ")
30✔
97

98
    @provenance_events = project.provenance_events.where.not(event_type: ProvenanceEvent::STATUS_UPDATE_EVENT_TYPE)
30✔
99

100
    @project_eligible_to_edit = true if project.status == Project::APPROVED_STATUS && eligible_editor?
30✔
101

102
    @project_metadata = @project.metadata
30✔
103
    @project_id = @project_metadata[:project_id] || {}
30✔
104
    @storage_capacity = @project_metadata[:storage_capacity]
30✔
105
    @size = @storage_capacity[:size]
30✔
106
    @unit = @storage_capacity[:unit]
30✔
107

108
    @requested_size = @size[:requested]
30✔
109
    @requested_unit = @unit[:requested]
30✔
110

111
    @approved_size = @size[:approved]
30✔
112
    @approved_unit = @unit[:approved]
30✔
113

114
    @storage_expectations = @project_metadata[:storage_performance_expectations]
30✔
115
    @requested_storage_expectations = @storage_expectations[:requested]
30✔
116
    @approved_storage_expectations = @storage_expectations[:approved]
30✔
117

118
    @project_purpose = @project_metadata[:project_purpose]
30✔
119

120

121
    @project_session = "details"
30✔
122

123
    respond_to do |format|
30✔
124
      format.html do
30✔
125
        @project = ProjectShowPresenter.new(project)
27✔
126
      end
127
      format.json do
30✔
128
        render json: project.to_json
2✔
129
      end
130
      format.xml do
30✔
131
        render xml: project.to_xml
1✔
132
      end
133
    end
134
  end
135

136
  def edit
1✔
137
    add_breadcrumb(project.title, project_path)
14✔
138
    add_breadcrumb("Edit")
14✔
139
    project
14✔
140
    if project.metadata_model.status != Project::APPROVED_STATUS
14✔
141
      flash[:notice] = "Pending projects can not be edited."
1✔
142
      redirect_to project
1✔
143
    elsif project.metadata_model.status == Project::APPROVED_STATUS && !eligible_editor? #check if the current user is a sponsor or a manager
13✔
144
      flash[:notice] = "Only data sponsors and data managers can revise this project."
2✔
145
      redirect_to project
2✔
146
    end
147
  end
148

149
  def update
1✔
150
    @project = Project.find(params[:id])
7✔
151
    #Approve action
152
    if params.key?("approved")
7✔
153
      @project.metadata_model.update_with_params(params, current_user)
3✔
154
      @project.approve!(current_user:)
3✔
155
    end
156

157
    #Edit action
158
    if params.key?("title")
7✔
159
      @project.metadata_model.status = @project.metadata_model.status || Project::PENDING_STATUS
4✔
160
      @project.metadata_model.update_with_params(params, current_user)
4✔
161
    end
162

163
    # @todo ProjectMetadata should be refactored to implement ProjectMetadata.valid?(updated_metadata)
164
    if project.save and params.key?("approved")
7✔
165
      redirect_to project_approval_received_path(@project)
3✔
166
    elsif project.save and params.key?("title")
4✔
167
      redirect_to project_revision_confirmation_path(@project)
4✔
168
    else
169
      render :edit
×
170
    end
171
  end
172

173
  def index
1✔
174
    if current_user.eligible_sysadmin?
5✔
175
      @projects = Project.all
1✔
176
    else
177
      flash[:alert] = I18n.t(:access_denied)
4✔
178
      redirect_to dashboard_path
4✔
179
    end
180
  end
181

182
  def confirmation; end
1✔
183
  def revision_confirmation; end
1✔
184

185
  def show
1✔
186

187
    return if project.blank?
29✔
188
    add_breadcrumb(project.title, project_path)
28✔
189
    add_breadcrumb("Contents")
28✔
190

191
    @latest_completed_download = current_user.user_requests.where(project_id: @project.id, state: "completed").order(:completion_time).last
28✔
192
    @storage_usage = project.storage_usage(session_id: current_user.mediaflux_session)
28✔
193
    @storage_capacity = project.storage_capacity(session_id: current_user.mediaflux_session)
24✔
194

195
    @num_files = project.asset_count(session_id: current_user.mediaflux_session)
24✔
196

197
    @file_list = project.file_list(session_id: current_user.mediaflux_session, size: 100)
24✔
198
    @files = @file_list[:files]
24✔
199
    @files.sort_by!(&:path)
24✔
200
    @project = ProjectShowPresenter.new(project)
24✔
201

202
    @project_session = "content"
24✔
203
    respond_to do |format|
24✔
204
      format.html { render }
47✔
205
      format.xml { render xml: @project.to_xml }
25✔
206
    end
207
  end
208

209
  # GET "projects/:id/:id-mf"
210
  #
211
  # This action is used to render the mediaflux metadata for a project.
212
  def show_mediaflux
1✔
213
    project_id = params[:id]
1✔
214
    project = Project.find(project_id)
1✔
215
    if project.mediaflux_id == 0
1✔
NEW
216
      flash[:error] = "Project has not been created in Mediaflux"
×
NEW
217
      redirect_to project_path(project_id)
×
218
    else
219
      respond_to do |format|
1✔
220
        format.xml do
1✔
221
          render xml: project.mediaflux_meta_xml(user: current_user)
1✔
222
        end
223
      end
224
    end
225
  end
226

227
  def project_job_service
1✔
228
    @project_job_service ||= ProjectJobService.new(project:)
×
229
  end
230

231
  def list_contents
1✔
232
    return if project.blank?
1✔
233

234
    project_job_service.list_contents_job(user: current_user)
×
235

236
    json_response = {
237
      message: "File list for \"#{project.title}\" is being generated in the background. A link to the downloadable file list will be available in the \"Recent Activity\" section of your dashboard when it is available. You may safely navigate away from this page or close this tab."
×
238
    }
239
    render json: json_response
×
240
  rescue => ex
241
    message = "Error producing document list (project id: #{project&.id}): #{ex.message}"
×
242
    Rails.logger.error(message)
×
243
    Honeybadger.notify(message)
×
244
    render json: { message: "Document list could not be generated." }
×
245
  end
246

247
  def file_list_download
1✔
248
    job_id = params[:job_id]
×
249
    user_request = FileInventoryRequest.where(job_id:job_id).first
×
250
    if user_request.nil?
×
251
      # TODO: handle error
252
      redirect_to "/"
×
253
    else
254
      filename = user_request.output_file
×
255
      send_data File.read(filename), type: "text/plain", filename: "filelist.csv", disposition: "attachment"
×
256
    end
257
  end
258

259
  def approve
1✔
260
    if current_user.eligible_sysadmin?
6✔
261
      add_breadcrumb(project.title, project_path)
3✔
262
      add_breadcrumb("Approval Settings", project_approve_path)
3✔
263
      add_breadcrumb("Edit")
3✔
264
      project
3✔
265
      @departments = project.departments.join(", ")
3✔
266
      @project_metadata = project.metadata
3✔
267
      sponsor_uid = @project_metadata[:data_sponsor]
3✔
268
      @data_sponsor = User.find_by(uid: sponsor_uid)
3✔
269
      @provenance_events = project.provenance_events.where.not(event_type: ProvenanceEvent::STATUS_UPDATE_EVENT_TYPE)
3✔
270

271
      @title = @project_metadata["title"]
3✔
272
    else redirect_to dashboard_path
3✔
273
    end
274
  end
275

276
  private
1✔
277

278
    def build_new_project
1✔
279
      @project ||= Project.new
26✔
280
    end
281

282
    def project
1✔
283
      @project ||= begin
530✔
284
        project = Project.find(params[:id])
76✔
285
        if project.user_has_access?(user: current_user)
76✔
286
          project
73✔
287
        else
288
          flash[:alert] = I18n.t(:access_denied)
3✔
289
          redirect_to dashboard_path
3✔
290
          nil
3✔
291
        end
292
      end
293
    end
294

295
    def eligible_editor?
1✔
296
      return true if current_user.eligible_sponsor? or current_user.eligible_manager?
20✔
297
    end
298

299
    def shared_file_location(filename)
1✔
300
      raise "Shared location is not configured" if Rails.configuration.mediaflux["shared_files_location"].blank?
×
301
      location = Pathname.new(Rails.configuration.mediaflux["shared_files_location"])
×
302
      location.join(filename).to_s
×
303
    end
304

305
    def set_breadcrumbs
1✔
306
      add_breadcrumb("Dashboard",dashboard_path)
141✔
307
    end
308
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