From fe4885959a617e38f290f052c67b28ac75b37caa Mon Sep 17 00:00:00 2001 From: NosovK Date: Fri, 1 Nov 2024 01:40:04 +0100 Subject: [PATCH 1/6] poc of different providers implementation --- api/fs-provider.js | 38 ++++++++++++++++++++++++++++++++++++++ api/memory-provider.js | 14 ++++++++++++++ api/sendpulse.js | 31 ++++--------------------------- example.js | 9 ++++++--- package.json | 2 +- 5 files changed, 63 insertions(+), 31 deletions(-) create mode 100644 api/fs-provider.js create mode 100644 api/memory-provider.js diff --git a/api/fs-provider.js b/api/fs-provider.js new file mode 100644 index 0000000..9764aa5 --- /dev/null +++ b/api/fs-provider.js @@ -0,0 +1,38 @@ +var fs = require('fs'); +/** + * Create directory + * + * @param directory + */ +function mkdirSyncRecursive(directory) { + var path = directory.replace(/\/$/, '').split('/'); + for (var i = 1; i <= path.length; i++) { + var segment = path.slice(0, i).join('/'); + segment.length > 0 && !fs.existsSync(segment) ? fs.mkdirSync(segment) : null; + } +}; + +class fsProvider { + constructor(path) { + + if (!fs.existsSync(path)) { + mkdirSyncRecursive(path); + } + if (path.substr(-1) !== '/') { + path += '/'; + } + this.path = path; + } + getToken(hashName) { + if (fs.existsSync(this.path + hashName)) { + return fs.readFileSync(this.path + hashName, {encoding: 'utf8'}); + } else { + return ""; + } + } + setToken(hashName, token) { + fs.writeFileSync(this.path + hashName, token); + } +} + +module.exports = fsProvider; \ No newline at end of file diff --git a/api/memory-provider.js b/api/memory-provider.js new file mode 100644 index 0000000..75fbe6b --- /dev/null +++ b/api/memory-provider.js @@ -0,0 +1,14 @@ + +class memoryProvider { + constructor() { + this.store = {}; + } + getToken(hashName) { + return this.store[hashName] || ""; + } + setToken(hashName, token) { + return this.store[hashName] = token; + } +} + +module.exports = memoryProvider; \ No newline at end of file diff --git a/api/sendpulse.js b/api/sendpulse.js index ea5e140..24038c8 100644 --- a/api/sendpulse.js +++ b/api/sendpulse.js @@ -12,12 +12,11 @@ var https = require('https'); var crypto = require('crypto'); -var fs = require('fs'); var API_URL = 'api.sendpulse.com'; var API_USER_ID = ''; var API_SECRET = ''; -var TOKEN_STORAGE = ''; +var TOKEN_STORAGE; var TOKEN = ''; var ERRORS = { @@ -49,18 +48,6 @@ function base64(data) { return b.toString('base64'); } -/** - * Create directory - * - * @param directory - */ -function mkdirSyncRecursive(directory) { - var path = directory.replace(/\/$/, '').split('/'); - for (var i = 1; i <= path.length; i++) { - var segment = path.slice(0, i).join('/'); - segment.length > 0 && !fs.existsSync(segment) ? fs.mkdirSync(segment) : null; - } -}; /** * Sendpulse API initialization @@ -80,18 +67,8 @@ function init(user_id, secret, storage, callback) { } } - if (!fs.existsSync(TOKEN_STORAGE)) { - mkdirSyncRecursive(TOKEN_STORAGE); - } - - if (TOKEN_STORAGE.substr(-1) !== '/') { - TOKEN_STORAGE += '/'; - } - var hashName = md5(API_USER_ID + '::' + API_SECRET); - if (fs.existsSync(TOKEN_STORAGE + hashName)) { - TOKEN = fs.readFileSync(TOKEN_STORAGE + hashName, {encoding: 'utf8'}); - } + TOKEN = TOKEN_STORAGE.getToken(hashName) if (!TOKEN.length) { getToken(callback); @@ -207,9 +184,9 @@ function getToken(callback) { return; } - TOKEN = data.access_token; + TOKEN = data.access_token ?? ""; var hashName = md5(API_USER_ID + '::' + API_SECRET); - fs.writeFileSync(TOKEN_STORAGE + hashName, TOKEN); + TOKEN_STORAGE.setToken(hashName, TOKEN); callback(TOKEN) } } diff --git a/example.js b/example.js index ea9ae42..bc4a87b 100644 --- a/example.js +++ b/example.js @@ -5,7 +5,9 @@ * https://sendpulse.com/api */ -var sendpulse = require("sendpulse-api"); +var sendpulse = require("./api/sendpulse"); +// var memoryProvider = require("./api/memory-provider"); +var fsProvider = require("./api/fs-provider"); /* * https://login.sendpulse.com/settings/#api @@ -14,9 +16,10 @@ var sendpulse = require("sendpulse-api"); var API_USER_ID="USER_ID"; var API_SECRET="USER_SECRET"; -var TOKEN_STORAGE="/tmp/"; +var provider = new fsProvider("./tmp/"); +// var provider = new memoryProvider(); -sendpulse.init(API_USER_ID, API_SECRET, TOKEN_STORAGE, function(token) { +sendpulse.init(API_USER_ID, API_SECRET, provider, function(token) { if (token && token.is_error) { // error handling } diff --git a/package.json b/package.json index 57effaf..5a9ecab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sendpulse-api", - "version": "1.1.7", + "version": "1.1.8", "description": "A simple SendPulse REST client library and example for Node.js", "main": "index.js", "scripts": { From 3c5c4bdcf52d7fe09186db973c3ff156ba2b036d Mon Sep 17 00:00:00 2001 From: NosovK Date: Fri, 1 Nov 2024 02:03:08 +0100 Subject: [PATCH 2/6] add node: to all node modules --- api/fs-provider.js | 2 +- api/sendpulse.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/fs-provider.js b/api/fs-provider.js index 9764aa5..02ba59d 100644 --- a/api/fs-provider.js +++ b/api/fs-provider.js @@ -1,4 +1,4 @@ -var fs = require('fs'); +var fs = require('node:fs'); /** * Create directory * diff --git a/api/sendpulse.js b/api/sendpulse.js index 24038c8..aab24a3 100644 --- a/api/sendpulse.js +++ b/api/sendpulse.js @@ -10,8 +10,8 @@ 'use strict'; -var https = require('https'); -var crypto = require('crypto'); +var https = require('node:https'); +var crypto = require('node:crypto'); var API_URL = 'api.sendpulse.com'; var API_USER_ID = ''; From 3d39e1140fa0132b6a63fea16477c106f1686695 Mon Sep 17 00:00:00 2001 From: Daniyar Date: Sat, 2 Nov 2024 05:57:42 +0500 Subject: [PATCH 3/6] replace https with fetch --- api/sendpulse.js | 90 +++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 55 deletions(-) diff --git a/api/sendpulse.js b/api/sendpulse.js index aab24a3..e1d1205 100644 --- a/api/sendpulse.js +++ b/api/sendpulse.js @@ -10,7 +10,7 @@ 'use strict'; -var https = require('node:https'); +// var https = require('node:https'); var crypto = require('node:crypto'); var API_URL = 'api.sendpulse.com'; @@ -89,76 +89,56 @@ function init(user_id, secret, storage, callback) { * Define the function that will be called * when a response is received. */ -function sendRequest(path, method, data, useToken, callback) { - var headers = {}; - headers['Content-Type'] = 'application/json'; - headers['Content-Length'] = Buffer.byteLength(JSON.stringify(data)); +function sendRequest(path, method = 'POST', data, useToken = false, callback) { + var headers = { + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(JSON.stringify(data)).toString(), + }; if (useToken && TOKEN.length) { headers['Authorization'] = 'Bearer ' + TOKEN; } - if (method === undefined) { - method = 'POST'; - } - if (useToken === undefined) { - useToken = false; - } var options = { - //uri: API_URL, - path: '/' + path, - port: 443, - hostname: API_URL, method: method, headers: headers, + body: JSON.stringify(data), }; - var req = https.request( - options, - function (response) { - var str = ''; - response.on('data', function (chunk) { - str += chunk; - }); - - response.on('end', function () { - try { - var answer = JSON.parse(str); - } catch (ex) { - var answer = returnError(ERRORS.INVALID_RESPONSE); + fetch(`https://${API_URL}/${path}`, options) + .then(response => response.text().then(str => { + let answer; + + try { + answer = JSON.parse(str); + } catch (ex) { + answer = returnError(ERRORS.INVALID_RESPONSE); + } + + if (response.status === 401) { + if (answer.error === 'invalid_client') { + callback(returnError(ERRORS.INVALID_CREDENTIALS)); + return; } - if (response.statusCode === 401) { - if (answer.error === 'invalid_client') { - callback(returnError(ERRORS.INVALID_CREDENTIALS)); + getToken(function (result) { + if (result && result.is_error === 1) { + callback(result); return; } - getToken(function (result) { - if (result && result.is_error === 1) { - callback(result); - return; - } - - sendRequest(path, method, data, true, callback); - }); - return; - } + // Рекурсивно вызываем функцию с useToken = true + sendRequest(path, method, data, true, callback); + }); + return; + } - callback(answer); - }); - } - ); - req.write(JSON.stringify(data)); - req.on('error', function (error) { - if (error.message !== undefined) { - var answer = returnError(error.message, error.errno); - } else { - var answer = returnError(error.code, error.errno); - } - callback(answer); - }); - req.end(); + callback(answer); + })) + .catch(error => { + const answer = error.message ? returnError(error.message, error.errno) : returnError(error.code, error.errno); + callback(answer); + }); } /** From b5d0e9e6617168b2d567a0e137561883e5348fb2 Mon Sep 17 00:00:00 2001 From: Daniyar Date: Sat, 2 Nov 2024 06:42:16 +0500 Subject: [PATCH 4/6] fix exports --- api/fs-provider.js | 51 +++++++++++++++++++++--------------------- api/memory-provider.js | 21 +++++++++-------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/api/fs-provider.js b/api/fs-provider.js index 02ba59d..f9c0f21 100644 --- a/api/fs-provider.js +++ b/api/fs-provider.js @@ -1,38 +1,39 @@ -var fs = require('node:fs'); +var fs = require("node:fs"); /** * Create directory * * @param directory */ function mkdirSyncRecursive(directory) { - var path = directory.replace(/\/$/, '').split('/'); - for (var i = 1; i <= path.length; i++) { - var segment = path.slice(0, i).join('/'); - segment.length > 0 && !fs.existsSync(segment) ? fs.mkdirSync(segment) : null; - } -}; + var path = directory.replace(/\/$/, "").split("/"); + for (var i = 1; i <= path.length; i++) { + var segment = path.slice(0, i).join("/"); + segment.length > 0 && !fs.existsSync(segment) + ? fs.mkdirSync(segment) + : null; + } +} class fsProvider { - constructor(path) { - - if (!fs.existsSync(path)) { - mkdirSyncRecursive(path); - } - if (path.substr(-1) !== '/') { - path += '/'; - } - this.path = path; + constructor(path) { + if (!fs.existsSync(path)) { + mkdirSyncRecursive(path); } - getToken(hashName) { - if (fs.existsSync(this.path + hashName)) { - return fs.readFileSync(this.path + hashName, {encoding: 'utf8'}); - } else { - return ""; - } + if (path.substr(-1) !== "/") { + path += "/"; } - setToken(hashName, token) { - fs.writeFileSync(this.path + hashName, token); + this.path = path; + } + getToken(hashName) { + if (fs.existsSync(this.path + hashName)) { + return fs.readFileSync(this.path + hashName, { encoding: "utf8" }); + } else { + return ""; } + } + setToken(hashName, token) { + fs.writeFileSync(this.path + hashName, token); + } } -module.exports = fsProvider; \ No newline at end of file +exports.fsProvider = fsProvider; diff --git a/api/memory-provider.js b/api/memory-provider.js index 75fbe6b..d532736 100644 --- a/api/memory-provider.js +++ b/api/memory-provider.js @@ -1,14 +1,13 @@ - class memoryProvider { - constructor() { - this.store = {}; - } - getToken(hashName) { - return this.store[hashName] || ""; - } - setToken(hashName, token) { - return this.store[hashName] = token; - } + constructor() { + this.store = {}; + } + getToken(hashName) { + return this.store[hashName] || ""; + } + setToken(hashName, token) { + return (this.store[hashName] = token); + } } -module.exports = memoryProvider; \ No newline at end of file +exports.memoryProvider = memoryProvider; From dba90043c43cce60963bae32a405c0cfa399734a Mon Sep 17 00:00:00 2001 From: Daniyar Date: Sun, 3 Nov 2024 06:22:52 +0500 Subject: [PATCH 5/6] replace md5 with sha256 --- api/sendpulse.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/api/sendpulse.js b/api/sendpulse.js index e1d1205..4893a3e 100644 --- a/api/sendpulse.js +++ b/api/sendpulse.js @@ -10,8 +10,6 @@ 'use strict'; -// var https = require('node:https'); -var crypto = require('node:crypto'); var API_URL = 'api.sendpulse.com'; var API_USER_ID = ''; @@ -26,15 +24,19 @@ var ERRORS = { }; /** - * MD5 + * SHA256 * * @param data * @return string */ -function md5(data) { - var md5sum = crypto.createHash('md5'); - md5sum.update(data); - return md5sum.digest('hex'); +async function sha256(data) { + const encoder = new TextEncoder(); + const dataBuffer = encoder.encode(data); + return crypto.subtle.digest('SHA-256', dataBuffer).then(()=>{ + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); + return hashHex; + }); } /** @@ -67,7 +69,7 @@ function init(user_id, secret, storage, callback) { } } - var hashName = md5(API_USER_ID + '::' + API_SECRET); + var hashName = sha256(API_USER_ID + '::' + API_SECRET); TOKEN = TOKEN_STORAGE.getToken(hashName) if (!TOKEN.length) { @@ -165,7 +167,7 @@ function getToken(callback) { } TOKEN = data.access_token ?? ""; - var hashName = md5(API_USER_ID + '::' + API_SECRET); + var hashName = sha256(API_USER_ID + '::' + API_SECRET); TOKEN_STORAGE.setToken(hashName, TOKEN); callback(TOKEN) } From 6319db2e87db4be1c02f241dcc4625140abe06e0 Mon Sep 17 00:00:00 2001 From: Daniyar Date: Sun, 3 Nov 2024 06:27:31 +0500 Subject: [PATCH 6/6] fix typo --- api/sendpulse.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/sendpulse.js b/api/sendpulse.js index 4893a3e..2af0681 100644 --- a/api/sendpulse.js +++ b/api/sendpulse.js @@ -32,7 +32,7 @@ var ERRORS = { async function sha256(data) { const encoder = new TextEncoder(); const dataBuffer = encoder.encode(data); - return crypto.subtle.digest('SHA-256', dataBuffer).then(()=>{ + return crypto.subtle.digest('SHA-256', dataBuffer).then((hashBuffer)=>{ const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); return hashHex;