@@ -13,15 +13,15 @@ module Web
1313 REQUIRED_TOKEN_KEYS = %i[ p s ] . freeze
1414 COMPRESSED_PAYLOAD_KEYS = %i[ u l e ] . freeze
1515
16- FeedToken = Data . define ( :username , :url , :expires_at , :signature ) do
17- def self . create_with_validation ( username :, url :, secret_key :, expires_in : DEFAULT_EXPIRY )
18- return unless valid_inputs? ( username , url , secret_key )
16+ FeedToken = Data . define ( :username , :url , :expires_at , :signature , :strategy ) do
17+ def self . create_with_validation ( username :, url :, secret_key :, strategy : , expires_in : DEFAULT_EXPIRY )
18+ return unless valid_inputs? ( username , url , secret_key , strategy )
1919
2020 expires_at = Time . now . to_i + expires_in . to_i
21- payload = build_payload ( username , url , expires_at )
21+ payload = build_payload ( username , url , expires_at , strategy )
2222 signature = generate_signature ( secret_key , payload )
2323
24- new ( username : username , url : url , expires_at : expires_at , signature : signature )
24+ new ( username : username , url : url , expires_at : expires_at , signature : signature , strategy : strategy )
2525 end
2626
2727 def self . decode ( encoded_token ) # rubocop:disable Metrics/MethodLength
@@ -35,7 +35,8 @@ def self.decode(encoded_token) # rubocop:disable Metrics/MethodLength
3535 username : payload [ :u ] ,
3636 url : payload [ :l ] ,
3737 expires_at : payload [ :e ] ,
38- signature : token_data [ :s ]
38+ signature : token_data [ :s ] ,
39+ strategy : payload [ :t ]
3940 )
4041 rescue JSON ::ParserError , ArgumentError , Zlib ::DataError , Zlib ::BufError
4142 nil
@@ -74,11 +75,15 @@ def valid_signature?(secret_key)
7475 private
7576
7677 def payload_for_signature
77- { username : username , url : url , expires_at : expires_at }
78+ payload = { username : username , url : url , expires_at : expires_at }
79+ payload [ :strategy ] = strategy if strategy
80+ payload
7881 end
7982
8083 def build_token_data
81- { p : { u : username , l : url , e : expires_at } , s : signature }
84+ payload = { u : username , l : url , e : expires_at }
85+ payload [ :t ] = strategy if strategy
86+ { p : payload , s : signature }
8287 end
8388
8489 def secure_compare ( first , second ) # rubocop:disable Naming/PredicateMethod
@@ -88,8 +93,8 @@ def secure_compare(first, second) # rubocop:disable Naming/PredicateMethod
8893 end
8994
9095 class << self
91- def build_payload ( username , url , expires_at )
92- { username : username , url : url , expires_at : expires_at }
96+ def build_payload ( username , url , expires_at , strategy )
97+ { username : username , url : url , expires_at : expires_at , strategy : strategy }
9398 end
9499
95100 def generate_signature ( secret_key , payload )
@@ -112,8 +117,9 @@ def valid_token_data?(token_data)
112117 COMPRESSED_PAYLOAD_KEYS . all? { |key | payload [ key ] }
113118 end
114119
115- def valid_inputs? ( username , url , secret_key )
116- valid_username? ( username ) && UrlValidator . valid_url? ( url ) && valid_secret_key? ( secret_key )
120+ def valid_inputs? ( username , url , secret_key , strategy )
121+ valid_username? ( username ) && UrlValidator . valid_url? ( url ) && valid_secret_key? ( secret_key ) &&
122+ valid_strategy? ( strategy )
117123 end
118124
119125 def valid_username? ( username )
@@ -123,6 +129,10 @@ def valid_username?(username)
123129 def valid_secret_key? ( secret_key )
124130 secret_key . is_a? ( String ) && !secret_key . empty?
125131 end
132+
133+ def valid_strategy? ( strategy )
134+ strategy . is_a? ( String ) && !strategy . empty? && strategy . length <= 50 && strategy . match? ( /\A [a-z0-9_]+\z / )
135+ end
126136 end
127137 end
128138 end
0 commit comments