mirror of https://github.com/docusealco/docuseal
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
3.8 KiB
145 lines
3.8 KiB
# frozen_string_literal: true
|
|
|
|
module Params
|
|
class BaseValidator
|
|
EMAIL_REGEXP = User::FULL_EMAIL_REGEXP
|
|
|
|
InvalidParameterError = Class.new(StandardError)
|
|
|
|
def self.call(...)
|
|
validator = new(...)
|
|
|
|
validator.call
|
|
rescue InvalidParameterError => e
|
|
Rollbar.warning(e) if defined?(Rollbar)
|
|
|
|
raise e unless validator.dry_run?
|
|
rescue StandardError => e
|
|
Rollbar.error(e) if defined?(Rollbar)
|
|
|
|
raise e unless Rails.env.production?
|
|
end
|
|
|
|
attr_reader :params, :dry_run
|
|
|
|
alias dry_run? dry_run
|
|
|
|
def initialize(params, dry_run: false)
|
|
@params = params
|
|
@dry_run = dry_run
|
|
@current_path = ''
|
|
end
|
|
|
|
def call
|
|
raise NotImplementedError
|
|
end
|
|
|
|
def raise_error(message)
|
|
message += " in `#{@current_path}`." if @current_path.present?
|
|
|
|
raise InvalidParameterError, message unless dry_run?
|
|
end
|
|
|
|
def required(params, keys, message: nil)
|
|
keys = Array.wrap(keys)
|
|
|
|
return if keys.any? { |key| params&.dig(key).present? }
|
|
|
|
raise_error(message || "#{keys.join(' or ')} is required")
|
|
end
|
|
|
|
def type(params, key, type, message: nil)
|
|
return if params.blank?
|
|
return if params[key].blank?
|
|
|
|
return if params[key].is_a?(type) || (type == Hash && params[key].is_a?(ActionController::Parameters))
|
|
|
|
type = 'Object' if type == Hash
|
|
|
|
raise_error(message || "#{key} must be a #{type}")
|
|
end
|
|
|
|
def format(params, key, regexp, message: nil)
|
|
return if params.blank?
|
|
return if params[key].blank?
|
|
return if regexp.match?(params[key].to_s)
|
|
|
|
raise_error(message || "#{key} must follow the #{regexp.source} format")
|
|
end
|
|
|
|
def email_format(params, key, message: nil)
|
|
return if params.blank?
|
|
return if params[key].blank?
|
|
return if params[key].to_s.include?('<')
|
|
|
|
if params[key].to_s.strip.split(/\s*[;,]\s*/).compact_blank
|
|
.all? { |email| EmailTypo::DotCom.call(email).match?(EMAIL_REGEXP) }
|
|
return
|
|
end
|
|
|
|
raise_error(message || "#{key} must follow the email format: '#{params[key]}'")
|
|
end
|
|
|
|
def unique_value(params, key, message: nil)
|
|
return unless params.is_a?(Array)
|
|
return if params.none?
|
|
return if params.all? { |p| p[key].blank? }
|
|
return if params.pluck(key).compact_blank.uniq.size == params.pluck(key).compact_blank.size
|
|
|
|
raise_error(message || "#{key} must be unique")
|
|
end
|
|
|
|
def in_path(params, path = [])
|
|
old_path = @current_path
|
|
|
|
@current_path = [old_path, *path].compact_blank.map(&:to_s).join('.')
|
|
|
|
param = params.dig(*path)
|
|
|
|
yield params.dig(*path) if param
|
|
|
|
@current_path = old_path
|
|
end
|
|
|
|
def in_path_each(params, path = [])
|
|
old_path = @current_path
|
|
|
|
params.dig(*path)&.each_with_index do |item, index|
|
|
@current_path = [old_path, [*path].map(&:to_s).join('.') + "[#{index}]"].compact_blank.join('.')
|
|
|
|
yield item if item
|
|
end
|
|
|
|
@current_path = old_path
|
|
end
|
|
|
|
def boolean(params, key, message: nil)
|
|
return if params.blank?
|
|
return unless params.key?(key)
|
|
return if params[key].nil?
|
|
|
|
value = ActiveModel::Type::Boolean.new.cast(params[key])
|
|
|
|
return if value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
|
|
|
raise_error(message || "#{key} must be true or false")
|
|
end
|
|
|
|
def value_in(params, key, values, allow_nil: false, message: nil)
|
|
return if params.blank?
|
|
return if allow_nil && params[key].nil?
|
|
return if values.include?(params[key])
|
|
|
|
raise_error(message || "#{key} must be one of #{values.join(', ')}")
|
|
end
|
|
|
|
def more_than(params, key, value, message: nil)
|
|
return if params.blank?
|
|
return if params[key].blank?
|
|
return if params[key].to_f > value
|
|
|
|
raise_error(message || "#{key} must be more than #{value}")
|
|
end
|
|
end
|
|
end
|