request_params_validation 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +557 -0
- data/Rakefile +32 -0
- data/lib/request_params_validation.rb +346 -0
- data/lib/request_params_validation/definitions.rb +57 -0
- data/lib/request_params_validation/definitions/action.rb +23 -0
- data/lib/request_params_validation/definitions/param.rb +182 -0
- data/lib/request_params_validation/definitions/request.rb +31 -0
- data/lib/request_params_validation/definitions/resource.rb +30 -0
- data/lib/request_params_validation/engine.rb +18 -0
- data/lib/request_params_validation/exceptions/base_errors.rb +10 -0
- data/lib/request_params_validation/exceptions/definitions_errors.rb +31 -0
- data/lib/request_params_validation/exceptions/validator_errors.rb +49 -0
- data/lib/request_params_validation/handler.rb +26 -0
- data/lib/request_params_validation/helpers.rb +17 -0
- data/lib/request_params_validation/params.rb +60 -0
- data/lib/request_params_validation/params/constants.rb +22 -0
- data/lib/request_params_validation/params/converter.rb +33 -0
- data/lib/request_params_validation/params/types/conversions.rb +41 -0
- data/lib/request_params_validation/params/types/validations.rb +57 -0
- data/lib/request_params_validation/params/validator.rb +74 -0
- data/lib/request_params_validation/params/validators/custom.rb +18 -0
- data/lib/request_params_validation/params/validators/format.rb +27 -0
- data/lib/request_params_validation/params/validators/inclusion.rb +27 -0
- data/lib/request_params_validation/params/validators/length.rb +37 -0
- data/lib/request_params_validation/params/validators/presence.rb +13 -0
- data/lib/request_params_validation/params/validators/type.rb +59 -0
- data/lib/request_params_validation/params/validators/value.rb +37 -0
- data/lib/request_params_validation/version.rb +3 -0
- metadata +87 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
module RequestParamsValidation
|
2
|
+
module Params
|
3
|
+
module Constants
|
4
|
+
HASH_TYPE = :hash
|
5
|
+
ARRAY_TYPE = :array
|
6
|
+
STRING_TYPE = :string
|
7
|
+
INTEGER_TYPE = :integer
|
8
|
+
DECIMAL_TYPE = :decimal
|
9
|
+
BOOLEAN_TYPE = :boolean
|
10
|
+
DATE_TYPE = :date
|
11
|
+
DATETIME_TYPE = :datetime
|
12
|
+
EMAIL_TYPE = :email
|
13
|
+
|
14
|
+
INTEGER_REGEXP = /^[+-]?([1-9]\d*|0)$/
|
15
|
+
DECIMAL_REGEXP = /^[+-]?([1-9]\d*|0)(\.[0-9]+)?$/
|
16
|
+
EMAIL_REGEXP = /\A[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z/
|
17
|
+
|
18
|
+
BOOLEAN_TRUE_VALUES = [true, 'true'] + RequestParamsValidation.extends.boolean_true_values
|
19
|
+
BOOLEAN_FALSE_VALUES = [false, 'false'] + RequestParamsValidation.extends.boolean_false_values
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'request_params_validation/params/types/conversions'
|
2
|
+
|
3
|
+
module RequestParamsValidation
|
4
|
+
module Params
|
5
|
+
module Converter
|
6
|
+
extend Params::Types::Conversions
|
7
|
+
|
8
|
+
def self.coerce(param, value)
|
9
|
+
type = param.type
|
10
|
+
|
11
|
+
method_name = "convert_to_#{type}"
|
12
|
+
|
13
|
+
return value unless self.respond_to?(method_name)
|
14
|
+
|
15
|
+
if [Params::DATE_TYPE, Params::DATETIME_TYPE].include?(type)
|
16
|
+
self.send(method_name, value, param.format.try(:strptime))
|
17
|
+
elsif type == Params::DECIMAL_TYPE
|
18
|
+
self.send(method_name, value, param.decimal_precision)
|
19
|
+
else
|
20
|
+
self.send(method_name, value)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.apply_transformation(param, value)
|
25
|
+
transform = param.transform
|
26
|
+
|
27
|
+
return value unless transform
|
28
|
+
|
29
|
+
transform.respond_to?(:call) ? transform.call(value) : value.send(transform)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module RequestParamsValidation
|
2
|
+
module Params
|
3
|
+
module Types
|
4
|
+
module Conversions
|
5
|
+
def convert_to_string(value)
|
6
|
+
String(value)
|
7
|
+
end
|
8
|
+
|
9
|
+
def convert_to_integer(value)
|
10
|
+
Integer(value)
|
11
|
+
end
|
12
|
+
|
13
|
+
def convert_to_decimal(value, precision)
|
14
|
+
precision = precision || RequestParamsValidation.formats.decimal_precision
|
15
|
+
|
16
|
+
value = Float(value)
|
17
|
+
|
18
|
+
value = value.round(precision) if precision
|
19
|
+
|
20
|
+
value
|
21
|
+
end
|
22
|
+
|
23
|
+
def convert_to_boolean(value)
|
24
|
+
Params::BOOLEAN_TRUE_VALUES.include?(value)
|
25
|
+
end
|
26
|
+
|
27
|
+
def convert_to_date(value, format)
|
28
|
+
format = format || RequestParamsValidation.formats.date
|
29
|
+
|
30
|
+
format ? Date.strptime(value, format) : Date.parse(value)
|
31
|
+
end
|
32
|
+
|
33
|
+
def convert_to_datetime(value, format)
|
34
|
+
format = format || RequestParamsValidation.formats.datetime
|
35
|
+
|
36
|
+
format ? DateTime.strptime(value, format) : DateTime.parse(value)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module RequestParamsValidation
|
2
|
+
module Params
|
3
|
+
module Types
|
4
|
+
module Validations
|
5
|
+
def valid_array?(value)
|
6
|
+
value.is_a?(Array)
|
7
|
+
end
|
8
|
+
|
9
|
+
def valid_hash?(value)
|
10
|
+
value.is_a?(Hash) || value.is_a?(ActionController::Parameters)
|
11
|
+
rescue NameError # For older versions of Rails
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_string?(value)
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid_integer?(value)
|
20
|
+
!!(value.to_s =~ Params::INTEGER_REGEXP)
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid_decimal?(value)
|
24
|
+
!!(value.to_s =~ Params::DECIMAL_REGEXP)
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid_email?(value)
|
28
|
+
!!(value =~ Params::EMAIL_REGEXP)
|
29
|
+
end
|
30
|
+
|
31
|
+
def valid_boolean?(value)
|
32
|
+
(Params::BOOLEAN_TRUE_VALUES + Params::BOOLEAN_FALSE_VALUES).include?(value)
|
33
|
+
end
|
34
|
+
|
35
|
+
def valid_date?(value, format)
|
36
|
+
format = format || RequestParamsValidation.formats.date
|
37
|
+
|
38
|
+
format ? Date.strptime(value, format) : Date.parse(value)
|
39
|
+
|
40
|
+
true
|
41
|
+
rescue ArgumentError, TypeError
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
def valid_datetime?(value, format)
|
46
|
+
format = format || RequestParamsValidation.formats.datetime
|
47
|
+
|
48
|
+
format ? DateTime.strptime(value, format) : DateTime.parse(value)
|
49
|
+
|
50
|
+
true
|
51
|
+
rescue ArgumentError, TypeError
|
52
|
+
false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'request_params_validation/params/converter'
|
2
|
+
|
3
|
+
Dir[File.join(File.dirname(__FILE__), 'validators/**/*.rb')].each { |f| require f }
|
4
|
+
|
5
|
+
module RequestParamsValidation
|
6
|
+
module Params
|
7
|
+
class Validator
|
8
|
+
|
9
|
+
Validators.constants(false).each do |validator|
|
10
|
+
include Validators.const_get(validator)
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :param, :value, :original_value
|
14
|
+
|
15
|
+
def initialize(param_definition, value)
|
16
|
+
@param = param_definition
|
17
|
+
@value = value
|
18
|
+
@original_value = value
|
19
|
+
end
|
20
|
+
|
21
|
+
def validate_and_coerce
|
22
|
+
validate_presence! if param.validate_presence?
|
23
|
+
|
24
|
+
if value.blank? && param.has_default?
|
25
|
+
@value = param.default
|
26
|
+
return value
|
27
|
+
end
|
28
|
+
|
29
|
+
return value if value.nil?
|
30
|
+
|
31
|
+
validate_type! if param.validate_type?
|
32
|
+
|
33
|
+
case param.type
|
34
|
+
when Params::ARRAY_TYPE
|
35
|
+
iterate_array
|
36
|
+
when Params::HASH_TYPE
|
37
|
+
iterate_hash
|
38
|
+
end
|
39
|
+
|
40
|
+
@value = Params::Converter.coerce(param, value)
|
41
|
+
|
42
|
+
validate_inclusion! if param.validate_inclusion?
|
43
|
+
validate_length! if param.validate_length?
|
44
|
+
validate_value! if param.validate_value?
|
45
|
+
validate_format! if param.validate_format?
|
46
|
+
validate_custom_validation! if param.validate_custom_validation?
|
47
|
+
|
48
|
+
@value = Params::Converter.apply_transformation(param, value)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def iterate_array
|
54
|
+
value.map! do |element_value|
|
55
|
+
self.class.new(param.elements, element_value).validate_and_coerce
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def iterate_hash
|
60
|
+
Params::validate!(param.sub_definition, value) # recursion for the sub_definition
|
61
|
+
end
|
62
|
+
|
63
|
+
def raise_error(exception_type, options = {})
|
64
|
+
options = options.merge(
|
65
|
+
param_key: param.key,
|
66
|
+
param_value: original_value,
|
67
|
+
param_type: param.type
|
68
|
+
)
|
69
|
+
|
70
|
+
raise RequestParamsValidation.exceptions.send(exception_type).new(options)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module RequestParamsValidation
|
2
|
+
module Params
|
3
|
+
module Validators
|
4
|
+
module Custom
|
5
|
+
def validate_custom_validation!
|
6
|
+
result = param.custom_validation.function.call(value)
|
7
|
+
|
8
|
+
unless result
|
9
|
+
raise_error(
|
10
|
+
:on_invalid_parameter_custom_validation,
|
11
|
+
details: param.custom_validation.message
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module RequestParamsValidation
|
2
|
+
module Params
|
3
|
+
module Validators
|
4
|
+
module Format
|
5
|
+
def validate_format!
|
6
|
+
regexp = param.format.regexp
|
7
|
+
|
8
|
+
if value !~ regexp
|
9
|
+
raise_error(
|
10
|
+
:on_invalid_parameter_format,
|
11
|
+
regexp: regexp,
|
12
|
+
details: param.format.message || default_invalid_format_message
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def default_invalid_format_message
|
18
|
+
if param.element_of_array?
|
19
|
+
'An element of the array has an invalid format'
|
20
|
+
else
|
21
|
+
'Value format is invalid'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module RequestParamsValidation
|
2
|
+
module Params
|
3
|
+
module Validators
|
4
|
+
module Inclusion
|
5
|
+
def validate_inclusion!
|
6
|
+
include_in = param.inclusion.in
|
7
|
+
|
8
|
+
unless include_in.include?(value)
|
9
|
+
raise_error(
|
10
|
+
:on_invalid_parameter_inclusion,
|
11
|
+
include_in: include_in,
|
12
|
+
details: param.inclusion.message || default_invalid_inclusion_message(include_in)
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def default_invalid_inclusion_message(include_in)
|
18
|
+
if param.element_of_array?
|
19
|
+
"All elements values of the array should be in #{include_in}"
|
20
|
+
else
|
21
|
+
"Value should be in #{include_in}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module RequestParamsValidation
|
2
|
+
module Params
|
3
|
+
module Validators
|
4
|
+
module Length
|
5
|
+
def validate_length!
|
6
|
+
min = param.length.min
|
7
|
+
max = param.length.max
|
8
|
+
|
9
|
+
if (min && value.length < min) || (max && value.length > max)
|
10
|
+
raise_error(
|
11
|
+
:on_invalid_parameter_length,
|
12
|
+
min: min,
|
13
|
+
max: max,
|
14
|
+
details: param.length.message || default_invalid_length_message(min, max)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def default_invalid_length_message(min, max)
|
20
|
+
message = if param.element_of_array?
|
21
|
+
'All elements of the array should have a length'
|
22
|
+
else
|
23
|
+
'Length should be'
|
24
|
+
end
|
25
|
+
|
26
|
+
if min && max
|
27
|
+
min == max ? "#{message} equal to #{max}" : "#{message} between #{min} and #{max}"
|
28
|
+
elsif min
|
29
|
+
"#{message} greater or equal than #{min}"
|
30
|
+
else
|
31
|
+
"#{message} less or equal than #{max}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module RequestParamsValidation
|
2
|
+
module Params
|
3
|
+
module Validators
|
4
|
+
module Presence
|
5
|
+
def validate_presence!
|
6
|
+
not_present = param.allow_blank ? value.nil? : value.blank?
|
7
|
+
|
8
|
+
raise_error(:on_missing_parameter) if not_present
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'request_params_validation/params/types/validations'
|
2
|
+
|
3
|
+
module RequestParamsValidation
|
4
|
+
module Params
|
5
|
+
module Validators
|
6
|
+
module Type
|
7
|
+
include Params::Types::Validations
|
8
|
+
include RequestParamsValidation.extends.types if RequestParamsValidation.extends.types
|
9
|
+
|
10
|
+
def validate_type!
|
11
|
+
type = param.type
|
12
|
+
|
13
|
+
method_name = "valid_#{type}?"
|
14
|
+
|
15
|
+
unless self.respond_to?(method_name)
|
16
|
+
raise UnsupportedTypeError.new(param_key: param.key, param_type: type)
|
17
|
+
end
|
18
|
+
|
19
|
+
valid = if [Params::DATE_TYPE, Params::DATETIME_TYPE].include?(type)
|
20
|
+
self.send(method_name, value, param.format.try(:strptime))
|
21
|
+
else
|
22
|
+
self.send(method_name, value)
|
23
|
+
end
|
24
|
+
|
25
|
+
unless valid
|
26
|
+
raise_error(
|
27
|
+
:on_invalid_parameter_type,
|
28
|
+
details: default_invalid_type_message(type)
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def default_invalid_type_message(type)
|
34
|
+
type = :object if type == Params::HASH_TYPE
|
35
|
+
|
36
|
+
message = if param.element_of_array?
|
37
|
+
"All elements of the array should be a valid #{type}"
|
38
|
+
else
|
39
|
+
"Value should be a valid #{type}"
|
40
|
+
end
|
41
|
+
|
42
|
+
if [Params::DATE_TYPE, Params::DATETIME_TYPE].include?(type)
|
43
|
+
format = param.format.try(:strptime) || RequestParamsValidation.formats.send(type)
|
44
|
+
|
45
|
+
if format
|
46
|
+
message = if param.format.try(:message)
|
47
|
+
param.format.message
|
48
|
+
else
|
49
|
+
"#{message} with the format #{format}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
message
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module RequestParamsValidation
|
2
|
+
module Params
|
3
|
+
module Validators
|
4
|
+
module Value
|
5
|
+
def validate_value!
|
6
|
+
min = param.value.min
|
7
|
+
max = param.value.max
|
8
|
+
|
9
|
+
if (min && value < min) || (max && value > max)
|
10
|
+
raise_error(
|
11
|
+
:on_invalid_parameter_value_size,
|
12
|
+
min: min,
|
13
|
+
max: max,
|
14
|
+
details: param.value.message || default_invalid_value_message(min, max)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def default_invalid_value_message(min, max)
|
20
|
+
message = if param.element_of_array?
|
21
|
+
'All elements of the array should have a value'
|
22
|
+
else
|
23
|
+
'Value should be'
|
24
|
+
end
|
25
|
+
|
26
|
+
if min && max
|
27
|
+
"#{message} between #{min} and #{max}"
|
28
|
+
elsif min
|
29
|
+
"#{message} greater or equal than #{min}"
|
30
|
+
else
|
31
|
+
"#{message} less or equal than #{max}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|