fix: X-Imp-* headers bridge UI→API impersonation + timezone GMT+4

This commit is contained in:
2026-06-11 20:17:07 +04:00
parent d0a0fdc264
commit 68ea44a81d
5 changed files with 50 additions and 14 deletions
+21 -5
View File
@@ -22,7 +22,7 @@ const API_BASE = process.env.API_BASE || 'http://localhost:' + (process.env.PORT
* @param {object} [body] — JSON body (для POST/PATCH)
* @returns {Promise<{status: number, data: any}>}
*/
function apiRequest(method, path, token, body) {
function apiRequest(method, path, token, body, impHeaders) {
return new Promise((resolve, reject) => {
const url = new URL(API_BASE + path);
const lib = url.protocol === 'https:' ? https : http;
@@ -38,6 +38,12 @@ function apiRequest(method, path, token, body) {
'Accept': 'application/json',
},
};
// Проброс контекста имперсонации из UI в API-слой
if (impHeaders) {
if (impHeaders.impEmail) opts.headers['X-Imp-Email'] = impHeaders.impEmail;
if (impHeaders.impOriginalEmail) opts.headers['X-Imp-OriginalEmail'] = impHeaders.impOriginalEmail;
if (impHeaders.impClientId) opts.headers['X-Imp-ClientId'] = impHeaders.impClientId;
}
if (bodyStr) {
opts.headers['Content-Type'] = 'application/json';
opts.headers['Content-Length'] = Buffer.byteLength(bodyStr);
@@ -65,13 +71,23 @@ function apiRequest(method, path, token, body) {
// Хелперы — один вызов на метод
const api = {
get: (path, token) => apiRequest('GET', path, token),
post: (path, token, body) => apiRequest('POST', path, token, body),
patch: (path, token, body) => apiRequest('PATCH', path, token, body),
delete: (path, token) => apiRequest('DELETE', path, token),
get: (path, token, imp) => apiRequest('GET', path, token, null, imp),
post: (path, token, body, imp) => apiRequest('POST', path, token, body, imp),
patch: (path, token, body, imp) => apiRequest('PATCH', path, token, body, imp),
delete: (path, token, imp) => apiRequest('DELETE', path, token, null, imp),
// Достать Bearer из сессии
token: (req) => req.session && req.session.token,
// Построить заголовки имперсонации из req.user (для проброса в API-слой)
impHeaders: (req) => {
if (!req.user || !req.user.isImpersonated) return null;
return {
impEmail: req.user.email,
impOriginalEmail: req.user.originalUserEmail,
impClientId: req.user.activeClientId || req.user.clientId,
};
},
};
module.exports = api;