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
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
1
3
|
module QueueIt
|
2
4
|
class Utils
|
3
5
|
def self.isNilOrEmpty(value)
|
@@ -9,6 +11,12 @@ module QueueIt
|
|
9
11
|
end
|
10
12
|
return value.to_s
|
11
13
|
end
|
14
|
+
def self.urlEncode(value)
|
15
|
+
return CGI.escape(value).gsub("+", "%20").gsub("%7E", "~")
|
16
|
+
end
|
17
|
+
def self.urlDecode(value)
|
18
|
+
return CGI.unescape(value)
|
19
|
+
end
|
12
20
|
end
|
13
21
|
|
14
22
|
class CancelEventConfig
|
@@ -16,19 +24,22 @@ module QueueIt
|
|
16
24
|
attr_accessor :queueDomain
|
17
25
|
attr_accessor :cookieDomain
|
18
26
|
attr_accessor :version
|
27
|
+
attr_accessor :actionName
|
19
28
|
|
20
29
|
def initialize
|
21
30
|
@eventId = nil
|
22
31
|
@queueDomain = nil
|
23
32
|
@cookieDomain = nil
|
24
33
|
@version = nil
|
34
|
+
@actionName = "unspecified"
|
25
35
|
end
|
26
36
|
|
27
37
|
def toString
|
28
38
|
return "EventId:" + Utils.toString(eventId) +
|
29
39
|
"&Version:" + Utils.toString(version) +
|
30
40
|
"&QueueDomain:" + Utils.toString(queueDomain) +
|
31
|
-
"&CookieDomain:" + Utils.toString(cookieDomain)
|
41
|
+
"&CookieDomain:" + Utils.toString(cookieDomain) +
|
42
|
+
"&ActionName:" + Utils.toString(actionName)
|
32
43
|
end
|
33
44
|
end
|
34
45
|
|
@@ -41,6 +52,7 @@ module QueueIt
|
|
41
52
|
attr_accessor :cookieValidityMinute
|
42
53
|
attr_accessor :cookieDomain
|
43
54
|
attr_accessor :version
|
55
|
+
attr_accessor :actionName
|
44
56
|
|
45
57
|
def initialize
|
46
58
|
@eventId = nil
|
@@ -51,6 +63,7 @@ module QueueIt
|
|
51
63
|
@cookieValidityMinute = nil
|
52
64
|
@cookieDomain = nil
|
53
65
|
@version = nil
|
66
|
+
@actionName = "unspecified"
|
54
67
|
end
|
55
68
|
|
56
69
|
def toString
|
@@ -61,7 +74,8 @@ module QueueIt
|
|
61
74
|
"&ExtendCookieValidity:" + Utils.toString(extendCookieValidity) +
|
62
75
|
"&CookieValidityMinute:" + Utils.toString(cookieValidityMinute) +
|
63
76
|
"&LayoutName:" + Utils.toString(layoutName) +
|
64
|
-
"&Culture:" + Utils.toString(culture)
|
77
|
+
"&Culture:" + Utils.toString(culture) +
|
78
|
+
"&ActionName:" + Utils.toString(actionName)
|
65
79
|
end
|
66
80
|
end
|
67
81
|
|
@@ -70,17 +84,33 @@ module QueueIt
|
|
70
84
|
attr_reader :eventId
|
71
85
|
attr_reader :queueId
|
72
86
|
attr_reader :redirectUrl
|
87
|
+
attr_reader :redirectType
|
88
|
+
attr_accessor :actionName
|
89
|
+
attr_accessor :isAjaxResult
|
73
90
|
|
74
|
-
def initialize(actionType, eventId, queueId, redirectUrl)
|
91
|
+
def initialize(actionType, eventId, queueId, redirectUrl, redirectType, actionName)
|
75
92
|
@actionType = actionType
|
76
93
|
@eventId = eventId
|
77
94
|
@queueId = queueId
|
78
95
|
@redirectUrl = redirectUrl
|
96
|
+
@redirectType = redirectType
|
97
|
+
@actionName = actionName
|
79
98
|
end
|
80
99
|
|
81
100
|
def doRedirect
|
82
101
|
return !Utils.isNilOrEmpty(@redirectUrl)
|
83
102
|
end
|
103
|
+
|
104
|
+
def getAjaxQueueRedirectHeaderKey
|
105
|
+
return "x-queueit-redirect"
|
106
|
+
end
|
107
|
+
|
108
|
+
def getAjaxRedirectUrl
|
109
|
+
if !Utils.isNilOrEmpty(@redirectUrl)
|
110
|
+
return Utils.urlEncode(@redirectUrl)
|
111
|
+
end
|
112
|
+
return ""
|
113
|
+
end
|
84
114
|
end
|
85
115
|
|
86
116
|
class KnownUserError < StandardError
|
@@ -92,5 +122,6 @@ module QueueIt
|
|
92
122
|
class ActionTypes
|
93
123
|
CANCEL = "Cancel"
|
94
124
|
QUEUE = "Queue"
|
125
|
+
IGNORE = "Ignore"
|
95
126
|
end
|
96
127
|
end
|
@@ -1,20 +1,20 @@
|
|
1
1
|
module QueueIt
|
2
2
|
class QueueUrlParams
|
3
|
-
KEY_VALUE_SEPARATOR_GROUP_CHAR = '~'
|
4
|
-
KEY_VALUE_SEPARATOR_CHAR = '_'
|
3
|
+
KEY_VALUE_SEPARATOR_GROUP_CHAR = '~'
|
4
|
+
KEY_VALUE_SEPARATOR_CHAR = '_'
|
5
5
|
TIMESTAMP_KEY = "ts"
|
6
|
-
|
7
|
-
EVENT_ID_KEY = "e"
|
8
|
-
EXTENDABLE_COOKIE_KEY = "ce"
|
9
|
-
HASH_KEY = "h"
|
10
|
-
QUEUE_ID_KEY = "q"
|
6
|
+
COOKIE_VALIDITY_MINUTES_KEY = "cv"
|
7
|
+
EVENT_ID_KEY = "e"
|
8
|
+
EXTENDABLE_COOKIE_KEY = "ce"
|
9
|
+
HASH_KEY = "h"
|
10
|
+
QUEUE_ID_KEY = "q"
|
11
11
|
REDIRECT_TYPE_KEY = "rt"
|
12
12
|
|
13
13
|
attr_accessor :timeStamp
|
14
14
|
attr_accessor :eventId
|
15
15
|
attr_accessor :hashCode
|
16
16
|
attr_accessor :extendableCookie
|
17
|
-
attr_accessor :
|
17
|
+
attr_accessor :cookieValidityMinutes
|
18
18
|
attr_accessor :queueITToken
|
19
19
|
attr_accessor :queueITTokenWithoutHash
|
20
20
|
attr_accessor :queueId
|
@@ -25,7 +25,7 @@ module QueueIt
|
|
25
25
|
@eventId = ""
|
26
26
|
@hashCode = ""
|
27
27
|
@extendableCookie = false
|
28
|
-
@
|
28
|
+
@cookieValidityMinutes = nil
|
29
29
|
@queueITToken = ""
|
30
30
|
@queueITTokenWithoutHash = ""
|
31
31
|
@queueId = ""
|
@@ -33,49 +33,49 @@ module QueueIt
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def self.extractQueueParams(queueitToken)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
paramsNameValueList = result.queueITToken.split(KEY_VALUE_SEPARATOR_GROUP_CHAR)
|
36
|
+
if(Utils.isNilOrEmpty(queueitToken))
|
37
|
+
return nil
|
38
|
+
end
|
39
|
+
result = QueueUrlParams.new
|
40
|
+
result.queueITToken = queueitToken
|
41
|
+
paramsNameValueList = result.queueITToken.split(KEY_VALUE_SEPARATOR_GROUP_CHAR)
|
43
42
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
43
|
+
paramsNameValueList.each do |pNameValue|
|
44
|
+
paramNameValueArr = pNameValue.split(KEY_VALUE_SEPARATOR_CHAR)
|
45
|
+
|
46
|
+
if(!paramNameValueArr.length().eql? 2)
|
47
|
+
next
|
73
48
|
end
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
49
|
+
|
50
|
+
case paramNameValueArr[0]
|
51
|
+
when HASH_KEY
|
52
|
+
result.hashCode = paramNameValueArr[1]
|
53
|
+
when TIMESTAMP_KEY
|
54
|
+
if paramNameValueArr[1] !~ /\D/
|
55
|
+
result.timeStamp = paramNameValueArr[1].to_i
|
56
|
+
else
|
57
|
+
result.timeStamp = 0
|
58
|
+
end
|
59
|
+
when COOKIE_VALIDITY_MINUTES_KEY
|
60
|
+
if paramNameValueArr[1] !~ /\D/
|
61
|
+
result.cookieValidityMinutes = paramNameValueArr[1].to_i
|
62
|
+
else
|
63
|
+
result.cookieValidityMinutes = nil
|
64
|
+
end
|
65
|
+
when EVENT_ID_KEY
|
66
|
+
result.eventId = paramNameValueArr[1]
|
67
|
+
when EXTENDABLE_COOKIE_KEY
|
68
|
+
if paramNameValueArr[1].upcase.eql? 'TRUE'
|
69
|
+
result.extendableCookie = true
|
70
|
+
end
|
71
|
+
when QUEUE_ID_KEY
|
72
|
+
result.queueId = paramNameValueArr[1]
|
73
|
+
when REDIRECT_TYPE_KEY
|
74
|
+
result.redirectType = paramNameValueArr[1]
|
75
|
+
end
|
78
76
|
end
|
77
|
+
result.queueITTokenWithoutHash = result.queueITToken.gsub((KEY_VALUE_SEPARATOR_GROUP_CHAR + HASH_KEY + KEY_VALUE_SEPARATOR_CHAR + result.hashCode), "")
|
78
|
+
return result
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
@@ -3,114 +3,155 @@ require 'cgi'
|
|
3
3
|
|
4
4
|
module QueueIt
|
5
5
|
class UserInQueueService
|
6
|
-
|
6
|
+
SDK_VERSION_NO = "3.6.1"
|
7
|
+
SDK_VERSION = "v3-ruby-" + SDK_VERSION_NO
|
7
8
|
|
8
9
|
def initialize(userInQueueStateRepository)
|
9
10
|
@userInQueueStateRepository = userInQueueStateRepository
|
10
11
|
end
|
11
12
|
|
12
13
|
def validateQueueRequest(targetUrl, queueitToken, config, customerId, secretKey)
|
13
|
-
state = @userInQueueStateRepository.getState(config.eventId, secretKey)
|
14
|
+
state = @userInQueueStateRepository.getState(config.eventId, config.cookieValidityMinute, secretKey, true)
|
14
15
|
if (state.isValid)
|
15
|
-
if (state.isStateExtendable && config.extendCookieValidity)
|
16
|
+
if (state.isStateExtendable && config.extendCookieValidity)
|
16
17
|
@userInQueueStateRepository.store(
|
17
18
|
config.eventId,
|
18
19
|
state.queueId,
|
19
|
-
|
20
|
-
config.cookieValidityMinute,
|
20
|
+
nil,
|
21
21
|
!Utils::isNilOrEmpty(config.cookieDomain) ? config.cookieDomain : '',
|
22
|
+
state.redirectType,
|
22
23
|
secretKey)
|
23
24
|
end
|
24
|
-
return RequestValidationResult.new(ActionTypes::QUEUE, config.eventId, state.queueId, nil)
|
25
|
+
return RequestValidationResult.new(ActionTypes::QUEUE, config.eventId, state.queueId, nil, state.redirectType, config.actionName)
|
25
26
|
end
|
26
|
-
|
27
|
+
|
27
28
|
queueParams = QueueUrlParams::extractQueueParams(queueitToken)
|
28
|
-
|
29
|
-
|
29
|
+
|
30
|
+
requestValidationResult = nil
|
31
|
+
isTokenValid = false
|
32
|
+
|
33
|
+
if (!queueParams.nil?)
|
34
|
+
tokenValidationResult = validateToken(config, queueParams, secretKey)
|
35
|
+
isTokenValid = tokenValidationResult.isValid
|
36
|
+
|
37
|
+
if (isTokenValid)
|
38
|
+
requestValidationResult = getValidTokenResult(config, queueParams, secretKey)
|
39
|
+
else
|
40
|
+
requestValidationResult = getErrorResult(customerId, targetUrl, config, queueParams, tokenValidationResult.errorCode)
|
41
|
+
end
|
30
42
|
else
|
31
|
-
|
43
|
+
requestValidationResult = getQueueResult(targetUrl, config, customerId)
|
44
|
+
end
|
45
|
+
|
46
|
+
if (state.isFound && !isTokenValid)
|
47
|
+
@userInQueueStateRepository.cancelQueueCookie(config.eventId, config.cookieDomain);
|
32
48
|
end
|
49
|
+
|
50
|
+
return requestValidationResult;
|
33
51
|
end
|
34
52
|
|
35
|
-
def validateCancelRequest(targetUrl,
|
36
|
-
state = @userInQueueStateRepository.getState(
|
53
|
+
def validateCancelRequest(targetUrl, cancelConfig, customerId, secretKey)
|
54
|
+
state = @userInQueueStateRepository.getState(cancelConfig.eventId, -1, secretKey, false)
|
37
55
|
if (state.isValid)
|
38
|
-
@userInQueueStateRepository.cancelQueueCookie(
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
redirectUrl = "https://" + domainAlias + "cancel/" + customerId + "/" + config.eventId + "/?" + query;
|
48
|
-
return RequestValidationResult.new(ActionTypes::CANCEL, config.eventId, state.queueId, redirectUrl)
|
56
|
+
@userInQueueStateRepository.cancelQueueCookie(cancelConfig.eventId, cancelConfig.cookieDomain)
|
57
|
+
query = getQueryString(customerId, cancelConfig.eventId, cancelConfig.version, cancelConfig.actionName, nil, nil) +
|
58
|
+
(!Utils::isNilOrEmpty(targetUrl) ? ("&r=" + Utils.urlEncode(targetUrl)) : "" )
|
59
|
+
uriPath = "cancel/" + customerId + "/" + cancelConfig.eventId + "/"
|
60
|
+
|
61
|
+
redirectUrl = generateRedirectUrl(cancelConfig.queueDomain, uriPath, query)
|
62
|
+
return RequestValidationResult.new(ActionTypes::CANCEL, cancelConfig.eventId, state.queueId, redirectUrl, state.redirectType, cancelConfig.actionName)
|
49
63
|
else
|
50
|
-
return RequestValidationResult.new(ActionTypes::CANCEL,
|
64
|
+
return RequestValidationResult.new(ActionTypes::CANCEL, cancelConfig.eventId, nil, nil, nil, cancelConfig.actionName)
|
51
65
|
end
|
52
66
|
end
|
53
67
|
|
54
|
-
def
|
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
|
-
|
68
|
+
def getValidTokenResult(config, queueParams, secretKey)
|
66
69
|
@userInQueueStateRepository.store(
|
67
70
|
config.eventId,
|
68
71
|
queueParams.queueId,
|
69
|
-
queueParams.
|
70
|
-
!(queueParams.cookieValidityMinute.nil?) ? queueParams.cookieValidityMinute : config.cookieValidityMinute,
|
72
|
+
queueParams.cookieValidityMinutes,
|
71
73
|
!Utils::isNilOrEmpty(config.cookieDomain) ? config.cookieDomain : '',
|
74
|
+
queueParams.redirectType,
|
72
75
|
secretKey)
|
73
|
-
|
76
|
+
|
77
|
+
return RequestValidationResult.new(ActionTypes::QUEUE, config.eventId, queueParams.queueId, nil, queueParams.redirectType, config.actionName)
|
74
78
|
end
|
75
79
|
|
76
|
-
def
|
77
|
-
query = getQueryString(customerId, config.eventId, config.version, config.culture, config.layoutName) +
|
80
|
+
def getErrorResult(customerId, targetUrl, config, qParams, errorCode)
|
81
|
+
query = getQueryString(customerId, config.eventId, config.version, config.actionName, config.culture, config.layoutName) +
|
78
82
|
"&queueittoken=" + qParams.queueITToken +
|
79
83
|
"&ts=" + Time.now.getutc.tv_sec.to_s +
|
80
|
-
(!Utils::isNilOrEmpty(targetUrl) ? ("&t=" +
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
redirectUrl = "https://" + domainAlias + "error/" + errorCode + "/?" + query
|
86
|
-
return RequestValidationResult.new(ActionTypes::QUEUE, config.eventId, nil, redirectUrl)
|
84
|
+
(!Utils::isNilOrEmpty(targetUrl) ? ("&t=" + Utils.urlEncode(targetUrl)) : "")
|
85
|
+
|
86
|
+
redirectUrl = generateRedirectUrl(config.queueDomain, "error/" + errorCode + "/", query)
|
87
|
+
|
88
|
+
return RequestValidationResult.new(ActionTypes::QUEUE, config.eventId, nil, redirectUrl, nil, config.actionName)
|
87
89
|
end
|
88
90
|
|
89
|
-
def
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
91
|
+
def getQueueResult(targetUrl, config, customerId)
|
92
|
+
query = getQueryString(customerId, config.eventId, config.version, config.actionName, config.culture, config.layoutName) +
|
93
|
+
(!Utils::isNilOrEmpty(targetUrl) ? "&t=" + Utils.urlEncode( targetUrl) : "")
|
94
|
+
|
95
|
+
redirectUrl = generateRedirectUrl(config.queueDomain, "", query)
|
96
|
+
|
97
|
+
return RequestValidationResult.new(ActionTypes::QUEUE, config.eventId, nil, redirectUrl, nil, config.actionName)
|
95
98
|
end
|
96
99
|
|
97
|
-
def getQueryString(customerId, eventId, configVersion, culture, layoutName)
|
100
|
+
def getQueryString(customerId, eventId, configVersion, actionName, culture, layoutName)
|
98
101
|
queryStringList = Array.new
|
99
|
-
queryStringList.push("c=" +
|
100
|
-
queryStringList.push("e=" +
|
101
|
-
queryStringList.push("ver=
|
102
|
+
queryStringList.push("c=" + Utils.urlEncode(customerId))
|
103
|
+
queryStringList.push("e=" + Utils.urlEncode(eventId))
|
104
|
+
queryStringList.push("ver=" + SDK_VERSION)
|
102
105
|
queryStringList.push("cver=" + (!configVersion.nil? ? configVersion.to_s : '-1'))
|
106
|
+
queryStringList.push("man=" + Utils.urlEncode(actionName))
|
107
|
+
|
103
108
|
if (!Utils::isNilOrEmpty(culture))
|
104
|
-
queryStringList.push("cid=" +
|
109
|
+
queryStringList.push("cid=" + Utils.urlEncode(culture))
|
105
110
|
end
|
106
111
|
if (!Utils::isNilOrEmpty(layoutName))
|
107
|
-
queryStringList.push("l=" +
|
112
|
+
queryStringList.push("l=" + Utils.urlEncode(layoutName))
|
108
113
|
end
|
109
114
|
return queryStringList.join("&")
|
110
115
|
end
|
111
116
|
|
112
|
-
def
|
113
|
-
|
117
|
+
def generateRedirectUrl(queueDomain, uriPath, query)
|
118
|
+
if (!queueDomain.end_with?("/") )
|
119
|
+
queueDomain = queueDomain + "/"
|
120
|
+
end
|
121
|
+
return "https://" + queueDomain + uriPath + "?" + query
|
122
|
+
end
|
123
|
+
|
124
|
+
def extendQueueCookie(eventId, cookieValidityMinutes, cookieDomain, secretKey)
|
125
|
+
@userInQueueStateRepository.reissueQueueCookie(eventId, cookieValidityMinutes, cookieDomain, secretKey)
|
126
|
+
end
|
127
|
+
|
128
|
+
def getIgnoreActionResult(actionName)
|
129
|
+
return RequestValidationResult.new(ActionTypes::IGNORE, nil, nil, nil, nil, actionName)
|
130
|
+
end
|
131
|
+
|
132
|
+
def validateToken(config, queueParams, secretKey)
|
133
|
+
calculatedHash = OpenSSL::HMAC.hexdigest('sha256', secretKey, queueParams.queueITTokenWithoutHash)
|
134
|
+
if (calculatedHash.upcase() != queueParams.hashCode.upcase())
|
135
|
+
return TokenValidationResult.new(false, "hash")
|
136
|
+
end
|
137
|
+
if (queueParams.eventId.upcase() != config.eventId.upcase())
|
138
|
+
return TokenValidationResult.new(false, "eventid")
|
139
|
+
end
|
140
|
+
if (queueParams.timeStamp < Time.now.getutc.tv_sec)
|
141
|
+
return TokenValidationResult.new(false, "timestamp")
|
142
|
+
end
|
143
|
+
|
144
|
+
return TokenValidationResult.new(true, nil)
|
145
|
+
end
|
146
|
+
|
147
|
+
class TokenValidationResult
|
148
|
+
attr_reader :isValid
|
149
|
+
attr_reader :errorCode
|
150
|
+
|
151
|
+
def initialize(isValid, errorCode)
|
152
|
+
@isValid = isValid
|
153
|
+
@errorCode = errorCode
|
154
|
+
end
|
114
155
|
end
|
115
156
|
end
|
116
157
|
end
|