mirror of
https://github.com/node-red/node-red-nodes.git
synced 2025-03-01 10:37:43 +00:00
188 lines
6.6 KiB
JavaScript
188 lines
6.6 KiB
JavaScript
"use strict";
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.OAuth1Helper = void 0;
|
|
const crypto = __importStar(require("crypto"));
|
|
class OAuth1Helper {
|
|
constructor(options) {
|
|
this.nonceLength = 32;
|
|
this.consumerKeys = options.consumerKeys;
|
|
}
|
|
static percentEncode(str) {
|
|
return encodeURIComponent(str)
|
|
.replace(/!/g, '%21')
|
|
.replace(/\*/g, '%2A')
|
|
.replace(/'/g, '%27')
|
|
.replace(/\(/g, '%28')
|
|
.replace(/\)/g, '%29');
|
|
}
|
|
hash(base, key) {
|
|
return crypto
|
|
.createHmac('sha1', key)
|
|
.update(base)
|
|
.digest('base64');
|
|
}
|
|
authorize(request, accessTokens = {}) {
|
|
const oauthInfo = {
|
|
oauth_consumer_key: this.consumerKeys.key,
|
|
oauth_nonce: this.getNonce(),
|
|
oauth_signature_method: 'HMAC-SHA1',
|
|
oauth_timestamp: this.getTimestamp(),
|
|
oauth_version: '1.0',
|
|
};
|
|
if (accessTokens.key !== undefined) {
|
|
oauthInfo.oauth_token = accessTokens.key;
|
|
}
|
|
if (!request.data) {
|
|
request.data = {};
|
|
}
|
|
oauthInfo.oauth_signature = this.getSignature(request, accessTokens.secret, oauthInfo);
|
|
return oauthInfo;
|
|
}
|
|
toHeader(oauthInfo) {
|
|
const sorted = sortObject(oauthInfo);
|
|
let header_value = 'OAuth ';
|
|
for (const element of sorted) {
|
|
if (element.key.indexOf('oauth_') !== 0) {
|
|
continue;
|
|
}
|
|
header_value += OAuth1Helper.percentEncode(element.key) + '="' + OAuth1Helper.percentEncode(element.value) + '",';
|
|
}
|
|
return {
|
|
// Remove the last ,
|
|
Authorization: header_value.slice(0, header_value.length - 1),
|
|
};
|
|
}
|
|
getNonce() {
|
|
const wordCharacters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
let result = '';
|
|
for (let i = 0; i < this.nonceLength; i++) {
|
|
result += wordCharacters[Math.trunc(Math.random() * wordCharacters.length)];
|
|
}
|
|
return result;
|
|
}
|
|
getTimestamp() {
|
|
return Math.trunc(new Date().getTime() / 1000);
|
|
}
|
|
getSignature(request, tokenSecret, oauthInfo) {
|
|
return this.hash(this.getBaseString(request, oauthInfo), this.getSigningKey(tokenSecret));
|
|
}
|
|
getSigningKey(tokenSecret) {
|
|
return OAuth1Helper.percentEncode(this.consumerKeys.secret) + '&' + OAuth1Helper.percentEncode(tokenSecret || '');
|
|
}
|
|
getBaseString(request, oauthInfo) {
|
|
return request.method.toUpperCase() + '&'
|
|
+ OAuth1Helper.percentEncode(this.getBaseUrl(request.url)) + '&'
|
|
+ OAuth1Helper.percentEncode(this.getParameterString(request, oauthInfo));
|
|
}
|
|
getParameterString(request, oauthInfo) {
|
|
const baseStringData = sortObject(percentEncodeData(mergeObject(oauthInfo, mergeObject(request.data, deParamUrl(request.url)))));
|
|
let dataStr = '';
|
|
for (const { key, value } of baseStringData) {
|
|
// check if the value is an array
|
|
// this means that this key has multiple values
|
|
if (value && Array.isArray(value)) {
|
|
// sort the array first
|
|
value.sort();
|
|
let valString = '';
|
|
// serialize all values for this key: e.g. formkey=formvalue1&formkey=formvalue2
|
|
value.forEach((item, i) => {
|
|
valString += key + '=' + item;
|
|
if (i < value.length) {
|
|
valString += '&';
|
|
}
|
|
});
|
|
dataStr += valString;
|
|
}
|
|
else {
|
|
dataStr += key + '=' + value + '&';
|
|
}
|
|
}
|
|
// Remove the last character
|
|
return dataStr.slice(0, dataStr.length - 1);
|
|
}
|
|
getBaseUrl(url) {
|
|
return url.split('?')[0];
|
|
}
|
|
}
|
|
exports.OAuth1Helper = OAuth1Helper;
|
|
exports.default = OAuth1Helper;
|
|
// Helper functions //
|
|
function mergeObject(obj1, obj2) {
|
|
return {
|
|
...obj1 || {},
|
|
...obj2 || {},
|
|
};
|
|
}
|
|
function sortObject(data) {
|
|
return Object.keys(data)
|
|
.sort()
|
|
.map(key => ({ key, value: data[key] }));
|
|
}
|
|
function deParam(string) {
|
|
const splitted = string.split('&');
|
|
const data = {};
|
|
for (const coupleKeyValue of splitted) {
|
|
const [key, value = ''] = coupleKeyValue.split('=');
|
|
// check if the key already exists
|
|
// this can occur if the QS part of the url contains duplicate keys like this: ?formkey=formvalue1&formkey=formvalue2
|
|
if (data[key]) {
|
|
// the key exists already
|
|
if (!Array.isArray(data[key])) {
|
|
// replace the value with an array containing the already present value
|
|
data[key] = [data[key]];
|
|
}
|
|
// and add the new found value to it
|
|
data[key].push(decodeURIComponent(value));
|
|
}
|
|
else {
|
|
// it doesn't exist, just put the found value in the data object
|
|
data[key] = decodeURIComponent(value);
|
|
}
|
|
}
|
|
return data;
|
|
}
|
|
function deParamUrl(url) {
|
|
const tmp = url.split('?');
|
|
if (tmp.length === 1)
|
|
return {};
|
|
return deParam(tmp[1]);
|
|
}
|
|
function percentEncodeData(data) {
|
|
const result = {};
|
|
for (const key in data) {
|
|
let value = data[key];
|
|
// check if the value is an array
|
|
if (value && Array.isArray(value)) {
|
|
value = value.map(v => OAuth1Helper.percentEncode(v));
|
|
}
|
|
else {
|
|
value = OAuth1Helper.percentEncode(value);
|
|
}
|
|
result[OAuth1Helper.percentEncode(key)] = value;
|
|
}
|
|
return result;
|
|
}
|