@drttix/drt-sdk 1.0.6 → 1.0.7
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.
- package/dist/cjs/src/scripts/generate-definition.js +20 -19
- package/dist/cjs/src/staging/portal.js +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/src/scripts/generate-definition.js +20 -19
- package/dist/esm/src/staging/portal.js +1 -0
- package/package.json +3 -3
- package/scripts/fix-import-extensions.mjs +16 -0
- package/src/scripts/generate-definition.ts +32 -26
- package/src/staging/portal.ts +1 -0
- package/.claude/admin-auth/auth.middleware.ts.txt +0 -149
- package/.claude/admin-auth/superuser.middleware.ts.txt +0 -41
- package/dist/cjs/src/generated/portal/models/BlockedSeatDetail.d.ts +0 -9
- package/dist/cjs/src/generated/portal/models/BlockedSeatDetail.js +0 -2
- package/dist/cjs/src/generated/portal/models/OrderDetail.d.ts +0 -4
- package/dist/cjs/src/generated/portal/models/OrderDetail.js +0 -2
- package/dist/esm/src/generated/portal/models/BlockedSeatDetail.d.ts +0 -9
- package/dist/esm/src/generated/portal/models/BlockedSeatDetail.js +0 -1
- package/dist/esm/src/generated/portal/models/OrderDetail.d.ts +0 -4
- package/dist/esm/src/generated/portal/models/OrderDetail.js +0 -1
|
@@ -13,6 +13,7 @@ if (!serviceName) {
|
|
|
13
13
|
const GENERATED_INDEX = path_1.default.resolve(`src/generated/${serviceName}/index.ts`);
|
|
14
14
|
const GENERATED_TYPES = path_1.default.resolve(`src/generated/${serviceName}/types.ts`);
|
|
15
15
|
const OUTPUT_FILE = path_1.default.resolve(`src/definitions/${serviceName}.ts`);
|
|
16
|
+
const STAGING_OUTPUT_FILE = path_1.default.resolve(`src/staging/${serviceName}.ts`);
|
|
16
17
|
if (!fs_1.default.existsSync(GENERATED_INDEX)) {
|
|
17
18
|
console.error(`❌ File not found: ${GENERATED_INDEX}`);
|
|
18
19
|
process.exit(1);
|
|
@@ -68,27 +69,27 @@ output += `// Re-export all types as a namespace\n`;
|
|
|
68
69
|
output += `export * as ${typesNamespace} from "../generated/${serviceName}/types";\n`;
|
|
69
70
|
fs_1.default.writeFileSync(OUTPUT_FILE, output);
|
|
70
71
|
console.log(`✅ Wrote ${serviceName} definition to: ${OUTPUT_FILE}`);
|
|
71
|
-
|
|
72
|
-
if (serviceName === 'portal') {
|
|
73
|
-
const STAGING_FILE = path_1.default.resolve('src/staging/portal.ts');
|
|
72
|
+
if (serviceName === 'portal' && services.length > 1) {
|
|
74
73
|
const stagingImports = [
|
|
74
|
+
`// AUTO-GENERATED FILE – DO NOT EDIT`,
|
|
75
|
+
`// Staging portal services - wraps all portal services to use staging API`,
|
|
76
|
+
'',
|
|
75
77
|
`import { OpenAPI as PortalOpenAPI } from "../generated/portal/core/OpenAPI";`,
|
|
76
78
|
`import { wrapServiceForStaging, STAGING_URLS } from "./wrapService";`,
|
|
77
|
-
|
|
78
|
-
...services.map((
|
|
79
|
+
'',
|
|
80
|
+
...services.map((service) => `import { ${service} } from "../generated/${serviceName}";`),
|
|
81
|
+
'',
|
|
82
|
+
`const wrap = <T extends object>(service: T) =>`,
|
|
83
|
+
`\twrapServiceForStaging(service, PortalOpenAPI, STAGING_URLS.portal);`,
|
|
84
|
+
'',
|
|
85
|
+
`export const portalStaging = {`,
|
|
86
|
+
...services.map((service) => `\t${service.replace('Service', '').toLowerCase()}: wrap(${service}),`),
|
|
87
|
+
`};`,
|
|
88
|
+
'',
|
|
89
|
+
`// Re-export types`,
|
|
90
|
+
`export * as PortalTypes from "../generated/${serviceName}/types";`,
|
|
91
|
+
'',
|
|
79
92
|
];
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
.join('\n');
|
|
83
|
-
let stagingOutput = `// AUTO-GENERATED FILE – DO NOT EDIT\n\n`;
|
|
84
|
-
stagingOutput += stagingImports.join('\n') + '\n\n';
|
|
85
|
-
stagingOutput += `const wrap = <T extends object>(service: T) =>\n`;
|
|
86
|
-
stagingOutput += `\twrapServiceForStaging(service, PortalOpenAPI, STAGING_URLS.portal);\n\n`;
|
|
87
|
-
stagingOutput += `export const portalStaging = {\n`;
|
|
88
|
-
stagingOutput += stagingKeys + '\n';
|
|
89
|
-
stagingOutput += `};\n\n`;
|
|
90
|
-
stagingOutput += `// Re-export types\n`;
|
|
91
|
-
stagingOutput += `export * as PortalTypes from "../generated/portal/types";\n`;
|
|
92
|
-
fs_1.default.writeFileSync(STAGING_FILE, stagingOutput);
|
|
93
|
-
console.log(`✅ Wrote staging portal definition to: ${STAGING_FILE}`);
|
|
93
|
+
fs_1.default.writeFileSync(STAGING_OUTPUT_FILE, stagingImports.join('\n'));
|
|
94
|
+
console.log(`✅ Wrote ${serviceName} staging definition to: ${STAGING_OUTPUT_FILE}`);
|
|
94
95
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// AUTO-GENERATED FILE – DO NOT EDIT
|
|
3
|
+
// Staging portal services - wraps all portal services to use staging API
|
|
3
4
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
5
|
if (k2 === undefined) k2 = k;
|
|
5
6
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -8,6 +8,7 @@ if (!serviceName) {
|
|
|
8
8
|
const GENERATED_INDEX = path.resolve(`src/generated/${serviceName}/index.ts`);
|
|
9
9
|
const GENERATED_TYPES = path.resolve(`src/generated/${serviceName}/types.ts`);
|
|
10
10
|
const OUTPUT_FILE = path.resolve(`src/definitions/${serviceName}.ts`);
|
|
11
|
+
const STAGING_OUTPUT_FILE = path.resolve(`src/staging/${serviceName}.ts`);
|
|
11
12
|
if (!fs.existsSync(GENERATED_INDEX)) {
|
|
12
13
|
console.error(`❌ File not found: ${GENERATED_INDEX}`);
|
|
13
14
|
process.exit(1);
|
|
@@ -63,27 +64,27 @@ output += `// Re-export all types as a namespace\n`;
|
|
|
63
64
|
output += `export * as ${typesNamespace} from "../generated/${serviceName}/types.js";\n`;
|
|
64
65
|
fs.writeFileSync(OUTPUT_FILE, output);
|
|
65
66
|
console.log(`✅ Wrote ${serviceName} definition to: ${OUTPUT_FILE}`);
|
|
66
|
-
|
|
67
|
-
if (serviceName === 'portal') {
|
|
68
|
-
const STAGING_FILE = path.resolve('src/staging/portal.ts');
|
|
67
|
+
if (serviceName === 'portal' && services.length > 1) {
|
|
69
68
|
const stagingImports = [
|
|
69
|
+
`// AUTO-GENERATED FILE – DO NOT EDIT`,
|
|
70
|
+
`// Staging portal services - wraps all portal services to use staging API`,
|
|
71
|
+
'',
|
|
70
72
|
`import { OpenAPI as PortalOpenAPI } from "../generated/portal/core/OpenAPI.js";`,
|
|
71
73
|
`import { wrapServiceForStaging, STAGING_URLS } from "./wrapService.js";`,
|
|
72
|
-
|
|
73
|
-
...services.map((
|
|
74
|
+
'',
|
|
75
|
+
...services.map((service) => `import { ${service} } from "../generated/${serviceName}.js";`),
|
|
76
|
+
'',
|
|
77
|
+
`const wrap = <T extends object>(service: T) =>`,
|
|
78
|
+
`\twrapServiceForStaging(service, PortalOpenAPI, STAGING_URLS.portal);`,
|
|
79
|
+
'',
|
|
80
|
+
`export const portalStaging = {`,
|
|
81
|
+
...services.map((service) => `\t${service.replace('Service', '').toLowerCase()}: wrap(${service}),`),
|
|
82
|
+
`};`,
|
|
83
|
+
'',
|
|
84
|
+
`// Re-export types`,
|
|
85
|
+
`export * as PortalTypes from "../generated/${serviceName}/types.js";`,
|
|
86
|
+
'',
|
|
74
87
|
];
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
.join('\n');
|
|
78
|
-
let stagingOutput = `// AUTO-GENERATED FILE – DO NOT EDIT\n\n`;
|
|
79
|
-
stagingOutput += stagingImports.join('\n') + '\n\n';
|
|
80
|
-
stagingOutput += `const wrap = <T extends object>(service: T) =>\n`;
|
|
81
|
-
stagingOutput += `\twrapServiceForStaging(service, PortalOpenAPI, STAGING_URLS.portal);\n\n`;
|
|
82
|
-
stagingOutput += `export const portalStaging = {\n`;
|
|
83
|
-
stagingOutput += stagingKeys + '\n';
|
|
84
|
-
stagingOutput += `};\n\n`;
|
|
85
|
-
stagingOutput += `// Re-export types\n`;
|
|
86
|
-
stagingOutput += `export * as PortalTypes from "../generated/portal/types.js";\n`;
|
|
87
|
-
fs.writeFileSync(STAGING_FILE, stagingOutput);
|
|
88
|
-
console.log(`✅ Wrote staging portal definition to: ${STAGING_FILE}`);
|
|
88
|
+
fs.writeFileSync(STAGING_OUTPUT_FILE, stagingImports.join('\n'));
|
|
89
|
+
console.log(`✅ Wrote ${serviceName} staging definition to: ${STAGING_OUTPUT_FILE}`);
|
|
89
90
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// AUTO-GENERATED FILE – DO NOT EDIT
|
|
2
|
+
// Staging portal services - wraps all portal services to use staging API
|
|
2
3
|
import { OpenAPI as PortalOpenAPI } from "../generated/portal/core/OpenAPI.js";
|
|
3
4
|
import { wrapServiceForStaging, STAGING_URLS } from "./wrapService.js";
|
|
4
5
|
import { AccountService } from "../generated/portal/index.js";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drttix/drt-sdk",
|
|
3
3
|
"description": "DRT SDK",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.7",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
7
7
|
"types": "dist/esm/index.d.ts",
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"prepublishOnly": "npx tsx src/scripts/check-version-not-published.ts && npm run build"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@types/node": "^24.
|
|
33
|
+
"@types/node": "^24.12.2",
|
|
34
34
|
"esbuild": "^0.20.0",
|
|
35
35
|
"typescript": "^5.8.3"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@drttix/drt-sdk": "^0.2.
|
|
38
|
+
"@drttix/drt-sdk": "^0.2.91"
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -78,6 +78,22 @@ async function main() {
|
|
|
78
78
|
await fixFile(rootIndex);
|
|
79
79
|
|
|
80
80
|
await walk(root);
|
|
81
|
+
|
|
82
|
+
// Mark the ESM output tree as a module package. The SDK root package
|
|
83
|
+
// stays `type: commonjs` so the CJS build continues to work, but the
|
|
84
|
+
// `exports.import` entry points into `dist/esm/*.js`. Without a nested
|
|
85
|
+
// package.json here, tools like Next treat those `.js` files as CJS and
|
|
86
|
+
// reject the ESM syntax.
|
|
87
|
+
const esmPackageJson = path.resolve(
|
|
88
|
+
process.cwd(),
|
|
89
|
+
'dist/esm/package.json',
|
|
90
|
+
);
|
|
91
|
+
await fs.writeFile(
|
|
92
|
+
esmPackageJson,
|
|
93
|
+
`${JSON.stringify({ type: 'module' }, null, 2)}\n`,
|
|
94
|
+
'utf8',
|
|
95
|
+
);
|
|
96
|
+
|
|
81
97
|
console.log('Done.');
|
|
82
98
|
} catch (err) {
|
|
83
99
|
console.error(err);
|
|
@@ -5,7 +5,7 @@ const [, , serviceName] = process.argv;
|
|
|
5
5
|
|
|
6
6
|
if (!serviceName) {
|
|
7
7
|
console.error(
|
|
8
|
-
'❌ Please provide a service name as an argument (e.g., "shopper")'
|
|
8
|
+
'❌ Please provide a service name as an argument (e.g., "shopper")',
|
|
9
9
|
);
|
|
10
10
|
process.exit(1);
|
|
11
11
|
}
|
|
@@ -13,6 +13,7 @@ if (!serviceName) {
|
|
|
13
13
|
const GENERATED_INDEX = path.resolve(`src/generated/${serviceName}/index.ts`);
|
|
14
14
|
const GENERATED_TYPES = path.resolve(`src/generated/${serviceName}/types.ts`);
|
|
15
15
|
const OUTPUT_FILE = path.resolve(`src/definitions/${serviceName}.ts`);
|
|
16
|
+
const STAGING_OUTPUT_FILE = path.resolve(`src/staging/${serviceName}.ts`);
|
|
16
17
|
|
|
17
18
|
if (!fs.existsSync(GENERATED_INDEX)) {
|
|
18
19
|
console.error(`❌ File not found: ${GENERATED_INDEX}`);
|
|
@@ -37,13 +38,13 @@ const services = exportLines
|
|
|
37
38
|
const typeLines = contents
|
|
38
39
|
.split('\n')
|
|
39
40
|
.filter(
|
|
40
|
-
(line) => line.startsWith('export type {') && line.includes('models')
|
|
41
|
+
(line) => line.startsWith('export type {') && line.includes('models'),
|
|
41
42
|
);
|
|
42
43
|
|
|
43
44
|
const typeExports = typeLines
|
|
44
45
|
.map((line) => {
|
|
45
46
|
const match = line.match(
|
|
46
|
-
/export type { (\w+) } from '\.\/models\/(\w+)'
|
|
47
|
+
/export type { (\w+) } from '\.\/models\/(\w+)'/,
|
|
47
48
|
);
|
|
48
49
|
if (match) {
|
|
49
50
|
return `export type { ${match[1]} } from './models/${match[2]}';`;
|
|
@@ -60,7 +61,7 @@ fs.writeFileSync(GENERATED_TYPES, typesOutput);
|
|
|
60
61
|
console.log(`✅ Wrote types to: ${GENERATED_TYPES}`);
|
|
61
62
|
|
|
62
63
|
const imports = services.map(
|
|
63
|
-
(service) => `import { ${service} } from "../generated/${serviceName}"
|
|
64
|
+
(service) => `import { ${service} } from "../generated/${serviceName}";`,
|
|
64
65
|
);
|
|
65
66
|
|
|
66
67
|
const objectName = serviceName.toLowerCase();
|
|
@@ -88,31 +89,36 @@ output += `export * as ${typesNamespace} from "../generated/${serviceName}/types
|
|
|
88
89
|
fs.writeFileSync(OUTPUT_FILE, output);
|
|
89
90
|
console.log(`✅ Wrote ${serviceName} definition to: ${OUTPUT_FILE}`);
|
|
90
91
|
|
|
91
|
-
|
|
92
|
-
if (serviceName === 'portal') {
|
|
93
|
-
const STAGING_FILE = path.resolve('src/staging/portal.ts');
|
|
94
|
-
|
|
92
|
+
if (serviceName === 'portal' && services.length > 1) {
|
|
95
93
|
const stagingImports = [
|
|
94
|
+
`// AUTO-GENERATED FILE – DO NOT EDIT`,
|
|
95
|
+
`// Staging portal services - wraps all portal services to use staging API`,
|
|
96
|
+
'',
|
|
96
97
|
`import { OpenAPI as PortalOpenAPI } from "../generated/portal/core/OpenAPI";`,
|
|
97
98
|
`import { wrapServiceForStaging, STAGING_URLS } from "./wrapService";`,
|
|
98
|
-
|
|
99
|
-
...services.map(
|
|
99
|
+
'',
|
|
100
|
+
...services.map(
|
|
101
|
+
(service) =>
|
|
102
|
+
`import { ${service} } from "../generated/${serviceName}";`,
|
|
103
|
+
),
|
|
104
|
+
'',
|
|
105
|
+
`const wrap = <T extends object>(service: T) =>`,
|
|
106
|
+
`\twrapServiceForStaging(service, PortalOpenAPI, STAGING_URLS.portal);`,
|
|
107
|
+
'',
|
|
108
|
+
`export const portalStaging = {`,
|
|
109
|
+
...services.map(
|
|
110
|
+
(service) =>
|
|
111
|
+
`\t${service.replace('Service', '').toLowerCase()}: wrap(${service}),`,
|
|
112
|
+
),
|
|
113
|
+
`};`,
|
|
114
|
+
'',
|
|
115
|
+
`// Re-export types`,
|
|
116
|
+
`export * as PortalTypes from "../generated/${serviceName}/types";`,
|
|
117
|
+
'',
|
|
100
118
|
];
|
|
101
119
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
let stagingOutput = `// AUTO-GENERATED FILE – DO NOT EDIT\n\n`;
|
|
107
|
-
stagingOutput += stagingImports.join('\n') + '\n\n';
|
|
108
|
-
stagingOutput += `const wrap = <T extends object>(service: T) =>\n`;
|
|
109
|
-
stagingOutput += `\twrapServiceForStaging(service, PortalOpenAPI, STAGING_URLS.portal);\n\n`;
|
|
110
|
-
stagingOutput += `export const portalStaging = {\n`;
|
|
111
|
-
stagingOutput += stagingKeys + '\n';
|
|
112
|
-
stagingOutput += `};\n\n`;
|
|
113
|
-
stagingOutput += `// Re-export types\n`;
|
|
114
|
-
stagingOutput += `export * as PortalTypes from "../generated/portal/types";\n`;
|
|
115
|
-
|
|
116
|
-
fs.writeFileSync(STAGING_FILE, stagingOutput);
|
|
117
|
-
console.log(`✅ Wrote staging portal definition to: ${STAGING_FILE}`);
|
|
120
|
+
fs.writeFileSync(STAGING_OUTPUT_FILE, stagingImports.join('\n'));
|
|
121
|
+
console.log(
|
|
122
|
+
`✅ Wrote ${serviceName} staging definition to: ${STAGING_OUTPUT_FILE}`,
|
|
123
|
+
);
|
|
118
124
|
}
|
package/src/staging/portal.ts
CHANGED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ForbiddenException,
|
|
3
|
-
Injectable,
|
|
4
|
-
Logger,
|
|
5
|
-
NestMiddleware,
|
|
6
|
-
UnauthorizedException,
|
|
7
|
-
} from '@nestjs/common';
|
|
8
|
-
import { NextFunction, Request, Response } from 'express';
|
|
9
|
-
import { ErrorCode } from '../shared/consts/errorCodes';
|
|
10
|
-
import { EXCEPTION_PATHS, HEADER_STUDIO_KEY } from '../shared/consts/values';
|
|
11
|
-
import { MssqlService } from '../database/mssql/services/mssql.service';
|
|
12
|
-
import { CacheService } from '../shared/service/cache.service';
|
|
13
|
-
import { CommonService } from '../shared/service/common.service';
|
|
14
|
-
import { DRT } from '@drttix/drt-api';
|
|
15
|
-
|
|
16
|
-
@Injectable()
|
|
17
|
-
export class AuthMiddleware implements NestMiddleware {
|
|
18
|
-
constructor(
|
|
19
|
-
private readonly msSqlService: MssqlService,
|
|
20
|
-
private readonly cacheService: CacheService,
|
|
21
|
-
private readonly commonService: CommonService,
|
|
22
|
-
private readonly logger: Logger,
|
|
23
|
-
) {}
|
|
24
|
-
|
|
25
|
-
async use(req: Request, res: Response, next: NextFunction): Promise<void> {
|
|
26
|
-
const headerStudioId = Number(req.headers[HEADER_STUDIO_KEY]);
|
|
27
|
-
|
|
28
|
-
if (!headerStudioId) {
|
|
29
|
-
throw new UnauthorizedException(ErrorCode.MISSING_STUDIO_ID);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const shopperGuidKey =
|
|
33
|
-
this.commonService.formatShopperGuid(headerStudioId);
|
|
34
|
-
|
|
35
|
-
let shopperGuid = req.cookies[shopperGuidKey];
|
|
36
|
-
|
|
37
|
-
if (!shopperGuid) {
|
|
38
|
-
shopperGuid = this.commonService.getFormattedGuid();
|
|
39
|
-
this.logger.log(
|
|
40
|
-
`[Middleware] Generated NEW shopperGuid=${shopperGuid}`,
|
|
41
|
-
);
|
|
42
|
-
} else {
|
|
43
|
-
this.logger.log(
|
|
44
|
-
`[Middleware] Using EXISTING cookie shopperGuid=${shopperGuid}`,
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const clientIp = req.ip as string;
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
await this.msSqlService.checkSession(
|
|
52
|
-
headerStudioId,
|
|
53
|
-
shopperGuid,
|
|
54
|
-
clientIp,
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
// Call is here to seed the session service with the correct session.
|
|
58
|
-
// TODO: Replace this and the above checkSession
|
|
59
|
-
await DRT.session.getSession(shopperGuid, headerStudioId);
|
|
60
|
-
|
|
61
|
-
this.setCookie(res, shopperGuidKey, shopperGuid);
|
|
62
|
-
} catch (error) {
|
|
63
|
-
this.logger.error(error);
|
|
64
|
-
throw new UnauthorizedException(ErrorCode.UNAUTHORIZED);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// If the route is not in the exceptions list, validate the session and permissions
|
|
68
|
-
this.logger.log(
|
|
69
|
-
`[Middleware] req.baseUrl="${req.baseUrl}", req.path="${req.path}", req.originalUrl="${req.originalUrl}"`,
|
|
70
|
-
);
|
|
71
|
-
if (!EXCEPTION_PATHS.includes(req.baseUrl)) {
|
|
72
|
-
const isValidLogin = await this.cacheService.checkStudioLogin(
|
|
73
|
-
shopperGuid,
|
|
74
|
-
Number(headerStudioId),
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
if (!isValidLogin) {
|
|
78
|
-
throw new UnauthorizedException(ErrorCode.INVALID_LOGIN);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const isUserPrimary = await this.msSqlService.getPrimaryStatus(
|
|
82
|
-
shopperGuid,
|
|
83
|
-
Number(headerStudioId),
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
const isValid = await this.validateRoute(
|
|
87
|
-
req.baseUrl,
|
|
88
|
-
req.method,
|
|
89
|
-
shopperGuid,
|
|
90
|
-
isUserPrimary,
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
if (!isValid) {
|
|
94
|
-
throw new ForbiddenException(ErrorCode.FORBIDDEN);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
req.cookies = { [`${shopperGuidKey}`]: shopperGuid };
|
|
99
|
-
next();
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
setCookie(res: Response, key: string, value: string | number): void {
|
|
103
|
-
res.cookie(key, value, {
|
|
104
|
-
httpOnly: true,
|
|
105
|
-
secure: true,
|
|
106
|
-
sameSite: 'lax',
|
|
107
|
-
path: '/',
|
|
108
|
-
// eslint-disable-next-line no-magic-numbers
|
|
109
|
-
maxAge: 60 * 60 * 24,
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async validateRoute(
|
|
114
|
-
currentRoute: string,
|
|
115
|
-
currentMethod: string,
|
|
116
|
-
shopperGuid: string,
|
|
117
|
-
isUserPrimary: number,
|
|
118
|
-
): Promise<boolean> {
|
|
119
|
-
const cachedRoutes = await this.cacheService.getCachedRoutes();
|
|
120
|
-
// Replace numbers in the route with a generic 'id'
|
|
121
|
-
currentRoute = currentRoute.replace(/\d+/g, 'id');
|
|
122
|
-
|
|
123
|
-
const routeMatch = cachedRoutes.find(
|
|
124
|
-
route =>
|
|
125
|
-
route.route === currentRoute && route.method === currentMethod,
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
if (!routeMatch) {
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (routeMatch.primaryUserOnly === 1 && isUserPrimary !== 1) {
|
|
133
|
-
return false;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (routeMatch.rejectOnFail === 0) {
|
|
137
|
-
return true;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const portalObjects =
|
|
141
|
-
await this.cacheService.getUserPermissions(shopperGuid);
|
|
142
|
-
|
|
143
|
-
if (portalObjects.some(item => item.id === routeMatch.portalObjectId)) {
|
|
144
|
-
return true;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ForbiddenException,
|
|
3
|
-
Injectable,
|
|
4
|
-
Logger,
|
|
5
|
-
NestMiddleware,
|
|
6
|
-
} from '@nestjs/common';
|
|
7
|
-
import { NextFunction, Request, Response } from 'express';
|
|
8
|
-
import { MssqlService } from '../database/mssql/services/mssql.service';
|
|
9
|
-
import { ErrorCode } from '../shared/consts/errorCodes';
|
|
10
|
-
import { HEADER_STUDIO_KEY } from '../shared/consts/values';
|
|
11
|
-
import { CommonService } from '../shared/service/common.service';
|
|
12
|
-
|
|
13
|
-
@Injectable()
|
|
14
|
-
export class SuperUserMiddleware implements NestMiddleware {
|
|
15
|
-
constructor(
|
|
16
|
-
private readonly msSqlService: MssqlService,
|
|
17
|
-
private readonly commonService: CommonService,
|
|
18
|
-
private readonly logger: Logger,
|
|
19
|
-
) {}
|
|
20
|
-
|
|
21
|
-
async use(req: Request, res: Response, next: NextFunction): Promise<void> {
|
|
22
|
-
const headerStudioId = Number(req.headers[HEADER_STUDIO_KEY]);
|
|
23
|
-
|
|
24
|
-
const shopperGuidKey =
|
|
25
|
-
this.commonService.formatShopperGuid(headerStudioId);
|
|
26
|
-
|
|
27
|
-
let shopperGuid = req.cookies[shopperGuidKey];
|
|
28
|
-
|
|
29
|
-
const adminDetails =
|
|
30
|
-
await this.msSqlService.getAdminDetails(shopperGuid);
|
|
31
|
-
|
|
32
|
-
if (adminDetails.superuser !== 1) {
|
|
33
|
-
this.logger.log(
|
|
34
|
-
`Unauthorized access attempt to superuser route by shopperGuid: ${shopperGuid} on Studio: ${headerStudioId}`,
|
|
35
|
-
);
|
|
36
|
-
throw new ForbiddenException(ErrorCode.FORBIDDEN);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
next();
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|