scinote-web/app/controllers/teams_controller.rb

350 lines
11 KiB
Ruby
Raw Normal View History

class TeamsController < ApplicationController
before_action :load_vars, only: %i(parse_sheet import_samples
export_samples export_projects)
2016-02-12 23:52:43 +08:00
before_action :check_create_samples_permissions, only: %i(parse_sheet
import_samples)
2016-02-12 23:52:43 +08:00
before_action :check_view_samples_permission, only: [:export_samples]
2018-10-15 20:25:12 +08:00
before_action :check_export_projects_permissions, only: :export_projects
2016-02-12 23:52:43 +08:00
def parse_sheet
session[:return_to] ||= request.referer
2018-01-17 00:50:33 +08:00
unless import_params[:file]
return parse_sheet_error(t('teams.parse_sheet.errors.no_file_selected'))
end
if import_params[:file].size > Rails.configuration.x.file_max_size_mb.megabytes
error = t('general.file.size_exceeded',
file_size: Rails.configuration.x.file_max_size_mb)
return parse_sheet_error(error)
end
2016-02-12 23:52:43 +08:00
begin
2018-01-17 00:50:33 +08:00
sheet = SpreadsheetParser.open_spreadsheet(import_params[:file])
@header, @columns = SpreadsheetParser.first_two_rows(sheet)
2016-02-12 23:52:43 +08:00
2017-10-17 21:23:54 +08:00
if @header.empty? || @columns.empty?
return parse_sheet_error(t('teams.parse_sheet.errors.empty_file'))
end
2016-02-12 23:52:43 +08:00
# Fill in fields for dropdown
@available_fields = @team.get_available_sample_fields
# Truncate long fields
@available_fields.update(@available_fields) do |_k, v|
v.truncate(Constants::NAME_TRUNCATION_LENGTH_DROPDOWN)
end
2016-02-12 23:52:43 +08:00
# Save file for next step (importing)
@temp_file = TempFile.new(
session_id: session.id,
2018-01-17 00:50:33 +08:00
file: import_params[:file]
)
2016-02-12 23:52:43 +08:00
if @temp_file.save
@temp_file.destroy_obsolete
respond_to do |format|
format.json do
render json: {
html: render_to_string(
partial: 'samples/parse_samples_modal.html.erb'
)
}
2016-02-12 23:52:43 +08:00
end
end
else
return parse_sheet_error(
t('teams.parse_sheet.errors.temp_file_failure')
)
2016-02-12 23:52:43 +08:00
end
rescue ArgumentError, CSV::MalformedCSVError
return parse_sheet_error(t('teams.parse_sheet.errors.invalid_file',
encoding: ''.encoding))
rescue TypeError
return parse_sheet_error(t('teams.parse_sheet.errors.invalid_extension'))
2016-02-12 23:52:43 +08:00
end
end
def import_samples
session[:return_to] ||= request.referer
respond_to do |format|
2018-01-17 00:50:33 +08:00
if import_params[:file_id]
@temp_file = TempFile.find_by_id(import_params[:file_id])
2016-02-12 23:52:43 +08:00
if @temp_file
# Check if session_id is equal to prevent file stealing
if @temp_file.session_id == session.id
# Check if mappings exists or else we don't have anything to parse
2018-01-17 00:50:33 +08:00
if import_params[:mappings]
@sheet = SpreadsheetParser.open_spreadsheet(@temp_file.file)
2016-02-12 23:52:43 +08:00
# Check for duplicated values
2018-01-17 00:50:33 +08:00
h1 = import_params[:mappings].clone.delete_if { |_, v| v.empty? }
2016-02-12 23:52:43 +08:00
if h1.length == h1.invert.length
# Check if there exist mapping for sample name (it's mandatory)
2018-01-17 00:50:33 +08:00
if import_params[:mappings].value?('-1')
result = @team.import_samples(@sheet,
import_params[:mappings],
current_user)
2016-02-12 23:52:43 +08:00
nr_of_added = result[:nr_of_added]
total_nr = result[:total_nr]
if result[:status] == :ok
# If no errors are present, redirect back
# to samples table
flash[:success] = t(
"teams.import_samples.success_flash",
2016-02-12 23:52:43 +08:00
nr: nr_of_added,
samples: t(
"teams.import_samples.sample",
2016-02-12 23:52:43 +08:00
count: total_nr
)
)
@temp_file.destroy
format.html {
redirect_to session.delete(:return_to)
}
format.json {
flash.keep(:success)
render json: { status: :ok }
}
else
# Otherwise, also redirect back,
# but display different message
flash[:alert] = t(
"teams.import_samples.partial_success_flash",
2016-02-12 23:52:43 +08:00
nr: nr_of_added,
samples: t(
"teams.import_samples.sample",
2016-02-12 23:52:43 +08:00
count: total_nr
)
)
@temp_file.destroy
format.html {
redirect_to session.delete(:return_to)
}
format.json {
flash.keep(:alert)
render json: { status: :unprocessable_entity }
}
end
else
# This is currently the only AJAX error response
flash_alert = t(
"teams.import_samples.errors.no_sample_name")
2016-02-12 23:52:43 +08:00
format.html {
flash[:alert] = flash_alert
redirect_to session.delete(:return_to)
}
format.json {
render json: {
html: render_to_string({
partial: "parse_error.html.erb",
locals: { error: flash_alert }
})
},
status: :unprocessable_entity
}
end
else
# This code should never execute unless user tampers with
# JS (selects same column in more than one dropdown)
flash_alert = t(
"teams.import_samples.errors.duplicated_values")
2016-02-12 23:52:43 +08:00
format.html {
flash[:alert] = flash_alert
redirect_to session.delete(:return_to)
}
format.json {
render json: {
html: render_to_string({
partial: "parse_error.html.erb",
locals: { error: flash_alert }
})
},
status: :unprocessable_entity
}
end
else
@temp_file.destroy
flash[:alert] = t(
"teams.import_samples.errors.no_data_to_parse")
2016-02-12 23:52:43 +08:00
format.html {
redirect_to session.delete(:return_to)
}
format.json {
flash.keep(:alert)
render json: { status: :unprocessable_entity }
}
end
else
@temp_file.destroy
flash[:alert] = t(
"teams.import_samples.errors.session_expired")
2016-02-12 23:52:43 +08:00
format.html {
redirect_to session.delete(:return_to)
}
format.json {
flash.keep(:alert)
render json: { status: :unprocessable_entity }
}
end
else
# No temp file to begin with, so no need to destroy it
flash[:alert] = t(
"teams.import_samples.errors.temp_file_not_found")
2016-02-12 23:52:43 +08:00
format.html {
redirect_to session.delete(:return_to)
}
format.json {
flash.keep(:alert)
render json: { status: :unprocessable_entity }
}
end
else
flash[:alert] = t(
"teams.import_samples.errors.temp_file_not_found")
2016-02-12 23:52:43 +08:00
format.html {
redirect_to session.delete(:return_to)
}
format.json {
flash.keep(:alert)
render json: { status: :unprocessable_entity }
}
end
end
end
def export_samples
2018-01-17 00:50:33 +08:00
if export_params[:sample_ids] && export_params[:header_ids]
2017-06-07 19:51:16 +08:00
generate_samples_zip
else
flash[:alert] = t('zip_export.export_error')
2016-02-12 23:52:43 +08:00
end
2017-12-08 00:59:23 +08:00
redirect_back(fallback_location: root_path)
2016-02-12 23:52:43 +08:00
end
def export_projects
if export_projects_params[:project_ids]
# Check if user has enough requests for the day
2018-10-15 20:25:12 +08:00
limit = (ENV['EXPORT_ALL_LIMIT_24_HOURS'] || 3).to_i
if limit.zero? \
|| current_user.export_vars['num_of_export_all_last_24_hours'] >= limit
render json: {
html: render_to_string(
partial: 'projects/export/error.html.erb',
locals: { limit: limit }
),
title: t('projects.export_projects.modal_title_error')
}
else
current_user.export_vars['num_of_export_all_last_24_hours'] += 1
current_user.save
ids = generate_export_projects_zip
curr_num = current_user.export_vars['num_of_export_all_last_24_hours']
render json: {
html: render_to_string(
partial: 'projects/export/success.html.erb',
locals: { num_projects: ids.length,
limit: limit,
num_of_requests_left: limit - curr_num }
),
title: t('projects.export_projects.modal_title_success')
}
end
end
end
def routing_error(error = 'Routing error', status = :not_found, exception=nil)
redirect_to root_path
end
private
def parse_sheet_error(error)
respond_to do |format|
format.html do
flash[:alert] = error
session[:return_to] ||= request.referer
redirect_to session.delete(:return_to)
end
format.json do
render json: { message: error },
status: :unprocessable_entity
end
end
end
2016-02-12 23:52:43 +08:00
def load_vars
@team = Team.find_by_id(params[:id])
2016-02-12 23:52:43 +08:00
unless @team
2016-02-12 23:52:43 +08:00
render_404
end
end
2018-01-17 00:50:33 +08:00
def import_params
params.permit(:id, :file, :file_id, mappings: {}).to_h
end
def export_params
params.permit(sample_ids: [], header_ids: []).to_h
end
def export_projects_params
params.permit(:id, project_ids: []).to_h
end
def check_create_samples_permissions
render_403 unless can_create_samples?(@team)
2016-02-12 23:52:43 +08:00
end
def check_view_samples_permission
unless can_read_team?(@team)
2016-02-12 23:52:43 +08:00
render_403
end
end
def check_export_projects_permissions
2018-09-23 20:34:21 +08:00
render_403 unless can_read_team?(@team)
if export_projects_params[:project_ids]
projects = Project.where(id: export_projects_params[:project_ids])
2018-09-23 20:34:21 +08:00
projects.each do |project|
render_403 unless can_read_project?(current_user, project)
2018-09-23 20:34:21 +08:00
end
end
end
2017-06-07 19:51:16 +08:00
def generate_samples_zip
zip = ZipExport.create(user: current_user)
zip.generate_exportable_zip(
current_user,
2018-01-17 00:50:33 +08:00
@team.to_csv(
Sample.where(id: export_params[:sample_ids]),
export_params[:header_ids]
),
:samples
)
2016-02-12 23:52:43 +08:00
end
def generate_export_projects_zip
ids = Project.where(id: export_projects_params[:project_ids],
team_id: @team)
.index_by(&:id)
options = { team: @team }
zip = TeamZipExport.create(user: current_user)
zip.generate_exportable_zip(
current_user,
ids,
:teams,
options
)
ids
end
2016-02-12 23:52:43 +08:00
end