queueit_knownuserv3 3.2.3
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 +15 -0
- data/Gemfile +4 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/queueit_knownuserv3.rb +9 -0
- data/lib/queueit_knownuserv3/integration_config_helpers.rb +265 -0
- data/lib/queueit_knownuserv3/known_user.rb +310 -0
- data/lib/queueit_knownuserv3/models.rb +96 -0
- data/lib/queueit_knownuserv3/queue_url_params.rb +81 -0
- data/lib/queueit_knownuserv3/user_in_queue_service.rb +116 -0
- data/lib/queueit_knownuserv3/user_in_queue_state_cookie_repository.rb +125 -0
- data/queueit_knownuserv3.gemspec +31 -0
- metadata +84 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZTZmYWVkMDlhZmY4NzIwYzBiYjkyMmY0Njg4YTlmYzMyYzczNzI4OQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NDE4OTVjYzEyZWJmOGIwMzkwMTFiYWU2Yzg5ZjRiOGMxNGE0ZmMwOA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YWMzOGU1YTU2NDJjYTQwODJkMzdlNjBjNTU2Y2U2MTA3NWRkNmJmZTFhOGYy
|
10
|
+
MWIzYjY4Y2Q0ZTE1OTBjOTFkODM0NGJiMzIzZDRjNDc2ZTc3MDk2ODIwZmVi
|
11
|
+
YjJkN2QwZWIwODg5NzE0MDg5YmE5MDFlZTZhZWY1NWY3M2FkYTM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NDQ1MjI5YmZiMDEwNGU3MTFkNWUxYjhhYTIyNjBhZmE5MGRmMmExODAwNWYw
|
14
|
+
NGZiMzM4NzYzN2YyYmEyYjc1YzAwZTc2OTNkZDdiYjg4Njc2YzlkNWI2OGE4
|
15
|
+
MjUwMWUyOTE2NGY2NjYyNWQxMzg1YTA0YjM5OTlmZTY0MDcxMWI=
|
data/Gemfile
ADDED
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "queueit_knownuserv3"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require_relative "queueit_knownuserv3/known_user"
|
2
|
+
require_relative "queueit_knownuserv3/models"
|
3
|
+
require_relative "queueit_knownuserv3/queue_url_params"
|
4
|
+
require_relative "queueit_knownuserv3/user_in_queue_state_cookie_repository"
|
5
|
+
require_relative "queueit_knownuserv3/user_in_queue_service"
|
6
|
+
require_relative "queueit_knownuserv3/integration_config_helpers"
|
7
|
+
|
8
|
+
module QueueIt
|
9
|
+
end
|
@@ -0,0 +1,265 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module QueueIt
|
4
|
+
class IntegrationEvaluator
|
5
|
+
def getMatchedIntegrationConfig(customerIntegration, currentPageUrl, cookieList, userAgent)
|
6
|
+
if (!customerIntegration.kind_of?(Hash) || !customerIntegration.key?("Integrations") ||
|
7
|
+
!customerIntegration["Integrations"].kind_of?(Array))
|
8
|
+
return nil;
|
9
|
+
end
|
10
|
+
customerIntegration["Integrations"].each do |integrationConfig|
|
11
|
+
next if !integrationConfig.kind_of?(Hash) || !integrationConfig.key?("Triggers") || !integrationConfig["Triggers"].kind_of?(Array)
|
12
|
+
|
13
|
+
integrationConfig["Triggers"].each do |trigger|
|
14
|
+
if(!trigger.kind_of?(Hash))
|
15
|
+
return false
|
16
|
+
end
|
17
|
+
if(evaluateTrigger(trigger, currentPageUrl, cookieList, userAgent))
|
18
|
+
return integrationConfig
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
return nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def evaluateTrigger(trigger, currentPageUrl, cookieList, userAgent)
|
27
|
+
if (!trigger.key?("LogicalOperator") ||
|
28
|
+
!trigger.key?("TriggerParts") ||
|
29
|
+
!trigger["TriggerParts"].kind_of?(Array))
|
30
|
+
return false;
|
31
|
+
end
|
32
|
+
|
33
|
+
if(trigger["LogicalOperator"].eql? "Or")
|
34
|
+
trigger["TriggerParts"].each do |triggerPart|
|
35
|
+
if(!triggerPart.kind_of?(Hash))
|
36
|
+
return false
|
37
|
+
end
|
38
|
+
if(evaluateTriggerPart(triggerPart, currentPageUrl, cookieList, userAgent))
|
39
|
+
return true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
return false
|
43
|
+
else
|
44
|
+
trigger["TriggerParts"].each do |triggerPart|
|
45
|
+
if(!triggerPart.kind_of?(Hash))
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
if(!evaluateTriggerPart(triggerPart, currentPageUrl, cookieList, userAgent))
|
49
|
+
return false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
return true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def evaluateTriggerPart(triggerPart, currentPageUrl, cookieList, userAgent)
|
57
|
+
if (!triggerPart.key?("ValidatorType"))
|
58
|
+
return false
|
59
|
+
end
|
60
|
+
|
61
|
+
case triggerPart["ValidatorType"]
|
62
|
+
when "UrlValidator"
|
63
|
+
return UrlValidatorHelper.evaluate(triggerPart, currentPageUrl)
|
64
|
+
when "CookieValidator"
|
65
|
+
return CookieValidatorHelper.evaluate(triggerPart, cookieList)
|
66
|
+
when "UserAgentValidator"
|
67
|
+
return UserAgentValidatorHelper.evaluate(triggerPart, userAgent)
|
68
|
+
else
|
69
|
+
return false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class UrlValidatorHelper
|
75
|
+
def self.evaluate(triggerPart, url)
|
76
|
+
if (!triggerPart.key?("Operator") ||
|
77
|
+
!triggerPart.key?("IsNegative") ||
|
78
|
+
!triggerPart.key?("IsIgnoreCase") ||
|
79
|
+
!triggerPart.key?("ValueToCompare") ||
|
80
|
+
!triggerPart.key?("UrlPart"))
|
81
|
+
return false;
|
82
|
+
end
|
83
|
+
|
84
|
+
urlPart = UrlValidatorHelper.getUrlPart(triggerPart["UrlPart"], url)
|
85
|
+
|
86
|
+
return ComparisonOperatorHelper.evaluate(
|
87
|
+
triggerPart["Operator"],
|
88
|
+
triggerPart["IsNegative"],
|
89
|
+
triggerPart["IsIgnoreCase"],
|
90
|
+
urlPart,
|
91
|
+
triggerPart["ValueToCompare"])
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.getUrlPart(urlPart, url)
|
95
|
+
begin
|
96
|
+
urlParts = URI.parse(url)
|
97
|
+
case urlPart
|
98
|
+
when "PagePath"
|
99
|
+
return urlParts.path
|
100
|
+
when "PageUrl"
|
101
|
+
return url
|
102
|
+
when "HostName"
|
103
|
+
return urlParts.host
|
104
|
+
else
|
105
|
+
return ''
|
106
|
+
end
|
107
|
+
rescue
|
108
|
+
return ''
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class CookieValidatorHelper
|
114
|
+
def self.evaluate(triggerPart, cookieList)
|
115
|
+
begin
|
116
|
+
if (!triggerPart.key?("Operator") ||
|
117
|
+
!triggerPart.key?("IsNegative") ||
|
118
|
+
!triggerPart.key?("IsIgnoreCase") ||
|
119
|
+
!triggerPart.key?("ValueToCompare") ||
|
120
|
+
!triggerPart.key?("CookieName"))
|
121
|
+
return false;
|
122
|
+
end
|
123
|
+
|
124
|
+
if(cookieList.nil?)
|
125
|
+
return false
|
126
|
+
end
|
127
|
+
|
128
|
+
cookieName = triggerPart["CookieName"]
|
129
|
+
cookieValue = ''
|
130
|
+
if(!cookieName.nil? && !cookieList[cookieName.to_sym].nil?)
|
131
|
+
cookieValue = cookieList[cookieName.to_sym]
|
132
|
+
end
|
133
|
+
return ComparisonOperatorHelper.evaluate(
|
134
|
+
triggerPart["Operator"],
|
135
|
+
triggerPart["IsNegative"],
|
136
|
+
triggerPart["IsIgnoreCase"],
|
137
|
+
cookieValue,
|
138
|
+
triggerPart["ValueToCompare"])
|
139
|
+
rescue
|
140
|
+
return false
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
class UserAgentValidatorHelper
|
146
|
+
def self.evaluate(triggerPart, userAgent)
|
147
|
+
begin
|
148
|
+
if (!triggerPart.key?("Operator") ||
|
149
|
+
!triggerPart.key?("IsNegative") ||
|
150
|
+
!triggerPart.key?("IsIgnoreCase") ||
|
151
|
+
!triggerPart.key?("ValueToCompare"))
|
152
|
+
return false;
|
153
|
+
end
|
154
|
+
|
155
|
+
return ComparisonOperatorHelper.evaluate(
|
156
|
+
triggerPart["Operator"],
|
157
|
+
triggerPart["IsNegative"],
|
158
|
+
triggerPart["IsIgnoreCase"],
|
159
|
+
userAgent,
|
160
|
+
triggerPart["ValueToCompare"])
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
class ComparisonOperatorHelper
|
166
|
+
def self.evaluate(opt, isNegative, ignoreCase, left, right)
|
167
|
+
if(left.nil?)
|
168
|
+
left = ''
|
169
|
+
end
|
170
|
+
if(right.nil?)
|
171
|
+
right = ''
|
172
|
+
end
|
173
|
+
|
174
|
+
case opt
|
175
|
+
when "Equals"
|
176
|
+
return ComparisonOperatorHelper.equals(left, right, isNegative, ignoreCase)
|
177
|
+
when "Contains"
|
178
|
+
return ComparisonOperatorHelper.contains(left, right, isNegative, ignoreCase)
|
179
|
+
when "StartsWith"
|
180
|
+
return ComparisonOperatorHelper.startsWith(left, right, isNegative, ignoreCase)
|
181
|
+
when "EndsWith"
|
182
|
+
return ComparisonOperatorHelper.endsWith(left, right, isNegative, ignoreCase)
|
183
|
+
when "MatchesWith"
|
184
|
+
return ComparisonOperatorHelper.matchesWith(left, right, isNegative, ignoreCase)
|
185
|
+
else
|
186
|
+
return false
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def self.equals(left, right, isNegative, ignoreCase)
|
191
|
+
if(ignoreCase)
|
192
|
+
evaluation = left.upcase.eql? right.upcase
|
193
|
+
else
|
194
|
+
evaluation = left.eql? right
|
195
|
+
end
|
196
|
+
|
197
|
+
if(isNegative)
|
198
|
+
return !evaluation
|
199
|
+
else
|
200
|
+
return evaluation
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def self.contains(left, right, isNegative, ignoreCase)
|
205
|
+
if(right.eql? "*")
|
206
|
+
return true
|
207
|
+
end
|
208
|
+
|
209
|
+
if(ignoreCase)
|
210
|
+
left = left.upcase
|
211
|
+
right = right.upcase
|
212
|
+
end
|
213
|
+
|
214
|
+
evaluation = left.include? right
|
215
|
+
if(isNegative)
|
216
|
+
return !evaluation
|
217
|
+
else
|
218
|
+
return evaluation
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def self.startsWith(left, right, isNegative, ignoreCase)
|
223
|
+
if(ignoreCase)
|
224
|
+
evaluation = left.upcase.start_with? right.upcase
|
225
|
+
else
|
226
|
+
evaluation = left.start_with? right
|
227
|
+
end
|
228
|
+
|
229
|
+
if(isNegative)
|
230
|
+
return !evaluation
|
231
|
+
else
|
232
|
+
return evaluation
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def self.endsWith(left, right, isNegative, ignoreCase)
|
237
|
+
if(ignoreCase)
|
238
|
+
evaluation = left.upcase.end_with? right.upcase
|
239
|
+
else
|
240
|
+
evaluation = left.end_with? right
|
241
|
+
end
|
242
|
+
|
243
|
+
if(isNegative)
|
244
|
+
return !evaluation
|
245
|
+
else
|
246
|
+
return evaluation
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def self.matchesWith(left, right, isNegative, ignoreCase)
|
251
|
+
if(ignoreCase)
|
252
|
+
pattern = Regexp.new(right, Regexp::IGNORECASE)
|
253
|
+
else
|
254
|
+
pattern = Regexp.new(right)
|
255
|
+
end
|
256
|
+
|
257
|
+
evaluation = pattern.match(left) != nil
|
258
|
+
if(isNegative)
|
259
|
+
return !evaluation
|
260
|
+
else
|
261
|
+
return evaluation
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
@@ -0,0 +1,310 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module QueueIt
|
4
|
+
class KnownUser
|
5
|
+
QUEUEIT_TOKEN_KEY = "queueittoken"
|
6
|
+
QUEUEIT_DEBUG_KEY = "queueitdebug"
|
7
|
+
|
8
|
+
@@userInQueueService = nil
|
9
|
+
def self.getUserInQueueService(cookieJar)
|
10
|
+
if (@@userInQueueService == nil)
|
11
|
+
return UserInQueueService.new(UserInQueueStateCookieRepository.new(CookieManager.new(cookieJar)))
|
12
|
+
end
|
13
|
+
|
14
|
+
return @@userInQueueService
|
15
|
+
end
|
16
|
+
private_class_method :getUserInQueueService
|
17
|
+
|
18
|
+
def self.convertToInt(value)
|
19
|
+
begin
|
20
|
+
converted = Integer(value)
|
21
|
+
rescue
|
22
|
+
converted = 0
|
23
|
+
end
|
24
|
+
return converted
|
25
|
+
end
|
26
|
+
private_class_method :convertToInt
|
27
|
+
|
28
|
+
def self.getIsDebug(queueitToken, secretKey)
|
29
|
+
qParams = QueueUrlParams.extractQueueParams(queueitToken)
|
30
|
+
if(qParams == nil)
|
31
|
+
return false
|
32
|
+
end
|
33
|
+
|
34
|
+
redirectType = qParams.redirectType
|
35
|
+
if(redirectType == nil)
|
36
|
+
return false
|
37
|
+
end
|
38
|
+
|
39
|
+
if (redirectType.upcase.eql?("DEBUG"))
|
40
|
+
calculatedHash = OpenSSL::HMAC.hexdigest('sha256', secretKey, qParams.queueITTokenWithoutHash)
|
41
|
+
valid = qParams.hashCode.eql?(calculatedHash)
|
42
|
+
return valid
|
43
|
+
end
|
44
|
+
return false
|
45
|
+
end
|
46
|
+
private_class_method :getIsDebug
|
47
|
+
|
48
|
+
def self.setDebugCookie(debugEntries, cookieJar)
|
49
|
+
if(debugEntries == nil || debugEntries.length == 0)
|
50
|
+
return
|
51
|
+
end
|
52
|
+
|
53
|
+
cookieManager = CookieManager.new(cookieJar)
|
54
|
+
cookieValue = ''
|
55
|
+
debugEntries.each do |entry|
|
56
|
+
cookieValue << (entry[0].to_s + '=' + entry[1].to_s + '|')
|
57
|
+
end
|
58
|
+
cookieValue = cookieValue.chop # remove trailing char
|
59
|
+
cookieManager.setCookie(QUEUEIT_DEBUG_KEY, cookieValue, nil, nil)
|
60
|
+
end
|
61
|
+
private_class_method :setDebugCookie
|
62
|
+
|
63
|
+
def self._resolveQueueRequestByLocalConfig(targetUrl, queueitToken, queueConfig, customerId, secretKey, cookieJar, request, debugEntries)
|
64
|
+
isDebug = getIsDebug(queueitToken, secretKey)
|
65
|
+
if(isDebug)
|
66
|
+
debugEntries["TargetUrl"] = targetUrl
|
67
|
+
debugEntries["QueueitToken"] = queueitToken
|
68
|
+
debugEntries["OriginalUrl"] = request.original_url
|
69
|
+
if(queueConfig == nil)
|
70
|
+
debugEntries["QueueConfig"] = "NULL"
|
71
|
+
else
|
72
|
+
debugEntries["QueueConfig"] = queueConfig.toString()
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
if(Utils.isNilOrEmpty(customerId))
|
77
|
+
raise KnownUserError, "customerId can not be nil or empty."
|
78
|
+
end
|
79
|
+
|
80
|
+
if(Utils.isNilOrEmpty(secretKey))
|
81
|
+
raise KnownUserError, "secretKey can not be nil or empty."
|
82
|
+
end
|
83
|
+
|
84
|
+
if(queueConfig == nil)
|
85
|
+
raise KnownUserError, "queueConfig can not be nil."
|
86
|
+
end
|
87
|
+
|
88
|
+
if(Utils.isNilOrEmpty(queueConfig.eventId))
|
89
|
+
raise KnownUserError, "queueConfig.eventId can not be nil or empty."
|
90
|
+
end
|
91
|
+
|
92
|
+
if(Utils.isNilOrEmpty(queueConfig.queueDomain))
|
93
|
+
raise KnownUserError, "queueConfig.queueDomain can not be nil or empty."
|
94
|
+
end
|
95
|
+
|
96
|
+
minutes = convertToInt(queueConfig.cookieValidityMinute)
|
97
|
+
if(minutes <= 0)
|
98
|
+
raise KnownUserError, "queueConfig.cookieValidityMinute should be integer greater than 0."
|
99
|
+
end
|
100
|
+
|
101
|
+
if(![true, false].include? queueConfig.extendCookieValidity)
|
102
|
+
raise KnownUserError, "queueConfig.extendCookieValidity should be valid boolean."
|
103
|
+
end
|
104
|
+
|
105
|
+
userInQueueService = getUserInQueueService(cookieJar)
|
106
|
+
userInQueueService.validateQueueRequest(targetUrl, queueitToken, queueConfig, customerId, secretKey)
|
107
|
+
end
|
108
|
+
private_class_method :_resolveQueueRequestByLocalConfig
|
109
|
+
|
110
|
+
def self._cancelRequestByLocalConfig(targetUrl, queueitToken, cancelConfig, customerId, secretKey, cookieJar, request, debugEntries)
|
111
|
+
isDebug = getIsDebug(queueitToken, secretKey)
|
112
|
+
if(isDebug)
|
113
|
+
debugEntries["TargetUrl"] = targetUrl
|
114
|
+
debugEntries["QueueitToken"] = queueitToken
|
115
|
+
debugEntries["OriginalUrl"] = request.original_url
|
116
|
+
if(cancelConfig == nil)
|
117
|
+
debugEntries["CancelConfig"] = "NULL"
|
118
|
+
else
|
119
|
+
debugEntries["CancelConfig"] = cancelConfig.toString()
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
if(Utils.isNilOrEmpty(targetUrl))
|
124
|
+
raise KnownUserError, "targetUrl can not be nil or empty."
|
125
|
+
end
|
126
|
+
|
127
|
+
if(Utils.isNilOrEmpty(customerId))
|
128
|
+
raise KnownUserError, "customerId can not be nil or empty."
|
129
|
+
end
|
130
|
+
|
131
|
+
if(Utils.isNilOrEmpty(secretKey))
|
132
|
+
raise KnownUserError, "secretKey can not be nil or empty."
|
133
|
+
end
|
134
|
+
|
135
|
+
if(cancelConfig == nil)
|
136
|
+
raise KnownUserError, "cancelConfig can not be nil."
|
137
|
+
end
|
138
|
+
|
139
|
+
if(Utils.isNilOrEmpty(cancelConfig.eventId))
|
140
|
+
raise KnownUserError, "cancelConfig.eventId can not be nil or empty."
|
141
|
+
end
|
142
|
+
|
143
|
+
if(Utils.isNilOrEmpty(cancelConfig.queueDomain))
|
144
|
+
raise KnownUserError, "cancelConfig.queueDomain can not be nil or empty."
|
145
|
+
end
|
146
|
+
|
147
|
+
userInQueueService = getUserInQueueService(cookieJar)
|
148
|
+
userInQueueService.validateCancelRequest(targetUrl, cancelConfig, customerId, secretKey)
|
149
|
+
end
|
150
|
+
private_class_method :_cancelRequestByLocalConfig
|
151
|
+
|
152
|
+
def self.extendQueueCookie(eventId, cookieValidityMinute, cookieDomain, secretKey, cookieJar)
|
153
|
+
if(Utils.isNilOrEmpty(eventId))
|
154
|
+
raise KnownUserError, "eventId can not be nil or empty."
|
155
|
+
end
|
156
|
+
|
157
|
+
if(Utils.isNilOrEmpty(secretKey))
|
158
|
+
raise KnownUserError, "secretKey can not be nil or empty."
|
159
|
+
end
|
160
|
+
|
161
|
+
minutes = convertToInt(cookieValidityMinute)
|
162
|
+
if(minutes <= 0)
|
163
|
+
raise KnownUserError, "cookieValidityMinute should be integer greater than 0."
|
164
|
+
end
|
165
|
+
|
166
|
+
userInQueueService = getUserInQueueService(cookieJar)
|
167
|
+
userInQueueService.extendQueueCookie(eventId, cookieValidityMinute, cookieDomain, secretKey)
|
168
|
+
end
|
169
|
+
|
170
|
+
def self.resolveQueueRequestByLocalConfig(targetUrl, queueitToken, queueConfig, customerId, secretKey, cookieJar, request)
|
171
|
+
debugEntries = Hash.new
|
172
|
+
begin
|
173
|
+
return _resolveQueueRequestByLocalConfig(targetUrl, queueitToken, queueConfig, customerId, secretKey, cookieJar, request, debugEntries)
|
174
|
+
ensure
|
175
|
+
setDebugCookie(debugEntries, cookieJar)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def self.validateRequestByIntegrationConfig(currentUrlWithoutQueueITToken, queueitToken, integrationsConfigString, customerId, secretKey, cookieJar, request)
|
180
|
+
if(Utils.isNilOrEmpty(currentUrlWithoutQueueITToken))
|
181
|
+
raise KnownUserError, "currentUrlWithoutQueueITToken can not be nil or empty."
|
182
|
+
end
|
183
|
+
|
184
|
+
if(Utils.isNilOrEmpty(integrationsConfigString))
|
185
|
+
raise KnownUserError, "integrationsConfigString can not be nil or empty."
|
186
|
+
end
|
187
|
+
|
188
|
+
begin
|
189
|
+
customerIntegration = JSON.parse(integrationsConfigString)
|
190
|
+
|
191
|
+
debugEntries = Hash.new
|
192
|
+
isDebug = getIsDebug(queueitToken, secretKey)
|
193
|
+
if(isDebug)
|
194
|
+
debugEntries["ConfigVersion"] = customerIntegration["Version"]
|
195
|
+
debugEntries["PureUrl"] = currentUrlWithoutQueueITToken
|
196
|
+
debugEntries["QueueitToken"] = queueitToken
|
197
|
+
debugEntries["OriginalUrl"] = request.original_url
|
198
|
+
end
|
199
|
+
|
200
|
+
integrationEvaluator = IntegrationEvaluator.new
|
201
|
+
matchedConfig = integrationEvaluator.getMatchedIntegrationConfig(customerIntegration, currentUrlWithoutQueueITToken, cookieJar, request.user_agent)
|
202
|
+
|
203
|
+
if(isDebug)
|
204
|
+
if(matchedConfig == nil)
|
205
|
+
debugEntries["MatchedConfig"] = "NULL"
|
206
|
+
else
|
207
|
+
debugEntries["MatchedConfig"] = matchedConfig["Name"]
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
if(matchedConfig == nil)
|
212
|
+
return RequestValidationResult.new(nil, nil, nil, nil)
|
213
|
+
end
|
214
|
+
|
215
|
+
if(!matchedConfig.key?("ActionType") || Utils.isNilOrEmpty(matchedConfig["ActionType"]) || matchedConfig["ActionType"].eql?(ActionTypes::QUEUE))
|
216
|
+
queueConfig = QueueEventConfig.new
|
217
|
+
queueConfig.eventId = matchedConfig["EventId"]
|
218
|
+
queueConfig.queueDomain = matchedConfig["QueueDomain"]
|
219
|
+
queueConfig.layoutName = matchedConfig["LayoutName"]
|
220
|
+
queueConfig.culture = matchedConfig["Culture"]
|
221
|
+
queueConfig.cookieDomain = matchedConfig["CookieDomain"]
|
222
|
+
queueConfig.extendCookieValidity = matchedConfig["ExtendCookieValidity"]
|
223
|
+
queueConfig.cookieValidityMinute = matchedConfig["CookieValidityMinute"]
|
224
|
+
queueConfig.version = customerIntegration["Version"]
|
225
|
+
|
226
|
+
case matchedConfig["RedirectLogic"]
|
227
|
+
when "ForcedTargetUrl"
|
228
|
+
targetUrl = matchedConfig["ForcedTargetUrl"]
|
229
|
+
when "EventTargetUrl"
|
230
|
+
targetUrl = ''
|
231
|
+
else
|
232
|
+
targetUrl = currentUrlWithoutQueueITToken
|
233
|
+
end
|
234
|
+
|
235
|
+
return _resolveQueueRequestByLocalConfig(targetUrl, queueitToken, queueConfig, customerId, secretKey, cookieJar, request, debugEntries)
|
236
|
+
|
237
|
+
else # cancel action
|
238
|
+
cancelConfig = CancelEventConfig.new;
|
239
|
+
cancelConfig.eventId = matchedConfig["EventId"]
|
240
|
+
cancelConfig.queueDomain = matchedConfig["QueueDomain"]
|
241
|
+
cancelConfig.cookieDomain = matchedConfig["CookieDomain"]
|
242
|
+
cancelConfig.version = customerIntegration["Version"]
|
243
|
+
|
244
|
+
return _cancelRequestByLocalConfig(currentUrlWithoutQueueITToken, queueitToken, cancelConfig, customerId, secretKey, cookieJar, request, debugEntries);
|
245
|
+
end
|
246
|
+
rescue StandardError => stdErr
|
247
|
+
raise KnownUserError, "integrationConfiguration text was not valid: " + stdErr.message
|
248
|
+
ensure
|
249
|
+
setDebugCookie(debugEntries, cookieJar)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def self.cancelRequestByLocalConfig(targetUrl, queueitToken, cancelConfig, customerId, secretKey, cookieJar, request)
|
254
|
+
debugEntries = Hash.new
|
255
|
+
begin
|
256
|
+
return _cancelRequestByLocalConfig(targetUrl, queueitToken, cancelConfig, customerId, secretKey, cookieJar, request, debugEntries)
|
257
|
+
ensure
|
258
|
+
setDebugCookie(debugEntries, cookieJar)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
class CookieManager
|
264
|
+
@cookies = {}
|
265
|
+
|
266
|
+
def initialize(cookieJar)
|
267
|
+
@cookies = cookieJar
|
268
|
+
end
|
269
|
+
|
270
|
+
def getCookie(name)
|
271
|
+
key = name.to_sym
|
272
|
+
if(!Utils.isNilOrEmpty(@cookies[key]))
|
273
|
+
return @cookies[key]
|
274
|
+
end
|
275
|
+
return nil
|
276
|
+
end
|
277
|
+
|
278
|
+
def setCookie(name, value, expire, domain)
|
279
|
+
key = name.to_sym
|
280
|
+
noDomain = Utils.isNilOrEmpty(domain)
|
281
|
+
deleteCookie = Utils.isNilOrEmpty(value)
|
282
|
+
noExpire = Utils.isNilOrEmpty(expire)
|
283
|
+
|
284
|
+
if(noDomain)
|
285
|
+
if(deleteCookie)
|
286
|
+
@cookies.delete(key)
|
287
|
+
else
|
288
|
+
if(noExpire)
|
289
|
+
@cookies[key] = { :value => value }
|
290
|
+
else
|
291
|
+
@cookies[key] = { :value => value, :expires => expire }
|
292
|
+
end
|
293
|
+
end
|
294
|
+
else
|
295
|
+
if(deleteCookie)
|
296
|
+
@cookies.delete(key, :domain => domain)
|
297
|
+
else
|
298
|
+
if(noExpire)
|
299
|
+
@cookies[key] = { :value => value, :domain => domain }
|
300
|
+
else
|
301
|
+
@cookies[key] = { :value => value, :expires => expire, :domain => domain }
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
|
310
|
+
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module QueueIt
|
2
|
+
class Utils
|
3
|
+
def self.isNilOrEmpty(value)
|
4
|
+
return !value || value.to_s == ''
|
5
|
+
end
|
6
|
+
def self.toString(value)
|
7
|
+
if(value == nil)
|
8
|
+
return ''
|
9
|
+
end
|
10
|
+
return value.to_s
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class CancelEventConfig
|
15
|
+
attr_accessor :eventId
|
16
|
+
attr_accessor :queueDomain
|
17
|
+
attr_accessor :cookieDomain
|
18
|
+
attr_accessor :version
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@eventId = nil
|
22
|
+
@queueDomain = nil
|
23
|
+
@cookieDomain = nil
|
24
|
+
@version = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def toString
|
28
|
+
return "EventId:" + Utils.toString(eventId) +
|
29
|
+
"&Version:" + Utils.toString(version) +
|
30
|
+
"&QueueDomain:" + Utils.toString(queueDomain) +
|
31
|
+
"&CookieDomain:" + Utils.toString(cookieDomain)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class QueueEventConfig
|
36
|
+
attr_accessor :eventId
|
37
|
+
attr_accessor :layoutName
|
38
|
+
attr_accessor :culture
|
39
|
+
attr_accessor :queueDomain
|
40
|
+
attr_accessor :extendCookieValidity
|
41
|
+
attr_accessor :cookieValidityMinute
|
42
|
+
attr_accessor :cookieDomain
|
43
|
+
attr_accessor :version
|
44
|
+
|
45
|
+
def initialize
|
46
|
+
@eventId = nil
|
47
|
+
@layoutName = nil
|
48
|
+
@culture = nil
|
49
|
+
@queueDomain = nil
|
50
|
+
@extendCookieValidity = nil
|
51
|
+
@cookieValidityMinute = nil
|
52
|
+
@cookieDomain = nil
|
53
|
+
@version = nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def toString
|
57
|
+
return "EventId:" + Utils.toString(eventId) +
|
58
|
+
"&Version:" + Utils.toString(version) +
|
59
|
+
"&QueueDomain:" + Utils.toString(queueDomain) +
|
60
|
+
"&CookieDomain:" + Utils.toString(cookieDomain) +
|
61
|
+
"&ExtendCookieValidity:" + Utils.toString(extendCookieValidity) +
|
62
|
+
"&CookieValidityMinute:" + Utils.toString(cookieValidityMinute) +
|
63
|
+
"&LayoutName:" + Utils.toString(layoutName) +
|
64
|
+
"&Culture:" + Utils.toString(culture)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class RequestValidationResult
|
69
|
+
attr_reader :actionType
|
70
|
+
attr_reader :eventId
|
71
|
+
attr_reader :queueId
|
72
|
+
attr_reader :redirectUrl
|
73
|
+
|
74
|
+
def initialize(actionType, eventId, queueId, redirectUrl)
|
75
|
+
@actionType = actionType
|
76
|
+
@eventId = eventId
|
77
|
+
@queueId = queueId
|
78
|
+
@redirectUrl = redirectUrl
|
79
|
+
end
|
80
|
+
|
81
|
+
def doRedirect
|
82
|
+
return !Utils.isNilOrEmpty(@redirectUrl)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class KnownUserError < StandardError
|
87
|
+
def initialize(message)
|
88
|
+
super(message)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class ActionTypes
|
93
|
+
CANCEL = "Cancel"
|
94
|
+
QUEUE = "Queue"
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module QueueIt
|
2
|
+
class QueueUrlParams
|
3
|
+
KEY_VALUE_SEPARATOR_GROUP_CHAR = '~';
|
4
|
+
KEY_VALUE_SEPARATOR_CHAR = '_';
|
5
|
+
TIMESTAMP_KEY = "ts"
|
6
|
+
COOKIE_VALIDITY_MINUTE_KEY = "cv";
|
7
|
+
EVENT_ID_KEY = "e";
|
8
|
+
EXTENDABLE_COOKIE_KEY = "ce";
|
9
|
+
HASH_KEY = "h";
|
10
|
+
QUEUE_ID_KEY = "q";
|
11
|
+
REDIRECT_TYPE_KEY = "rt"
|
12
|
+
|
13
|
+
attr_accessor :timeStamp
|
14
|
+
attr_accessor :eventId
|
15
|
+
attr_accessor :hashCode
|
16
|
+
attr_accessor :extendableCookie
|
17
|
+
attr_accessor :cookieValidityMinute
|
18
|
+
attr_accessor :queueITToken
|
19
|
+
attr_accessor :queueITTokenWithoutHash
|
20
|
+
attr_accessor :queueId
|
21
|
+
attr_accessor :redirectType
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@timeStamp = 0
|
25
|
+
@eventId = ""
|
26
|
+
@hashCode = ""
|
27
|
+
@extendableCookie = false
|
28
|
+
@cookieValidityMinute = nil
|
29
|
+
@queueITToken = ""
|
30
|
+
@queueITTokenWithoutHash = ""
|
31
|
+
@queueId = ""
|
32
|
+
@redirectType = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.extractQueueParams(queueitToken)
|
36
|
+
begin
|
37
|
+
if(Utils.isNilOrEmpty(queueitToken))
|
38
|
+
return nil
|
39
|
+
end
|
40
|
+
result = QueueUrlParams.new
|
41
|
+
result.queueITToken = queueitToken
|
42
|
+
paramsNameValueList = result.queueITToken.split(KEY_VALUE_SEPARATOR_GROUP_CHAR)
|
43
|
+
|
44
|
+
paramsNameValueList.each do |pNameValue|
|
45
|
+
paramNameValueArr = pNameValue.split(KEY_VALUE_SEPARATOR_CHAR)
|
46
|
+
|
47
|
+
case paramNameValueArr[0]
|
48
|
+
when TIMESTAMP_KEY
|
49
|
+
begin
|
50
|
+
result.timeStamp = Integer(paramNameValueArr[1])
|
51
|
+
rescue
|
52
|
+
result.timeStamp = 0
|
53
|
+
end
|
54
|
+
when COOKIE_VALIDITY_MINUTE_KEY
|
55
|
+
begin
|
56
|
+
result.cookieValidityMinute = Integer(paramNameValueArr[1])
|
57
|
+
rescue
|
58
|
+
result.cookieValidityMinute = nil
|
59
|
+
end
|
60
|
+
when EVENT_ID_KEY
|
61
|
+
result.eventId = paramNameValueArr[1]
|
62
|
+
when EXTENDABLE_COOKIE_KEY
|
63
|
+
if paramNameValueArr[1].upcase.eql? 'TRUE'
|
64
|
+
result.extendableCookie = true
|
65
|
+
end
|
66
|
+
when HASH_KEY
|
67
|
+
result.hashCode = paramNameValueArr[1]
|
68
|
+
when QUEUE_ID_KEY
|
69
|
+
result.queueId = paramNameValueArr[1]
|
70
|
+
when REDIRECT_TYPE_KEY
|
71
|
+
result.redirectType = paramNameValueArr[1]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
result.queueITTokenWithoutHash = result.queueITToken.gsub((KEY_VALUE_SEPARATOR_GROUP_CHAR + HASH_KEY + KEY_VALUE_SEPARATOR_CHAR + result.hashCode), "")
|
75
|
+
return result
|
76
|
+
rescue
|
77
|
+
return nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
module QueueIt
|
5
|
+
class UserInQueueService
|
6
|
+
SDK_VERSION = "3.2.3"
|
7
|
+
|
8
|
+
def initialize(userInQueueStateRepository)
|
9
|
+
@userInQueueStateRepository = userInQueueStateRepository
|
10
|
+
end
|
11
|
+
|
12
|
+
def validateQueueRequest(targetUrl, queueitToken, config, customerId, secretKey)
|
13
|
+
state = @userInQueueStateRepository.getState(config.eventId, secretKey)
|
14
|
+
if (state.isValid)
|
15
|
+
if (state.isStateExtendable && config.extendCookieValidity)
|
16
|
+
@userInQueueStateRepository.store(
|
17
|
+
config.eventId,
|
18
|
+
state.queueId,
|
19
|
+
true,
|
20
|
+
config.cookieValidityMinute,
|
21
|
+
!Utils::isNilOrEmpty(config.cookieDomain) ? config.cookieDomain : '',
|
22
|
+
secretKey)
|
23
|
+
end
|
24
|
+
return RequestValidationResult.new(ActionTypes::QUEUE, config.eventId, state.queueId, nil)
|
25
|
+
end
|
26
|
+
|
27
|
+
queueParams = QueueUrlParams::extractQueueParams(queueitToken)
|
28
|
+
if(!queueParams.nil?)
|
29
|
+
return getQueueITTokenValidationResult(targetUrl, config.eventId, config, queueParams, customerId, secretKey)
|
30
|
+
else
|
31
|
+
return getInQueueRedirectResult(targetUrl, config, customerId)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def validateCancelRequest(targetUrl, config, customerId, secretKey)
|
36
|
+
state = @userInQueueStateRepository.getState(config.eventId, secretKey)
|
37
|
+
if (state.isValid)
|
38
|
+
@userInQueueStateRepository.cancelQueueCookie(config.eventId, config.cookieDomain)
|
39
|
+
|
40
|
+
query = getQueryString(customerId, config.eventId, config.version, nil, nil) + ( !Utils::isNilOrEmpty(targetUrl) ? ("&r=" + CGI.escape(targetUrl)) : "" )
|
41
|
+
|
42
|
+
domainAlias = config.queueDomain
|
43
|
+
if (!domainAlias.end_with?("/") )
|
44
|
+
domainAlias = domainAlias + "/"
|
45
|
+
end
|
46
|
+
|
47
|
+
redirectUrl = "https://" + domainAlias + "cancel/" + customerId + "/" + config.eventId + "/?" + query;
|
48
|
+
return RequestValidationResult.new(ActionTypes::CANCEL, config.eventId, state.queueId, redirectUrl)
|
49
|
+
else
|
50
|
+
return RequestValidationResult.new(ActionTypes::CANCEL, config.eventId, nil, nil)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def getQueueITTokenValidationResult(targetUrl, eventId, config, queueParams,customerId, secretKey)
|
55
|
+
calculatedHash = OpenSSL::HMAC.hexdigest('sha256', secretKey, queueParams.queueITTokenWithoutHash)
|
56
|
+
if (calculatedHash.upcase() != queueParams.hashCode.upcase())
|
57
|
+
return getVaidationErrorResult(customerId, targetUrl, config, queueParams, "hash")
|
58
|
+
end
|
59
|
+
if (queueParams.eventId.upcase() != eventId.upcase())
|
60
|
+
return getVaidationErrorResult(customerId, targetUrl, config, queueParams, "eventid")
|
61
|
+
end
|
62
|
+
if (queueParams.timeStamp < Time.now.getutc.tv_sec)
|
63
|
+
return getVaidationErrorResult(customerId, targetUrl, config, queueParams, "timestamp")
|
64
|
+
end
|
65
|
+
|
66
|
+
@userInQueueStateRepository.store(
|
67
|
+
config.eventId,
|
68
|
+
queueParams.queueId,
|
69
|
+
queueParams.extendableCookie,
|
70
|
+
!(queueParams.cookieValidityMinute.nil?) ? queueParams.cookieValidityMinute : config.cookieValidityMinute,
|
71
|
+
!Utils::isNilOrEmpty(config.cookieDomain) ? config.cookieDomain : '',
|
72
|
+
secretKey)
|
73
|
+
return RequestValidationResult.new(ActionTypes::QUEUE, config.eventId, queueParams.queueId, nil)
|
74
|
+
end
|
75
|
+
|
76
|
+
def getVaidationErrorResult(customerId, targetUrl, config, qParams, errorCode)
|
77
|
+
query = getQueryString(customerId, config.eventId, config.version, config.culture, config.layoutName) +
|
78
|
+
"&queueittoken=" + qParams.queueITToken +
|
79
|
+
"&ts=" + Time.now.getutc.tv_sec.to_s +
|
80
|
+
(!Utils::isNilOrEmpty(targetUrl) ? ("&t=" + CGI.escape(targetUrl)) : "")
|
81
|
+
domainAlias = config.queueDomain
|
82
|
+
if (!domainAlias.end_with?("/") )
|
83
|
+
domainAlias = domainAlias + "/"
|
84
|
+
end
|
85
|
+
redirectUrl = "https://" + domainAlias + "error/" + errorCode + "?" + query
|
86
|
+
return RequestValidationResult.new(ActionTypes::QUEUE, config.eventId, nil, redirectUrl)
|
87
|
+
end
|
88
|
+
|
89
|
+
def getInQueueRedirectResult(targetUrl, config, customerId)
|
90
|
+
redirectUrl = "https://" + config.queueDomain +
|
91
|
+
"?" + getQueryString(customerId, config.eventId, config.version, config.culture, config.layoutName) +
|
92
|
+
(!Utils::isNilOrEmpty(targetUrl) ? "&t=" +
|
93
|
+
CGI.escape( targetUrl) : "")
|
94
|
+
return RequestValidationResult.new(ActionTypes::QUEUE, config.eventId, nil, redirectUrl)
|
95
|
+
end
|
96
|
+
|
97
|
+
def getQueryString(customerId, eventId, configVersion, culture, layoutName)
|
98
|
+
queryStringList = Array.new
|
99
|
+
queryStringList.push("c=" + CGI.escape(customerId))
|
100
|
+
queryStringList.push("e=" + CGI.escape(eventId))
|
101
|
+
queryStringList.push("ver=v3-ruby-" + SDK_VERSION)
|
102
|
+
queryStringList.push("cver=" + (!configVersion.nil? ? configVersion.to_s : '-1'))
|
103
|
+
if (!Utils::isNilOrEmpty(culture))
|
104
|
+
queryStringList.push("cid=" + CGI.escape(culture))
|
105
|
+
end
|
106
|
+
if (!Utils::isNilOrEmpty(layoutName))
|
107
|
+
queryStringList.push("l=" + CGI.escape(layoutName))
|
108
|
+
end
|
109
|
+
return queryStringList.join("&")
|
110
|
+
end
|
111
|
+
|
112
|
+
def extendQueueCookie(eventId, cookieValidityMinute, cookieDomain, secretKey)
|
113
|
+
@userInQueueStateRepository.extendQueueCookie(eventId, cookieValidityMinute, cookieDomain, secretKey)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'base64'
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module QueueIt
|
6
|
+
class UserInQueueStateCookieRepository
|
7
|
+
QUEUEIT_DATA_KEY = "QueueITAccepted-SDFrts345E-V3"
|
8
|
+
|
9
|
+
def initialize(cookieManager)
|
10
|
+
@cookieManager = cookieManager
|
11
|
+
end
|
12
|
+
|
13
|
+
def cancelQueueCookie(eventId, cookieDomain)
|
14
|
+
cookieKey = self.class.getCookieKey(eventId)
|
15
|
+
@cookieManager.setCookie(cookieKey, nil, -1, cookieDomain)
|
16
|
+
end
|
17
|
+
|
18
|
+
def store(eventId, queueId, isStateExtendable, cookieValidityMinute, cookieDomain, secretKey)
|
19
|
+
cookieKey = self.class.getCookieKey(eventId)
|
20
|
+
expirationTime = (Time.now.getutc.tv_sec + (cookieValidityMinute * 60)).to_s
|
21
|
+
isStateExtendableString = (isStateExtendable) ? 'true' : 'false'
|
22
|
+
cookieValue = createCookieValue(queueId, isStateExtendableString, expirationTime, secretKey)
|
23
|
+
@cookieManager.setCookie(cookieKey, cookieValue, Time.now + (24*60*60), cookieDomain)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.getCookieKey(eventId)
|
27
|
+
return QUEUEIT_DATA_KEY + '_' + eventId
|
28
|
+
end
|
29
|
+
|
30
|
+
def createCookieValue(queueId, isStateExtendable, expirationTime, secretKey)
|
31
|
+
hashValue = OpenSSL::HMAC.hexdigest('sha256', secretKey, queueId + isStateExtendable + expirationTime)
|
32
|
+
cookieValue = "QueueId=" + queueId + "&IsCookieExtendable=" + isStateExtendable + "&Expires=" + expirationTime + "&Hash=" + hashValue
|
33
|
+
return cookieValue
|
34
|
+
end
|
35
|
+
|
36
|
+
def getCookieNameValueMap(cookieValue)
|
37
|
+
result = Hash.new
|
38
|
+
cookieNameValues = cookieValue.split("&")
|
39
|
+
if (cookieNameValues.length != 4)
|
40
|
+
return result
|
41
|
+
end
|
42
|
+
|
43
|
+
cookieNameValues.each do |item|
|
44
|
+
arr = item.split("=")
|
45
|
+
if(arr.length == 2)
|
46
|
+
result[arr[0]] = arr[1]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
return result
|
50
|
+
end
|
51
|
+
|
52
|
+
def isCookieValid(cookieNameValueMap, secretKey)
|
53
|
+
begin
|
54
|
+
if (!cookieNameValueMap.key?("IsCookieExtendable"))
|
55
|
+
return false
|
56
|
+
end
|
57
|
+
if (!cookieNameValueMap.key?("Expires"))
|
58
|
+
return false
|
59
|
+
end
|
60
|
+
if (!cookieNameValueMap.key?("Hash"))
|
61
|
+
return false
|
62
|
+
end
|
63
|
+
if (!cookieNameValueMap.key?("QueueId"))
|
64
|
+
return false
|
65
|
+
end
|
66
|
+
hashValue = OpenSSL::HMAC.hexdigest('sha256', secretKey, cookieNameValueMap["QueueId"] + cookieNameValueMap["IsCookieExtendable"] + cookieNameValueMap["Expires"])
|
67
|
+
if (hashValue != cookieNameValueMap["Hash"])
|
68
|
+
return false
|
69
|
+
end
|
70
|
+
if(Integer(cookieNameValueMap["Expires"]) < Time.now.getutc.tv_sec)
|
71
|
+
return false
|
72
|
+
end
|
73
|
+
return true
|
74
|
+
rescue
|
75
|
+
return false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def extendQueueCookie(eventId, cookieValidityMinute, cookieDomain, secretKey)
|
80
|
+
cookieKey = self.class.getCookieKey(eventId)
|
81
|
+
cookieValue = @cookieManager.getCookie(cookieKey)
|
82
|
+
if (cookieValue.nil?)
|
83
|
+
return
|
84
|
+
end
|
85
|
+
|
86
|
+
cookieNameValueMap = getCookieNameValueMap(cookieValue)
|
87
|
+
if (!isCookieValid(cookieNameValueMap, secretKey))
|
88
|
+
return
|
89
|
+
end
|
90
|
+
expirationTime = (Time.now.getutc.tv_sec + (cookieValidityMinute * 60)).to_s
|
91
|
+
cookieValue = createCookieValue(cookieNameValueMap["QueueId"], cookieNameValueMap["IsCookieExtendable"], expirationTime, secretKey)
|
92
|
+
@cookieManager.setCookie(cookieKey, cookieValue, Time.now + (24*60*60), cookieDomain)
|
93
|
+
end
|
94
|
+
|
95
|
+
def getState(eventId, secretKey)
|
96
|
+
cookieKey = cookieKey = self.class.getCookieKey(eventId)
|
97
|
+
if (@cookieManager.getCookie(cookieKey).nil?)
|
98
|
+
return StateInfo.new(false, nil, false, 0)
|
99
|
+
end
|
100
|
+
cookieNameValueMap = getCookieNameValueMap(@cookieManager.getCookie(cookieKey))
|
101
|
+
if (!isCookieValid(cookieNameValueMap, secretKey))
|
102
|
+
return StateInfo.new(false, nil, false,0)
|
103
|
+
end
|
104
|
+
return StateInfo.new(
|
105
|
+
true,
|
106
|
+
cookieNameValueMap["QueueId"],
|
107
|
+
cookieNameValueMap["IsCookieExtendable"] == 'true',
|
108
|
+
Integer(cookieNameValueMap["Expires"]))
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class StateInfo
|
113
|
+
attr_reader :isValid
|
114
|
+
attr_reader :queueId
|
115
|
+
attr_reader :isStateExtendable
|
116
|
+
attr_reader :expires # used just for unit tests
|
117
|
+
|
118
|
+
def initialize(isValid, queueId, isStateExtendable, expires)
|
119
|
+
@isValid = isValid
|
120
|
+
@queueId = queueId
|
121
|
+
@isStateExtendable = isStateExtendable
|
122
|
+
@expires = expires
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'queueit_knownuserv3/user_in_queue_service'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "queueit_knownuserv3"
|
8
|
+
spec.version = QueueIt::UserInQueueService::SDK_VERSION
|
9
|
+
spec.authors = ["Queue-it"]
|
10
|
+
spec.email = ["support@queue-it.com"]
|
11
|
+
spec.licenses = "LGPL-3.0"
|
12
|
+
spec.summary = %q{ Gem for implementing Queue-it KnownUser V3}
|
13
|
+
spec.homepage = "https://www.queue-it.com/"
|
14
|
+
|
15
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
16
|
+
# delete this section to allow pushing this gem to any host.
|
17
|
+
|
18
|
+
# if spec.respond_to?(:metadata)
|
19
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
20
|
+
# else
|
21
|
+
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
22
|
+
# end
|
23
|
+
|
24
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
spec.bindir = "exe"
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ["lib"]
|
28
|
+
|
29
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
30
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: queueit_knownuserv3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 3.2.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Queue-it
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-10-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.11'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.11'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
- support@queue-it.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- Gemfile
|
49
|
+
- Rakefile
|
50
|
+
- bin/console
|
51
|
+
- bin/setup
|
52
|
+
- lib/queueit_knownuserv3.rb
|
53
|
+
- lib/queueit_knownuserv3/integration_config_helpers.rb
|
54
|
+
- lib/queueit_knownuserv3/known_user.rb
|
55
|
+
- lib/queueit_knownuserv3/models.rb
|
56
|
+
- lib/queueit_knownuserv3/queue_url_params.rb
|
57
|
+
- lib/queueit_knownuserv3/user_in_queue_service.rb
|
58
|
+
- lib/queueit_knownuserv3/user_in_queue_state_cookie_repository.rb
|
59
|
+
- queueit_knownuserv3.gemspec
|
60
|
+
homepage: https://www.queue-it.com/
|
61
|
+
licenses:
|
62
|
+
- LGPL-3.0
|
63
|
+
metadata: {}
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 2.6.13
|
81
|
+
signing_key:
|
82
|
+
specification_version: 4
|
83
|
+
summary: Gem for implementing Queue-it KnownUser V3
|
84
|
+
test_files: []
|