@osimatic/helpers-js 1.0.33 → 1.0.36
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.
- package/{changelog.txt → CHANGELOG} +7 -1
- package/form_helper.js +6 -15
- package/network.js +66 -46
- package/package.json +1 -1
- package/web_rtc.js +103 -0
- package/.idea/helpers-js.iml +0 -8
- package/.idea/modules.xml +0 -8
- package/.idea/vcs.xml +0 -6
|
@@ -39,4 +39,10 @@ remplacer l'utilisation des variables httpHeaders / _httpHeaders par HTTPRequest
|
|
|
39
39
|
FlashMessage.displayRequestFailure(status, exception, modal) -> FlashMessage.displayError(labelErrorOccured, modal)
|
|
40
40
|
FormHelper.logRequestFailure(status, exception) -> HTTPRequest.logJqueryRequestFailure(jqxhr, status, exception) (le log de l'erreur est devenu inutile car fait de base dans la classe HTTPRequest)
|
|
41
41
|
|
|
42
|
-
Location.checkCoordinates(...) -> GeographicCoordinates.check(...) (car Location est déjà défini en javascript natif)
|
|
42
|
+
Location.checkCoordinates(...) -> GeographicCoordinates.check(...) (car Location est déjà défini en javascript natif)
|
|
43
|
+
|
|
44
|
+
FormHelper.getFormErrorTextBis(...) -> FormHelper.getFormErrorText(...)
|
|
45
|
+
FormHelper.displayFormErrorsFromXhr(form, btnSubmit, xhr) -> FormHelper.displayFormErrors(form, btnSubmit, xhr.responseJSON)
|
|
46
|
+
|
|
47
|
+
1.0.35 :
|
|
48
|
+
ajout méthode HTTPRequest.init() (charge le polyfill de fetch)
|
package/form_helper.js
CHANGED
|
@@ -183,16 +183,6 @@ class FormHelper {
|
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
static getFormErrorText(errors) {
|
|
186
|
-
let errorLabels = '';
|
|
187
|
-
for (let property in errors) {
|
|
188
|
-
if (typeof errors[property] != 'function') {
|
|
189
|
-
errorLabels += '<span>' + errors[property] + '</span><br>';
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
return errorLabels;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
static getFormErrorTextBis(errors) {
|
|
196
186
|
let errorLabels = '';
|
|
197
187
|
for (let property in errors) {
|
|
198
188
|
// console.log(property);
|
|
@@ -208,7 +198,7 @@ class FormHelper {
|
|
|
208
198
|
}
|
|
209
199
|
|
|
210
200
|
static displayFormErrors(form, btnSubmit, errors, errorWrapperDiv) {
|
|
211
|
-
this.displayFormErrorsFromText(form, this.
|
|
201
|
+
this.displayFormErrorsFromText(form, this.getFormErrorText(errors), errorWrapperDiv);
|
|
212
202
|
if (btnSubmit != null) {
|
|
213
203
|
if (btnSubmit.buttonLoader != null) {
|
|
214
204
|
btnSubmit.buttonLoader('reset');
|
|
@@ -218,10 +208,6 @@ class FormHelper {
|
|
|
218
208
|
}
|
|
219
209
|
}
|
|
220
210
|
|
|
221
|
-
static displayFormErrorsFromXhr(form, btnSubmit, xhr) {
|
|
222
|
-
this.displayFormErrors(form, btnSubmit, xhr.responseJSON);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
211
|
static displayFormErrorsFromText(form, errorLabels, errorWrapperDiv) {
|
|
226
212
|
let errorDiv = '<div class="alert alert-danger form_errors">'+errorLabels+'</div>';
|
|
227
213
|
|
|
@@ -292,6 +278,11 @@ class FormHelper {
|
|
|
292
278
|
console.log('request failure. Status: '+status+' ; Exception: '+exception);
|
|
293
279
|
}
|
|
294
280
|
|
|
281
|
+
/** @deprecated **/
|
|
282
|
+
static displayFormErrorsFromXhr(form, btnSubmit, xhr) {
|
|
283
|
+
this.displayFormErrors(form, btnSubmit, xhr.responseJSON);
|
|
284
|
+
}
|
|
285
|
+
|
|
295
286
|
}
|
|
296
287
|
|
|
297
288
|
module.exports = { FormHelper };
|
package/network.js
CHANGED
|
@@ -1,24 +1,18 @@
|
|
|
1
1
|
|
|
2
2
|
class HTTPRequest {
|
|
3
|
+
static init() {
|
|
4
|
+
require('whatwg-fetch'); //fetch polyfill loaded in window.fetch
|
|
5
|
+
}
|
|
6
|
+
|
|
3
7
|
static setRefreshTokenUrl(url) {
|
|
4
8
|
this.refreshTokenUrl = url;
|
|
5
9
|
}
|
|
10
|
+
|
|
6
11
|
static setRefreshTokenCallback(callback) {
|
|
7
12
|
this.refreshTokenCallback = callback;
|
|
8
13
|
}
|
|
9
14
|
|
|
10
|
-
static setHeader(key, value) {
|
|
11
|
-
if (typeof this.headers == 'undefined') {
|
|
12
|
-
this.headers = {};
|
|
13
|
-
}
|
|
14
|
-
this.headers[key] = value;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
15
|
static getHeaders(asObject) {
|
|
18
|
-
//if (typeof httpHeaders != 'undefined') {
|
|
19
|
-
// return httpHeaders;
|
|
20
|
-
//}
|
|
21
|
-
|
|
22
16
|
if (typeof this.headers == 'undefined') {
|
|
23
17
|
this.headers = {};
|
|
24
18
|
}
|
|
@@ -31,9 +25,34 @@ class HTTPRequest {
|
|
|
31
25
|
Object.entries(this.headers).forEach(([key, value]) => {
|
|
32
26
|
httpHeaders.append(key, value);
|
|
33
27
|
});
|
|
28
|
+
|
|
34
29
|
return httpHeaders;
|
|
35
30
|
}
|
|
36
31
|
|
|
32
|
+
static getHeader(key) {
|
|
33
|
+
if (typeof this.headers == 'undefined') {
|
|
34
|
+
this.headers = {};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return this.headers[key];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static setHeader(key, value) {
|
|
41
|
+
if (typeof this.headers == 'undefined') {
|
|
42
|
+
this.headers = {};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.headers[key] = value;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static setAuthorizationHeader(accessToken) {
|
|
49
|
+
if (typeof this.headers == 'undefined') {
|
|
50
|
+
this.headers = {};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
this.headers['Authorization'] = 'Bearer ' + accessToken;
|
|
54
|
+
}
|
|
55
|
+
|
|
37
56
|
static formatQueryString(data) {
|
|
38
57
|
if (data == null) {
|
|
39
58
|
return '';
|
|
@@ -82,49 +101,52 @@ class HTTPRequest {
|
|
|
82
101
|
//console.log(url, jsonData);
|
|
83
102
|
//console.log(response.status, response.statusText, jsonData['error']);
|
|
84
103
|
|
|
85
|
-
if (response.status == 401 && (response.statusText ===
|
|
104
|
+
if (response.status == 401 && (response.statusText === 'Expired JWT Token' || typeof jsonData['error'] != 'undefined' && jsonData['error'] === 'expired_token')) {
|
|
86
105
|
HTTPRequest.refreshToken(() => HTTPRequest.get(url, data, successCallback, errorCallback));
|
|
87
106
|
return;
|
|
88
107
|
}
|
|
89
108
|
|
|
90
109
|
if (response.ok) {
|
|
91
|
-
successCallback(jsonData);
|
|
110
|
+
successCallback(jsonData, response);
|
|
92
111
|
return;
|
|
93
112
|
}
|
|
94
113
|
}
|
|
95
114
|
catch (e) {
|
|
96
115
|
console.error(e);
|
|
97
116
|
if (typeof errorCallback != 'undefined' && errorCallback != null) {
|
|
98
|
-
errorCallback(response
|
|
117
|
+
errorCallback(response);
|
|
99
118
|
}
|
|
100
119
|
return;
|
|
101
120
|
}
|
|
102
121
|
|
|
103
122
|
HTTPRequest.logRequestFailure(response, jsonData);
|
|
104
123
|
if (typeof errorCallback != 'undefined' && errorCallback != null) {
|
|
105
|
-
errorCallback(response,
|
|
124
|
+
errorCallback(response, jsonData);
|
|
106
125
|
}
|
|
107
126
|
return;
|
|
108
127
|
}
|
|
109
128
|
|
|
110
|
-
//l'api fetch n'est pas dispo pour ce navigateur => normalement ce cas ne devrait pas arriver car le polyfill est chargé
|
|
111
|
-
console.error('fetch\'s polyfill used');
|
|
129
|
+
//l'api fetch n'est pas dispo pour ce navigateur => normalement ce cas ne devrait pas arriver car le polyfill est chargé dans la méthode init
|
|
112
130
|
$.ajax({
|
|
113
131
|
type: 'GET',
|
|
114
132
|
url: url,
|
|
115
133
|
headers: HTTPRequest.getHeaders(true),
|
|
116
134
|
dataType: 'json',
|
|
117
135
|
cache: false,
|
|
118
|
-
success: (data) =>
|
|
136
|
+
success: (data, status, jqxhr) => {
|
|
137
|
+
if (typeof successCallback != 'undefined' && successCallback != null) {
|
|
138
|
+
successCallback(data, jqxhr);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
119
141
|
error: (jqxhr, status, errorThrown) => {
|
|
120
|
-
if (
|
|
142
|
+
if (jqxhr.status == 401 && (jqxhr.statusText === 'Expired JWT Token' || (typeof jqxhr.responseJSON['message'] != 'undefined' && jqxhr.responseJSON['message'] === 'Expired JWT Token') || (typeof jqxhr.responseJSON['error'] != 'undefined' && jqxhr.responseJSON['error'] === 'expired_token' ))) {
|
|
121
143
|
HTTPRequest.refreshToken(() => HTTPRequest.get(url, data, successCallback, errorCallback));
|
|
122
144
|
return;
|
|
123
145
|
}
|
|
124
146
|
|
|
125
147
|
HTTPRequest.logJqueryRequestFailure(jqxhr, status, errorThrown);
|
|
126
148
|
if (typeof errorCallback != 'undefined' && errorCallback != null) {
|
|
127
|
-
errorCallback(jqxhr,
|
|
149
|
+
errorCallback(jqxhr, jqxhr.responseJSON);
|
|
128
150
|
}
|
|
129
151
|
}
|
|
130
152
|
});
|
|
@@ -157,7 +179,7 @@ class HTTPRequest {
|
|
|
157
179
|
/*console.log(url);
|
|
158
180
|
console.log(blobData);*/
|
|
159
181
|
|
|
160
|
-
if (response.status == 401 && response.statusText ===
|
|
182
|
+
if (response.status == 401 && response.statusText === 'Expired JWT Token') {
|
|
161
183
|
HTTPRequest.refreshToken(() => HTTPRequest.download(url, data, errorCallback, completeCallback, method));
|
|
162
184
|
return;
|
|
163
185
|
}
|
|
@@ -168,26 +190,23 @@ class HTTPRequest {
|
|
|
168
190
|
else {
|
|
169
191
|
HTTPRequest.logRequestFailure(response, null);
|
|
170
192
|
if (typeof errorCallback != 'undefined' && errorCallback != null) {
|
|
171
|
-
errorCallback(response
|
|
193
|
+
errorCallback(response);
|
|
172
194
|
}
|
|
173
195
|
}
|
|
174
196
|
}
|
|
175
197
|
catch (e) {
|
|
176
198
|
console.error(e);
|
|
177
199
|
if (typeof errorCallback != 'undefined' && errorCallback != null) {
|
|
178
|
-
errorCallback(response
|
|
200
|
+
errorCallback(response);
|
|
179
201
|
}
|
|
180
202
|
}
|
|
181
203
|
if (typeof completeCallback != 'undefined' && completeCallback != null) {
|
|
182
|
-
completeCallback(response
|
|
204
|
+
completeCallback(response);
|
|
183
205
|
}
|
|
184
206
|
return;
|
|
185
207
|
}
|
|
186
208
|
|
|
187
|
-
//l'api fetch n'est pas dispo pour ce navigateur => normalement ce cas ne devrait pas arriver car le polyfill est chargé
|
|
188
|
-
console.error('fetch\'s polyfill used');
|
|
189
|
-
|
|
190
|
-
|
|
209
|
+
//l'api fetch n'est pas dispo pour ce navigateur => normalement ce cas ne devrait pas arriver car le polyfill est chargé dans la méthode init
|
|
191
210
|
let ajaxOptions = {
|
|
192
211
|
type: 'GET',
|
|
193
212
|
url: url,
|
|
@@ -207,19 +226,19 @@ class HTTPRequest {
|
|
|
207
226
|
$.ajax(Object.assign({...ajaxOptions}, {
|
|
208
227
|
success: (data, status, jqxhr) => File.download(data, jqxhr.getResponseHeader('Content-Type'), jqxhr.getResponseHeader('Content-Disposition')),
|
|
209
228
|
error: (jqxhr, status, errorThrown) => {
|
|
210
|
-
if (
|
|
229
|
+
if (jqxhr.status == 401 && (jqxhr.statusText === 'Expired JWT Token' || (typeof jqxhr.responseJSON['message'] != 'undefined' && jqxhr.responseJSON['message'] === 'Expired JWT Token') || (typeof jqxhr.responseJSON['error'] != 'undefined' && jqxhr.responseJSON['error'] === 'expired_token' ))) {
|
|
211
230
|
HTTPRequest.refreshToken(() => HTTPRequest.download(url, data, errorCallback, completeCallback, method));
|
|
212
231
|
return;
|
|
213
232
|
}
|
|
214
233
|
|
|
215
234
|
HTTPRequest.logJqueryRequestFailure(jqxhr, status, errorThrown);
|
|
216
235
|
if (typeof errorCallback != 'undefined' && errorCallback != null) {
|
|
217
|
-
errorCallback(jqxhr
|
|
236
|
+
errorCallback(jqxhr);
|
|
218
237
|
}
|
|
219
238
|
},
|
|
220
|
-
complete: (jqxhr
|
|
239
|
+
complete: (jqxhr) => {
|
|
221
240
|
if (typeof completeCallback != 'undefined' && completeCallback != null) {
|
|
222
|
-
completeCallback(jqxhr
|
|
241
|
+
completeCallback(jqxhr);
|
|
223
242
|
}
|
|
224
243
|
}
|
|
225
244
|
}));
|
|
@@ -228,7 +247,7 @@ class HTTPRequest {
|
|
|
228
247
|
static async post(url, formData, successCallback, errorCallback, formErrorCallback) {
|
|
229
248
|
formData = this.formatFormData(formData);
|
|
230
249
|
|
|
231
|
-
if (window.fetch
|
|
250
|
+
if (window.fetch) {
|
|
232
251
|
const response = await fetch(url, {
|
|
233
252
|
method: 'POST',
|
|
234
253
|
body: formData,
|
|
@@ -239,43 +258,44 @@ class HTTPRequest {
|
|
|
239
258
|
|
|
240
259
|
let jsonData = {};
|
|
241
260
|
try {
|
|
242
|
-
|
|
261
|
+
if (response.statusText !== 'No Content') {
|
|
262
|
+
jsonData = await response.json();
|
|
263
|
+
}
|
|
243
264
|
//console.log(url, jsonData);
|
|
244
265
|
|
|
245
|
-
if (response.status == 401 && url !== HTTPRequest.refreshTokenUrl && (response.statusText ===
|
|
266
|
+
if (response.status == 401 && url !== HTTPRequest.refreshTokenUrl && (response.statusText === 'Expired JWT Token' || (typeof jsonData['error'] != 'undefined' && jsonData['error'] === 'expired_token'))) {
|
|
246
267
|
HTTPRequest.refreshToken(() => HTTPRequest.post(url, formData, successCallback, errorCallback, formErrorCallback));
|
|
247
268
|
return;
|
|
248
269
|
}
|
|
249
270
|
|
|
250
271
|
if (response.ok) {
|
|
251
272
|
if (typeof successCallback != 'undefined' && successCallback != null) {
|
|
252
|
-
successCallback(jsonData);
|
|
273
|
+
successCallback(jsonData, response);
|
|
253
274
|
}
|
|
254
275
|
return;
|
|
255
276
|
}
|
|
256
277
|
|
|
257
278
|
if (response.status == 400 && typeof formErrorCallback != 'undefined' && formErrorCallback != null) {
|
|
258
|
-
formErrorCallback(
|
|
279
|
+
formErrorCallback(jsonData, response);
|
|
259
280
|
return;
|
|
260
281
|
}
|
|
261
282
|
}
|
|
262
283
|
catch (e) {
|
|
263
284
|
console.error(e);
|
|
264
285
|
if (typeof errorCallback != 'undefined' && errorCallback != null) {
|
|
265
|
-
errorCallback(response
|
|
286
|
+
errorCallback(response);
|
|
266
287
|
}
|
|
267
288
|
return;
|
|
268
289
|
}
|
|
269
290
|
|
|
270
291
|
HTTPRequest.logRequestFailure(response, jsonData);
|
|
271
292
|
if (typeof errorCallback != 'undefined' && errorCallback != null) {
|
|
272
|
-
errorCallback(response,
|
|
293
|
+
errorCallback(response, jsonData);
|
|
273
294
|
}
|
|
274
295
|
return;
|
|
275
296
|
}
|
|
276
297
|
|
|
277
|
-
//l'api fetch n'est pas dispo pour ce navigateur => normalement ce cas ne devrait pas arriver car le polyfill est chargé
|
|
278
|
-
console.error('fetch\'s polyfill used');
|
|
298
|
+
//l'api fetch n'est pas dispo pour ce navigateur => normalement ce cas ne devrait pas arriver car le polyfill est chargé dans la méthode init
|
|
279
299
|
$.ajax({
|
|
280
300
|
type: 'POST',
|
|
281
301
|
url: url,
|
|
@@ -285,24 +305,24 @@ class HTTPRequest {
|
|
|
285
305
|
cache: false,
|
|
286
306
|
contentType: false,
|
|
287
307
|
processData: false,
|
|
288
|
-
success: (data) => {
|
|
308
|
+
success: (data, status, jqxhr) => {
|
|
289
309
|
if (typeof successCallback != 'undefined' && successCallback != null) {
|
|
290
|
-
successCallback(data);
|
|
310
|
+
successCallback(data, jqxhr);
|
|
291
311
|
}
|
|
292
312
|
},
|
|
293
313
|
error: (jqxhr, status, errorThrown) => {
|
|
294
|
-
if (
|
|
314
|
+
if (url !== HTTPRequest.refreshTokenUrl && jqxhr.status == 401 && (jqxhr.statusText === 'Expired JWT Token' || (typeof jqxhr.responseJSON['message'] != 'undefined' && jqxhr.responseJSON['message'] === 'Expired JWT Token') || (typeof jqxhr.responseJSON['error'] != 'undefined' && jqxhr.responseJSON['error'] === 'expired_token' ))) {
|
|
295
315
|
HTTPRequest.refreshToken(() => HTTPRequest.post(url, formData, successCallback, errorCallback, formErrorCallback));
|
|
296
316
|
return;
|
|
297
317
|
}
|
|
298
318
|
if (jqxhr.status == 400 && typeof formErrorCallback != 'undefined' && formErrorCallback != null) {
|
|
299
|
-
formErrorCallback(jqxhr,
|
|
319
|
+
formErrorCallback(jqxhr.responseJSON, jqxhr);
|
|
300
320
|
return;
|
|
301
321
|
}
|
|
302
322
|
|
|
303
323
|
HTTPRequest.logJqueryRequestFailure(jqxhr, status, errorThrown);
|
|
304
324
|
if (typeof errorCallback != 'undefined' && errorCallback != null) {
|
|
305
|
-
errorCallback(jqxhr,
|
|
325
|
+
errorCallback(jqxhr, jqxhr.responseJSON);
|
|
306
326
|
}
|
|
307
327
|
}
|
|
308
328
|
});
|
package/package.json
CHANGED
package/web_rtc.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
class WebRTC {
|
|
2
|
+
static init (turnSecret, turnUrl, stunUrl) {
|
|
3
|
+
this.turnSecret = turnSecret;
|
|
4
|
+
this.turnUrl = turnUrl;
|
|
5
|
+
this.stunUrl = stunUrl;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
static offer(stream, onICECandidateCallback) {
|
|
9
|
+
return new Promise((resolve, reject) => {
|
|
10
|
+
try {
|
|
11
|
+
let { username, password } = this.getTurnCredentials();
|
|
12
|
+
let peerConn = new RTCPeerConnection(
|
|
13
|
+
{
|
|
14
|
+
iceServers: [
|
|
15
|
+
{ urls: this.turnUrl, username: username, credential: password },
|
|
16
|
+
{ urls: this.stunUrl }
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
stream.getTracks().forEach(track => peerConn.addTrack(track, stream));
|
|
22
|
+
|
|
23
|
+
peerConn.onicecandidate = (event) => onICECandidateCallback(event);
|
|
24
|
+
|
|
25
|
+
peerConn.createOffer()
|
|
26
|
+
.then(sdp => peerConn.setLocalDescription(sdp))
|
|
27
|
+
.then(() => resolve(peerConn));
|
|
28
|
+
} catch (error) {
|
|
29
|
+
reject(error);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static answer (remoteDescription, onTrackCallback, onICECandidateCallback) {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
try {
|
|
37
|
+
let { username, password } = this.getTurnCredentials();
|
|
38
|
+
let peerConn = new RTCPeerConnection(
|
|
39
|
+
{
|
|
40
|
+
iceServers: [
|
|
41
|
+
{ urls: this.turnUrl, username: username, credential: password },
|
|
42
|
+
{ urls: this.stunUrl }
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
peerConn.ontrack = event => onTrackCallback(event);
|
|
48
|
+
peerConn.onicecandidate = event => onICECandidateCallback(event);
|
|
49
|
+
|
|
50
|
+
peerConn.setRemoteDescription(remoteDescription)
|
|
51
|
+
.then(() => peerConn.createAnswer())
|
|
52
|
+
.then(sdp => peerConn.setLocalDescription(sdp))
|
|
53
|
+
.then(() => resolve(peerConn));
|
|
54
|
+
} catch (error) {
|
|
55
|
+
reject(error);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static disconnectPeer(peerConn) {
|
|
61
|
+
if (peerConn) {
|
|
62
|
+
peerConn.onicecandidate = null;
|
|
63
|
+
peerConn.ontrack = null;
|
|
64
|
+
|
|
65
|
+
if (peerConn.signalingState != 'closed') {
|
|
66
|
+
peerConn.getSenders().forEach(sender => peerConn.removeTrack(sender));
|
|
67
|
+
peerConn.close();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
peerConn = null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return peerConn;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/*
|
|
77
|
+
The idea is that WebRTC (or other) clients receive temporary TURN credentials where the user name is comprised of the (Unix)
|
|
78
|
+
expiry timestamp and the password is derived from a secret shared between the service generating those credentials and eturnal.
|
|
79
|
+
The service offering the credentials performs a Base64(HMAC-SHA1($secret, $timestamp)) operation to generate the ephemeral password,
|
|
80
|
+
and eturnal does the same to verify it.
|
|
81
|
+
|
|
82
|
+
https://eturnal.net/documentation/
|
|
83
|
+
https://datatracker.ietf.org/doc/html/draft-uberti-behave-turn-rest-00
|
|
84
|
+
https://stackoverflow.com/questions/35766382/coturn-how-to-use-turn-rest-api
|
|
85
|
+
*/
|
|
86
|
+
static getTurnCredentials() {
|
|
87
|
+
try {
|
|
88
|
+
let crypto = require('crypto');
|
|
89
|
+
let username = String(parseInt(Date.now() / 1000) + 24 * 3600);
|
|
90
|
+
let hmac = crypto.createHmac('sha1', this.turnSecret);
|
|
91
|
+
|
|
92
|
+
hmac.setEncoding('base64');
|
|
93
|
+
hmac.write(username);
|
|
94
|
+
hmac.end();
|
|
95
|
+
|
|
96
|
+
return { username: username, password: hmac.read() };
|
|
97
|
+
} catch(error) {
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
module.exports = { WebRTC };
|
package/.idea/helpers-js.iml
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<module type="WEB_MODULE" version="4">
|
|
3
|
-
<component name="NewModuleRootManager">
|
|
4
|
-
<content url="file://$MODULE_DIR$" />
|
|
5
|
-
<orderEntry type="inheritedJdk" />
|
|
6
|
-
<orderEntry type="sourceFolder" forTests="false" />
|
|
7
|
-
</component>
|
|
8
|
-
</module>
|
package/.idea/modules.xml
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<project version="4">
|
|
3
|
-
<component name="ProjectModuleManager">
|
|
4
|
-
<modules>
|
|
5
|
-
<module fileurl="file://$PROJECT_DIR$/.idea/helpers-js.iml" filepath="$PROJECT_DIR$/.idea/helpers-js.iml" />
|
|
6
|
-
</modules>
|
|
7
|
-
</component>
|
|
8
|
-
</project>
|