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.
		
		
		
		
		
			
		
			
				
					
					
						
							146 lines
						
					
					
						
							3.9 KiB
						
					
					
				
			
		
		
	
	
							146 lines
						
					
					
						
							3.9 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(%r{\s*[;,/]\s*}).compact_blank
 | 
						|
                    .all? { |email| EmailTypo::DotCom.call(email).match?(EMAIL_REGEXP) || email.include?('--') }
 | 
						|
        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 = [], skip_blank: false)
 | 
						|
      old_path = @current_path
 | 
						|
 | 
						|
      @current_path = [old_path, *path].compact_blank.map(&:to_s).join('.')
 | 
						|
 | 
						|
      param = params.dig(*path)
 | 
						|
      param = nil if skip_blank && param.blank?
 | 
						|
 | 
						|
      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
 |