@almatar/branding 1.0.0-beta.3.1 → 1.0.0-beta.3.3
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.
|
@@ -22,12 +22,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
22
22
|
exports.BrandIdentifier = void 0;
|
|
23
23
|
const Boom = __importStar(require("@hapi/boom"));
|
|
24
24
|
const BrandManager_1 = require("./BrandManager");
|
|
25
|
+
const url = __importStar(require("url"));
|
|
25
26
|
class BrandIdentifier {
|
|
26
27
|
constructor(type) {
|
|
27
28
|
this.type = type;
|
|
28
29
|
}
|
|
29
30
|
async getBrand(req) {
|
|
31
|
+
var _a;
|
|
30
32
|
const brandManager = new BrandManager_1.BrandManager(this.type);
|
|
33
|
+
// Priority 1: Query parameter brand (super admin override)
|
|
34
|
+
const queryBrand = this.getQueryBrand(req);
|
|
35
|
+
// Troubleshoot logs (keep while integrating across microservices)
|
|
36
|
+
// tslint:disable-next-line no-console
|
|
37
|
+
console.log('[BrandIdentifier] Query brand detection:', {
|
|
38
|
+
'req.query': req === null || req === void 0 ? void 0 : req.query,
|
|
39
|
+
'req.query.brand': (_a = req === null || req === void 0 ? void 0 : req.query) === null || _a === void 0 ? void 0 : _a.brand,
|
|
40
|
+
'req.url': req === null || req === void 0 ? void 0 : req.url,
|
|
41
|
+
'req.originalUrl': req === null || req === void 0 ? void 0 : req.originalUrl,
|
|
42
|
+
'queryBrand (final)': queryBrand,
|
|
43
|
+
});
|
|
44
|
+
if (queryBrand) {
|
|
45
|
+
// tslint:disable-next-line no-console
|
|
46
|
+
console.log('[BrandIdentifier] Using query parameter brand (overriding token brands):', queryBrand);
|
|
47
|
+
// Return as array so ContextNamespace stores it as employeeBrands (used by filters)
|
|
48
|
+
return [queryBrand];
|
|
49
|
+
}
|
|
31
50
|
if (req.headers['x-brand']) {
|
|
32
51
|
// B2C scenario - return the brand from x-brand header
|
|
33
52
|
return brandManager.getB2CBrand(req);
|
|
@@ -36,12 +55,16 @@ class BrandIdentifier {
|
|
|
36
55
|
// Employee/Console scenario - extract from token or x-employee-brands header
|
|
37
56
|
const brand = await brandManager.getConsoleBrands(req);
|
|
38
57
|
if (brand && brand.length > 0) {
|
|
58
|
+
// tslint:disable-next-line no-console
|
|
59
|
+
console.log('[BrandIdentifier] Using console/token brands:', brand);
|
|
39
60
|
return brand;
|
|
40
61
|
}
|
|
41
62
|
// If no brand found but we have authorization, try extracting from token directly
|
|
42
63
|
if (req.headers.authorization) {
|
|
43
64
|
const tokenBrands = brandManager.extractBrandFromToken(req.headers.authorization);
|
|
44
65
|
if (tokenBrands && tokenBrands.length > 0) {
|
|
66
|
+
// tslint:disable-next-line no-console
|
|
67
|
+
console.log('[BrandIdentifier] Using brands extracted directly from token:', tokenBrands);
|
|
45
68
|
return tokenBrands;
|
|
46
69
|
}
|
|
47
70
|
}
|
|
@@ -78,6 +101,29 @@ class BrandIdentifier {
|
|
|
78
101
|
const brandManager = new BrandManager_1.BrandManager(this.type);
|
|
79
102
|
return brandManager.getDefaultBrand();
|
|
80
103
|
}
|
|
104
|
+
getQueryBrand(req) {
|
|
105
|
+
var _a, _b;
|
|
106
|
+
try {
|
|
107
|
+
// Express/NestJS typically populates req.query
|
|
108
|
+
const fromQuery = (_a = req === null || req === void 0 ? void 0 : req.query) === null || _a === void 0 ? void 0 : _a.brand;
|
|
109
|
+
if (typeof fromQuery === 'string' && fromQuery.trim()) {
|
|
110
|
+
return fromQuery.trim();
|
|
111
|
+
}
|
|
112
|
+
// Fallback to parsing URLs if req.query isn't populated yet
|
|
113
|
+
const urlToParse = (req === null || req === void 0 ? void 0 : req.originalUrl) || (req === null || req === void 0 ? void 0 : req.url);
|
|
114
|
+
if (typeof urlToParse === 'string' && urlToParse.includes('?')) {
|
|
115
|
+
const parsedUrl = url.parse(urlToParse, true);
|
|
116
|
+
const parsedBrand = (_b = parsedUrl.query) === null || _b === void 0 ? void 0 : _b.brand;
|
|
117
|
+
if (typeof parsedBrand === 'string' && parsedBrand.trim()) {
|
|
118
|
+
return parsedBrand.trim();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
// ignore - fall back to other brand sources
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
81
127
|
error(message) {
|
|
82
128
|
switch (this.type) {
|
|
83
129
|
case 'hapi':
|
package/lib/lib/Storage.d.ts
CHANGED
package/lib/lib/Storage.js
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
2
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
22
|
const BrandIdentifier_1 = require("./BrandIdentifier");
|
|
23
|
+
const url = __importStar(require("url"));
|
|
4
24
|
const createNamespace = require('cls-hooked').createNamespace;
|
|
5
25
|
const namespaceName = 'request';
|
|
6
26
|
const ns = createNamespace(namespaceName);
|
|
@@ -16,19 +36,52 @@ class ContextNamespace {
|
|
|
16
36
|
});
|
|
17
37
|
}
|
|
18
38
|
static async setEBrand(req, res, next) {
|
|
39
|
+
var _a, _b, _c;
|
|
19
40
|
const brandIdentifier = new BrandIdentifier_1.BrandIdentifier('express');
|
|
20
41
|
const brand = await brandIdentifier.getBrand(req);
|
|
42
|
+
// Check if query parameter brand was used (allows super admin to query specific brand)
|
|
43
|
+
const queryBrand = ContextNamespace.getQueryBrand(req);
|
|
44
|
+
const isQueryParameterBrand = !!queryBrand;
|
|
45
|
+
// Troubleshoot logs (keep while integrating across microservices)
|
|
46
|
+
// tslint:disable-next-line no-console
|
|
47
|
+
console.log('[ContextNamespace] setEBrand request snapshot:', {
|
|
48
|
+
'req.url': req === null || req === void 0 ? void 0 : req.url,
|
|
49
|
+
'req.originalUrl': req === null || req === void 0 ? void 0 : req.originalUrl,
|
|
50
|
+
'req.query': req === null || req === void 0 ? void 0 : req.query,
|
|
51
|
+
'queryBrand (final)': queryBrand,
|
|
52
|
+
'hasAuthorization': !!((_a = req === null || req === void 0 ? void 0 : req.headers) === null || _a === void 0 ? void 0 : _a.authorization),
|
|
53
|
+
'incoming x-brand': (_b = req === null || req === void 0 ? void 0 : req.headers) === null || _b === void 0 ? void 0 : _b['x-brand'],
|
|
54
|
+
'incoming x-employee-brands': (_c = req === null || req === void 0 ? void 0 : req.headers) === null || _c === void 0 ? void 0 : _c['x-employee-brands'],
|
|
55
|
+
});
|
|
21
56
|
// Check if this is a B2C request (x-brand header) - don't set x-employee-brands for B2C
|
|
22
|
-
const isB2CRequest = !!req.headers['x-brand'];
|
|
23
|
-
// Check if this is an employee/console request (authorization token)
|
|
24
|
-
const isEmployeeRequest = !!req.headers.authorization || !!req.headers['x-employee-brands'];
|
|
57
|
+
const isB2CRequest = !!req.headers['x-brand'] && !isQueryParameterBrand;
|
|
58
|
+
// Check if this is an employee/console request (authorization token or query parameter brand)
|
|
59
|
+
const isEmployeeRequest = !!req.headers.authorization || !!req.headers['x-employee-brands'] || isQueryParameterBrand;
|
|
25
60
|
if (Array.isArray(brand)) {
|
|
26
|
-
// Employee/Console scenario with multiple brands
|
|
61
|
+
// Employee/Console scenario with multiple brands (or query parameter brand)
|
|
27
62
|
// tslint:disable-next-line no-console
|
|
28
|
-
console.log('[ContextNamespace] Setting employeeBrands in context:', brand);
|
|
63
|
+
console.log('[ContextNamespace] Setting employeeBrands in context:', brand, isQueryParameterBrand ? '(from query parameter)' : '');
|
|
64
|
+
// IMPORTANT: If query parameter brand is used, clear any existing brand context first
|
|
65
|
+
// This ensures query parameter brand takes absolute priority
|
|
66
|
+
if (isQueryParameterBrand) {
|
|
67
|
+
// Clear any existing brand context to ensure query parameter brand is used
|
|
68
|
+
ns.set('brand', null);
|
|
69
|
+
// tslint:disable-next-line no-console
|
|
70
|
+
console.log('[ContextNamespace] Cleared existing brand context to prioritize query parameter brand');
|
|
71
|
+
}
|
|
72
|
+
// IMPORTANT: Set employeeBrands in context - this is what MongooseModel pre-hooks will read
|
|
29
73
|
ns.set('employeeBrands', brand);
|
|
30
|
-
//
|
|
31
|
-
|
|
74
|
+
// Troubleshoot: verify it was set
|
|
75
|
+
// tslint:disable-next-line no-console
|
|
76
|
+
console.log('[ContextNamespace] employeeBrands in context now:', ns.get('employeeBrands'));
|
|
77
|
+
// If query parameter brand is used with authorization token, always set x-employee-brands header
|
|
78
|
+
if (isQueryParameterBrand && req.headers.authorization && brand.length > 0) {
|
|
79
|
+
req.headers['x-employee-brands'] = brand.join(',');
|
|
80
|
+
// tslint:disable-next-line no-console
|
|
81
|
+
console.log('[ContextNamespace] Set x-employee-brands from query brand (with token):', req.headers['x-employee-brands']);
|
|
82
|
+
}
|
|
83
|
+
else if (isEmployeeRequest && brand.length > 0) {
|
|
84
|
+
// Set x-employee-brands header for employee requests (normal flow)
|
|
32
85
|
req.headers['x-employee-brands'] = brand.join(',');
|
|
33
86
|
// tslint:disable-next-line no-console
|
|
34
87
|
console.log('[ContextNamespace] Setting x-employee-brands header on request:', req.headers['x-employee-brands']);
|
|
@@ -49,10 +102,18 @@ class ContextNamespace {
|
|
|
49
102
|
// tslint:disable-next-line no-console
|
|
50
103
|
console.log('[ContextNamespace] Setting brand in context (Employee):', brand);
|
|
51
104
|
ns.set('brand', brand);
|
|
52
|
-
//
|
|
53
|
-
req.headers
|
|
54
|
-
|
|
55
|
-
|
|
105
|
+
// If query parameter brand is used with authorization token, always set x-employee-brands header
|
|
106
|
+
if (isQueryParameterBrand && req.headers.authorization) {
|
|
107
|
+
req.headers['x-employee-brands'] = brand;
|
|
108
|
+
// tslint:disable-next-line no-console
|
|
109
|
+
console.log('[ContextNamespace] Set x-employee-brands from query brand (with token):', req.headers['x-employee-brands']);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Set x-employee-brands header for employee requests (normal flow)
|
|
113
|
+
req.headers['x-employee-brands'] = brand;
|
|
114
|
+
// tslint:disable-next-line no-console
|
|
115
|
+
console.log('[ContextNamespace] Setting x-employee-brands header on request:', req.headers['x-employee-brands']);
|
|
116
|
+
}
|
|
56
117
|
next();
|
|
57
118
|
}
|
|
58
119
|
else {
|
|
@@ -83,9 +144,16 @@ class ContextNamespace {
|
|
|
83
144
|
});
|
|
84
145
|
}
|
|
85
146
|
static async setHBrand(req, reply) {
|
|
147
|
+
var _a;
|
|
86
148
|
const brandIdentifier = new BrandIdentifier_1.BrandIdentifier('hapi');
|
|
87
149
|
const brand = await brandIdentifier.getBrand(req);
|
|
150
|
+
// Check if query parameter brand was used
|
|
151
|
+
const queryBrand = (_a = req.query) === null || _a === void 0 ? void 0 : _a.brand;
|
|
152
|
+
const isQueryParameterBrand = !!queryBrand;
|
|
88
153
|
if (Array.isArray(brand)) {
|
|
154
|
+
// Employee/Console scenario with multiple brands (or query parameter brand)
|
|
155
|
+
// tslint:disable-next-line no-console
|
|
156
|
+
console.log('[ContextNamespace] Setting employeeBrands in context (Hapi):', brand, isQueryParameterBrand ? '(from query parameter)' : '');
|
|
89
157
|
ns.set('employeeBrands', brand);
|
|
90
158
|
reply();
|
|
91
159
|
}
|
|
@@ -137,5 +205,26 @@ class ContextNamespace {
|
|
|
137
205
|
const brand = (_a = ns.get('brandsList')) === null || _a === void 0 ? void 0 : _a.filter((b) => b.key === brandKey)[0];
|
|
138
206
|
return (_b = brand.products) === null || _b === void 0 ? void 0 : _b.includes(product);
|
|
139
207
|
}
|
|
208
|
+
static getQueryBrand(req) {
|
|
209
|
+
var _a, _b;
|
|
210
|
+
try {
|
|
211
|
+
const fromQuery = (_a = req === null || req === void 0 ? void 0 : req.query) === null || _a === void 0 ? void 0 : _a.brand;
|
|
212
|
+
if (typeof fromQuery === 'string' && fromQuery.trim()) {
|
|
213
|
+
return fromQuery.trim();
|
|
214
|
+
}
|
|
215
|
+
const urlToParse = (req === null || req === void 0 ? void 0 : req.originalUrl) || (req === null || req === void 0 ? void 0 : req.url);
|
|
216
|
+
if (typeof urlToParse === 'string' && urlToParse.includes('?')) {
|
|
217
|
+
const parsedUrl = url.parse(urlToParse, true);
|
|
218
|
+
const parsedBrand = (_b = parsedUrl.query) === null || _b === void 0 ? void 0 : _b.brand;
|
|
219
|
+
if (typeof parsedBrand === 'string' && parsedBrand.trim()) {
|
|
220
|
+
return parsedBrand.trim();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
// ignore
|
|
226
|
+
}
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
140
229
|
}
|
|
141
230
|
exports.default = ContextNamespace;
|
|
@@ -38,6 +38,13 @@ class MongooseModel {
|
|
|
38
38
|
const employeeBrands = Storage_1.default.getEmployeeBrands();
|
|
39
39
|
const brand = Storage_1.default.getBrand();
|
|
40
40
|
const contextBrands = employeeBrands || (brand ? [brand] : null);
|
|
41
|
+
// Troubleshoot logs (keep while integrating across microservices)
|
|
42
|
+
// tslint:disable-next-line no-console
|
|
43
|
+
console.log('[MongooseModel] addPreCondition - Context:', {
|
|
44
|
+
employeeBrands,
|
|
45
|
+
brand,
|
|
46
|
+
contextBrands,
|
|
47
|
+
});
|
|
41
48
|
// Only apply filter if brands are explicitly set (not null/undefined)
|
|
42
49
|
if (contextBrands && contextBrands.length > 0) {
|
|
43
50
|
// Use $in to check if entity's brand is in the user's brands array
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@almatar/branding",
|
|
3
|
-
"version": "1.0.0-beta.3.
|
|
3
|
+
"version": "1.0.0-beta.3.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"typeorm": "^0.3.0",
|
|
42
|
-
"@nestjs/axios": "^4.0.0"
|
|
42
|
+
"@nestjs/axios": "^3.0.0 || ^4.0.0"
|
|
43
43
|
},
|
|
44
44
|
"author": "",
|
|
45
45
|
"license": "ISC",
|