Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion app/controllers/api/v1/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ class Api::V1::BaseController < ApplicationController

InvalidFilterError = Class.new(StandardError)

class << self
def valid_uuid?(value)
value.to_s.match?(UUID_PATTERN)
end
end

# Skip regular session-based authentication for API
skip_authentication

Expand Down Expand Up @@ -220,7 +226,7 @@ def render_json(data, status: :ok)
end

def valid_uuid?(value)
value.to_s.match?(UUID_PATTERN)
self.class.valid_uuid?(value)
end

def safe_page_param
Expand Down
49 changes: 39 additions & 10 deletions app/controllers/api/v1/imports_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Api::V1::ImportsController < Api::V1::BaseController
include Pagy::Backend

# Ensure proper scope authorization
before_action :ensure_read_scope, only: [ :index, :show, :rows ]
before_action :ensure_read_scope, only: [ :index, :show, :rows, :preflight ]
before_action :ensure_write_scope, only: [ :create ]
before_action :set_import_with_rows, only: [ :show ]
before_action :set_import, only: [ :rows ]
Expand Down Expand Up @@ -77,10 +77,10 @@ def create
if params[:file].present?
file = params[:file]

if file.size > Import::MAX_CSV_SIZE
if file.size > Import.max_csv_size
return render json: {
error: "file_too_large",
message: "File is too large. Maximum size is #{Import::MAX_CSV_SIZE / 1.megabyte}MB."
message: "File is too large. Maximum size is #{Import.max_csv_size / 1.megabyte}MB."
}, status: :unprocessable_entity
end

Expand All @@ -93,10 +93,10 @@ def create

@import.raw_file_str = file.read
elsif params[:raw_file_content].present?
if params[:raw_file_content].bytesize > Import::MAX_CSV_SIZE
if params[:raw_file_content].bytesize > Import.max_csv_size
return render json: {
error: "content_too_large",
message: "Content is too large. Maximum size is #{Import::MAX_CSV_SIZE / 1.megabyte}MB."
message: "Content is too large. Maximum size is #{Import.max_csv_size / 1.megabyte}MB."
}, status: :unprocessable_entity
end

Expand Down Expand Up @@ -136,6 +136,30 @@ def create
render json: { error: "internal_server_error", message: e.message }, status: :internal_server_error
end

def preflight
preflight_result = Import::Preflight.new(family: current_resource_owner.family, params: preflight_params).call
render json: preflight_result.payload, status: preflight_result.status
rescue ActiveRecord::RecordNotFound
render json: {
error: "record_not_found",
message: "The requested resource was not found"
}, status: :not_found
rescue CSV::MalformedCSVError => e
render json: {
error: "invalid_csv",
message: "CSV content could not be parsed",
errors: [ e.message ]
}, status: :unprocessable_entity
rescue StandardError => e
Rails.logger.error "ImportsController#preflight error: #{e.message}"
e.backtrace&.each { |line| Rails.logger.error line }

render json: {
error: "internal_server_error",
message: "Error: #{e.message}"
}, status: :internal_server_error
Comment thread
coderabbitai[bot] marked this conversation as resolved.
end

private

def set_import
Expand Down Expand Up @@ -186,10 +210,15 @@ def import_config_params
:signage_convention,
:col_sep,
:amount_type_strategy,
:amount_type_inflow_value
:amount_type_inflow_value,
:rows_to_skip
)
end

def preflight_params
params.permit(*Import::Preflight::PARAM_KEYS)
end

def create_sure_import(family)
content, filename, content_type = sure_import_upload_attributes
return unless content
Expand Down Expand Up @@ -282,10 +311,10 @@ def sure_import_upload_attributes
end

def sure_import_file_upload_attributes(file)
if file.size > SureImport::MAX_NDJSON_SIZE
if file.size > SureImport.max_ndjson_size
render json: {
error: "file_too_large",
message: "File is too large. Maximum size is #{SureImport::MAX_NDJSON_SIZE / 1.megabyte}MB."
message: "File is too large. Maximum size is #{SureImport.max_ndjson_size / 1.megabyte}MB."
}, status: :unprocessable_entity
return
end
Expand All @@ -308,10 +337,10 @@ def sure_import_file_upload_attributes(file)
end

def sure_import_raw_content_attributes(content)
if content.bytesize > SureImport::MAX_NDJSON_SIZE
if content.bytesize > SureImport.max_ndjson_size
render json: {
error: "content_too_large",
message: "Content is too large. Maximum size is #{SureImport::MAX_NDJSON_SIZE / 1.megabyte}MB."
message: "Content is too large. Maximum size is #{SureImport.max_ndjson_size / 1.megabyte}MB."
}, status: :unprocessable_entity
return
end
Expand Down
5 changes: 5 additions & 0 deletions app/models/import.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class Import < ApplicationRecord
MaxRowCountExceededError = Class.new(StandardError)
MappingError = Class.new(StandardError)

# Shared CSV upload/content limit for web and API imports, including preflight.
MAX_CSV_SIZE = 10.megabytes
MAX_PDF_SIZE = 25.megabytes
ALLOWED_CSV_MIME_TYPES = %w[text/csv text/plain application/vnd.ms-excel application/csv].freeze
Expand All @@ -24,6 +25,10 @@ def self.reasonable_date_range
Date.new(1970, 1, 1)..Date.today.next_year(5)
end

def self.max_csv_size
MAX_CSV_SIZE
end

AMOUNT_TYPE_STRATEGIES = %w[signed_amount custom_column].freeze

belongs_to :family
Expand Down
Loading
Loading