2024-05-18 09:00:44 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
2024-03-15 18:27:31 -04:00
|
|
|
class ImportsController < ApplicationController
|
2025-04-03 12:41:05 -04:00
|
|
|
include ActiveStorage::SetCurrent
|
|
|
|
|
|
2024-03-15 18:27:31 -04:00
|
|
|
before_action :authenticate_user!
|
2025-04-18 13:48:02 -04:00
|
|
|
before_action :set_import, only: %i[show edit update destroy]
|
2025-07-28 12:53:19 -04:00
|
|
|
before_action :authorize_import, only: %i[show edit update destroy]
|
2025-05-16 12:51:48 -04:00
|
|
|
before_action :validate_points_limit, only: %i[new create]
|
2025-07-28 12:53:19 -04:00
|
|
|
|
|
|
|
|
after_action :verify_authorized, except: %i[index]
|
|
|
|
|
after_action :verify_policy_scoped, only: %i[index]
|
|
|
|
|
|
2024-03-15 18:27:31 -04:00
|
|
|
def index
|
2025-07-28 12:53:19 -04:00
|
|
|
@imports = policy_scope(Import)
|
2025-06-30 16:29:28 -04:00
|
|
|
.select(:id, :name, :source, :created_at, :processed, :status)
|
2024-09-08 10:52:35 -04:00
|
|
|
.order(created_at: :desc)
|
|
|
|
|
.page(params[:page])
|
2024-03-15 18:27:31 -04:00
|
|
|
end
|
|
|
|
|
|
2024-05-18 09:00:44 -04:00
|
|
|
def show; end
|
2024-03-15 18:27:31 -04:00
|
|
|
|
2025-04-18 13:48:02 -04:00
|
|
|
def edit; end
|
|
|
|
|
|
2024-03-15 18:27:31 -04:00
|
|
|
def new
|
|
|
|
|
@import = Import.new
|
2025-07-28 12:53:19 -04:00
|
|
|
|
|
|
|
|
authorize @import
|
2024-03-15 18:27:31 -04:00
|
|
|
end
|
|
|
|
|
|
2025-04-18 13:48:02 -04:00
|
|
|
def update
|
|
|
|
|
@import.update(import_params)
|
|
|
|
|
|
|
|
|
|
redirect_to imports_url, notice: 'Import was successfully updated.', status: :see_other
|
|
|
|
|
end
|
|
|
|
|
|
2024-03-15 18:27:31 -04:00
|
|
|
def create
|
2025-07-29 14:14:24 -04:00
|
|
|
@import = Import.new
|
|
|
|
|
|
|
|
|
|
authorize @import
|
|
|
|
|
|
2025-05-03 15:46:30 -04:00
|
|
|
files_params = params.dig(:import, :files)
|
|
|
|
|
raw_files = Array(files_params).reject(&:blank?)
|
2024-04-25 16:28:34 -04:00
|
|
|
|
2025-05-03 15:35:02 -04:00
|
|
|
if raw_files.empty?
|
2025-08-22 13:10:40 -04:00
|
|
|
redirect_to new_import_path, alert: 'No files were selected for upload', status: :unprocessable_entity and return
|
2025-05-03 15:35:02 -04:00
|
|
|
end
|
|
|
|
|
|
2025-05-03 15:46:30 -04:00
|
|
|
created_imports = []
|
2024-03-15 18:27:31 -04:00
|
|
|
|
2025-05-03 15:46:30 -04:00
|
|
|
raw_files.each do |item|
|
|
|
|
|
next if item.is_a?(ActionDispatch::Http::UploadedFile)
|
2024-05-31 17:18:57 -04:00
|
|
|
|
2025-05-03 15:46:30 -04:00
|
|
|
import = create_import_from_signed_id(item)
|
|
|
|
|
created_imports << import if import.present?
|
2024-04-06 16:31:33 -04:00
|
|
|
end
|
|
|
|
|
|
2025-05-03 15:46:30 -04:00
|
|
|
if created_imports.any?
|
2025-05-03 15:35:02 -04:00
|
|
|
redirect_to imports_url,
|
2025-05-03 15:46:30 -04:00
|
|
|
notice: "#{created_imports.size} files are queued to be imported in background",
|
2025-08-22 13:10:40 -04:00
|
|
|
status: :see_other and return
|
2025-05-03 15:35:02 -04:00
|
|
|
else
|
|
|
|
|
redirect_to new_import_path,
|
|
|
|
|
alert: 'No valid file references were found. Please upload files using the file selector.',
|
2025-08-22 13:10:40 -04:00
|
|
|
status: :unprocessable_entity and return
|
2025-05-03 15:35:02 -04:00
|
|
|
end
|
2024-03-15 18:27:31 -04:00
|
|
|
rescue StandardError => e
|
2025-05-03 15:46:30 -04:00
|
|
|
if created_imports.present?
|
|
|
|
|
import_ids = created_imports.map(&:id).compact
|
|
|
|
|
Import.where(id: import_ids).destroy_all if import_ids.any?
|
|
|
|
|
end
|
2024-03-24 13:55:35 -04:00
|
|
|
|
2025-05-03 15:35:02 -04:00
|
|
|
Rails.logger.error "Import error: #{e.message}"
|
|
|
|
|
Rails.logger.error e.backtrace.join("\n")
|
2025-05-03 14:36:09 -04:00
|
|
|
ExceptionReporter.call(e)
|
|
|
|
|
|
2025-05-03 15:35:02 -04:00
|
|
|
redirect_to new_import_path, alert: e.message, status: :unprocessable_entity
|
2024-03-15 18:27:31 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def destroy
|
2025-02-15 12:49:30 -05:00
|
|
|
Imports::Destroy.new(current_user, @import).call
|
2024-06-30 11:47:36 -04:00
|
|
|
|
2024-05-18 09:00:44 -04:00
|
|
|
redirect_to imports_url, notice: 'Import was successfully destroyed.', status: :see_other
|
2024-03-15 18:27:31 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
|
|
def set_import
|
|
|
|
|
@import = Import.find(params[:id])
|
|
|
|
|
end
|
|
|
|
|
|
2025-07-28 12:53:19 -04:00
|
|
|
def authorize_import
|
|
|
|
|
authorize @import
|
|
|
|
|
end
|
|
|
|
|
|
2024-03-15 18:27:31 -04:00
|
|
|
def import_params
|
2025-08-22 13:10:40 -04:00
|
|
|
params.require(:import).permit(:name, files: [])
|
2024-03-15 18:27:31 -04:00
|
|
|
end
|
2025-05-03 15:35:02 -04:00
|
|
|
|
|
|
|
|
def create_import_from_signed_id(signed_id)
|
|
|
|
|
Rails.logger.debug "Creating import from signed ID: #{signed_id[0..20]}..."
|
|
|
|
|
|
|
|
|
|
blob = ActiveStorage::Blob.find_signed(signed_id)
|
|
|
|
|
|
2025-08-22 13:10:40 -04:00
|
|
|
import = current_user.imports.build(name: blob.filename.to_s)
|
2025-05-03 15:35:02 -04:00
|
|
|
import.file.attach(blob)
|
2025-08-22 14:13:10 -04:00
|
|
|
import.source = detect_import_source(import.file) if import.source.blank?
|
2025-08-22 13:10:40 -04:00
|
|
|
|
2025-05-03 15:35:02 -04:00
|
|
|
import.save!
|
|
|
|
|
|
|
|
|
|
import
|
|
|
|
|
end
|
2025-05-16 12:51:48 -04:00
|
|
|
|
2025-08-22 13:10:40 -04:00
|
|
|
def detect_import_source(file_attachment)
|
|
|
|
|
temp_file_path = Imports::SecureFileDownloader.new(file_attachment).download_to_temp_file
|
2025-08-22 14:13:10 -04:00
|
|
|
|
2025-08-22 14:40:06 -04:00
|
|
|
Imports::SourceDetector.new_from_file_header(temp_file_path).detect_source
|
2025-08-22 13:10:40 -04:00
|
|
|
rescue StandardError => e
|
|
|
|
|
Rails.logger.warn "Failed to auto-detect import source for #{file_attachment.filename}: #{e.message}"
|
|
|
|
|
nil
|
|
|
|
|
ensure
|
|
|
|
|
# Cleanup temp file
|
|
|
|
|
if temp_file_path && File.exist?(temp_file_path)
|
|
|
|
|
File.unlink(temp_file_path)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2025-05-16 12:51:48 -04:00
|
|
|
def validate_points_limit
|
|
|
|
|
limit_exceeded = PointsLimitExceeded.new(current_user).call
|
|
|
|
|
|
2025-05-16 13:53:42 -04:00
|
|
|
redirect_to imports_path, alert: 'Points limit exceeded', status: :unprocessable_entity if limit_exceeded
|
2025-05-16 12:51:48 -04:00
|
|
|
end
|
2024-03-15 18:27:31 -04:00
|
|
|
end
|