@sendsafely/sendsafely 1.1.0 → 1.1.2

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.
@@ -0,0 +1,99 @@
1
+ const fetch = require('make-fetch-happen');
2
+ const sjcl = require("sjcl");
3
+ const URL = require('url').URL;
4
+
5
+ function FetchRequest(param) {
6
+ if(!param.hasOwnProperty('signedRequest')) {
7
+ if(typeof param !== 'object') {
8
+ throw new Error('FetchRequest: Invalid parameters');
9
+ }
10
+ if(!param.hasOwnProperty('url')) {
11
+ throw new Error('FetchRequest: url is missing');
12
+ }
13
+ if(!param.hasOwnProperty('apiKey')) {
14
+ throw new Error('FetchRequest: apiKey is missing');
15
+ }
16
+ if(!param.hasOwnProperty('apiKeySecret')) {
17
+ throw new Error('FetchRequest: apiKeySecret is missing');
18
+ }
19
+ }
20
+
21
+ let myself = this;
22
+ myself.url = param.url; // scheme + domain + port for signed request, full url for non signed request
23
+ myself.apiPrefix = '/api/v2.0';
24
+ myself.apiKey = param.apiKey;
25
+ myself.apiKeySecret = param.apiKeySecret;
26
+ myself.requestAPI = param.hasOwnProperty('requestAPI') ? param.requestAPI: 'NODE_API';
27
+ myself.options = {};
28
+
29
+ myself.sendRequest = function (url, options) {
30
+ return fetch(url, options);
31
+ }
32
+
33
+ myself.sendSignedRequest = function (endpoint, data) {
34
+ buildHttpsOptions(endpoint, data);
35
+ return fetch(myself.url + myself.apiPrefix + endpoint.url, myself.options);
36
+ };
37
+
38
+ let buildHttpsOptions = function(endpoint, data) {
39
+ if(typeof endpoint !== 'object') {
40
+ throw new Error('FetchRequest: Invalid endpoint parameters');
41
+ }
42
+ if(!endpoint.hasOwnProperty('url')) {
43
+ throw new Error('FetchRequest: url is missing');
44
+ }
45
+ if(!endpoint.hasOwnProperty('HTTPMethod')) {
46
+ throw new Error('FetchRequest: HTTPMethod is missing');
47
+ }
48
+ if(!endpoint.hasOwnProperty('mimetype')) {
49
+ throw new Error('FetchRequest: mimetype is missing');
50
+ }
51
+
52
+ let timestamp = dateString();
53
+ let signature = myself.apiKey + myself.apiPrefix + endpoint.url.split("?")[0] + timestamp;
54
+ if(endpoint.hasOwnProperty('messageData')) {
55
+ signature += JSON.stringify(endpoint.messageData);
56
+ } else if(data !== '' && data !== null) {
57
+ signature += JSON.stringify(data);
58
+ }
59
+ signature = signMessage(signature);
60
+
61
+ let method = endpoint.HTTPMethod;
62
+ let headers = {
63
+ 'Content-Type': endpoint.mimetype,
64
+ 'ss-api-key':myself.apiKey,
65
+ 'ss-request-timestamp': timestamp,
66
+ 'ss-request-signature': signature,
67
+ 'ss-request-api': myself.requestAPI,
68
+ };
69
+
70
+ let options = {
71
+ headers: headers,
72
+ method: method,
73
+ }
74
+
75
+ if(data !== null) {
76
+ if(endpoint.mimetype.includes('multipart/form-data')) {
77
+ options.headers['Content-Length'] = Buffer.from(data).length;
78
+ options.body = data;
79
+ } else {
80
+ options.body = JSON.stringify(data);
81
+ }
82
+ }
83
+
84
+ myself.options = options;
85
+ }
86
+
87
+
88
+ let dateString = function() {
89
+ let time = new Date().toISOString();
90
+ return time.substr(0, 19) + "+0000";
91
+ }
92
+
93
+ let signMessage = function(messageString) {
94
+ let hmacFunction = new sjcl.misc.hmac(sjcl.codec.utf8String.toBits(myself.apiKeySecret), sjcl.hash.sha256);// Key, Hash
95
+ return sjcl.codec.hex.fromBits(hmacFunction.encrypt(messageString));
96
+ }
97
+ }
98
+
99
+ module.exports = {FetchRequest};
package/FileUtil.js ADDED
@@ -0,0 +1,110 @@
1
+ const fs = require('fs');
2
+ const path = require("path");
3
+
4
+ function FileUtil(param) {
5
+
6
+ if(param === undefined || typeof param !== 'object') {
7
+ throw new Error('FileUtil: Invalid parameters');
8
+ }
9
+
10
+ if(!param.hasOwnProperty('filePath')) {
11
+ throw new Error('FileUtil: filePath is needed');
12
+ }
13
+
14
+ if(!param.hasOwnProperty('callback')) {
15
+ throw new Error('FileUtil: callback is needed');
16
+ }
17
+
18
+ if(param.hasOwnProperty('callback') && typeof param.callback !== 'function') {
19
+ throw new Error('FileUtil: callback must be a function');
20
+ }
21
+
22
+ let myself = this;
23
+ this.SEGMENT_SIZE = 2621440;
24
+ this.filePath = param.filePath;
25
+ this.callback = param.callback;
26
+ this.file = {size: 0, name: '', totalParts: 0};
27
+ this.readableStream = fs.createReadStream(myself.filePath);
28
+ this.reading = false;
29
+ this.eof = false;
30
+ this.data = [];
31
+ this.tempSize = 0;
32
+
33
+ this.init = function() {
34
+ return new Promise(function(resolve) {
35
+ fs.stat(myself.filePath, (err, stats) => {
36
+ if (err) {
37
+ throw new Error('FileUtil: File does not exist, ' + myself.filePath);
38
+ } else {
39
+ myself.file.size = stats.size;
40
+ myself.file.name = path.basename(myself.filePath);
41
+
42
+ if(myself.file.size > (myself.SEGMENT_SIZE/4)) {
43
+ myself.file.totalParts = Math.ceil((myself.file.size-(myself.SEGMENT_SIZE/4))/myself.SEGMENT_SIZE);
44
+ } else {
45
+ myself.file.totalParts = 1;
46
+ }
47
+
48
+ resolve(myself.file);
49
+
50
+ myself.readableStream.on('readable', function() {
51
+ // keep reading chunk until it reaches SEGMENT_SIZE
52
+ if(myself.reading && !myself.eof) {
53
+ processChunk();
54
+ }
55
+ });
56
+
57
+ myself.readableStream.on('end', function() {
58
+ // done reading file
59
+ if(!myself.eof) {
60
+ myself.eof = true;
61
+ callback(true);
62
+ }
63
+ });
64
+ }
65
+ });
66
+
67
+ });
68
+ }
69
+
70
+ this.read = function() {
71
+ if(!myself.reading && !myself.eof) {
72
+ myself.reading = true;
73
+ processChunk();
74
+ }
75
+ }
76
+
77
+ function processChunk() {
78
+ if(myself.tempSize === myself.SEGMENT_SIZE) {
79
+ // callback when data size reaches SEGMENT_SIZE
80
+ callback(false);
81
+ } else {
82
+ let chunk = myself.readableStream.read();
83
+ if(chunk !== null) {
84
+ myself.data.push(new Uint8Array(chunk));
85
+ myself.tempSize += chunk.length;
86
+ }
87
+ }
88
+ }
89
+
90
+ function callback(isComplete) {
91
+ myself.tempSize = 0;
92
+ myself.reading = false;
93
+ myself.callback({data: concatenate(myself.data), complete: isComplete});
94
+ myself.data = [];
95
+ }
96
+
97
+ function concatenate(arrays) {
98
+ var totalLength = arrays.reduce(function(total, arr) {
99
+ return total + arr.length
100
+ }, 0);
101
+ var result = new Uint8Array(totalLength);
102
+ arrays.reduce(function(offset, arr){
103
+ result.set(arr, offset);
104
+ return offset + arr.length;
105
+ }, 0);
106
+ return result;
107
+ }
108
+ }
109
+
110
+ module.exports = {FileUtil};