1 | "use strict";
|
2 |
|
3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
4 |
|
5 | Object.defineProperty(exports, "__esModule", {
|
6 | value: true
|
7 | });
|
8 | exports["default"] = void 0;
|
9 |
|
10 | var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
11 |
|
12 | var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
|
13 |
|
14 | var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
15 |
|
16 | var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
17 |
|
18 | var _tusJsClient = _interopRequireDefault(require("tus-js-client"));
|
19 |
|
20 | var _resolveUrl = _interopRequireDefault(require("@availity/resolve-url"));
|
21 |
|
22 |
|
23 | var hashCode = function hashCode(str) {
|
24 | var hash = 0;
|
25 | if (str.length === 0) return hash;
|
26 |
|
27 | for (var i = 0; i < str.length; i++) {
|
28 | var _char = str.charCodeAt(i);
|
29 |
|
30 | hash = (hash << 5) - hash + _char;
|
31 |
|
32 |
|
33 | hash = hash & hash;
|
34 | }
|
35 |
|
36 | return hash;
|
37 | };
|
38 |
|
39 | var defaultOptions = {
|
40 | endpoint: '/ms/api/availity/internal/core/vault/upload/v1/resumable',
|
41 | chunkSize: 3e6,
|
42 |
|
43 | removeFingerprintOnSuccess: true,
|
44 | pollingTime: 5000,
|
45 | retryDelays: [0, 1000, 3000, 5000],
|
46 | stripFileNamePathSegments: true,
|
47 | fingerprint: function fingerprint(file) {
|
48 | var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
49 | var callback = arguments.length > 2 ? arguments[2] : undefined;
|
50 | var attributes = [file.name, file.type, file.size, file.lastModified];
|
51 | var attributesKey = 'tus-';
|
52 |
|
53 | for (var i = 0; i < attributes.length; i++) {
|
54 | if (attributes[i]) {
|
55 | attributesKey += "".concat(attributes[i], "-");
|
56 | }
|
57 | }
|
58 |
|
59 | var keys = Object.keys(options.metadata || {}).map(function (key) {
|
60 | return options.metadata[key];
|
61 | });
|
62 | var signature = [attributes.toString().replace(/,/g, ''), options.endpoint, keys].join('');
|
63 | var print = Math.abs(hashCode(signature));
|
64 |
|
65 | if (callback) {
|
66 | return callback(null, "".concat(attributesKey).concat(print));
|
67 | }
|
68 |
|
69 | return "".concat(attributesKey).concat(print);
|
70 | }
|
71 | };
|
72 |
|
73 | var Upload = function () {
|
74 | function Upload(file, options) {
|
75 | var _this = this;
|
76 |
|
77 | (0, _classCallCheck2["default"])(this, Upload);
|
78 |
|
79 | if (!file) {
|
80 | throw new Error('[options.file] must be defined and of type File(s)');
|
81 | }
|
82 |
|
83 | if (!options || !options.bucketId) {
|
84 | throw new Error('[options.bucketId] must be defined');
|
85 | }
|
86 |
|
87 | if (!options.customerId) {
|
88 | throw new Error('[options.customerId] must be defined');
|
89 | }
|
90 |
|
91 | if (!options.clientId) {
|
92 | throw new Error('[options.clientId] must be defined');
|
93 | }
|
94 |
|
95 | this.file = file;
|
96 | this.options = (0, _objectSpread2["default"])({}, defaultOptions, {}, options);
|
97 | this.options.endpoint = (0, _resolveUrl["default"])({
|
98 | relative: this.options.endpoint
|
99 | });
|
100 | this.percentage = 0;
|
101 | this.onError = [];
|
102 | this.onSuccess = [];
|
103 | this.onProgress = [];
|
104 | this.bytesTotal = 0;
|
105 | this.bytesSent = 0;
|
106 | this.bytesScanned = 0;
|
107 | this.errorMessage = null;
|
108 | this.status = 'pending';
|
109 | this.timeoutID = undefined;
|
110 | this.error = null;
|
111 | this.waitForPassword = true;
|
112 | var fileName = this.trimFileName(file.name);
|
113 | var metadata = {
|
114 | 'availity-filename': fileName,
|
115 | 'availity-content-type': file.type,
|
116 | 'availity-attachment-name': 'N/A'
|
117 | };
|
118 | Object.assign(metadata, this.options.metadata);
|
119 | var upload = new _tusJsClient["default"].Upload(this.file, {
|
120 | resume: true,
|
121 | endpoint: "".concat(this.options.endpoint, "/").concat(this.options.bucketId, "/"),
|
122 | chunkSize: this.options.chunkSize,
|
123 | retryDelays: this.options.retryDelays,
|
124 | removeFingerprintOnSuccess: this.options.removeFingerprintOnSuccess,
|
125 | fingerprint: this.options.fingerprint,
|
126 | metadata: metadata,
|
127 | headers: {
|
128 | 'X-XSRF-TOKEN': this.getToken(),
|
129 | 'X-Availity-Customer-ID': this.options.customerId,
|
130 | 'X-Client-ID': this.options.clientId
|
131 | },
|
132 | onError: function onError(err) {
|
133 | _this.setError('rejected', 'Network Error', err);
|
134 |
|
135 | _this.error = err;
|
136 | },
|
137 | onProgress: function onProgress(bytesSent, bytesTotal) {
|
138 | _this.bytesSent = bytesSent;
|
139 | _this.bytesTotal = bytesTotal;
|
140 | _this.percentage = _this.getPercentage();
|
141 |
|
142 | _this.onProgress.forEach(function (cb) {
|
143 | return cb();
|
144 | });
|
145 | },
|
146 | onSuccess: function onSuccess() {
|
147 | var xhr = _this.upload._xhr;
|
148 | _this.bytesScanned = parseInt(xhr.getResponseHeader('AV-Scan-Bytes'), 10) || 0;
|
149 | _this.percentage = _this.getPercentage();
|
150 |
|
151 | var result = _this.getResult(xhr);
|
152 |
|
153 | if (result.status === 'accepted') {
|
154 | _this.percentage = 100;
|
155 | _this.status = result.status;
|
156 | _this.errorMessage = null;
|
157 | var references = xhr.getResponseHeader('references');
|
158 |
|
159 | if (references) {
|
160 | _this.references = JSON.parse(references);
|
161 | }
|
162 |
|
163 | _this.onSuccess.forEach(function (cb) {
|
164 | return cb();
|
165 | });
|
166 |
|
167 | return;
|
168 | }
|
169 |
|
170 | if (result.status === 'rejected') {
|
171 | _this.setError(result.status, result.message);
|
172 |
|
173 | return;
|
174 | }
|
175 |
|
176 | _this.scan();
|
177 | }
|
178 | });
|
179 | this.upload = upload;
|
180 | this.id = this.generateId();
|
181 | }
|
182 |
|
183 | (0, _createClass2["default"])(Upload, [{
|
184 | key: "inStatusCategory",
|
185 | value: function inStatusCategory(status, category) {
|
186 | return status >= category && status < category + 100;
|
187 | }
|
188 | }, {
|
189 | key: "scan",
|
190 | value: function scan(data) {
|
191 | var _this2 = this;
|
192 |
|
193 | clearTimeout(this.timeoutID);
|
194 | var xhr = new window.XMLHttpRequest();
|
195 | xhr.open('HEAD', this.upload.url, true);
|
196 | xhr.setRequestHeader('Tus-Resumable', '1.0.0');
|
197 | xhr.setRequestHeader('X-Client-ID', this.options.clientId);
|
198 | xhr.setRequestHeader('X-Availity-Customer-ID', this.options.customerId);
|
199 | xhr.setRequestHeader('X-XSRF-TOKEN', this.getToken());
|
200 |
|
201 | if (data) {
|
202 | xhr.setRequestHeader(data.header, data.value);
|
203 | }
|
204 |
|
205 |
|
206 | xhr.onload = function () {
|
207 | if (!_this2.inStatusCategory(xhr.status, 200)) {
|
208 | _this2.setError('rejected', "Invalid status returned: ".concat(xhr.status), xhr);
|
209 |
|
210 | return;
|
211 | }
|
212 |
|
213 | _this2.bytesScanned = parseInt(xhr.getResponseHeader('AV-Scan-Bytes'), 10);
|
214 | _this2.percentage = _this2.getPercentage();
|
215 |
|
216 | var result = _this2.getResult(xhr);
|
217 |
|
218 | if (result.status === 'rejected') {
|
219 | _this2.setError(result.status, result.message);
|
220 |
|
221 | return;
|
222 | }
|
223 |
|
224 | if (result.status === 'encrypted') {
|
225 | if (_this2.waitForPassword) {
|
226 | _this2.setError(result.status, result.message);
|
227 |
|
228 | clearTimeout(_this2.timeoutId);
|
229 | return;
|
230 | }
|
231 | }
|
232 |
|
233 | if (result.status === 'accepted') {
|
234 | _this2.percentage = 100;
|
235 | _this2.status = result.status;
|
236 | _this2.errorMessage = null;
|
237 | var references = xhr.getResponseHeader('references');
|
238 |
|
239 | if (references) {
|
240 | _this2.references = JSON.parse(references);
|
241 | }
|
242 |
|
243 | _this2.onSuccess.forEach(function (cb) {
|
244 | return cb();
|
245 | });
|
246 |
|
247 | return;
|
248 | }
|
249 |
|
250 | if (result.status === 'decrypting') {
|
251 | _this2.setError(result.status, result.message);
|
252 | }
|
253 |
|
254 | _this2.onProgress.forEach(function (cb) {
|
255 | return cb();
|
256 | });
|
257 |
|
258 | _this2.timeoutId = setTimeout(function () {
|
259 | _this2.scan();
|
260 | }, _this2.options.pollingTime);
|
261 | };
|
262 |
|
263 |
|
264 | xhr.onerror = function (err) {
|
265 | _this2.setError('rejected', 'Network Error', err);
|
266 |
|
267 | _this2.error = err;
|
268 | };
|
269 |
|
270 | xhr.send(null);
|
271 | }
|
272 | }, {
|
273 | key: "getPercentage",
|
274 | value: function getPercentage() {
|
275 | var processedBytes = this.bytesSent + this.bytesScanned;
|
276 | var combinedTotalBytes = this.bytesTotal * 2;
|
277 | return processedBytes / combinedTotalBytes * 100;
|
278 | }
|
279 | }, {
|
280 | key: "getToken",
|
281 | value: function getToken() {
|
282 | return document.cookie.replace(/(?:(?:^|.*;\s*)XSRF-TOKEN\s*=\s*([^;]*).*$)|^.*$/, '$1');
|
283 | }
|
284 | }, {
|
285 | key: "start",
|
286 | value: function start() {
|
287 | if (!this.isValidFile()) {
|
288 | return;
|
289 | }
|
290 |
|
291 | this.upload.start();
|
292 | }
|
293 | }, {
|
294 | key: "generateId",
|
295 | value: function generateId() {
|
296 | var fingerprint = this.options.fingerprint;
|
297 | return fingerprint(this.file, this.options).replace(/[^a-zA-Z0-9-]/g, '');
|
298 | }
|
299 | }, {
|
300 | key: "fingerprint",
|
301 | value: function fingerprint(file) {
|
302 | var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
303 | var callback = arguments.length > 2 ? arguments[2] : undefined;
|
304 | var attributes = [file.name, file.type, file.size, file.lastModified];
|
305 | var attributesKey = 'tus-';
|
306 |
|
307 | for (var i = 0; i < attributes.length; i++) {
|
308 | if (attributes[i]) {
|
309 | attributesKey += "".concat(attributes[i], "-");
|
310 | }
|
311 | }
|
312 |
|
313 | var keys = Object.keys(options.metadata || {}).map(function (key) {
|
314 | return options.metadata[key];
|
315 | });
|
316 | var signature = [attributes.toString().replace(/,/g, ''), options.endpoint, keys].join('');
|
317 | var print = Math.abs(hashCode(signature));
|
318 |
|
319 | if (callback) {
|
320 | return callback(null, "".concat(attributesKey).concat(print));
|
321 | }
|
322 |
|
323 | return "".concat(attributesKey).concat(print);
|
324 | }
|
325 | }, {
|
326 | key: "sendPassword",
|
327 | value: function sendPassword(pw) {
|
328 | this.waitForPassword = false;
|
329 | this.scan({
|
330 | header: 'Encryption-Password',
|
331 | value: pw
|
332 | });
|
333 | }
|
334 | }, {
|
335 | key: "isValidSize",
|
336 | value: function isValidSize() {
|
337 | if (this.options.maxSize) {
|
338 | if (this.file.size > this.options.maxSize) {
|
339 | this.setError('rejected', 'Document is too large');
|
340 | return false;
|
341 | }
|
342 | }
|
343 |
|
344 | return true;
|
345 | }
|
346 | }, {
|
347 | key: "isAllowedFileTypes",
|
348 | value: function isAllowedFileTypes() {
|
349 | if (this.options.fileTypes) {
|
350 | if (!this.file.name) {
|
351 | return false;
|
352 | }
|
353 |
|
354 | var fileName = this.file.name;
|
355 | var fileExt = fileName.substring(fileName.lastIndexOf('.')).toLowerCase();
|
356 |
|
357 | for (var i = 0; i < this.options.fileTypes.length; i++) {
|
358 | this.options.fileTypes[i] = this.options.fileTypes[i].toLowerCase();
|
359 | }
|
360 |
|
361 | if (this.options.fileTypes.indexOf(fileExt) < 0) {
|
362 | this.setError('rejected', "Document type ".concat(fileExt, " is not allowed"));
|
363 | return false;
|
364 | }
|
365 | }
|
366 |
|
367 | return true;
|
368 | }
|
369 | }, {
|
370 | key: "isAllowedFileNameCharacters",
|
371 | value: function isAllowedFileNameCharacters() {
|
372 | if (this.options.allowedFileNameCharacters) {
|
373 | var fileName = this.file.name.substring(0, this.file.name.lastIndexOf('.'));
|
374 | var regExp = new RegExp("([^".concat(this.options.allowedFileNameCharacters, "])"), 'g');
|
375 |
|
376 | if (fileName && fileName.match(regExp) !== null) {
|
377 | this.setError('rejected', 'File name contains characters not allowed');
|
378 | return false;
|
379 | }
|
380 | }
|
381 |
|
382 | return true;
|
383 | }
|
384 | }, {
|
385 | key: "isValidFile",
|
386 | value: function isValidFile() {
|
387 | return this.isAllowedFileNameCharacters() && this.isAllowedFileTypes() && this.isValidSize();
|
388 | }
|
389 | }, {
|
390 | key: "trimFileName",
|
391 | value: function trimFileName(fileName) {
|
392 | if (this.options.stripFileNamePathSegments) {
|
393 | fileName = fileName.substring(fileName.lastIndexOf('\\') + 1);
|
394 | fileName = fileName.substring(fileName.lastIndexOf('/') + 1);
|
395 | }
|
396 |
|
397 | return fileName;
|
398 | }
|
399 | }, {
|
400 | key: "getResult",
|
401 | value: function getResult(xhr) {
|
402 | var scanResult = xhr.getResponseHeader('AV-Scan-Result');
|
403 | var uploadResult = xhr.getResponseHeader('Upload-Result');
|
404 | var decryptResult = xhr.getResponseHeader('Decryption-Result');
|
405 | var msg = xhr.getResponseHeader('Upload-Message');
|
406 |
|
407 | if (scanResult === 'rejected') {
|
408 | return {
|
409 | status: scanResult,
|
410 | message: msg || 'Failed AV scan'
|
411 | };
|
412 | }
|
413 |
|
414 | if (uploadResult === 'rejected') {
|
415 | this.waitForPassword = true;
|
416 |
|
417 | if (decryptResult === 'rejected') {
|
418 | return {
|
419 | status: uploadResult,
|
420 | message: msg || 'Maximum password attempts reached'
|
421 | };
|
422 | }
|
423 |
|
424 | return {
|
425 | status: uploadResult,
|
426 | message: msg || 'File upload rejected'
|
427 | };
|
428 | }
|
429 |
|
430 | if (uploadResult === 'encrypted') {
|
431 |
|
432 | if (!this.waitForPassword && (decryptResult === null || decryptResult === 'pending')) {
|
433 | return {
|
434 | status: 'decrypting',
|
435 | message: msg || 'Decrypting file'
|
436 | };
|
437 | }
|
438 |
|
439 | if (decryptResult === 'rejected') {
|
440 | this.waitForPassword = true;
|
441 | return {
|
442 | status: uploadResult,
|
443 | message: msg || 'Incorrect password'
|
444 | };
|
445 | }
|
446 |
|
447 | return {
|
448 | status: uploadResult,
|
449 | message: msg || 'Encrypted files require a password'
|
450 | };
|
451 | }
|
452 |
|
453 | if (scanResult === 'accepted' && uploadResult === 'accepted') {
|
454 | return {
|
455 | status: 'accepted',
|
456 | message: msg || ''
|
457 | };
|
458 | }
|
459 |
|
460 | return {
|
461 | status: 'pending',
|
462 | message: msg || ''
|
463 | };
|
464 | }
|
465 | }, {
|
466 | key: "setError",
|
467 | value: function setError(status, message, err) {
|
468 | var _this3 = this;
|
469 |
|
470 | this.status = status;
|
471 |
|
472 | try {
|
473 | this.parseErrorMessage(message, err);
|
474 | } catch (error) {
|
475 |
|
476 | }
|
477 |
|
478 | this.onError.forEach(function (cb) {
|
479 | return cb(err || new Error(_this3.errorMessage));
|
480 | });
|
481 | }
|
482 | }, {
|
483 | key: "parseErrorMessage",
|
484 | value: function parseErrorMessage(message, err) {
|
485 | if (err) {
|
486 | var msg = err.originalRequest.getResponseHeader('Upload-Message');
|
487 |
|
488 | if (!msg) {
|
489 | var temp = err.message.match(/response\Wtext:\W(.*)\)/);
|
490 |
|
491 | if (temp && temp.length === 2) {
|
492 | var _temp = (0, _slicedToArray2["default"])(temp, 2);
|
493 |
|
494 | msg = _temp[1];
|
495 | }
|
496 | }
|
497 |
|
498 | if (!msg) {
|
499 | msg = message;
|
500 | }
|
501 |
|
502 | this.errorMessage = msg;
|
503 | } else {
|
504 | this.errorMessage = message;
|
505 | }
|
506 | }
|
507 | }, {
|
508 | key: "abort",
|
509 | value: function abort() {
|
510 | if (this.upload) {
|
511 | this.upload.abort();
|
512 | }
|
513 | }
|
514 | }]);
|
515 | return Upload;
|
516 | }();
|
517 |
|
518 | var _default = Upload;
|
519 | exports["default"] = _default; |
\ | No newline at end of file |