@@ -7,66 +7,88 @@ def initialize(config)
77 @config = config
88 end
99
10- def valid?
11- return if config . nil? || config == OPT_OUT
12- raise CookiesConfigError . new ( "config must be a hash." ) unless config . is_a? Hash
13-
14- # secure and httponly - validate only boolean or Hash configuration
15- [ :secure , :httponly ] . each do |attribute |
16- if config [ attribute ] && !( config [ attribute ] . is_a? ( Hash ) || config [ attribute ] . is_a? ( TrueClass ) || config [ attribute ] . is_a? ( FalseClass ) )
17- raise CookiesConfigError . new ( "#{ attribute } cookie config must be a hash or boolean" )
18- end
19- end
10+ def validate!
11+ return if config . nil? || config == SecureHeaders ::OPT_OUT
2012
21- # secure and httponly - validate exclusive use of only or except but not both at the same time
22- [ :secure , :httponly ] . each do |attribute |
23- if config [ attribute ] . is_a? ( Hash )
24- if config [ attribute ] . key? ( :only ) && config [ attribute ] . key? ( :except )
25- raise CookiesConfigError . new ( "#{ attribute } cookie config is invalid, simultaneous use of conditional arguments `only` and `except` is not permitted." )
26- end
13+ validate_config!
14+ validate_secure_config! if config [ :secure ]
15+ validate_httponly_config! if config [ :httponly ]
16+ validate_samesite_config! if config [ :samesite ]
17+ end
2718
28- if ( intersection = ( config [ attribute ] . fetch ( :only , [ ] ) & config [ attribute ] . fetch ( :only , [ ] ) ) ) . any?
29- raise CookiesConfigError . new ( "#{ attribute } cookie config is invalid, cookies #{ intersection . join ( ', ' ) } cannot be enforced as lax and strict" )
30- end
31- end
32- end
19+ private
3320
34- if config [ :samesite ]
35- raise CookiesConfigError . new ( "samesite cookie config must be a hash" ) unless config [ :samesite ] . is_a? ( Hash )
21+ def validate_config!
22+ raise CookiesConfigError . new ( "config must be a hash." ) unless is_hash? ( config )
23+ end
3624
37- # when configuring with booleans, only one enforcement is permitted
38- if config [ :samesite ] . key? ( :lax ) && config [ :samesite ] [ :lax ] . is_a? ( TrueClass ) && config [ :samesite ] . key? ( :strict )
39- raise CookiesConfigError . new ( "samesite cookie config is invalid, combination use of booleans and Hash to configure lax and strict enforcement is not permitted." )
40- elsif config [ :samesite ] . key? ( :strict ) && config [ :samesite ] [ :strict ] . is_a? ( TrueClass ) && config [ :samesite ] . key? ( :lax )
41- raise CookiesConfigError . new ( "samesite cookie config is invalid, combination use of booleans and Hash to configure lax and strict enforcement is not permitted." )
42- end
25+ def validate_secure_config!
26+ validate_hash_or_boolean! ( :secure )
27+ validate_exclusive_use_of_hash_constraints! ( config [ :secure ] , :secure )
28+ end
4329
44- # validate Hash-based samesite configuration
45- if config [ :samesite ] . key? ( :lax ) && config [ :samesite ] [ :lax ] . is_a? ( Hash )
46- # validate exclusive use of only or except but not both at the same time
47- if config [ :samesite ] [ :lax ] . key? ( :only ) && config [ :samesite ] [ :lax ] . key? ( :except )
48- raise CookiesConfigError . new ( "samesite lax cookie config is invalid, simultaneous use of conditional arguments `only` and `except` is not permitted." )
49- end
30+ def validate_httponly_config!
31+ validate_hash_or_boolean! ( :httponly )
32+ validate_exclusive_use_of_hash_constraints! ( config [ :httponly ] , :httponly )
33+ end
34+
35+ def validate_samesite_config!
36+ raise CookiesConfigError . new ( "samesite cookie config must be a hash" ) unless is_hash? ( config [ :samesite ] )
37+
38+ validate_samesite_boolean_config!
39+ validate_samesite_hash_config!
40+ end
5041
51- if config [ :samesite ] . key? ( :strict )
52- # validate exclusivity of only and except members
53- if ( intersection = ( config [ :samesite ] [ :lax ] . fetch ( :only , [ ] ) & config [ :samesite ] [ :strict ] . fetch ( :only , [ ] ) ) ) . any?
54- raise CookiesConfigError . new ( "samesite cookie config is invalid, cookie(s) #{ intersection . join ( ', ' ) } cannot be enforced as lax and strict" )
55- end
42+ # when configuring with booleans, only one enforcement is permitted
43+ def validate_samesite_boolean_config!
44+ if config [ :samesite ] . key? ( :lax ) && config [ :samesite ] [ :lax ] . is_a? ( TrueClass ) && config [ :samesite ] . key? ( :strict )
45+ raise CookiesConfigError . new ( "samesite cookie config is invalid, combination use of booleans and Hash to configure lax and strict enforcement is not permitted." )
46+ elsif config [ :samesite ] . key? ( :strict ) && config [ :samesite ] [ :strict ] . is_a? ( TrueClass ) && config [ :samesite ] . key? ( :lax )
47+ raise CookiesConfigError . new ( "samesite cookie config is invalid, combination use of booleans and Hash to configure lax and strict enforcement is not permitted." )
48+ end
49+ end
5650
57- if ( intersection = ( config [ :samesite ] [ :lax ] . fetch ( :except , [ ] ) & config [ :samesite ] [ :strict ] . fetch ( :except , [ ] ) ) ) . any?
58- raise CookiesConfigError . new ( "samesite cookie config is invalid, cookie(s) #{ intersection . join ( ', ' ) } cannot be enforced as lax and strict" )
59- end
51+ def validate_samesite_hash_config!
52+ # validate Hash-based samesite configuration
53+ if is_hash? ( config [ :samesite ] [ :lax ] )
54+ validate_exclusive_use_of_hash_constraints! ( config [ :samesite ] [ :lax ] , 'samesite lax' )
55+
56+ if is_hash? ( config [ :samesite ] [ :strict ] )
57+ validate_exclusive_use_of_hash_constraints! ( config [ :samesite ] [ :strict ] , 'samesite strict' )
58+
59+ # validate exclusivity of only and except members within strict and lax
60+ if ( intersection = ( config [ :samesite ] [ :lax ] . fetch ( :only , [ ] ) & config [ :samesite ] [ :strict ] . fetch ( :only , [ ] ) ) ) . any?
61+ raise CookiesConfigError . new ( "samesite cookie config is invalid, cookie(s) #{ intersection . join ( ', ' ) } cannot be enforced as lax and strict" )
6062 end
61- end
6263
63- if config [ :samesite ] . key? ( :strict ) && config [ :samesite ] [ :strict ] . is_a? ( Hash )
64- # validate exclusive use of only or except but not both at the same time
65- if config [ :samesite ] [ :strict ] . key? ( :only ) && config [ :samesite ] [ :strict ] . key? ( :except )
66- raise CookiesConfigError . new ( "samesite strict cookie config is invalid, simultaneous use of conditional arguments `only` and `except` is not permitted." )
64+ if ( intersection = ( config [ :samesite ] [ :lax ] . fetch ( :except , [ ] ) & config [ :samesite ] [ :strict ] . fetch ( :except , [ ] ) ) ) . any?
65+ raise CookiesConfigError . new ( "samesite cookie config is invalid, cookie(s) #{ intersection . join ( ', ' ) } cannot be enforced as lax and strict" )
6766 end
6867 end
6968 end
7069 end
70+
71+ def validate_hash_or_boolean! ( attribute )
72+ if !( is_hash? ( config [ attribute ] ) || is_boolean? ( config [ attribute ] ) )
73+ raise CookiesConfigError . new ( "#{ attribute } cookie config must be a hash or boolean" )
74+ end
75+ end
76+
77+ # validate exclusive use of only or except but not both at the same time
78+ def validate_exclusive_use_of_hash_constraints! ( conf , attribute )
79+ return unless is_hash? ( conf )
80+
81+ if conf . key? ( :only ) && conf . key? ( :except )
82+ raise CookiesConfigError . new ( "#{ attribute } cookie config is invalid, simultaneous use of conditional arguments `only` and `except` is not permitted." )
83+ end
84+ end
85+
86+ def is_hash? ( obj )
87+ obj && obj . is_a? ( Hash )
88+ end
89+
90+ def is_boolean? ( obj )
91+ obj && ( obj . is_a? ( TrueClass ) || obj . is_a? ( FalseClass ) )
92+ end
7193 end
7294end
0 commit comments