2021-03-11 07:30:15 +01:00
|
|
|
# frozen_string_literal: true
|
2024-10-16 13:52:03 +02:00
|
|
|
require "addressable/uri"
|
2021-02-20 07:59:41 +01:00
|
|
|
|
2020-11-26 04:05:50 +01:00
|
|
|
class ::CustomWizard::UpdateValidator
|
|
|
|
attr_reader :updater
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2020-11-26 04:05:50 +01:00
|
|
|
def initialize(updater)
|
|
|
|
@updater = updater
|
|
|
|
end
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2020-11-26 04:05:50 +01:00
|
|
|
def perform
|
2024-10-16 13:52:03 +02:00
|
|
|
updater.step.fields.each { |field| validate_field(field) }
|
2020-11-26 04:05:50 +01:00
|
|
|
end
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2020-11-26 04:05:50 +01:00
|
|
|
def validate_field(field)
|
2024-10-16 13:52:03 +02:00
|
|
|
return if field.type == "text_only"
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2020-11-26 04:05:50 +01:00
|
|
|
field_id = field.id.to_s
|
|
|
|
value = @updater.submission[field_id]
|
|
|
|
min_length = false
|
2022-03-16 12:33:34 +01:00
|
|
|
label = field.raw[:label]
|
2020-11-26 04:05:50 +01:00
|
|
|
type = field.type
|
|
|
|
required = field.required
|
|
|
|
min_length = field.min_length if is_text_type(field)
|
2020-12-08 08:14:37 +01:00
|
|
|
max_length = field.max_length if is_text_type(field)
|
2020-11-26 04:05:50 +01:00
|
|
|
file_types = field.file_types
|
|
|
|
format = field.format
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2020-11-26 04:05:50 +01:00
|
|
|
if required && !value
|
2024-10-16 13:52:03 +02:00
|
|
|
@updater.errors.add(field_id, I18n.t("wizard.field.required", label: label))
|
2020-11-26 04:05:50 +01:00
|
|
|
end
|
|
|
|
|
2021-07-30 12:33:48 +02:00
|
|
|
if value.is_a?(String) && (stripped_length = value.strip.length) > 0
|
|
|
|
if min_length.present? && stripped_length < min_length.to_i
|
2024-10-16 13:52:03 +02:00
|
|
|
@updater.errors.add(
|
|
|
|
field_id,
|
|
|
|
I18n.t("wizard.field.too_short", label: label, min: min_length.to_i),
|
|
|
|
)
|
2021-07-30 12:33:48 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
if max_length.present? && stripped_length > max_length.to_i
|
2024-10-16 13:52:03 +02:00
|
|
|
@updater.errors.add(
|
|
|
|
field_id,
|
|
|
|
I18n.t("wizard.field.too_long", label: label, max: max_length.to_i),
|
|
|
|
)
|
2021-07-30 12:33:48 +02:00
|
|
|
end
|
2020-12-08 08:14:37 +01:00
|
|
|
end
|
|
|
|
|
2021-02-20 07:59:41 +01:00
|
|
|
if is_url_type(field) && value.present? && !check_if_url(value)
|
2024-10-16 13:52:03 +02:00
|
|
|
@updater.errors.add(field_id, I18n.t("wizard.field.not_url", label: label))
|
2020-11-26 04:05:50 +01:00
|
|
|
end
|
|
|
|
|
2024-10-16 13:52:03 +02:00
|
|
|
@updater.submission[field_id] = standardise_boolean(value) if type === "checkbox"
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2024-10-16 13:52:03 +02:00
|
|
|
if type === "upload" && value.present? && !validate_file_type(value, file_types)
|
|
|
|
@updater.errors.add(
|
|
|
|
field_id,
|
|
|
|
I18n.t("wizard.field.invalid_file", label: label, types: file_types),
|
|
|
|
)
|
2020-11-26 04:05:50 +01:00
|
|
|
end
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2024-10-16 13:52:03 +02:00
|
|
|
if %w[date date_time].include?(type) && value.present? && !validate_date(value, format)
|
|
|
|
@updater.errors.add(field_id, I18n.t("wizard.field.invalid_date"))
|
2020-11-26 04:05:50 +01:00
|
|
|
end
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2024-10-16 13:52:03 +02:00
|
|
|
if type === "time" && value.present? && !validate_time(value)
|
|
|
|
@updater.errors.add(field_id, I18n.t("wizard.field.invalid_time"))
|
2021-03-11 07:30:15 +01:00
|
|
|
end
|
|
|
|
|
2020-11-26 04:05:50 +01:00
|
|
|
self.class.field_validators.each do |validator|
|
2024-10-16 13:52:03 +02:00
|
|
|
validator[:block].call(field, value, @updater) if type === validator[:type]
|
2020-11-26 04:05:50 +01:00
|
|
|
end
|
|
|
|
end
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2020-11-26 04:05:50 +01:00
|
|
|
def self.sorted_field_validators
|
|
|
|
@sorted_field_validators ||= []
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.field_validators
|
|
|
|
sorted_field_validators.map { |h| { type: h[:type], block: h[:block] } }
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.add_field_validator(priority = 0, type, &block)
|
|
|
|
sorted_field_validators << { priority: priority, type: type, block: block }
|
|
|
|
@sorted_field_validators.sort_by! { |h| -h[:priority] }
|
|
|
|
end
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2020-11-26 04:05:50 +01:00
|
|
|
private
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2020-11-26 04:05:50 +01:00
|
|
|
def validate_file_type(value, file_types)
|
2024-10-16 13:52:03 +02:00
|
|
|
file_types
|
|
|
|
.split(",")
|
|
|
|
.map { |t| t.gsub(".", "") }
|
|
|
|
.include?(File.extname(value["original_filename"])[1..-1])
|
2020-11-26 04:05:50 +01:00
|
|
|
end
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2021-06-26 09:45:33 +02:00
|
|
|
def validate_date(value, format)
|
|
|
|
v8.eval("moment('#{value}', '#{format}', true).isValid()")
|
2020-11-26 04:05:50 +01:00
|
|
|
end
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2020-11-26 04:05:50 +01:00
|
|
|
def validate_time(value)
|
|
|
|
begin
|
|
|
|
Time.parse(value)
|
|
|
|
true
|
|
|
|
rescue ArgumentError
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def is_text_type(field)
|
2024-10-16 13:52:03 +02:00
|
|
|
%w[text textarea composer].include? field.type
|
2020-11-26 04:05:50 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def is_url_type(field)
|
2024-10-16 13:52:03 +02:00
|
|
|
["url"].include? field.type
|
2020-11-26 04:05:50 +01:00
|
|
|
end
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2024-10-16 13:52:03 +02:00
|
|
|
SCHEMES ||= %w[http https]
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2021-02-20 07:59:41 +01:00
|
|
|
def check_if_url(url)
|
|
|
|
parsed = Addressable::URI.parse(url) or return false
|
|
|
|
SCHEMES.include?(parsed.scheme)
|
|
|
|
rescue Addressable::URI::InvalidURIError
|
|
|
|
false
|
2020-11-26 04:05:50 +01:00
|
|
|
end
|
2021-03-11 07:30:15 +01:00
|
|
|
|
2020-11-26 04:05:50 +01:00
|
|
|
def standardise_boolean(value)
|
|
|
|
ActiveRecord::Type::Boolean.new.cast(value)
|
|
|
|
end
|
2021-06-26 09:45:33 +02:00
|
|
|
|
|
|
|
def v8
|
|
|
|
return @ctx if @ctx
|
|
|
|
|
|
|
|
@ctx = PrettyText.v8
|
2023-11-07 09:42:13 +01:00
|
|
|
@ctx.load("#{Rails.root}/vendor/assets/javascripts/moment.js")
|
2021-06-26 09:45:33 +02:00
|
|
|
@ctx
|
|
|
|
end
|
2021-03-11 07:30:15 +01:00
|
|
|
end
|