Merge remote-tracking branch 'origin/main' into oauth2_additional_params

This commit is contained in:
lohit-bruno
2025-08-13 21:16:16 +05:30
135 changed files with 6301 additions and 1396 deletions

View File

@@ -237,12 +237,47 @@ const parseBruFileMeta = (data) => {
metaJson[key] = isNaN(value) ? value : Number(value);
}
});
return { meta: metaJson };
// Transform to the format expected by bruno-app
let requestType = metaJson.type;
if (requestType === 'http') {
requestType = 'http-request';
} else if (requestType === 'graphql') {
requestType = 'graphql-request';
} else {
requestType = 'http-request';
}
const sequence = metaJson.seq;
const transformedJson = {
type: requestType,
name: metaJson.name,
seq: !isNaN(sequence) ? Number(sequence) : 1,
settings: {},
tags: metaJson.tags || [],
request: {
method: '',
url: '',
params: [],
headers: [],
auth: { mode: 'none' },
body: { mode: 'none' },
script: {},
vars: {},
assertions: [],
tests: '',
docs: ''
}
};
return transformedJson;
} else {
console.log('No "meta" block found in the file.');
return null;
}
} catch (err) {
console.error('Error reading file:', err);
return null;
}
}

View File

@@ -1,197 +1 @@
const { Cookie, CookieJar } = require('tough-cookie');
const each = require('lodash/each');
const moment = require('moment');
const { isPotentiallyTrustworthyOrigin } = require('@usebruno/requests').utils;
const cookieJar = new CookieJar();
const addCookieToJar = (setCookieHeader, requestUrl) => {
const cookie = Cookie.parse(setCookieHeader, { loose: true });
cookieJar.setCookieSync(cookie, requestUrl, {
ignoreError: true // silently ignore things like parse errors and invalid domains
});
};
const getCookiesForUrl = (url) => {
return cookieJar.getCookiesSync(url, {
secure: isPotentiallyTrustworthyOrigin(url)
});
};
const getCookieStringForUrl = (url) => {
const cookies = getCookiesForUrl(url);
if (!Array.isArray(cookies) || !cookies.length) {
return '';
}
const validCookies = cookies.filter((cookie) => !cookie.expires || cookie.expires > Date.now());
return validCookies.map((cookie) => cookie.cookieString()).join('; ');
};
const getDomainsWithCookies = () => {
return new Promise((resolve, reject) => {
const domainCookieMap = {};
cookieJar.store.getAllCookies((err, cookies) => {
if (err) {
return reject(err);
}
cookies.forEach((cookie) => {
if (!domainCookieMap[cookie.domain]) {
domainCookieMap[cookie.domain] = [cookie];
} else {
domainCookieMap[cookie.domain].push(cookie);
}
});
const domains = Object.keys(domainCookieMap);
const domainsWithCookies = [];
each(domains, (domain) => {
const cookies = domainCookieMap[domain];
const validCookies = cookies.filter((cookie) => !cookie.expires || cookie.expires > Date.now());
if (validCookies.length) {
domainsWithCookies.push({
domain,
cookies: validCookies,
cookieString: validCookies.map((cookie) => cookie.cookieString()).join('; ')
});
}
});
resolve(domainsWithCookies);
});
});
};
const deleteCookie = (domain, path, cookieKey) => {
return new Promise((resolve, reject) => {
cookieJar.store.removeCookie(domain, path, cookieKey, (err) => {
if (err) {
return reject(err);
}
return resolve();
});
});
};
const deleteCookiesForDomain = (domain) => {
return new Promise((resolve, reject) => {
cookieJar.store.removeCookies(domain, null, (err) => {
if (err) {
return reject(err);
}
return resolve();
});
});
};
const updateCookieObj = (cookieObj, oldCookie) => {
return {
...cookieObj,
// Preserve immutable properties from old cookie
path: oldCookie.path,
key: oldCookie.key,
domain: oldCookie.domain,
// Handle other mutable properties
expires: cookieObj?.expires && moment(cookieObj.expires).isValid() ? new Date(cookieObj.expires) : Infinity,
creation: oldCookie?.creation && moment(oldCookie.creation).isValid() ? new Date(oldCookie.creation) : new Date(),
lastAccessed:
oldCookie?.lastAccessed && moment(oldCookie.lastAccessed).isValid()
? new Date(oldCookie.lastAccessed)
: new Date()
};
};
const createCookieObj = (cookieObj) => {
return {
...cookieObj,
path: cookieObj.path || '/',
expires: cookieObj?.expires && moment(cookieObj.expires).isValid() ? new Date(cookieObj.expires) : Infinity,
creation: cookieObj?.creation && moment(cookieObj.creation).isValid() ? new Date(cookieObj.creation) : new Date(),
lastAccessed:
cookieObj?.lastAccessed && moment(cookieObj.lastAccessed).isValid()
? new Date(cookieObj.lastAccessed)
: new Date()
};
};
const addCookieForDomain = (domain, cookieObj) => {
return new Promise((resolve, reject) => {
try {
const cookie = new Cookie(createCookieObj(cookieObj));
cookieJar.store.putCookie(cookie, (err) => {
if (err) {
return reject(err);
}
return resolve();
});
} catch (err) {
reject(err);
}
});
};
const modifyCookieForDomain = (domain, oldCookieObj, cookieObj) => {
return new Promise((resolve, reject) => {
try {
const oldCookie = new Cookie(createCookieObj(oldCookieObj));
const newCookie = new Cookie(updateCookieObj(cookieObj, oldCookie));
cookieJar.store.updateCookie(oldCookie, newCookie, (removeErr) => {
if (removeErr) {
return reject(removeErr);
}
return resolve();
});
} catch (err) {
reject(err);
}
});
};
const parseCookieString = (cookieStr) => {
try {
const cookie = Cookie.parse(cookieStr);
if (!cookie) return null;
return {
...cookie,
expires: cookie.expires === Infinity ? null : cookie.expires
};
} catch (err) {
throw new Error(err);
}
};
const createCookieString = (cookieObj) => {
const cookie = new Cookie(createCookieObj(cookieObj));
// cookie.toString() omits the domain
let cookieString = cookie.toString();
// Manually append domain and hostOnly if they exist
if (cookieObj.hostOnly && !cookieString.includes('Domain=')) {
cookieString += `; Domain=${cookieObj.domain}`;
}
return cookieString;
};
module.exports = {
addCookieToJar,
getCookiesForUrl,
getCookieStringForUrl,
getDomainsWithCookies,
deleteCookie,
deleteCookiesForDomain,
addCookieForDomain,
modifyCookieForDomain,
parseCookieString,
createCookieString,
updateCookieObj,
createCookieObj
};
module.exports = require('@usebruno/common').cookies;

View File

@@ -54,11 +54,16 @@ function aes256Decrypt(data) {
return decrypted;
} catch (err) {
// If decryption fails, fall back to old key derivation
const { key: oldKey, iv: oldIv } = deriveKeyAndIv(rawKey, 32, 16);
const decipher = crypto.createDecipheriv('aes-256-cbc', oldKey, oldIv);
let decrypted = decipher.update(data, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
try {
const { key: oldKey, iv: oldIv } = deriveKeyAndIv(rawKey, 32, 16);
const decipher = crypto.createDecipheriv('aes-256-cbc', oldKey, oldIv);
const decrypted = decipher.update(data, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
} catch (fallbackErr) {
console.error('AES256 decryption failed with both methods:', err, fallbackErr);
throw new Error('AES256 decryption failed: ' + fallbackErr.message);
}
}
}
@@ -73,16 +78,21 @@ function safeStorageEncrypt(str) {
return encryptedString;
}
function safeStorageDecrypt(str) {
// Convert the hexadecimal string to a buffer
const encryptedStringBuffer = Buffer.from(str, 'hex');
try {
// Convert the hexadecimal string to a buffer
const encryptedStringBuffer = Buffer.from(str, 'hex');
// Decrypt the buffer
const decryptedStringBuffer = safeStorage.decryptString(encryptedStringBuffer);
// Decrypt the buffer
const decryptedStringBuffer = safeStorage.decryptString(encryptedStringBuffer);
// Convert the decrypted buffer to a string
const decryptedString = decryptedStringBuffer.toString();
// Convert the decrypted buffer to a string
const decryptedString = decryptedStringBuffer.toString();
return decryptedString;
return decryptedString;
} catch (err) {
console.error('SafeStorage decryption failed:', err);
throw new Error('SafeStorage decryption failed: ' + err.message);
}
}
function encryptString(str) {
@@ -142,7 +152,29 @@ function decryptString(str) {
}
}
function decryptStringSafe(str) {
try {
const result = decryptString(str);
return { success: true, value: result };
} catch (err) {
console.error('Decryption failed:', err.message);
return { success: false, error: err.message, value: '' };
}
}
function encryptStringSafe(str) {
try {
const result = encryptString(str);
return { success: true, value: result };
} catch (err) {
console.error('Encryption failed:', err.message);
return { success: false, error: err.message, value: '' };
}
}
module.exports = {
encryptString,
decryptString
encryptStringSafe,
decryptString,
decryptStringSafe
};

View File

@@ -368,6 +368,9 @@ function setupProxyAgents({
{ proxy: https_proxy,...tlsOptions },
timeline
);
} else {
const TimelineHttpsAgent = createTimelineAgentClass(https.Agent);
requestConfig.httpsAgent = new TimelineHttpsAgent(tlsOptions, timeline);
}
} catch (error) {
throw new Error('Invalid system https_proxy');