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

pulibrary / tigerdata-app / ec8f0551-6db9-46dd-ae6a-eb0683262c5a

23 Jul 2025 01:20PM UTC coverage: 65.984% (-0.4%) from 66.374%
ec8f0551-6db9-46dd-ae6a-eb0683262c5a

push

circleci

hectorcorrea
Adjust test to use new namespace setup in the Docker container

4 of 18 branches covered (22.22%)

2642 of 4004 relevant lines covered (65.98%)

301.38 hits per line

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

84.07
/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

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

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

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

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

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

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

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

186
  def show
1✔
187

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

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

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

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

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

210
  # GET "projects/:id/:id-mf"
211
  #
212
  # This action is used to render the mediaflux metadata for a project.
213
  def show_mediaflux
1✔
214
    project_id = params[:id]
1✔
215
    project = Project.find(project_id)
1✔
216

217
    respond_to do |format|
1✔
218
      format.xml do
1✔
219
        render xml: project.mediaflux_meta_xml
1✔
220
      end
221
    end
222
  end
223

224
  def project_job_service
1✔
225
    @project_job_service ||= ProjectJobService.new(project:)
×
226
  end
227

228
  def list_contents
1✔
229
    return if project.blank?
1✔
230

231
    project_job_service.list_contents_job(user: current_user)
×
232

233
    json_response = {
234
      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."
×
235
    }
236
    render json: json_response
×
237
  rescue => ex
238
    message = "Error producing document list (project id: #{project&.id}): #{ex.message}"
×
239
    Rails.logger.error(message)
×
240
    Honeybadger.notify(message)
×
241
    render json: { message: "Document list could not be generated." }
×
242
  end
243

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

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

268
      @title = @project_metadata["title"]
3✔
269
    else redirect_to dashboard_path
3✔
270
    end
271
  end
272

273
  private
1✔
274

275
    def build_new_project
1✔
276
      @project ||= Project.new
26✔
277
    end
278

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

292
    def eligible_editor?
1✔
293
      return true if current_user.eligible_sponsor? or current_user.eligible_manager?
20✔
294
    end
295

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

302
    def set_breadcrumbs
1✔
303
      add_breadcrumb("Dashboard",dashboard_path)
141✔
304
    end
305
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

© 2026 Coveralls, Inc