freeclimb 4.1.4 → 4.3.0
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 +4 -4
- data/CHANGELOG.md +17 -0
- data/Gemfile.lock +1 -1
- data/README.md +29 -4
- data/docs/DefaultApi.md +4 -1
- data/lib/freeclimb/api/default_api.rb +7 -0
- data/lib/freeclimb/models/account_result.rb +2 -0
- data/lib/freeclimb/models/account_result_all_of.rb +2 -0
- data/lib/freeclimb/models/call_result.rb +3 -0
- data/lib/freeclimb/models/call_result_all_of.rb +3 -0
- data/lib/freeclimb/models/conference_result.rb +2 -0
- data/lib/freeclimb/models/conference_result_all_of.rb +2 -0
- data/lib/freeclimb/models/create_conference.rb +1 -0
- data/lib/freeclimb/models/create_conference_all_of.rb +1 -0
- data/lib/freeclimb/models/create_conference_request.rb +1 -0
- data/lib/freeclimb/models/get_speech.rb +1 -0
- data/lib/freeclimb/models/get_speech_all_of.rb +1 -0
- data/lib/freeclimb/models/log_result.rb +1 -0
- data/lib/freeclimb/models/message_result.rb +1 -0
- data/lib/freeclimb/models/message_result_all_of.rb +1 -0
- data/lib/freeclimb/models/update_conference_request.rb +1 -0
- data/lib/freeclimb/utils/request_verifier.rb +61 -0
- data/lib/freeclimb/utils/signature_information.rb +45 -0
- data/lib/freeclimb/version.rb +1 -1
- data/lib/freeclimb.rb +4 -0
- data/openapi.json +38 -25
- data/spec/api/default_api_spec.rb +5 -1
- data/spec/utils/request_verifier_spec.rb +148 -0
- data/spec/utils/signature_information_spec.rb +39 -0
- metadata +79 -73
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3fe5bf8c6790b57956fa74c9c4ca271e6647335b530451e5a0df169ca04ab698
|
4
|
+
data.tar.gz: e88e5d809bdc9a229a617a197bc2abf162540ed41d14382c4ff92f38a50bdfde
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1bc204e826ee90288418715a41d73fa3b5dd6913918758e3f7e81cf53f7a8c720eda653e0749e0be62c6687d7c57a63581693ba789d66817c062a4dab61fa0bd
|
7
|
+
data.tar.gz: 026c172225aa3d1345397ab4fbb909ff37a5fc533aee95e986f44b99a72ec3a8bc029adc225199353a67df462ffafd51d84847f8a245def11c8deb19b0bbbd3e
|
data/CHANGELOG.md
CHANGED
@@ -9,11 +9,28 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
9
9
|
|
10
10
|
None
|
11
11
|
|
12
|
+
<a name="4.3.0"></a>
|
13
|
+
|
14
|
+
## [4.3.0] - 2023-04-27
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
|
18
|
+
- Introduce application ID filtering for list calls method
|
19
|
+
|
20
|
+
<a name="4.2.0"></a>
|
21
|
+
|
22
|
+
## [4.2.0] - 2023-04-03
|
23
|
+
|
24
|
+
### Added
|
25
|
+
|
26
|
+
- Introduce signing secret verification class (RequestVerifier) - https://docs.freeclimb.com/docs/validating-requests-from-freeclimb#how-to-verify-requests-manually
|
27
|
+
|
12
28
|
<a name="4.1.4"></a>
|
13
29
|
|
14
30
|
## [4.1.4] - 2023-03-31
|
15
31
|
|
16
32
|
### Changed
|
33
|
+
|
17
34
|
- PerclScript.to_json serialization fixed
|
18
35
|
|
19
36
|
<a name="4.1.3"></a>
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -7,7 +7,7 @@ FreeClimb is a cloud-based application programming interface (API) that puts the
|
|
7
7
|
This SDK is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
8
8
|
|
9
9
|
- API version: 1.0.0
|
10
|
-
- Package version: 4.
|
10
|
+
- Package version: 4.3.0
|
11
11
|
- Build package: org.openapitools.codegen.languages.RubyClientCodegen
|
12
12
|
For more information, please visit [https://www.freeclimb.com/support/](https://www.freeclimb.com/support/)
|
13
13
|
|
@@ -15,7 +15,7 @@ For more information, please visit [https://www.freeclimb.com/support/](https://
|
|
15
15
|
|
16
16
|
Add this to the Gemfile:
|
17
17
|
|
18
|
-
gem 'freeclimb', '~> 4.
|
18
|
+
gem 'freeclimb', '~> 4.3.0'
|
19
19
|
|
20
20
|
and run from your terminal
|
21
21
|
|
@@ -44,9 +44,9 @@ gem build freeclimb.gemspec
|
|
44
44
|
Then either install the gem locally:
|
45
45
|
|
46
46
|
```shell
|
47
|
-
gem install ./freeclimb-4.
|
47
|
+
gem install ./freeclimb-4.3.0.gem
|
48
48
|
```
|
49
|
-
(for development, run `gem install --dev ./freeclimb-4.
|
49
|
+
(for development, run `gem install --dev ./freeclimb-4.3.0.gem` to install the development dependencies)
|
50
50
|
|
51
51
|
## Getting Started
|
52
52
|
|
@@ -286,6 +286,31 @@ Class | Method | HTTP request | Description
|
|
286
286
|
- **Type**: HTTP basic authentication
|
287
287
|
|
288
288
|
|
289
|
+
<a name="documentation-for-verify-request-signature"></a>
|
290
|
+
|
291
|
+
## Documentation for verifying request signature
|
292
|
+
|
293
|
+
- To verify the signature request, we will need to use the verifySignatureRequest method within the Request Verifier class
|
294
|
+
|
295
|
+
Freeclimb::RequestVerifier.verify_request_signature(requestBody, requestHeader, signingSecret, tolerance)
|
296
|
+
|
297
|
+
This is a method that you can call directly from the request verifier class, it will throw exceptions depending on whether all parts of the request signature is valid otherwise it will throw a specific error message depending on which request signature part is causing issues
|
298
|
+
|
299
|
+
This method requires a requestBody of type string, a requestHeader of type string, a signingSecret of type string, and a tolerance value of type int
|
300
|
+
|
301
|
+
Example code down below
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
class RequestVerifier
|
305
|
+
def verify_request_signature_example()
|
306
|
+
request_header = "t=1679944186,v1=c3957749baf61df4b1506802579cc69a74c77a1ae21447b930e5a704f9ec4120,v1=1ba18712726898fbbe48cd862dd096a709f7ad761a5bab14bda9ac24d963a6a8"
|
307
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7793"
|
308
|
+
tolerance = (5 * 60)
|
309
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
310
|
+
Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance)
|
311
|
+
```
|
312
|
+
|
313
|
+
|
289
314
|
## Getting Help
|
290
315
|
|
291
316
|
If you are experiencing difficulties, [contact support](https://freeclimb.com/support).
|
data/docs/DefaultApi.md
CHANGED
@@ -2104,7 +2104,8 @@ opts = {
|
|
2104
2104
|
status: Freeclimb::CallStatus::QUEUED, # CallStatus | Only show Calls currently in this status. May be `queued`, `ringing`, `inProgress`, `canceled`, `completed`, `failed`, `busy`, or `noAnswer`.
|
2105
2105
|
start_time: 'start_time_example', # String | Only show Calls that started at or after this time, given as YYYY-MM-DD hh:mm:ss.
|
2106
2106
|
end_time: 'end_time_example', # String | Only show Calls that ended at or before this time, given as YYYY-MM- DD hh:mm:ss.
|
2107
|
-
parent_call_id: 'parent_call_id_example' # String | Only show Calls spawned by the call with this ID.
|
2107
|
+
parent_call_id: 'parent_call_id_example', # String | Only show Calls spawned by the call with this ID.
|
2108
|
+
application_id: ['inner_example'] # Array<String> | Only show calls belonging to the given applicationId. This parameter can be repeated to return calls from multiple Applications.
|
2108
2109
|
}
|
2109
2110
|
|
2110
2111
|
begin
|
@@ -2154,6 +2155,8 @@ end
|
|
2154
2155
|
|
2155
2156
|
| **parent_call_id** | **String** | Only show Calls spawned by the call with this ID. | [optional] |
|
2156
2157
|
|
2158
|
+
| **application_id** | [**Array<String>**](String.md) | Only show calls belonging to the given applicationId. This parameter can be repeated to return calls from multiple Applications. | [optional] |
|
2159
|
+
|
2157
2160
|
|
2158
2161
|
### Return type
|
2159
2162
|
|
@@ -1798,6 +1798,7 @@ module Freeclimb
|
|
1798
1798
|
# @option opts [String] :start_time Only show Calls that started at or after this time, given as YYYY-MM-DD hh:mm:ss.
|
1799
1799
|
# @option opts [String] :end_time Only show Calls that ended at or before this time, given as YYYY-MM- DD hh:mm:ss.
|
1800
1800
|
# @option opts [String] :parent_call_id Only show Calls spawned by the call with this ID.
|
1801
|
+
# @option opts [Array<String>] :application_id Only show calls belonging to the given applicationId. This parameter can be repeated to return calls from multiple Applications.
|
1801
1802
|
# @return [CallList]
|
1802
1803
|
def list_calls(opts = {})
|
1803
1804
|
data, _status_code, _headers = list_calls_with_http_info(opts)
|
@@ -1813,11 +1814,16 @@ module Freeclimb
|
|
1813
1814
|
# @option opts [String] :start_time Only show Calls that started at or after this time, given as YYYY-MM-DD hh:mm:ss.
|
1814
1815
|
# @option opts [String] :end_time Only show Calls that ended at or before this time, given as YYYY-MM- DD hh:mm:ss.
|
1815
1816
|
# @option opts [String] :parent_call_id Only show Calls spawned by the call with this ID.
|
1817
|
+
# @option opts [Array<String>] :application_id Only show calls belonging to the given applicationId. This parameter can be repeated to return calls from multiple Applications.
|
1816
1818
|
# @return [Array<(CallList, Integer, Hash)>] CallList data, response status code and response headers
|
1817
1819
|
def list_calls_with_http_info(opts = {})
|
1818
1820
|
if @api_client.config.debugging
|
1819
1821
|
@api_client.config.logger.debug 'Calling API: DefaultApi.list_calls ...'
|
1820
1822
|
end
|
1823
|
+
if @api_client.config.client_side_validation && !opts[:'application_id'].nil? && opts[:'application_id'].length > 16
|
1824
|
+
fail ArgumentError, 'invalid value for "opts[:"application_id"]" when calling DefaultApi.list_calls, number of items must be less than or equal to 16.'
|
1825
|
+
end
|
1826
|
+
|
1821
1827
|
# resource path
|
1822
1828
|
local_var_path = '/Accounts/{accountId}/Calls'.sub('{' + 'accountId' + '}', CGI.escape(account_id.to_s))
|
1823
1829
|
|
@@ -1830,6 +1836,7 @@ module Freeclimb
|
|
1830
1836
|
query_params[:'startTime'] = opts[:'start_time'] if !opts[:'start_time'].nil?
|
1831
1837
|
query_params[:'endTime'] = opts[:'end_time'] if !opts[:'end_time'].nil?
|
1832
1838
|
query_params[:'parentCallId'] = opts[:'parent_call_id'] if !opts[:'parent_call_id'].nil?
|
1839
|
+
query_params[:'applicationId'] = @api_client.build_collection_param(opts[:'application_id'], :multi) if !opts[:'application_id'].nil?
|
1833
1840
|
|
1834
1841
|
# header parameters
|
1835
1842
|
header_params = opts[:header_params] || {}
|
@@ -133,11 +133,14 @@ module Freeclimb
|
|
133
133
|
:'from',
|
134
134
|
:'to',
|
135
135
|
:'phone_number_id',
|
136
|
+
:'call_status',
|
136
137
|
:'start_time',
|
137
138
|
:'connect_time',
|
138
139
|
:'end_time',
|
139
140
|
:'duration',
|
140
141
|
:'connect_duration',
|
142
|
+
:'direction',
|
143
|
+
:'answered_by',
|
141
144
|
:'subresource_uris'
|
142
145
|
])
|
143
146
|
end
|
@@ -113,11 +113,14 @@ module Freeclimb
|
|
113
113
|
:'from',
|
114
114
|
:'to',
|
115
115
|
:'phone_number_id',
|
116
|
+
:'call_status',
|
116
117
|
:'start_time',
|
117
118
|
:'connect_time',
|
118
119
|
:'end_time',
|
119
120
|
:'duration',
|
120
121
|
:'connect_duration',
|
122
|
+
:'direction',
|
123
|
+
:'answered_by',
|
121
124
|
:'subresource_uris'
|
122
125
|
])
|
123
126
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Freeclimb
|
2
|
+
class RequestVerifier
|
3
|
+
class << self
|
4
|
+
@@DEFAULT_TOLERANCE = 5 * 60 * 1000
|
5
|
+
|
6
|
+
def verify_request_signature(request_body, request_header, signing_secret, tolerance=DEFAULT_TOLERANCE)
|
7
|
+
request_verifier_object = Freeclimb::RequestVerifier.new()
|
8
|
+
request_verifier_object.instance_eval{ check_request_body(request_body) }
|
9
|
+
request_verifier_object.instance_eval{ check_request_header(request_header) }
|
10
|
+
request_verifier_object.instance_eval{ check_signing_secret(signing_secret) }
|
11
|
+
request_verifier_object.instance_eval{ check_tolerance(tolerance) }
|
12
|
+
info = Freeclimb::SignatureInformation.new(request_header)
|
13
|
+
request_verifier_object.instance_eval{ verify_tolerance(info, tolerance) }
|
14
|
+
request_verifier_object.instance_eval{ verify_signature(info, request_body, signing_secret)}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def check_request_body(request_body)
|
21
|
+
if request_body == "" || request_body == nil
|
22
|
+
raise 'Request Body cannot be empty or null'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def check_request_header(request_header)
|
27
|
+
if request_header == "" || request_header == nil
|
28
|
+
raise 'Error with request header, Request header is empty'
|
29
|
+
elsif !(request_header.include? "t")
|
30
|
+
raise 'Error with request header, timestamp is not present'
|
31
|
+
elsif !(request_header.include? "v1")
|
32
|
+
raise 'Error with request header, signatures are not present'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def check_signing_secret(signing_secret)
|
37
|
+
if signing_secret == "" || signing_secret == nil
|
38
|
+
raise 'Signing secret cannot be empty or null'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def check_tolerance(tolerance)
|
43
|
+
if tolerance <= 0 || !(tolerance.is_a? Integer)
|
44
|
+
raise 'Tolerance value must be a positive integer'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def verify_tolerance(info, tolerance)
|
49
|
+
currentTime = info.get_current_unix_time()
|
50
|
+
if !info.is_request_time_valid(tolerance)
|
51
|
+
raise "Request time exceeded tolerance threshold. Request: " + info.request_timestamp.to_s + ", CurrentTime: " + currentTime.to_s + ", tolerance: " + tolerance.to_s
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def verify_signature(info, request_body, signing_secret)
|
56
|
+
if !info.is_signature_safe(request_body, signing_secret)
|
57
|
+
raise "Unverified signature request, If this request was unexpected, it may be from a bad actor. Please proceed with caution. If the request was exepected, please check any typos or issues with the signingSecret"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'openssl'
|
3
|
+
|
4
|
+
module Freeclimb
|
5
|
+
class SignatureInformation
|
6
|
+
attr_accessor :request_timestamp
|
7
|
+
attr_accessor :signatures
|
8
|
+
|
9
|
+
def initialize(request_header)
|
10
|
+
@request_timestamp = 0
|
11
|
+
@signatures = []
|
12
|
+
signatureHeader = request_header.try(:split, ",")
|
13
|
+
signatureHeader.each { |signature|
|
14
|
+
header, value = signature.try(:split, "=")
|
15
|
+
if header == "t"
|
16
|
+
@request_timestamp = value.to_i
|
17
|
+
elsif header == "v1"
|
18
|
+
@signatures.append(value)
|
19
|
+
end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def is_request_time_valid(tolerance)
|
24
|
+
currentTime = self.get_current_unix_time()
|
25
|
+
timeCalculation = @request_timestamp + tolerance
|
26
|
+
return (timeCalculation) < currentTime
|
27
|
+
end
|
28
|
+
|
29
|
+
def is_signature_safe(request_body, signing_secret)
|
30
|
+
hashValue = self.compute_hash(request_body, signing_secret)
|
31
|
+
return @signatures.include? hashValue
|
32
|
+
end
|
33
|
+
|
34
|
+
def compute_hash(request_body, signing_secret)
|
35
|
+
data = @request_timestamp.to_s + "." + request_body
|
36
|
+
return OpenSSL::HMAC.hexdigest('sha256', signing_secret, data)
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_current_unix_time()
|
40
|
+
return DateTime.now.strftime('%s').to_i
|
41
|
+
end
|
42
|
+
|
43
|
+
private :compute_hash
|
44
|
+
end
|
45
|
+
end
|
data/lib/freeclimb/version.rb
CHANGED
data/lib/freeclimb.rb
CHANGED
@@ -148,6 +148,10 @@ require 'freeclimb/models/unpark'
|
|
148
148
|
# APIs
|
149
149
|
require 'freeclimb/api/default_api'
|
150
150
|
|
151
|
+
#Utils
|
152
|
+
require 'freeclimb/utils/signature_information'
|
153
|
+
require 'freeclimb/utils/request_verifier'
|
154
|
+
|
151
155
|
module Freeclimb
|
152
156
|
class << self
|
153
157
|
# Customize default settings for the SDK using block.
|
data/openapi.json
CHANGED
@@ -85,28 +85,33 @@
|
|
85
85
|
"type": "string",
|
86
86
|
"enum": ["closed", "suspended", "active"],
|
87
87
|
"x-enum-varnames": ["CLOSED", "SUSPENDED", "ACTIVE"],
|
88
|
-
"description": "The status of this account. It is one of: active, suspended, or closed."
|
88
|
+
"description": "The status of this account. It is one of: active, suspended, or closed.",
|
89
|
+
"nullable": true
|
89
90
|
},
|
90
91
|
"AccountType": {
|
91
92
|
"type": "string",
|
92
93
|
"description": "The type of this account. It is one of: trial or full.",
|
93
94
|
"enum": ["trial", "full"],
|
94
|
-
"x-enum-varnames": ["TRIAL", "FULL"]
|
95
|
+
"x-enum-varnames": ["TRIAL", "FULL"],
|
96
|
+
"nullable": true
|
95
97
|
},
|
96
98
|
"AnsweredBy": {
|
97
99
|
"type": "string",
|
100
|
+
"nullable": true,
|
98
101
|
"enum": ["human", "machine"],
|
99
102
|
"x-enum-varnames": ["HUMAN", "MACHINE"],
|
100
103
|
"description": "If this Call was initiated with answering machine detection, either `human` or `machine`. Empty otherwise."
|
101
104
|
},
|
102
105
|
"CallDirection": {
|
103
106
|
"type": "string",
|
107
|
+
"nullable": true,
|
104
108
|
"enum": ["inbound", "outboundAPI", "outboundDial"],
|
105
109
|
"x-enum-varnames": ["INBOUND", "OUTBOUND_API", "OUTBOUND_DIAL"],
|
106
110
|
"description": "Direction of the Call. `inbound` for Calls into FreeClimb, `outboundAPI` for Calls initiated via the REST API, `outboundDial` for Calls initiated by the `OutDial` PerCL command."
|
107
111
|
},
|
108
112
|
"CallStatus": {
|
109
113
|
"type": "string",
|
114
|
+
"nullable": true,
|
110
115
|
"enum": [
|
111
116
|
"queued",
|
112
117
|
"ringing",
|
@@ -131,6 +136,7 @@
|
|
131
136
|
},
|
132
137
|
"ConferenceStatus": {
|
133
138
|
"type": "string",
|
139
|
+
"nullable": true,
|
134
140
|
"enum": ["empty", "populated", "inProgress", "terminated"],
|
135
141
|
"x-enum-varnames": ["EMPTY", "POPULATED", "IN_PROGRESS", "TERMINATED"],
|
136
142
|
"description": "The status of the Conference. One of: creating, empty, populated, inProgress, or terminated."
|
@@ -194,6 +200,7 @@
|
|
194
200
|
"GrammarType": {
|
195
201
|
"type": "string",
|
196
202
|
"enum": ["URL", "BUILTIN"],
|
203
|
+
"nullable": true,
|
197
204
|
"x-enum-varnames": ["URL", "BUILT_IN"],
|
198
205
|
"description": "The grammar file type to use for speech recognition. A value of 'URL' indicates the grammarFile attribute specifies a URL that points to the grammar file. A value of `BUILTIN` indicates the grammarFile attribute specifies the name of one of the platform built-in grammar files."
|
199
206
|
},
|
@@ -265,6 +272,7 @@
|
|
265
272
|
"LogLevel": {
|
266
273
|
"type": "string",
|
267
274
|
"enum": ["info", "warning", "error"],
|
275
|
+
"nullable": true,
|
268
276
|
"x-enum-varnames": ["INFO", "WARNING", "ERROR"],
|
269
277
|
"description": "Level of the log. Possible values are info, warning, and error."
|
270
278
|
},
|
@@ -280,6 +288,7 @@
|
|
280
288
|
},
|
281
289
|
"MessageStatus": {
|
282
290
|
"type": "string",
|
291
|
+
"nullable": true,
|
283
292
|
"description": "Indicates the state of the message through the message lifecycle including: new, queued, rejected, sending, sent, failed, received, undelivered, expired, deleted, and unknown",
|
284
293
|
"enum": [
|
285
294
|
"new",
|
@@ -310,9 +319,10 @@
|
|
310
319
|
},
|
311
320
|
"PlayBeep": {
|
312
321
|
"type": "string",
|
322
|
+
"nullable": true,
|
313
323
|
"enum": ["always", "never", "entryOnly", "exitOnly"],
|
314
324
|
"x-enum-varnames": ["ALWAYS", "NEVER", "ENTRY_ONLY", "EXIT_ONLY"],
|
315
|
-
"description": "
|
325
|
+
"description": "Indicates whether to play a beep when a Participant enters or leaves the Conference. either `always`, `never`, `entryOnly`, or `exitOnly`. Leaving this unset will make conference default to `always` ",
|
316
326
|
"default": "always",
|
317
327
|
"x-enum-default-attr": "ALWAYS"
|
318
328
|
},
|
@@ -520,7 +530,6 @@
|
|
520
530
|
"type": "boolean"
|
521
531
|
},
|
522
532
|
"playBeep": {
|
523
|
-
"description": "Indicates whether to play a beep when a Participant enters or leaves the Conference. either `always`, `never`, `entryOnly`, or `exitOnly`. Leaving this unset will make conference default to `always` ",
|
524
533
|
"$ref": "#/components/schemas/PlayBeep"
|
525
534
|
},
|
526
535
|
"record": {
|
@@ -653,8 +662,7 @@
|
|
653
662
|
"format": "uri"
|
654
663
|
},
|
655
664
|
"grammarType": {
|
656
|
-
"$ref": "#/components/schemas/GrammarType"
|
657
|
-
"nullable": true
|
665
|
+
"$ref": "#/components/schemas/GrammarType"
|
658
666
|
},
|
659
667
|
"grammarFile": {
|
660
668
|
"description": "The grammar file to use for speech recognition. If grammarType is set to URL, this attribute is specified as a download URL.",
|
@@ -1297,12 +1305,10 @@
|
|
1297
1305
|
"nullable": true
|
1298
1306
|
},
|
1299
1307
|
"type": {
|
1300
|
-
"$ref": "#/components/schemas/AccountType"
|
1301
|
-
"nullable": true
|
1308
|
+
"$ref": "#/components/schemas/AccountType"
|
1302
1309
|
},
|
1303
1310
|
"status": {
|
1304
|
-
"$ref": "#/components/schemas/AccountStatus"
|
1305
|
-
"nullable": true
|
1311
|
+
"$ref": "#/components/schemas/AccountStatus"
|
1306
1312
|
},
|
1307
1313
|
"subresourceUris": {
|
1308
1314
|
"type": "object",
|
@@ -1648,8 +1654,7 @@
|
|
1648
1654
|
"nullable": true
|
1649
1655
|
},
|
1650
1656
|
"callStatus": {
|
1651
|
-
"$ref": "#/components/schemas/CallStatus"
|
1652
|
-
"nullable": true
|
1657
|
+
"$ref": "#/components/schemas/CallStatus"
|
1653
1658
|
},
|
1654
1659
|
"startTime": {
|
1655
1660
|
"type": "string",
|
@@ -1677,12 +1682,10 @@
|
|
1677
1682
|
"nullable": true
|
1678
1683
|
},
|
1679
1684
|
"direction": {
|
1680
|
-
"$ref": "#/components/schemas/CallDirection"
|
1681
|
-
"nullable": true
|
1685
|
+
"$ref": "#/components/schemas/CallDirection"
|
1682
1686
|
},
|
1683
1687
|
"answeredBy": {
|
1684
|
-
"$ref": "#/components/schemas/AnsweredBy"
|
1685
|
-
"nullable": true
|
1688
|
+
"$ref": "#/components/schemas/AnsweredBy"
|
1686
1689
|
},
|
1687
1690
|
"subresourceUris": {
|
1688
1691
|
"type": "object",
|
@@ -1834,9 +1837,7 @@
|
|
1834
1837
|
"nullable": true
|
1835
1838
|
},
|
1836
1839
|
"level": {
|
1837
|
-
"$ref": "#/components/schemas/LogLevel"
|
1838
|
-
|
1839
|
-
"nullable": true
|
1840
|
+
"$ref": "#/components/schemas/LogLevel"
|
1840
1841
|
},
|
1841
1842
|
"requestId": {
|
1842
1843
|
"type": "string",
|
@@ -1909,8 +1910,7 @@
|
|
1909
1910
|
},
|
1910
1911
|
"playBeep": {
|
1911
1912
|
"$ref": "#/components/schemas/PlayBeep",
|
1912
|
-
"description": "Setting that controls when a beep is played. One of: always, never, entryOnly, exitOnly. Defaults to always."
|
1913
|
-
"nullable": true
|
1913
|
+
"description": "Setting that controls when a beep is played. One of: always, never, entryOnly, exitOnly. Defaults to always."
|
1914
1914
|
},
|
1915
1915
|
"record": {
|
1916
1916
|
"type": "boolean",
|
@@ -1918,8 +1918,7 @@
|
|
1918
1918
|
"nullable": true
|
1919
1919
|
},
|
1920
1920
|
"status": {
|
1921
|
-
"$ref": "#/components/schemas/ConferenceStatus"
|
1922
|
-
"nullable": true
|
1921
|
+
"$ref": "#/components/schemas/ConferenceStatus"
|
1923
1922
|
},
|
1924
1923
|
"waitUrl": {
|
1925
1924
|
"type": "string",
|
@@ -2036,8 +2035,7 @@
|
|
2036
2035
|
"nullable": true
|
2037
2036
|
},
|
2038
2037
|
"status": {
|
2039
|
-
"$ref": "#/components/schemas/MessageStatus"
|
2040
|
-
"nullable": true
|
2038
|
+
"$ref": "#/components/schemas/MessageStatus"
|
2041
2039
|
},
|
2042
2040
|
"from": {
|
2043
2041
|
"type": "string",
|
@@ -3066,6 +3064,21 @@
|
|
3066
3064
|
"type": "string"
|
3067
3065
|
}
|
3068
3066
|
},
|
3067
|
+
{
|
3068
|
+
"name": "applicationId",
|
3069
|
+
"in": "query",
|
3070
|
+
"description": "Only show calls belonging to the given applicationId. This parameter can be repeated to return calls from multiple Applications.",
|
3071
|
+
"explode": true,
|
3072
|
+
"required": false,
|
3073
|
+
"schema": {
|
3074
|
+
"type": "array",
|
3075
|
+
"maxItems": 16,
|
3076
|
+
"items": {
|
3077
|
+
"type": "string",
|
3078
|
+
"pattern": "^AP[0-9a-fA-F]{40}$"
|
3079
|
+
}
|
3080
|
+
}
|
3081
|
+
},
|
3069
3082
|
{
|
3070
3083
|
"$ref": "#/components/parameters/AccountId"
|
3071
3084
|
}
|
@@ -128,6 +128,8 @@ describe 'DefaultApi' do
|
|
128
128
|
|
129
129
|
@parent_call_id_list_calls_test_value = 'parentCallId_example'
|
130
130
|
|
131
|
+
@application_id_list_calls_test_value = ['AP0123456789ABCDEFabcedf000000000000000001', 'AP0123456789ABCDEFabcedf000000000000000002', 'AP0123456789ABCDEFabcedf000000000000000002']
|
132
|
+
|
131
133
|
@status_list_conferences_test_value = 'status_example'
|
132
134
|
|
133
135
|
@alias_list_conferences_test_value = 'alias_example'
|
@@ -914,6 +916,7 @@ describe 'DefaultApi' do
|
|
914
916
|
# @option opts [String] :start_time Only show Calls that started at or after this time, given as YYYY-MM-DD hh:mm:ss.
|
915
917
|
# @option opts [String] :end_time Only show Calls that ended at or before this time, given as YYYY-MM- DD hh:mm:ss.
|
916
918
|
# @option opts [String] :parent_call_id Only show Calls spawned by the call with this ID.
|
919
|
+
# @option opts [Array<String>] :application_id Only show calls belonging to the given applicationId. This parameter can be repeated to return calls from multiple Applications.
|
917
920
|
# @return [CallList]
|
918
921
|
describe 'list_calls test' do
|
919
922
|
it 'should work' do
|
@@ -925,11 +928,12 @@ describe 'DefaultApi' do
|
|
925
928
|
start_time = @start_time_list_calls_test_value
|
926
929
|
end_time = @end_time_list_calls_test_value
|
927
930
|
parent_call_id = @parent_call_id_list_calls_test_value
|
931
|
+
application_id = @application_id_list_calls_test_value
|
928
932
|
|
929
933
|
result = @api_instance.list_calls(
|
930
934
|
|
931
935
|
{
|
932
|
-
:active => active,:to => to,:from => from,:status => status,:start_time => start_time,:end_time => end_time,:parent_call_id => parent_call_id,
|
936
|
+
:active => active,:to => to,:from => from,:status => status,:start_time => start_time,:end_time => end_time,:parent_call_id => parent_call_id,:application_id => application_id,
|
933
937
|
}
|
934
938
|
)
|
935
939
|
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'RequestVerifier' do
|
4
|
+
before do
|
5
|
+
@request_verifier_object = Freeclimb::RequestVerifier.new()
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#check_request_body' do
|
9
|
+
context 'Request Body is empty' do
|
10
|
+
it 'throws "Request Body cannot be empty or null"' do
|
11
|
+
request_header = "t=1679944186,v1=c3957749baf61df4b1506802579cc69a74c77a1ae21447b930e5a704f9ec4120,v1=1ba18712726898fbbe48cd862dd096a709f7ad761a5bab14bda9ac24d963a6a8"
|
12
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7793"
|
13
|
+
tolerance = 5 * 60
|
14
|
+
request_body = ""
|
15
|
+
expect { Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance) }.to raise_error("Request Body cannot be empty or null")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
context 'Request Body is nil' do
|
19
|
+
it 'throws "Request Body cannot be empty or null"' do
|
20
|
+
request_header = "t=1679944186,v1=c3957749baf61df4b1506802579cc69a74c77a1ae21447b930e5a704f9ec4120,v1=1ba18712726898fbbe48cd862dd096a709f7ad761a5bab14bda9ac24d963a6a8"
|
21
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7793"
|
22
|
+
tolerance = 5 * 60
|
23
|
+
request_body = nil
|
24
|
+
expect { Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance) }.to raise_error("Request Body cannot be empty or null")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#check_request_header' do
|
30
|
+
context 'signatures are not present' do
|
31
|
+
it 'throws "Error with request header, signatures are not present"' do
|
32
|
+
request_header = "t=1679944186,"
|
33
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7793"
|
34
|
+
tolerance = 5 * 60
|
35
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
36
|
+
expect { Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance) }.to raise_error("Error with request header, signatures are not present")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
context 'timestamp is not present' do
|
40
|
+
it 'throws "Error with request header, timestamp is not present"' do
|
41
|
+
request_header = "v1=c3957749baf61df4b1506802579cc69a74c77a1ae21447b930e5a704f9ec4120,v1=1ba18712726898fbbe48cd862dd096a709f7ad761a5bab14bda9ac24d963a6a8"
|
42
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7793"
|
43
|
+
tolerance = 5 * 60
|
44
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
45
|
+
expect { Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance) }.to raise_error("Error with request header, timestamp is not present")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
context 'Request header is empty' do
|
49
|
+
it 'throws "Error with request header, Request header is empty"' do
|
50
|
+
request_header = ""
|
51
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7793"
|
52
|
+
tolerance = 5 * 60
|
53
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
54
|
+
expect { Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance) }.to raise_error("Error with request header, Request header is empty")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#check_signing_secret' do
|
60
|
+
context 'Signing secret is empty' do
|
61
|
+
it 'throws "Signing secret cannot be empty or null"' do
|
62
|
+
request_header = "t=1679944186,v1=c3957749baf61df4b1506802579cc69a74c77a1ae21447b930e5a704f9ec4120,v1=1ba18712726898fbbe48cd862dd096a709f7ad761a5bab14bda9ac24d963a6a8"
|
63
|
+
signing_secret = ""
|
64
|
+
tolerance = 5 * 60
|
65
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
66
|
+
expect { Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance) }.to raise_error("Signing secret cannot be empty or null")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
context 'Signing secret is nil' do
|
70
|
+
it 'throws "Signing secret cannot be empty or null"' do
|
71
|
+
request_header = "t=1679944186,v1=c3957749baf61df4b1506802579cc69a74c77a1ae21447b930e5a704f9ec4120,v1=1ba18712726898fbbe48cd862dd096a709f7ad761a5bab14bda9ac24d963a6a8"
|
72
|
+
signing_secret = nil
|
73
|
+
tolerance = 5 * 60
|
74
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
75
|
+
expect { Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance) }.to raise_error("Signing secret cannot be empty or null")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#check_tolerance' do
|
81
|
+
context 'Tolerance value is a negative value' do
|
82
|
+
it 'throws "Tolerance value must be a positive integer"' do
|
83
|
+
request_header = "t=1679944186,v1=c3957749baf61df4b1506802579cc69a74c77a1ae21447b930e5a704f9ec4120,v1=1ba18712726898fbbe48cd862dd096a709f7ad761a5bab14bda9ac24d963a6a8"
|
84
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7793"
|
85
|
+
tolerance = -5
|
86
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
87
|
+
expect { Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance) }.to raise_error("Tolerance value must be a positive integer")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
context 'Tolerance value is 0' do
|
91
|
+
it 'throws "Tolerance value must be a positive integer"' do
|
92
|
+
request_header = "t=1679944186,v1=c3957749baf61df4b1506802579cc69a74c77a1ae21447b930e5a704f9ec4120,v1=1ba18712726898fbbe48cd862dd096a709f7ad761a5bab14bda9ac24d963a6a8"
|
93
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7793"
|
94
|
+
tolerance = 0
|
95
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
96
|
+
expect { Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance) }.to raise_error("Tolerance value must be a positive integer")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
context 'Tolerance value is NaN' do
|
100
|
+
it 'throws "Tolerance value must be a positive integer"' do
|
101
|
+
request_header = "t=1679944186,v1=c3957749baf61df4b1506802579cc69a74c77a1ae21447b930e5a704f9ec4120,v1=1ba18712726898fbbe48cd862dd096a709f7ad761a5bab14bda9ac24d963a6a8"
|
102
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7793"
|
103
|
+
tolerance = Float::NAN
|
104
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
105
|
+
expect { Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance) }.to raise_error("Tolerance value must be a positive integer")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#verify_tolerance' do
|
111
|
+
context 'Request plus tolerance is not less than the current datetime' do
|
112
|
+
it 'throws "Request time exceeded tolerance threshold. Request: 1900871395, CurrentTime: currentTimeValue, tolerance, toleranceValue"' do
|
113
|
+
currentTime = DateTime.now.strftime('%s').to_i
|
114
|
+
request_header = "t=1900871395,v1=1d798c86e977ff734dec3a8b8d67fe8621dcc1df46ef4212e0bfe2e122b01bfd,v1=1ba18712726898fbbe48cd862dd096a709f7ad761a5bab14bda9ac24d963a6a8"
|
115
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7793"
|
116
|
+
tolerance = (5 * 60)
|
117
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
118
|
+
expect { Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance) }.to raise_error("Request time exceeded tolerance threshold. Request: 1900871395" + ", CurrentTime: " + currentTime.to_s + ", tolerance: " + tolerance.to_s)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe '#verify_signature' do
|
124
|
+
context 'Signature request is unverified, signing secret does not exist in signatures, potential typo' do
|
125
|
+
it 'throws "Unverified signature request, If this request was unexpected, it may be from a bad actor. Please proceed with caution. If the request was exepected, please check any typos or issues with the signingSecret"' do
|
126
|
+
currentTime = DateTime.now.strftime('%s').to_i
|
127
|
+
request_header = "t=1679944186,v1=c3957749baf61df4b1506802579cc69a74c77a1ae21447b930e5a704f9ec4120,v1=1ba18712726898fbbe48cd862dd096a709f7ad761a5bab14bda9ac24d963a6a8"
|
128
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7794"
|
129
|
+
tolerance = (5 * 60)
|
130
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
131
|
+
expect { Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance) }.to raise_error("Unverified signature request, If this request was unexpected, it may be from a bad actor. Please proceed with caution. If the request was exepected, please check any typos or issues with the signingSecret")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe '#verify_request_signature' do
|
137
|
+
context 'Request is valid' do
|
138
|
+
it 'No errors are thrown' do
|
139
|
+
request_header = "t=1679944186,v1=c3957749baf61df4b1506802579cc69a74c77a1ae21447b930e5a704f9ec4120,v1=1ba18712726898fbbe48cd862dd096a709f7ad761a5bab14bda9ac24d963a6a8"
|
140
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7793"
|
141
|
+
tolerance = (5 * 60)
|
142
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
143
|
+
expect { Freeclimb::RequestVerifier.verify_request_signature(request_body, request_header, signing_secret, tolerance) }.not_to raise_error
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
$time_stamp = 1679944186
|
3
|
+
$FIXNUM_MAX = (2**(0.size * 8 -2) -1)
|
4
|
+
describe 'SignatureInformation' do
|
5
|
+
before do
|
6
|
+
@request_header = "t=#{$time_stamp},v1=c3957749baf61df4b1506802579cc69a74c77a1ae21447b930e5a704f9ec4120,v1=1ba18712726898fbbe48cd862dd096a709f7ad761a5bab14bda9ac24d963a6a8"
|
7
|
+
@signature_information_object = Freeclimb::SignatureInformation.new(@request_header)
|
8
|
+
end
|
9
|
+
describe '#is_request_time_valid' do
|
10
|
+
context 'request time is within tolerance threshold' do
|
11
|
+
it 'returns true' do
|
12
|
+
tolerance = 5 * 60
|
13
|
+
expect(@signature_information_object.is_request_time_valid(tolerance)).to be true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
context 'request time is not within tolerance threshold' do
|
17
|
+
it 'returns false since it does not match condition of request time being within tolerance threshold' do
|
18
|
+
tolerance = $FIXNUM_MAX - $time_stamp
|
19
|
+
expect(@signature_information_object.is_request_time_valid(tolerance)).to be false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
describe '#is_signature_safe' do
|
24
|
+
context 'signingSecret exists in signature array' do
|
25
|
+
it 'returns true' do
|
26
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
27
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7793"
|
28
|
+
expect(@signature_information_object.is_signature_safe(request_body, signing_secret)).to be true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
context 'signingSecret does not exists in signature array' do
|
32
|
+
it 'returns false since it does not match condition of signingSecret being within signature array' do
|
33
|
+
request_body = "{\"accountId\":\"AC1334ffb694cd8d969f51cddf5f7c9b478546d50c\",\"callId\":\"CAccb0b00506553cda09b51c5477f672a49e0b2213\",\"callStatus\":\"ringing\",\"conferenceId\":null,\"direction\":\"inbound\",\"from\":\"+13121000109\",\"parentCallId\":null,\"queueId\":null,\"requestType\":\"inboundCall\",\"to\":\"+13121000096\"}"
|
34
|
+
signing_secret = "sigsec_ead6d3b6904196c60835d039e91b3341c77a7794"
|
35
|
+
expect(@signature_information_object.is_signature_safe(request_body, signing_secret)).to be false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: freeclimb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OpenAPI-Generator
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: typhoeus
|
@@ -330,6 +330,8 @@ files:
|
|
330
330
|
- lib/freeclimb/models/update_conference_participant_request.rb
|
331
331
|
- lib/freeclimb/models/update_conference_request.rb
|
332
332
|
- lib/freeclimb/models/update_conference_request_status.rb
|
333
|
+
- lib/freeclimb/utils/request_verifier.rb
|
334
|
+
- lib/freeclimb/utils/signature_information.rb
|
333
335
|
- lib/freeclimb/version.rb
|
334
336
|
- openapi.json
|
335
337
|
- spec/api/default_api_spec.rb
|
@@ -423,6 +425,8 @@ files:
|
|
423
425
|
- spec/models/update_conference_request_status_spec.rb
|
424
426
|
- spec/quickstart_spec.rb
|
425
427
|
- spec/spec_helper.rb
|
428
|
+
- spec/utils/request_verifier_spec.rb
|
429
|
+
- spec/utils/signature_information_spec.rb
|
426
430
|
homepage: https://freeclimb.com
|
427
431
|
licenses:
|
428
432
|
- Unlicense
|
@@ -451,90 +455,92 @@ test_files:
|
|
451
455
|
- spec/api_client_spec.rb
|
452
456
|
- spec/configuration_spec.rb
|
453
457
|
- spec/factories.rb
|
454
|
-
- spec/models/
|
455
|
-
- spec/models/
|
456
|
-
- spec/models/
|
457
|
-
- spec/models/
|
458
|
-
- spec/models/
|
459
|
-
- spec/models/
|
460
|
-
- spec/models/
|
461
|
-
- spec/models/
|
458
|
+
- spec/models/account_status_spec.rb
|
459
|
+
- spec/models/add_to_conference_spec.rb
|
460
|
+
- spec/models/incoming_number_list_spec.rb
|
461
|
+
- spec/models/call_list_spec.rb
|
462
|
+
- spec/models/queue_result_status_spec.rb
|
463
|
+
- spec/models/capabilities_spec.rb
|
464
|
+
- spec/models/queue_request_spec.rb
|
465
|
+
- spec/models/conference_status_spec.rb
|
466
|
+
- spec/models/queue_member_spec.rb
|
467
|
+
- spec/models/get_speech_reason_spec.rb
|
468
|
+
- spec/models/message_result_spec.rb
|
469
|
+
- spec/models/park_spec.rb
|
462
470
|
- spec/models/answered_by_spec.rb
|
471
|
+
- spec/models/log_result_spec.rb
|
472
|
+
- spec/models/message_direction_spec.rb
|
473
|
+
- spec/models/record_utterance_term_reason_spec.rb
|
474
|
+
- spec/models/conference_participant_result_spec.rb
|
475
|
+
- spec/models/remove_from_conference_spec.rb
|
476
|
+
- spec/models/redirect_spec.rb
|
477
|
+
- spec/models/conference_participant_list_spec.rb
|
478
|
+
- spec/models/percl_command_spec.rb
|
463
479
|
- spec/models/grammar_type_spec.rb
|
480
|
+
- spec/models/call_direction_spec.rb
|
481
|
+
- spec/models/log_list_spec.rb
|
482
|
+
- spec/models/available_number_spec.rb
|
483
|
+
- spec/models/set_listen_spec.rb
|
484
|
+
- spec/models/unpark_spec.rb
|
485
|
+
- spec/models/play_beep_spec.rb
|
486
|
+
- spec/models/available_number_list_spec.rb
|
487
|
+
- spec/models/create_conference_spec.rb
|
464
488
|
- spec/models/account_result_spec.rb
|
489
|
+
- spec/models/message_request_spec.rb
|
490
|
+
- spec/models/update_conference_request_status_spec.rb
|
491
|
+
- spec/models/get_speech_spec.rb
|
465
492
|
- spec/models/incoming_number_request_spec.rb
|
466
|
-
- spec/models/
|
467
|
-
- spec/models/
|
493
|
+
- spec/models/grammar_file_built_in_spec.rb
|
494
|
+
- spec/models/update_conference_participant_request_spec.rb
|
495
|
+
- spec/models/hangup_spec.rb
|
496
|
+
- spec/models/call_result_spec.rb
|
497
|
+
- spec/models/queue_member_list_spec.rb
|
498
|
+
- spec/models/make_call_request_spec.rb
|
499
|
+
- spec/models/account_type_spec.rb
|
500
|
+
- spec/models/log_level_spec.rb
|
501
|
+
- spec/models/set_talk_spec.rb
|
502
|
+
- spec/models/get_digits_spec.rb
|
468
503
|
- spec/models/start_record_call_spec.rb
|
469
|
-
- spec/models/conference_participant_result_spec.rb
|
470
|
-
- spec/models/message_result_spec.rb
|
471
|
-
- spec/models/record_utterance_term_reason_spec.rb
|
472
|
-
- spec/models/sms_spec.rb
|
473
|
-
- spec/models/get_speech_reason_spec.rb
|
474
|
-
- spec/models/message_request_spec.rb
|
475
|
-
- spec/models/account_status_spec.rb
|
476
|
-
- spec/models/out_dial_spec.rb
|
477
|
-
- spec/models/call_direction_spec.rb
|
478
|
-
- spec/models/language_spec.rb
|
479
|
-
- spec/models/play_beep_spec.rb
|
480
|
-
- spec/models/conference_status_spec.rb
|
481
|
-
- spec/models/request_type_spec.rb
|
482
|
-
- spec/models/terminate_conference_spec.rb
|
483
|
-
- spec/models/conference_result_spec.rb
|
484
|
-
- spec/models/create_conference_request_spec.rb
|
485
|
-
- spec/models/buy_incoming_number_request_spec.rb
|
486
|
-
- spec/models/reject_spec.rb
|
487
504
|
- spec/models/messages_list_spec.rb
|
488
|
-
- spec/models/
|
489
|
-
- spec/models/
|
490
|
-
- spec/models/
|
505
|
+
- spec/models/if_machine_spec.rb
|
506
|
+
- spec/models/reject_spec.rb
|
507
|
+
- spec/models/conference_result_spec.rb
|
508
|
+
- spec/models/recording_list_spec.rb
|
491
509
|
- spec/models/machine_type_spec.rb
|
492
|
-
- spec/models/
|
493
|
-
- spec/models/
|
494
|
-
- spec/models/
|
495
|
-
- spec/models/
|
496
|
-
- spec/models/queue_result_spec.rb
|
497
|
-
- spec/models/record_utterance_spec.rb
|
498
|
-
- spec/models/available_number_spec.rb
|
510
|
+
- spec/models/request_type_spec.rb
|
511
|
+
- spec/models/message_status_spec.rb
|
512
|
+
- spec/models/play_spec.rb
|
513
|
+
- spec/models/terminate_conference_spec.rb
|
499
514
|
- spec/models/pause_spec.rb
|
500
|
-
- spec/models/conference_participant_list_spec.rb
|
501
|
-
- spec/models/set_listen_spec.rb
|
502
|
-
- spec/models/available_number_list_spec.rb
|
503
|
-
- spec/models/add_to_conference_spec.rb
|
504
|
-
- spec/models/enqueue_spec.rb
|
505
515
|
- spec/models/application_result_spec.rb
|
506
|
-
- spec/models/call_result_spec.rb
|
507
|
-
- spec/models/update_call_request_spec.rb
|
508
|
-
- spec/models/call_status_spec.rb
|
509
|
-
- spec/models/grammar_file_built_in_spec.rb
|
510
|
-
- spec/models/capabilities_spec.rb
|
511
|
-
- spec/models/park_spec.rb
|
512
|
-
- spec/models/queue_request_spec.rb
|
513
|
-
- spec/models/message_direction_spec.rb
|
514
|
-
- spec/models/mutable_resource_model_spec.rb
|
515
516
|
- spec/models/update_conference_request_spec.rb
|
516
|
-
- spec/models/
|
517
|
-
- spec/models/
|
517
|
+
- spec/models/language_spec.rb
|
518
|
+
- spec/models/percl_script_spec.rb
|
518
519
|
- spec/models/play_early_media_spec.rb
|
519
|
-
- spec/models/remove_from_conference_spec.rb
|
520
|
-
- spec/models/account_type_spec.rb
|
521
|
-
- spec/models/queue_result_status_spec.rb
|
522
|
-
- spec/models/send_digits_spec.rb
|
523
520
|
- spec/models/say_spec.rb
|
524
|
-
- spec/models/
|
525
|
-
- spec/models/
|
526
|
-
- spec/models/
|
527
|
-
- spec/models/
|
528
|
-
- spec/models/
|
529
|
-
- spec/models/
|
530
|
-
- spec/models/
|
531
|
-
- spec/models/
|
532
|
-
- spec/models/
|
521
|
+
- spec/models/mutable_resource_model_spec.rb
|
522
|
+
- spec/models/out_dial_spec.rb
|
523
|
+
- spec/models/record_utterance_spec.rb
|
524
|
+
- spec/models/call_status_spec.rb
|
525
|
+
- spec/models/account_request_spec.rb
|
526
|
+
- spec/models/enqueue_spec.rb
|
527
|
+
- spec/models/create_conference_request_spec.rb
|
528
|
+
- spec/models/incoming_number_result_spec.rb
|
529
|
+
- spec/models/sms_spec.rb
|
530
|
+
- spec/models/filter_logs_request_spec.rb
|
533
531
|
- spec/models/update_call_request_status_spec.rb
|
532
|
+
- spec/models/dequeue_spec.rb
|
533
|
+
- spec/models/recording_result_spec.rb
|
534
|
+
- spec/models/queue_result_spec.rb
|
535
|
+
- spec/models/buy_incoming_number_request_spec.rb
|
536
|
+
- spec/models/pagination_model_spec.rb
|
537
|
+
- spec/models/update_call_request_spec.rb
|
534
538
|
- spec/models/queue_list_spec.rb
|
535
|
-
- spec/models/
|
536
|
-
- spec/models/
|
537
|
-
- spec/models/
|
538
|
-
- spec/models/
|
539
|
+
- spec/models/application_request_spec.rb
|
540
|
+
- spec/models/conference_list_spec.rb
|
541
|
+
- spec/models/send_digits_spec.rb
|
542
|
+
- spec/models/application_list_spec.rb
|
539
543
|
- spec/quickstart_spec.rb
|
540
544
|
- spec/spec_helper.rb
|
545
|
+
- spec/utils/request_verifier_spec.rb
|
546
|
+
- spec/utils/signature_information_spec.rb
|