queueit_knownuserv3 3.3.0 → 3.6.1
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.
- data/.devcontainer/Dockerfile +43 -0
- data/.devcontainer/devcontainer.json +30 -0
- data/.gitignore +5 -0
- data/.vscode/launch.json +15 -0
- data/ci-build.yml +17 -0
- data/lib/queueit_knownuserv3.rb +1 -0
- data/lib/queueit_knownuserv3/connector_diagnostics.rb +69 -0
- data/lib/queueit_knownuserv3/integration_config_helpers.rb +65 -75
- data/lib/queueit_knownuserv3/known_user.rb +170 -81
- data/lib/queueit_knownuserv3/models.rb +34 -3
- data/lib/queueit_knownuserv3/queue_url_params.rb +49 -49
- data/lib/queueit_knownuserv3/user_in_queue_service.rb +103 -62
- data/lib/queueit_knownuserv3/user_in_queue_state_cookie_repository.rb +110 -43
- data/license.txt +165 -0
- data/queueit_knownuserv3.gemspec +1 -4
- metadata +15 -34
- checksums.yaml +0 -15
@@ -0,0 +1,43 @@
|
|
1
|
+
#-------------------------------------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
3
|
+
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
|
4
|
+
#-------------------------------------------------------------------------------------------------------------
|
5
|
+
|
6
|
+
FROM ruby:1.9.3
|
7
|
+
|
8
|
+
# Avoid warnings by switching to noninteractive
|
9
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
10
|
+
|
11
|
+
# This Dockerfile adds a non-root 'vscode' user with sudo access. However, for Linux,
|
12
|
+
# this user's GID/UID must match your local user UID/GID to avoid permission issues
|
13
|
+
# with bind mounts. Update USER_UID / USER_GID if yours is not 1000. See
|
14
|
+
# https://aka.ms/vscode-remote/containers/non-root-user for details.
|
15
|
+
ARG USERNAME=vscode
|
16
|
+
ARG USER_UID=1000
|
17
|
+
ARG USER_GID=$USER_UID
|
18
|
+
|
19
|
+
# Configure apt and install packages
|
20
|
+
RUN apt-get update \
|
21
|
+
&& apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \
|
22
|
+
# Verify git, process tools installed
|
23
|
+
&& apt-get -y install git iproute2 procps lsb-release \
|
24
|
+
#
|
25
|
+
# Install ruby-debug-ide and ruby-debug-base19x
|
26
|
+
#&& gem install ruby-debug-ide \
|
27
|
+
#&& gem install ruby-debug-base19x \
|
28
|
+
#
|
29
|
+
# Create a non-root user to use if preferred - see https://aka.ms/vscode-remote/containers/non-root-user.
|
30
|
+
&& groupadd --gid $USER_GID $USERNAME \
|
31
|
+
&& useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \
|
32
|
+
# [Optional] Add sudo support for the non-root user
|
33
|
+
&& apt-get install -y sudo \
|
34
|
+
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME\
|
35
|
+
&& chmod 0440 /etc/sudoers.d/$USERNAME \
|
36
|
+
#
|
37
|
+
# Clean up
|
38
|
+
&& apt-get autoremove -y \
|
39
|
+
&& apt-get clean -y \
|
40
|
+
&& rm -rf /var/lib/apt/lists/*
|
41
|
+
|
42
|
+
# Switch back to dialog for any ad-hoc use of apt-get
|
43
|
+
ENV DEBIAN_FRONTEND=
|
@@ -0,0 +1,30 @@
|
|
1
|
+
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or the definition README at
|
2
|
+
// https://github.com/microsoft/vscode-dev-containers/tree/master/containers/ruby-2
|
3
|
+
{
|
4
|
+
"name": "Ruby",
|
5
|
+
"dockerFile": "Dockerfile",
|
6
|
+
|
7
|
+
// Use 'settings' to set *default* container specific settings.json values on container create.
|
8
|
+
// You can edit these settings after create using File > Preferences > Settings > Remote.
|
9
|
+
"settings": {
|
10
|
+
"terminal.integrated.shell.linux": "/bin/bash"
|
11
|
+
},
|
12
|
+
|
13
|
+
"workspaceMount": "src=${localWorkspaceFolder},dst=/workspace,type=bind,consistency=delegated",
|
14
|
+
"workspaceFolder": "/workspace",
|
15
|
+
// Uncomment the next line if you want to publish any ports.
|
16
|
+
// "appPort": [],
|
17
|
+
|
18
|
+
// Uncomment the next line to run commands after the container is created.
|
19
|
+
"postCreateCommand": "bundle install; gem install ruby-debug-ide -v 0.6.0; gem install ruby-debug-base19x",
|
20
|
+
|
21
|
+
// Uncomment the next line to use a non-root user. On Linux, this will prevent
|
22
|
+
// new files getting created as root, but you may need to update the USER_UID
|
23
|
+
// and USER_GID in .devcontainer/Dockerfile to match your user if not 1000.
|
24
|
+
// "runArgs": [ "-u", "vscode" ],
|
25
|
+
|
26
|
+
// Add the IDs of extensions you want installed when the container is created in the array below.
|
27
|
+
"extensions": [
|
28
|
+
"rebornix.Ruby"
|
29
|
+
]
|
30
|
+
}
|
data/.gitignore
ADDED
data/.vscode/launch.json
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
{
|
2
|
+
// Use IntelliSense to learn about possible attributes.
|
3
|
+
// Hover to view descriptions of existing attributes.
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
5
|
+
"version": "0.2.0",
|
6
|
+
"configurations": [
|
7
|
+
{
|
8
|
+
"name": "Debug",
|
9
|
+
"type": "Ruby",
|
10
|
+
"request": "launch",
|
11
|
+
"program": "${workspaceRoot}/test/test_queueit_knownuserv3.rb",
|
12
|
+
"cwd": "${workspaceRoot}"
|
13
|
+
}
|
14
|
+
]
|
15
|
+
}
|
data/ci-build.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Starter pipeline
|
2
|
+
# Start with a minimal pipeline that you can customize to build and deploy your code.
|
3
|
+
# Add steps that build, run tests, deploy, and more:
|
4
|
+
# https://aka.ms/yaml
|
5
|
+
|
6
|
+
trigger:
|
7
|
+
- master
|
8
|
+
|
9
|
+
pool:
|
10
|
+
name: 'Default'
|
11
|
+
|
12
|
+
steps:
|
13
|
+
- task: Docker@2
|
14
|
+
inputs:
|
15
|
+
command: 'buildAndPush'
|
16
|
+
Dockerfile: '**/test/Dockerfile'
|
17
|
+
buildContext: './'
|
data/lib/queueit_knownuserv3.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require_relative "queueit_knownuserv3/known_user"
|
2
2
|
require_relative "queueit_knownuserv3/models"
|
3
|
+
require_relative "queueit_knownuserv3/connector_diagnostics"
|
3
4
|
require_relative "queueit_knownuserv3/queue_url_params"
|
4
5
|
require_relative "queueit_knownuserv3/user_in_queue_state_cookie_repository"
|
5
6
|
require_relative "queueit_knownuserv3/user_in_queue_service"
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module QueueIt
|
2
|
+
class ConnectorDiagnostics
|
3
|
+
attr_accessor :isEnabled
|
4
|
+
attr_accessor :hasError
|
5
|
+
attr_accessor :validationResult
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@isEnabled = false
|
9
|
+
@hasError = false
|
10
|
+
@validationResult = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def setStateWithTokenError(customerId, errorCode)
|
14
|
+
@hasError = true
|
15
|
+
@validationResult = RequestValidationResult.new(
|
16
|
+
"ConnectorDiagnosticsRedirect",
|
17
|
+
nil, nil,
|
18
|
+
"https://" + customerId + ".api2.queue-it.net/" + customerId + "/diagnostics/connector/error/?code=" + errorCode,
|
19
|
+
nil, nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
def setStateWithSetupError()
|
23
|
+
@hasError = true
|
24
|
+
@validationResult = RequestValidationResult.new(
|
25
|
+
"ConnectorDiagnosticsRedirect",
|
26
|
+
nil, nil,
|
27
|
+
"https://api2.queue-it.net/diagnostics/connector/error/?code=setup",
|
28
|
+
nil, nil)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.verify(customerId, secretKey, queueitToken)
|
32
|
+
diagnostics = ConnectorDiagnostics.new
|
33
|
+
|
34
|
+
qParams = QueueUrlParams.extractQueueParams(queueitToken)
|
35
|
+
|
36
|
+
if(qParams == nil)
|
37
|
+
return diagnostics
|
38
|
+
end
|
39
|
+
|
40
|
+
if(qParams.redirectType == nil)
|
41
|
+
return diagnostics
|
42
|
+
end
|
43
|
+
|
44
|
+
if(not qParams.redirectType.upcase.eql?("DEBUG"))
|
45
|
+
return diagnostics
|
46
|
+
end
|
47
|
+
|
48
|
+
if(Utils.isNilOrEmpty(customerId) or Utils.isNilOrEmpty(secretKey))
|
49
|
+
diagnostics.setStateWithSetupError()
|
50
|
+
return diagnostics
|
51
|
+
end
|
52
|
+
|
53
|
+
calculatedHash = OpenSSL::HMAC.hexdigest('sha256', secretKey, qParams.queueITTokenWithoutHash)
|
54
|
+
if(not qParams.hashCode.eql?(calculatedHash))
|
55
|
+
diagnostics.setStateWithTokenError(customerId, "hash")
|
56
|
+
return diagnostics
|
57
|
+
end
|
58
|
+
|
59
|
+
if(qParams.timeStamp < Time.now.getutc.tv_sec)
|
60
|
+
diagnostics.setStateWithTokenError(customerId, "timestamp")
|
61
|
+
return diagnostics
|
62
|
+
end
|
63
|
+
|
64
|
+
diagnostics.isEnabled = true
|
65
|
+
|
66
|
+
return diagnostics
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -75,14 +75,14 @@ module QueueIt
|
|
75
75
|
|
76
76
|
class UrlValidatorHelper
|
77
77
|
def self.evaluate(triggerPart, url)
|
78
|
-
if (
|
78
|
+
if (triggerPart.nil? ||
|
79
|
+
!triggerPart.key?("Operator") ||
|
79
80
|
!triggerPart.key?("IsNegative") ||
|
80
81
|
!triggerPart.key?("IsIgnoreCase") ||
|
81
|
-
!triggerPart.key?("ValueToCompare") ||
|
82
82
|
!triggerPart.key?("UrlPart"))
|
83
|
-
return false
|
83
|
+
return false
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
urlPart = UrlValidatorHelper.getUrlPart(triggerPart["UrlPart"], url)
|
87
87
|
|
88
88
|
return ComparisonOperatorHelper.evaluate(
|
@@ -90,7 +90,8 @@ module QueueIt
|
|
90
90
|
triggerPart["IsNegative"],
|
91
91
|
triggerPart["IsIgnoreCase"],
|
92
92
|
urlPart,
|
93
|
-
triggerPart["ValueToCompare"]
|
93
|
+
triggerPart["ValueToCompare"],
|
94
|
+
triggerPart["ValuesToCompare"])
|
94
95
|
end
|
95
96
|
|
96
97
|
def self.getUrlPart(urlPart, url)
|
@@ -115,12 +116,12 @@ module QueueIt
|
|
115
116
|
class CookieValidatorHelper
|
116
117
|
def self.evaluate(triggerPart, cookieJar)
|
117
118
|
begin
|
118
|
-
if (
|
119
|
+
if (triggerPart.nil? ||
|
120
|
+
!triggerPart.key?("Operator") ||
|
119
121
|
!triggerPart.key?("IsNegative") ||
|
120
122
|
!triggerPart.key?("IsIgnoreCase") ||
|
121
|
-
!triggerPart.key?("ValueToCompare") ||
|
122
123
|
!triggerPart.key?("CookieName"))
|
123
|
-
return false
|
124
|
+
return false
|
124
125
|
end
|
125
126
|
|
126
127
|
if(cookieJar.nil?)
|
@@ -137,7 +138,8 @@ module QueueIt
|
|
137
138
|
triggerPart["IsNegative"],
|
138
139
|
triggerPart["IsIgnoreCase"],
|
139
140
|
cookieValue,
|
140
|
-
triggerPart["ValueToCompare"]
|
141
|
+
triggerPart["ValueToCompare"],
|
142
|
+
triggerPart["ValuesToCompare"])
|
141
143
|
rescue
|
142
144
|
return false
|
143
145
|
end
|
@@ -147,33 +149,43 @@ module QueueIt
|
|
147
149
|
class UserAgentValidatorHelper
|
148
150
|
def self.evaluate(triggerPart, userAgent)
|
149
151
|
begin
|
150
|
-
if (
|
152
|
+
if (triggerPart.nil? ||
|
153
|
+
!triggerPart.key?("Operator") ||
|
151
154
|
!triggerPart.key?("IsNegative") ||
|
152
|
-
!triggerPart.key?("IsIgnoreCase")
|
153
|
-
|
154
|
-
return false;
|
155
|
+
!triggerPart.key?("IsIgnoreCase"))
|
156
|
+
return false
|
155
157
|
end
|
156
|
-
|
158
|
+
|
157
159
|
return ComparisonOperatorHelper.evaluate(
|
158
160
|
triggerPart["Operator"],
|
159
161
|
triggerPart["IsNegative"],
|
160
162
|
triggerPart["IsIgnoreCase"],
|
161
163
|
userAgent,
|
162
|
-
triggerPart["ValueToCompare"]
|
164
|
+
triggerPart["ValueToCompare"],
|
165
|
+
triggerPart["ValuesToCompare"])
|
163
166
|
end
|
164
167
|
end
|
165
168
|
end
|
166
169
|
|
167
170
|
class HttpHeaderValidatorHelper
|
168
171
|
def self.evaluate(triggerPart, headers)
|
169
|
-
begin
|
172
|
+
begin
|
173
|
+
if (triggerPart.nil? ||
|
174
|
+
!triggerPart.key?("Operator") ||
|
175
|
+
!triggerPart.key?("IsNegative") ||
|
176
|
+
!triggerPart.key?("IsIgnoreCase")
|
177
|
+
!triggerPart.key?("HttpHeaderName"))
|
178
|
+
return false
|
179
|
+
end
|
180
|
+
|
170
181
|
headerValue = headers[triggerPart['HttpHeaderName']]
|
171
182
|
return ComparisonOperatorHelper.evaluate(
|
172
183
|
triggerPart["Operator"],
|
173
184
|
triggerPart["IsNegative"],
|
174
185
|
triggerPart["IsIgnoreCase"],
|
175
186
|
headerValue,
|
176
|
-
triggerPart["ValueToCompare"]
|
187
|
+
triggerPart["ValueToCompare"],
|
188
|
+
triggerPart["ValuesToCompare"])
|
177
189
|
rescue
|
178
190
|
return false
|
179
191
|
end
|
@@ -181,35 +193,38 @@ module QueueIt
|
|
181
193
|
end
|
182
194
|
|
183
195
|
class ComparisonOperatorHelper
|
184
|
-
def self.evaluate(opt, isNegative, ignoreCase,
|
185
|
-
if(
|
186
|
-
|
196
|
+
def self.evaluate(opt, isNegative, ignoreCase, value, valueToCompare, valuesToCompare)
|
197
|
+
if (value.nil?)
|
198
|
+
value = ''
|
199
|
+
end
|
200
|
+
|
201
|
+
if (valueToCompare.nil?)
|
202
|
+
valueToCompare = ''
|
187
203
|
end
|
188
|
-
|
189
|
-
|
204
|
+
|
205
|
+
if (valuesToCompare.nil?)
|
206
|
+
valuesToCompare = []
|
190
207
|
end
|
191
208
|
|
192
209
|
case opt
|
193
210
|
when "Equals"
|
194
|
-
return ComparisonOperatorHelper.equals(
|
211
|
+
return ComparisonOperatorHelper.equals(value, valueToCompare, isNegative, ignoreCase)
|
195
212
|
when "Contains"
|
196
|
-
return ComparisonOperatorHelper.contains(
|
197
|
-
when "
|
198
|
-
return ComparisonOperatorHelper.
|
199
|
-
when "
|
200
|
-
return ComparisonOperatorHelper.
|
201
|
-
when "MatchesWith"
|
202
|
-
return ComparisonOperatorHelper.matchesWith(left, right, isNegative, ignoreCase)
|
213
|
+
return ComparisonOperatorHelper.contains(value, valueToCompare, isNegative, ignoreCase)
|
214
|
+
when "EqualsAny"
|
215
|
+
return ComparisonOperatorHelper.equalsAny(value, valuesToCompare, isNegative, ignoreCase)
|
216
|
+
when "ContainsAny"
|
217
|
+
return ComparisonOperatorHelper.containsAny(value, valuesToCompare, isNegative, ignoreCase)
|
203
218
|
else
|
204
219
|
return false
|
205
220
|
end
|
206
221
|
end
|
207
222
|
|
208
|
-
def self.equals(
|
223
|
+
def self.equals(value, valueToCompare, isNegative, ignoreCase)
|
209
224
|
if(ignoreCase)
|
210
|
-
evaluation =
|
225
|
+
evaluation = value.upcase.eql? valueToCompare.upcase
|
211
226
|
else
|
212
|
-
evaluation =
|
227
|
+
evaluation = value.eql? valueToCompare
|
213
228
|
end
|
214
229
|
|
215
230
|
if(isNegative)
|
@@ -219,31 +234,17 @@ module QueueIt
|
|
219
234
|
end
|
220
235
|
end
|
221
236
|
|
222
|
-
def self.contains(
|
223
|
-
if(
|
237
|
+
def self.contains(value, valueToCompare, isNegative, ignoreCase)
|
238
|
+
if((valueToCompare.eql? "*") && !(value.empty? || value.nil?))
|
224
239
|
return true
|
225
240
|
end
|
226
241
|
|
227
242
|
if(ignoreCase)
|
228
|
-
|
229
|
-
|
230
|
-
end
|
231
|
-
|
232
|
-
evaluation = left.include? right
|
233
|
-
if(isNegative)
|
234
|
-
return !evaluation
|
235
|
-
else
|
236
|
-
return evaluation
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
def self.startsWith(left, right, isNegative, ignoreCase)
|
241
|
-
if(ignoreCase)
|
242
|
-
evaluation = left.upcase.start_with? right.upcase
|
243
|
-
else
|
244
|
-
evaluation = left.start_with? right
|
243
|
+
value = value.upcase
|
244
|
+
valueToCompare = valueToCompare.upcase
|
245
245
|
end
|
246
246
|
|
247
|
+
evaluation = value.include? valueToCompare
|
247
248
|
if(isNegative)
|
248
249
|
return !evaluation
|
249
250
|
else
|
@@ -251,33 +252,22 @@ module QueueIt
|
|
251
252
|
end
|
252
253
|
end
|
253
254
|
|
254
|
-
def self.
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
end
|
260
|
-
|
261
|
-
if(isNegative)
|
262
|
-
return !evaluation
|
263
|
-
else
|
264
|
-
return evaluation
|
255
|
+
def self.equalsAny(value, valuesToCompare, isNegative, ignoreCase)
|
256
|
+
valuesToCompare.each do |valueToCompare|
|
257
|
+
if (ComparisonOperatorHelper.equals(value, valueToCompare, false, ignoreCase))
|
258
|
+
return !isNegative
|
259
|
+
end
|
265
260
|
end
|
261
|
+
return isNegative
|
266
262
|
end
|
267
263
|
|
268
|
-
def self.
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
end
|
274
|
-
|
275
|
-
evaluation = pattern.match(left) != nil
|
276
|
-
if(isNegative)
|
277
|
-
return !evaluation
|
278
|
-
else
|
279
|
-
return evaluation
|
264
|
+
def self.containsAny(value, valuesToCompare, isNegative, ignoreCase)
|
265
|
+
valuesToCompare.each do |valueToCompare|
|
266
|
+
if (ComparisonOperatorHelper.contains(value, valueToCompare, false, ignoreCase))
|
267
|
+
return !isNegative
|
268
|
+
end
|
280
269
|
end
|
270
|
+
return isNegative
|
281
271
|
end
|
282
272
|
end
|
283
273
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
+
require 'cgi'
|
1
2
|
require 'json'
|
2
3
|
|
3
4
|
module QueueIt
|
4
5
|
class KnownUser
|
5
6
|
QUEUEIT_TOKEN_KEY = "queueittoken"
|
6
7
|
QUEUEIT_DEBUG_KEY = "queueitdebug"
|
8
|
+
QUEUEIT_AJAX_HEADER_KEY = "x-queueit-ajaxpageurl"
|
7
9
|
|
8
10
|
@@userInQueueService = nil
|
9
11
|
def self.getUserInQueueService(cookieJar)
|
@@ -15,6 +17,19 @@ module QueueIt
|
|
15
17
|
end
|
16
18
|
private_class_method :getUserInQueueService
|
17
19
|
|
20
|
+
def self.isQueueAjaxCall(request)
|
21
|
+
return request.headers[QUEUEIT_AJAX_HEADER_KEY] != nil
|
22
|
+
end
|
23
|
+
private_class_method :isQueueAjaxCall
|
24
|
+
|
25
|
+
def self.generateTargetUrl(originalTargetUrl, request)
|
26
|
+
unless isQueueAjaxCall(request)
|
27
|
+
return originalTargetUrl
|
28
|
+
end
|
29
|
+
return CGI::unescape(request.headers[QUEUEIT_AJAX_HEADER_KEY])
|
30
|
+
end
|
31
|
+
private_class_method :generateTargetUrl
|
32
|
+
|
18
33
|
def self.convertToInt(value)
|
19
34
|
begin
|
20
35
|
converted = Integer(value)
|
@@ -25,25 +40,16 @@ module QueueIt
|
|
25
40
|
end
|
26
41
|
private_class_method :convertToInt
|
27
42
|
|
28
|
-
def self.
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
43
|
+
def self.logMoreRequestDetails(debugEntries, request)
|
44
|
+
debugEntries["ServerUtcTime"] = Time.now.utc.iso8601
|
45
|
+
debugEntries["RequestIP"] = request.remote_ip
|
46
|
+
debugEntries["RequestHttpHeader_Via"] = request.headers["via"]
|
47
|
+
debugEntries["RequestHttpHeader_Forwarded"] = request.headers["forwarded"]
|
48
|
+
debugEntries["RequestHttpHeader_XForwardedFor"] = request.headers["x-forwarded-for"]
|
49
|
+
debugEntries["RequestHttpHeader_XForwardedHost"] = request.headers["x-forwarded-host"]
|
50
|
+
debugEntries["RequestHttpHeader_XForwardedProto"] = request.headers["x-forwarded-proto"]
|
45
51
|
end
|
46
|
-
private_class_method :
|
52
|
+
private_class_method :logMoreRequestDetails
|
47
53
|
|
48
54
|
def self.setDebugCookie(debugEntries, cookieJar)
|
49
55
|
if(debugEntries == nil || debugEntries.length == 0)
|
@@ -60,17 +66,20 @@ module QueueIt
|
|
60
66
|
end
|
61
67
|
private_class_method :setDebugCookie
|
62
68
|
|
63
|
-
def self._resolveQueueRequestByLocalConfig(targetUrl, queueitToken, queueConfig, customerId, secretKey, request, debugEntries)
|
64
|
-
|
69
|
+
def self._resolveQueueRequestByLocalConfig(targetUrl, queueitToken, queueConfig, customerId, secretKey, request, debugEntries, isDebug)
|
70
|
+
|
65
71
|
if(isDebug)
|
72
|
+
debugEntries["SdkVersion"] = UserInQueueService::SDK_VERSION
|
73
|
+
debugEntries["Runtime"] = getRuntime()
|
66
74
|
debugEntries["TargetUrl"] = targetUrl
|
67
75
|
debugEntries["QueueitToken"] = queueitToken
|
68
|
-
debugEntries["OriginalUrl"] = request
|
76
|
+
debugEntries["OriginalUrl"] = getRealOriginalUrl(request)
|
69
77
|
if(queueConfig == nil)
|
70
78
|
debugEntries["QueueConfig"] = "NULL"
|
71
79
|
else
|
72
80
|
debugEntries["QueueConfig"] = queueConfig.toString()
|
73
81
|
end
|
82
|
+
logMoreRequestDetails(debugEntries, request)
|
74
83
|
end
|
75
84
|
|
76
85
|
if(Utils.isNilOrEmpty(customerId))
|
@@ -103,21 +112,28 @@ module QueueIt
|
|
103
112
|
end
|
104
113
|
|
105
114
|
userInQueueService = getUserInQueueService(request.cookie_jar)
|
106
|
-
userInQueueService.validateQueueRequest(targetUrl, queueitToken, queueConfig, customerId, secretKey)
|
115
|
+
result = userInQueueService.validateQueueRequest(targetUrl, queueitToken, queueConfig, customerId, secretKey)
|
116
|
+
result.isAjaxResult = isQueueAjaxCall(request)
|
117
|
+
|
118
|
+
return result
|
107
119
|
end
|
108
120
|
private_class_method :_resolveQueueRequestByLocalConfig
|
109
121
|
|
110
|
-
def self._cancelRequestByLocalConfig(targetUrl, queueitToken, cancelConfig, customerId, secretKey, request, debugEntries)
|
111
|
-
|
122
|
+
def self._cancelRequestByLocalConfig(targetUrl, queueitToken, cancelConfig, customerId, secretKey, request, debugEntries, isDebug)
|
123
|
+
targetUrl = generateTargetUrl(targetUrl, request)
|
124
|
+
|
112
125
|
if(isDebug)
|
126
|
+
debugEntries["SdkVersion"] = UserInQueueService::SDK_VERSION
|
127
|
+
debugEntries["Runtime"] = getRuntime()
|
113
128
|
debugEntries["TargetUrl"] = targetUrl
|
114
129
|
debugEntries["QueueitToken"] = queueitToken
|
115
|
-
debugEntries["OriginalUrl"] = request
|
130
|
+
debugEntries["OriginalUrl"] = getRealOriginalUrl(request)
|
116
131
|
if(cancelConfig == nil)
|
117
132
|
debugEntries["CancelConfig"] = "NULL"
|
118
133
|
else
|
119
134
|
debugEntries["CancelConfig"] = cancelConfig.toString()
|
120
135
|
end
|
136
|
+
logMoreRequestDetails(debugEntries, request)
|
121
137
|
end
|
122
138
|
|
123
139
|
if(Utils.isNilOrEmpty(targetUrl))
|
@@ -145,7 +161,10 @@ module QueueIt
|
|
145
161
|
end
|
146
162
|
|
147
163
|
userInQueueService = getUserInQueueService(request.cookie_jar)
|
148
|
-
userInQueueService.validateCancelRequest(targetUrl, cancelConfig, customerId, secretKey)
|
164
|
+
result = userInQueueService.validateCancelRequest(targetUrl, cancelConfig, customerId, secretKey)
|
165
|
+
result.isAjaxResult = isQueueAjaxCall(request)
|
166
|
+
|
167
|
+
return result
|
149
168
|
end
|
150
169
|
private_class_method :_cancelRequestByLocalConfig
|
151
170
|
|
@@ -169,38 +188,64 @@ module QueueIt
|
|
169
188
|
|
170
189
|
def self.resolveQueueRequestByLocalConfig(targetUrl, queueitToken, queueConfig, customerId, secretKey, request)
|
171
190
|
debugEntries = Hash.new
|
191
|
+
connectorDiagnostics = ConnectorDiagnostics.verify(customerId, secretKey, queueitToken)
|
192
|
+
|
193
|
+
if(connectorDiagnostics.hasError)
|
194
|
+
return connectorDiagnostics.validationResult
|
195
|
+
end
|
172
196
|
begin
|
173
|
-
|
197
|
+
targetUrl = generateTargetUrl(targetUrl, request)
|
198
|
+
return _resolveQueueRequestByLocalConfig(targetUrl, queueitToken, queueConfig, customerId, secretKey, request, debugEntries, connectorDiagnostics.isEnabled)
|
199
|
+
rescue Exception => e
|
200
|
+
if(connectorDiagnostics.isEnabled)
|
201
|
+
debugEntries["Exception"] = e.message
|
202
|
+
end
|
203
|
+
raise e
|
174
204
|
ensure
|
175
205
|
setDebugCookie(debugEntries, request.cookie_jar)
|
176
206
|
end
|
177
207
|
end
|
178
208
|
|
179
|
-
def self.validateRequestByIntegrationConfig(currentUrlWithoutQueueITToken, queueitToken,
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
if(
|
185
|
-
|
209
|
+
def self.validateRequestByIntegrationConfig(currentUrlWithoutQueueITToken, queueitToken, integrationConfigJson, customerId, secretKey, request)
|
210
|
+
debugEntries = Hash.new
|
211
|
+
customerIntegration = Hash.new
|
212
|
+
connectorDiagnostics = ConnectorDiagnostics.verify(customerId, secretKey, queueitToken)
|
213
|
+
|
214
|
+
if(connectorDiagnostics.hasError)
|
215
|
+
return connectorDiagnostics.validationResult
|
186
216
|
end
|
187
|
-
|
188
217
|
begin
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
isDebug = getIsDebug(queueitToken, secretKey)
|
193
|
-
if(isDebug)
|
194
|
-
debugEntries["ConfigVersion"] = customerIntegration["Version"]
|
218
|
+
if(connectorDiagnostics.isEnabled)
|
219
|
+
debugEntries["SdkVersion"] = UserInQueueService::SDK_VERSION
|
220
|
+
debugEntries["Runtime"] = getRuntime()
|
195
221
|
debugEntries["PureUrl"] = currentUrlWithoutQueueITToken
|
196
222
|
debugEntries["QueueitToken"] = queueitToken
|
197
|
-
debugEntries["OriginalUrl"] = request
|
223
|
+
debugEntries["OriginalUrl"] = getRealOriginalUrl(request)
|
224
|
+
logMoreRequestDetails(debugEntries, request)
|
198
225
|
end
|
199
|
-
|
226
|
+
|
227
|
+
customerIntegration = JSON.parse(integrationConfigJson)
|
228
|
+
|
229
|
+
if(connectorDiagnostics.isEnabled)
|
230
|
+
if(customerIntegration.length != 0 and customerIntegration["Version"] != nil)
|
231
|
+
debugEntries["ConfigVersion"] = customerIntegration["Version"]
|
232
|
+
else
|
233
|
+
debugEntries["ConfigVersion"] = "NULL"
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
if(Utils.isNilOrEmpty(currentUrlWithoutQueueITToken))
|
238
|
+
raise KnownUserError, "currentUrlWithoutQueueITToken can not be nil or empty."
|
239
|
+
end
|
240
|
+
|
241
|
+
if(customerIntegration.length == 0 || customerIntegration["Version"] == nil)
|
242
|
+
raise KnownUserError, "integrationConfigJson is not valid json."
|
243
|
+
end
|
244
|
+
|
200
245
|
integrationEvaluator = IntegrationEvaluator.new
|
201
246
|
matchedConfig = integrationEvaluator.getMatchedIntegrationConfig(customerIntegration, currentUrlWithoutQueueITToken, request)
|
202
247
|
|
203
|
-
if(
|
248
|
+
if(connectorDiagnostics.isEnabled)
|
204
249
|
if(matchedConfig == nil)
|
205
250
|
debugEntries["MatchedConfig"] = "NULL"
|
206
251
|
else
|
@@ -209,55 +254,99 @@ module QueueIt
|
|
209
254
|
end
|
210
255
|
|
211
256
|
if(matchedConfig == nil)
|
212
|
-
return RequestValidationResult.new(nil, nil, nil, nil)
|
257
|
+
return RequestValidationResult.new(nil, nil, nil, nil, nil, nil)
|
213
258
|
end
|
214
259
|
|
260
|
+
# unspecified or 'Queue' specified
|
215
261
|
if(!matchedConfig.key?("ActionType") || Utils.isNilOrEmpty(matchedConfig["ActionType"]) || matchedConfig["ActionType"].eql?(ActionTypes::QUEUE))
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
return _resolveQueueRequestByLocalConfig(targetUrl, queueitToken, queueConfig, customerId, secretKey, 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, request, debugEntries);
|
262
|
+
return handleQueueAction(currentUrlWithoutQueueITToken, queueitToken, customerIntegration,
|
263
|
+
customerId, secretKey, matchedConfig, request, debugEntries, connectorDiagnostics.isEnabled)
|
264
|
+
|
265
|
+
elsif(matchedConfig["ActionType"].eql?(ActionTypes::CANCEL))
|
266
|
+
return handleCancelAction(currentUrlWithoutQueueITToken, queueitToken, customerIntegration,
|
267
|
+
customerId, secretKey, matchedConfig, request, debugEntries, connectorDiagnostics.isEnabled)
|
268
|
+
|
269
|
+
# for all unknown types default to 'Ignore'
|
270
|
+
else
|
271
|
+
userInQueueService = getUserInQueueService(request.cookie_jar)
|
272
|
+
result = userInQueueService.getIgnoreActionResult(matchedConfig["Name"])
|
273
|
+
result.isAjaxResult = isQueueAjaxCall(request)
|
274
|
+
|
275
|
+
return result
|
276
|
+
end
|
277
|
+
rescue Exception => e
|
278
|
+
if(connectorDiagnostics.isEnabled)
|
279
|
+
debugEntries["Exception"] = e.message
|
245
280
|
end
|
246
|
-
|
247
|
-
raise KnownUserError, "integrationConfiguration text was not valid: " + stdErr.message
|
281
|
+
raise e
|
248
282
|
ensure
|
249
283
|
setDebugCookie(debugEntries, request.cookie_jar)
|
250
284
|
end
|
251
285
|
end
|
252
286
|
|
287
|
+
def self.handleQueueAction(currentUrlWithoutQueueITToken, queueitToken, customerIntegration, customerId, secretKey, matchedConfig, request, debugEntries, isDebug)
|
288
|
+
queueConfig = QueueEventConfig.new
|
289
|
+
queueConfig.eventId = matchedConfig["EventId"]
|
290
|
+
queueConfig.queueDomain = matchedConfig["QueueDomain"]
|
291
|
+
queueConfig.layoutName = matchedConfig["LayoutName"]
|
292
|
+
queueConfig.culture = matchedConfig["Culture"]
|
293
|
+
queueConfig.cookieDomain = matchedConfig["CookieDomain"]
|
294
|
+
queueConfig.extendCookieValidity = matchedConfig["ExtendCookieValidity"]
|
295
|
+
queueConfig.cookieValidityMinute = matchedConfig["CookieValidityMinute"]
|
296
|
+
queueConfig.version = customerIntegration["Version"]
|
297
|
+
queueConfig.actionName = matchedConfig["Name"]
|
298
|
+
|
299
|
+
case matchedConfig["RedirectLogic"]
|
300
|
+
when "ForcedTargetUrl"
|
301
|
+
targetUrl = matchedConfig["ForcedTargetUrl"]
|
302
|
+
when "EventTargetUrl"
|
303
|
+
targetUrl = ''
|
304
|
+
else
|
305
|
+
targetUrl = generateTargetUrl(currentUrlWithoutQueueITToken, request)
|
306
|
+
end
|
307
|
+
|
308
|
+
return _resolveQueueRequestByLocalConfig(targetUrl, queueitToken, queueConfig, customerId, secretKey, request, debugEntries, isDebug)
|
309
|
+
end
|
310
|
+
|
311
|
+
def self.handleCancelAction(currentUrlWithoutQueueITToken, queueitToken, customerIntegration, customerId, secretKey, matchedConfig, request, debugEntries, isDebug)
|
312
|
+
cancelConfig = CancelEventConfig.new
|
313
|
+
cancelConfig.eventId = matchedConfig["EventId"]
|
314
|
+
cancelConfig.queueDomain = matchedConfig["QueueDomain"]
|
315
|
+
cancelConfig.cookieDomain = matchedConfig["CookieDomain"]
|
316
|
+
cancelConfig.version = customerIntegration["Version"]
|
317
|
+
cancelConfig.actionName = matchedConfig["Name"]
|
318
|
+
|
319
|
+
return _cancelRequestByLocalConfig(currentUrlWithoutQueueITToken, queueitToken, cancelConfig, customerId, secretKey, request, debugEntries, isDebug)
|
320
|
+
end
|
321
|
+
|
253
322
|
def self.cancelRequestByLocalConfig(targetUrl, queueitToken, cancelConfig, customerId, secretKey, request)
|
254
323
|
debugEntries = Hash.new
|
324
|
+
connectorDiagnostics = ConnectorDiagnostics.verify(customerId, secretKey, queueitToken)
|
325
|
+
|
326
|
+
if(connectorDiagnostics.hasError)
|
327
|
+
return connectorDiagnostics.validationResult
|
328
|
+
end
|
255
329
|
begin
|
256
|
-
return _cancelRequestByLocalConfig(targetUrl, queueitToken, cancelConfig, customerId, secretKey, request, debugEntries)
|
330
|
+
return _cancelRequestByLocalConfig(targetUrl, queueitToken, cancelConfig, customerId, secretKey, request, debugEntries, connectorDiagnostics.isEnabled)
|
331
|
+
rescue Exception => e
|
332
|
+
if(connectorDiagnostics.isEnabled)
|
333
|
+
debugEntries["Exception"] = e.message
|
334
|
+
end
|
335
|
+
raise e
|
257
336
|
ensure
|
258
337
|
setDebugCookie(debugEntries, request.cookie_jar)
|
259
338
|
end
|
260
339
|
end
|
340
|
+
|
341
|
+
def self.getRealOriginalUrl(request)
|
342
|
+
# RoR could modify request.original_url if request contains x-forwarded-host/proto http headers.
|
343
|
+
# Therefore we need this method to be able to access the 'real' original url.
|
344
|
+
return request.env["rack.url_scheme"] + "://" + request.env["HTTP_HOST"] + request.original_fullpath
|
345
|
+
end
|
346
|
+
|
347
|
+
def self.getRuntime()
|
348
|
+
return RUBY_VERSION.to_s
|
349
|
+
end
|
261
350
|
end
|
262
351
|
|
263
352
|
class CookieManager
|
@@ -286,9 +375,9 @@ module QueueIt
|
|
286
375
|
@cookies.delete(key)
|
287
376
|
else
|
288
377
|
if(noExpire)
|
289
|
-
@cookies[key] = { :value => value }
|
378
|
+
@cookies[key] = { :value => value, :httponly => false }
|
290
379
|
else
|
291
|
-
@cookies[key] = { :value => value, :expires => expire }
|
380
|
+
@cookies[key] = { :value => value, :expires => expire, :httponly => false }
|
292
381
|
end
|
293
382
|
end
|
294
383
|
else
|
@@ -296,9 +385,9 @@ module QueueIt
|
|
296
385
|
@cookies.delete(key, :domain => domain)
|
297
386
|
else
|
298
387
|
if(noExpire)
|
299
|
-
@cookies[key] = { :value => value, :domain => domain }
|
388
|
+
@cookies[key] = { :value => value, :domain => domain, :httponly => false }
|
300
389
|
else
|
301
|
-
@cookies[key] = { :value => value, :expires => expire, :domain => domain }
|
390
|
+
@cookies[key] = { :value => value, :expires => expire, :domain => domain, :httponly => false }
|
302
391
|
end
|
303
392
|
end
|
304
393
|
end
|