@autofleet/zehut 3.4.2 → 4.0.0
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/README.md +38 -0
- package/lib/index.cjs +3 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.cts +188 -0
- package/lib/index.d.ts +154 -30
- package/lib/index.js +3 -87
- package/lib/index.js.map +1 -0
- package/package.json +23 -6
- package/lib/app-auth.d.ts +0 -2
- package/lib/app-auth.js +0 -14
- package/lib/authorization.d.ts +0 -8
- package/lib/authorization.js +0 -55
- package/lib/check-permission.d.ts +0 -6
- package/lib/check-permission.js +0 -16
- package/lib/errors.d.ts +0 -5
- package/lib/errors.js +0 -12
- package/lib/exceptions/appDoesNotExist.d.ts +0 -4
- package/lib/exceptions/appDoesNotExist.js +0 -10
- package/lib/secret-getter.d.ts +0 -2
- package/lib/secret-getter.js +0 -30
- package/lib/services.d.ts +0 -3
- package/lib/services.js +0 -27
- package/lib/tracer.d.ts +0 -21
- package/lib/tracer.js +0 -73
- package/lib/user/ApiUser.d.ts +0 -48
- package/lib/user/ApiUser.js +0 -187
- package/lib/user/index.d.ts +0 -27
- package/lib/user/index.js +0 -196
- package/lib/utils.d.ts +0 -8
- package/lib/utils.js +0 -103
package/lib/user/ApiUser.js
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.CONTEXTS_IDS_HEADER = exports.ELEVATED_PERMISSIONS_HEADER = void 0;
|
|
7
|
-
const node_cache_1 = __importDefault(require("node-cache"));
|
|
8
|
-
const object_hash_1 = __importDefault(require("object-hash"));
|
|
9
|
-
const outbreak_1 = require("@autofleet/outbreak");
|
|
10
|
-
const utils_1 = require("../utils");
|
|
11
|
-
const services_1 = require("../services");
|
|
12
|
-
exports.ELEVATED_PERMISSIONS_HEADER = 'x-af-elevated-permissions';
|
|
13
|
-
exports.CONTEXTS_IDS_HEADER = 'x-af-context-ids';
|
|
14
|
-
const userCache = new node_cache_1.default({ stdTTL: 10 });
|
|
15
|
-
const mergePermissions = (target, sources) => {
|
|
16
|
-
const permissions = {
|
|
17
|
-
...target,
|
|
18
|
-
fleets: { ...target?.fleets },
|
|
19
|
-
businessModels: { ...target?.businessModels },
|
|
20
|
-
demandSources: { ...target?.demandSources },
|
|
21
|
-
// Clone other nested objects as needed
|
|
22
|
-
};
|
|
23
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
24
|
-
for (const source of sources) {
|
|
25
|
-
Object.keys(source).forEach((entityType) => {
|
|
26
|
-
// eslint-disable-next-line no-param-reassign
|
|
27
|
-
permissions[entityType] ?? (permissions[entityType] = {});
|
|
28
|
-
Object.entries(source[entityType]).forEach(([entityId, perms]) => {
|
|
29
|
-
// eslint-disable-next-line no-param-reassign
|
|
30
|
-
permissions[entityType][entityId] = (permissions[entityType][entityId] || []).concat(perms);
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
return permissions;
|
|
35
|
-
};
|
|
36
|
-
class ApiUser {
|
|
37
|
-
constructor(id, accountType, elevatedPermissions, contextIds) {
|
|
38
|
-
this.id = id;
|
|
39
|
-
this.accountType = accountType;
|
|
40
|
-
this.contextIds = contextIds;
|
|
41
|
-
this.privateElevatedPermissionsHash = new Map();
|
|
42
|
-
this.appPermission = {};
|
|
43
|
-
this.emptyUser = !!id;
|
|
44
|
-
if (elevatedPermissions) {
|
|
45
|
-
this.privateElevatedPermissionsHash.set(Symbol('initial'), elevatedPermissions);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
async getUserPermissions() {
|
|
49
|
-
if (!this.id) {
|
|
50
|
-
return undefined;
|
|
51
|
-
}
|
|
52
|
-
if (this.privatePermissions) {
|
|
53
|
-
return this.privatePermissions;
|
|
54
|
-
}
|
|
55
|
-
const cacheKey = (0, object_hash_1.default)({
|
|
56
|
-
id: this.id,
|
|
57
|
-
contextIds: this.contextIds,
|
|
58
|
-
});
|
|
59
|
-
let data = userCache.get(cacheKey);
|
|
60
|
-
if (!data) {
|
|
61
|
-
({ data } = await services_1.IdentityNetwork.get(`/api/v1/users/${this.id}/authorization-payload`, { params: { contextIds: this.contextIds } }));
|
|
62
|
-
userCache.set(cacheKey, data);
|
|
63
|
-
}
|
|
64
|
-
this.accountType = data.accountType;
|
|
65
|
-
this.privatePermissions = data;
|
|
66
|
-
return this.privatePermissions;
|
|
67
|
-
}
|
|
68
|
-
async useCustomPermissionLoader(customPermissionLoader) {
|
|
69
|
-
if (!this.id) {
|
|
70
|
-
return undefined;
|
|
71
|
-
}
|
|
72
|
-
if (this.privatePermissions) {
|
|
73
|
-
return this.privatePermissions;
|
|
74
|
-
}
|
|
75
|
-
const cacheKey = this.id;
|
|
76
|
-
const cachedResult = userCache.get(cacheKey);
|
|
77
|
-
if (cachedResult) {
|
|
78
|
-
this.privatePermissions = cachedResult;
|
|
79
|
-
return cachedResult;
|
|
80
|
-
}
|
|
81
|
-
const data = await customPermissionLoader(this.id);
|
|
82
|
-
userCache.set(cacheKey, data);
|
|
83
|
-
this.privatePermissions = data;
|
|
84
|
-
return this.privatePermissions;
|
|
85
|
-
}
|
|
86
|
-
get businessModels() {
|
|
87
|
-
return this.getUserProperty('businessModels');
|
|
88
|
-
}
|
|
89
|
-
get fleets() {
|
|
90
|
-
return this.getUserProperty('fleets');
|
|
91
|
-
}
|
|
92
|
-
get demandSources() {
|
|
93
|
-
return this.getUserProperty('demandSources');
|
|
94
|
-
}
|
|
95
|
-
getUserProperty(key) {
|
|
96
|
-
if (!this.privatePermissions) {
|
|
97
|
-
throw new Error(`Cannot get ${key} without calling (async) getUserPermissions before`);
|
|
98
|
-
}
|
|
99
|
-
return Object.keys(this.privatePermissions[key] || {});
|
|
100
|
-
}
|
|
101
|
-
get elevatedPermissions() {
|
|
102
|
-
return mergePermissions(undefined, this.privateElevatedPermissionsHash.values());
|
|
103
|
-
}
|
|
104
|
-
get permissions() {
|
|
105
|
-
if (!this.privatePermissions) {
|
|
106
|
-
throw new Error('Cannot get permissions without calling (async) getUserPermissions before');
|
|
107
|
-
}
|
|
108
|
-
return mergePermissions(this.privatePermissions, this.privateElevatedPermissionsHash.values());
|
|
109
|
-
}
|
|
110
|
-
elevatePermissions(addedPermissions) {
|
|
111
|
-
// @itayankri is concerned about memory consumption, so create a symbol with no description, to avoid assigning memory for the description string
|
|
112
|
-
// eslint-disable-next-line symbol-description
|
|
113
|
-
const elevationId = Symbol();
|
|
114
|
-
// Validate that the added permissions are valid UUIDs
|
|
115
|
-
Object.values(addedPermissions).forEach((entityIds) => {
|
|
116
|
-
Object.keys(entityIds).forEach((entityId) => {
|
|
117
|
-
if (!(0, utils_1.validateUUID)(entityId)) {
|
|
118
|
-
throw new Error(`Entity id on elevatePermissions is not a valid UUID, provided: ${entityId}`);
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
const currentUserTrace = (0, outbreak_1.getCurrentContext)();
|
|
123
|
-
if (!currentUserTrace) {
|
|
124
|
-
throw new Error('Cannot find current user cross services trace');
|
|
125
|
-
}
|
|
126
|
-
const currentElevation = JSON.parse(currentUserTrace.context[exports.ELEVATED_PERMISSIONS_HEADER] || '{}');
|
|
127
|
-
const newElevation = Object.assign(currentElevation, addedPermissions);
|
|
128
|
-
this.privateElevatedPermissionsHash.set(elevationId, newElevation);
|
|
129
|
-
currentUserTrace.context.set(exports.ELEVATED_PERMISSIONS_HEADER, JSON.stringify(this.elevatedPermissions));
|
|
130
|
-
return () => {
|
|
131
|
-
this.privateElevatedPermissionsHash.delete(elevationId);
|
|
132
|
-
currentUserTrace.context.set(exports.ELEVATED_PERMISSIONS_HEADER, JSON.stringify(this.elevatedPermissions));
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
async getUserPermissionsLegacy() {
|
|
136
|
-
if (!this.id) {
|
|
137
|
-
return undefined;
|
|
138
|
-
}
|
|
139
|
-
if (this.privatePermissionsLegacy) {
|
|
140
|
-
return this.privatePermissionsLegacy;
|
|
141
|
-
}
|
|
142
|
-
const cacheKey = (0, object_hash_1.default)({
|
|
143
|
-
id: this.id,
|
|
144
|
-
contextIds: this.contextIds,
|
|
145
|
-
legacy: true,
|
|
146
|
-
});
|
|
147
|
-
let data = userCache.get(cacheKey);
|
|
148
|
-
if (!data) {
|
|
149
|
-
({ data } = await services_1.IdentityNetwork.get(`/api/v1/users/${this.id}/authorization-payload-legacy`, { params: { contextIds: this.contextIds } }));
|
|
150
|
-
userCache.set(cacheKey, data);
|
|
151
|
-
}
|
|
152
|
-
this.privatePermissionsLegacy = data;
|
|
153
|
-
return this.privatePermissionsLegacy;
|
|
154
|
-
}
|
|
155
|
-
get permissionsLegacy() {
|
|
156
|
-
if (!this.privatePermissionsLegacy) {
|
|
157
|
-
throw new Error('Cannot get permissionsLegacy without calling (async) getUserPermissionsLegacy before');
|
|
158
|
-
}
|
|
159
|
-
return this.privatePermissionsLegacy;
|
|
160
|
-
}
|
|
161
|
-
async getUserAppPermissions(appId, clientSecret) {
|
|
162
|
-
if (!this.id || !appId || !clientSecret) {
|
|
163
|
-
return undefined;
|
|
164
|
-
}
|
|
165
|
-
const currentAppPermission = this.appPermission[appId];
|
|
166
|
-
if (currentAppPermission) {
|
|
167
|
-
return currentAppPermission;
|
|
168
|
-
}
|
|
169
|
-
const cacheKey = `${this.id}:${appId}`;
|
|
170
|
-
const cachedResult = userCache.get(cacheKey);
|
|
171
|
-
if (cachedResult) {
|
|
172
|
-
this.appPermission[appId] = cachedResult;
|
|
173
|
-
return cachedResult;
|
|
174
|
-
}
|
|
175
|
-
const { data } = await services_1.AutofleetApiNetwork.post(`/api/v1/apps/${appId}/get-user-payload`, {
|
|
176
|
-
userId: this.id,
|
|
177
|
-
}, {
|
|
178
|
-
headers: {
|
|
179
|
-
'x-autofleet-apps-secret': clientSecret,
|
|
180
|
-
},
|
|
181
|
-
});
|
|
182
|
-
userCache.set(cacheKey, data);
|
|
183
|
-
this.appPermission[appId] = data;
|
|
184
|
-
return this.appPermission[appId];
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
exports.default = ApiUser;
|
package/lib/user/index.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { Handler, Request } from 'express';
|
|
2
|
-
import ApiUser, { CustomPermissionLoader } from './ApiUser';
|
|
3
|
-
import { newTrace } from '../tracer';
|
|
4
|
-
export declare const USER_OBJECT = "userObject";
|
|
5
|
-
declare module 'express-serve-static-core' {
|
|
6
|
-
interface Request {
|
|
7
|
-
user: ApiUser;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
export declare const middleware: (options?: {
|
|
11
|
-
eagerLoadUserPermissions?: boolean;
|
|
12
|
-
eagerLoadUserPermissionsLegacy?: boolean;
|
|
13
|
-
customPermissionLoader?: CustomPermissionLoader;
|
|
14
|
-
}) => Handler;
|
|
15
|
-
export declare const middlewareWithDecode: (options?: {
|
|
16
|
-
eagerLoadUserPermissions?: boolean;
|
|
17
|
-
eagerLoadUserPermissionsLegacy?: boolean;
|
|
18
|
-
returnErrorIfNoToken?: boolean;
|
|
19
|
-
}) => Handler;
|
|
20
|
-
export declare const appMiddleware: (options: {
|
|
21
|
-
appId: string;
|
|
22
|
-
clientSecret: string;
|
|
23
|
-
}) => Handler;
|
|
24
|
-
export declare const eagerLoadPermissionsMiddleware: Handler;
|
|
25
|
-
export declare const getDecodedBearer: (req: Request) => any;
|
|
26
|
-
export declare const createOrSetRabbitTrace: (trace: ReturnType<typeof newTrace> | undefined, userId: string | undefined) => Promise<void>;
|
|
27
|
-
export default ApiUser;
|
package/lib/user/index.js
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.createOrSetRabbitTrace = exports.getDecodedBearer = exports.eagerLoadPermissionsMiddleware = exports.appMiddleware = exports.middlewareWithDecode = exports.middleware = exports.USER_OBJECT = void 0;
|
|
30
|
-
const jsonwebtoken_1 = require("jsonwebtoken");
|
|
31
|
-
const ApiUser_1 = __importStar(require("./ApiUser"));
|
|
32
|
-
const tracer_1 = require("../tracer");
|
|
33
|
-
const app_auth_1 = require("../app-auth");
|
|
34
|
-
const appDoesNotExist_1 = __importDefault(require("../exceptions/appDoesNotExist"));
|
|
35
|
-
const utils_1 = require("../utils");
|
|
36
|
-
const IDENTITY_MS = 'identity-ms';
|
|
37
|
-
const ACCESS_TOKEN = 'accessToken';
|
|
38
|
-
exports.USER_OBJECT = 'userObject';
|
|
39
|
-
const USER_TRACING_HEADER = 'x-af-user-id';
|
|
40
|
-
const ORIGIN_HEADER = 'X-IAF-ORIGIN-SERVICE';
|
|
41
|
-
const USER_PERMISSIONS_HEADER = 'x-af-user-permissions';
|
|
42
|
-
const LOWER_CASE_ORIGIN_HEADER = ORIGIN_HEADER.toLowerCase();
|
|
43
|
-
const AUTOFLEET_APPS_SECRET_HEADER = 'x-autofleet-apps-secret';
|
|
44
|
-
const middleware = (options = {}) => async (req, res, next) => {
|
|
45
|
-
try {
|
|
46
|
-
const originHeader = (req.headers[ORIGIN_HEADER] || req.headers[LOWER_CASE_ORIGIN_HEADER] || '');
|
|
47
|
-
if (originHeader.toLowerCase() === IDENTITY_MS) {
|
|
48
|
-
next();
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
const { eagerLoadUserPermissions, eagerLoadUserPermissionsLegacy, customPermissionLoader, } = options;
|
|
52
|
-
const userId = req.headers[USER_TRACING_HEADER];
|
|
53
|
-
const trace = (0, tracer_1.newTrace)('userPayload');
|
|
54
|
-
if (!userId) {
|
|
55
|
-
next();
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
const elevatedPermissionsFromHeader = req.headers[ApiUser_1.ELEVATED_PERMISSIONS_HEADER] && req.headers[ApiUser_1.ELEVATED_PERMISSIONS_HEADER].length > 0
|
|
59
|
-
? JSON.parse(req.headers[ApiUser_1.ELEVATED_PERMISSIONS_HEADER])
|
|
60
|
-
: {};
|
|
61
|
-
const contextIds = req.headers?.[ApiUser_1.CONTEXTS_IDS_HEADER]?.split(',');
|
|
62
|
-
const userObject = new ApiUser_1.default(userId, 'user', elevatedPermissionsFromHeader, contextIds);
|
|
63
|
-
if (eagerLoadUserPermissions) {
|
|
64
|
-
if (customPermissionLoader) {
|
|
65
|
-
await userObject.useCustomPermissionLoader(customPermissionLoader);
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
await userObject.getUserPermissions();
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (eagerLoadUserPermissionsLegacy) {
|
|
72
|
-
await userObject.getUserPermissionsLegacy();
|
|
73
|
-
}
|
|
74
|
-
req.user = userObject;
|
|
75
|
-
trace.context.set(exports.USER_OBJECT, userObject);
|
|
76
|
-
// Added in order to support outbreak.
|
|
77
|
-
// @ts-expect-error we are setting an object onto the request headers.
|
|
78
|
-
req.headers[USER_PERMISSIONS_HEADER] = userObject;
|
|
79
|
-
next();
|
|
80
|
-
}
|
|
81
|
-
catch (e) {
|
|
82
|
-
res.status(401).json({ error: 'cannot authenticate user' });
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
exports.middleware = middleware;
|
|
86
|
-
const middlewareWithDecode = (options = {}) => async (req, res, next) => {
|
|
87
|
-
const { eagerLoadUserPermissions, eagerLoadUserPermissionsLegacy, returnErrorIfNoToken, } = options;
|
|
88
|
-
const trace = (0, tracer_1.newTrace)('userPayload');
|
|
89
|
-
let decoded;
|
|
90
|
-
if (req.headers.authorization) {
|
|
91
|
-
try {
|
|
92
|
-
decoded = await (0, utils_1.decodeBearer)(req.headers.authorization);
|
|
93
|
-
}
|
|
94
|
-
catch (e) {
|
|
95
|
-
if (e instanceof jsonwebtoken_1.TokenExpiredError) {
|
|
96
|
-
res.status(401).json({ errors: ['Access token expired'] });
|
|
97
|
-
}
|
|
98
|
-
else if (e instanceof jsonwebtoken_1.JsonWebTokenError) {
|
|
99
|
-
res.status(400).json({ errors: [e.message] });
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
res.status(500).json({ errors: ['Server error while parsing token'] });
|
|
103
|
-
}
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
const userId = decoded?.user?.id;
|
|
107
|
-
if (userId) {
|
|
108
|
-
req.headers[USER_TRACING_HEADER] = userId;
|
|
109
|
-
}
|
|
110
|
-
const contextIds = req.headers?.[ApiUser_1.CONTEXTS_IDS_HEADER]?.split(',');
|
|
111
|
-
const userObject = new ApiUser_1.default(userId, decoded?.user?.accountType, undefined, contextIds);
|
|
112
|
-
if (eagerLoadUserPermissions || eagerLoadUserPermissionsLegacy) {
|
|
113
|
-
await Promise.all([
|
|
114
|
-
eagerLoadUserPermissions && userObject.getUserPermissions(),
|
|
115
|
-
eagerLoadUserPermissionsLegacy && userObject.getUserPermissionsLegacy(),
|
|
116
|
-
]);
|
|
117
|
-
}
|
|
118
|
-
req.user = userObject;
|
|
119
|
-
trace.context.set(exports.USER_OBJECT, userObject);
|
|
120
|
-
// Added in order to support outbreak.
|
|
121
|
-
// @ts-expect-error we are setting an object onto the request headers.
|
|
122
|
-
req.headers[USER_PERMISSIONS_HEADER] = userObject;
|
|
123
|
-
}
|
|
124
|
-
else if (returnErrorIfNoToken) {
|
|
125
|
-
res.status(401).json({ errors: ['No token provided'] });
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
next();
|
|
129
|
-
};
|
|
130
|
-
exports.middlewareWithDecode = middlewareWithDecode;
|
|
131
|
-
const appMiddleware = (options) => async (req, res, next) => {
|
|
132
|
-
const { appId, clientSecret, } = options;
|
|
133
|
-
const trace = (0, tracer_1.newTrace)('userPayload');
|
|
134
|
-
let decoded;
|
|
135
|
-
if (!req.headers.authorization) {
|
|
136
|
-
res.status(401).json({ errors: ['No token provided'] });
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
try {
|
|
140
|
-
decoded = await (0, app_auth_1.decodeAppBearer)(req.headers.authorization, appId);
|
|
141
|
-
if (!decoded) {
|
|
142
|
-
throw new appDoesNotExist_1.default();
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
catch (e) {
|
|
146
|
-
if (e instanceof jsonwebtoken_1.TokenExpiredError) {
|
|
147
|
-
res.status(401).json({ errors: ['Access token expired'] });
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
if ([jsonwebtoken_1.JsonWebTokenError, appDoesNotExist_1.default].some((Err) => e instanceof Err)) {
|
|
151
|
-
res.status(400).json({ errors: [e.message] });
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
res.status(500).json({ errors: ['Server error while parsing token'] });
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
const userId = decoded?.userId;
|
|
158
|
-
if (userId) {
|
|
159
|
-
req.headers[USER_TRACING_HEADER] = userId;
|
|
160
|
-
}
|
|
161
|
-
const userObject = new ApiUser_1.default(userId);
|
|
162
|
-
if (appId) {
|
|
163
|
-
req.headers[AUTOFLEET_APPS_SECRET_HEADER] = clientSecret;
|
|
164
|
-
// Won't work until we find a better solution for identity ms
|
|
165
|
-
await userObject.getUserAppPermissions(appId, clientSecret);
|
|
166
|
-
}
|
|
167
|
-
req.user = userObject;
|
|
168
|
-
trace.context.set(exports.USER_OBJECT, userObject);
|
|
169
|
-
trace.context.set(ACCESS_TOKEN, (0, utils_1.getAuthFromBearer)(req.headers.authorization));
|
|
170
|
-
// Added in order to support outbreak.
|
|
171
|
-
// @ts-expect-error we are setting an object onto the request headers.
|
|
172
|
-
req.headers[USER_PERMISSIONS_HEADER] = userObject;
|
|
173
|
-
next();
|
|
174
|
-
};
|
|
175
|
-
exports.appMiddleware = appMiddleware;
|
|
176
|
-
const eagerLoadPermissionsMiddleware = async (req, res, next) => {
|
|
177
|
-
await req.user.getUserPermissions();
|
|
178
|
-
next();
|
|
179
|
-
};
|
|
180
|
-
exports.eagerLoadPermissionsMiddleware = eagerLoadPermissionsMiddleware;
|
|
181
|
-
const getDecodedBearer = (req) => {
|
|
182
|
-
if (!req.headers.authorization) {
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
return (0, utils_1.decodeBearer)(req.headers.authorization);
|
|
186
|
-
};
|
|
187
|
-
exports.getDecodedBearer = getDecodedBearer;
|
|
188
|
-
const createOrSetRabbitTrace = async (trace, userId) => {
|
|
189
|
-
const userObject = new ApiUser_1.default(userId);
|
|
190
|
-
await userObject.getUserPermissions();
|
|
191
|
-
// eslint-disable-next-line no-param-reassign
|
|
192
|
-
trace ?? (trace = (0, tracer_1.newTrace)(tracer_1.traceTypes.RABBIT));
|
|
193
|
-
trace.context.set(exports.USER_OBJECT, userObject);
|
|
194
|
-
};
|
|
195
|
-
exports.createOrSetRabbitTrace = createOrSetRabbitTrace;
|
|
196
|
-
exports.default = ApiUser_1.default;
|
package/lib/utils.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import type { UUID } from 'node:crypto';
|
|
3
|
-
export declare const getAuthFromBearer: (bearer: string) => string;
|
|
4
|
-
export declare const decodeBearer: (bearer: string, appSecret?: string) => any;
|
|
5
|
-
export declare const parsePermissions: (contextId: any, decodedToken: any) => any;
|
|
6
|
-
export declare const getEntitiesFromContext: (contextId: string, decodedToken: any) => any;
|
|
7
|
-
export declare const getContextAttributes: (contextId: string, decodedToken: any) => any;
|
|
8
|
-
export declare function validateUUID(uuid: unknown): uuid is UUID;
|
package/lib/utils.js
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.validateUUID = exports.getContextAttributes = exports.getEntitiesFromContext = exports.parsePermissions = exports.decodeBearer = exports.getAuthFromBearer = void 0;
|
|
27
|
-
const jwt = __importStar(require("jsonwebtoken"));
|
|
28
|
-
const secret_getter_1 = require("./secret-getter");
|
|
29
|
-
const CONTEXT_PROPS = ['fleetId', 'businessModelId', 'demandSourceId'];
|
|
30
|
-
const CONTEXT_MAP_PROPS = {
|
|
31
|
-
fleet: 'fleets',
|
|
32
|
-
business: 'businessModels',
|
|
33
|
-
demand: 'demandSources',
|
|
34
|
-
};
|
|
35
|
-
const getAuthFromBearer = (bearer) => bearer.replace('Bearer ', '');
|
|
36
|
-
exports.getAuthFromBearer = getAuthFromBearer;
|
|
37
|
-
const decodeBearer = (bearer, appSecret) => {
|
|
38
|
-
const token = (0, exports.getAuthFromBearer)(bearer);
|
|
39
|
-
const decoded = jwt.verify(token, appSecret || (0, secret_getter_1.getTokenSecret)(token));
|
|
40
|
-
return decoded;
|
|
41
|
-
};
|
|
42
|
-
exports.decodeBearer = decodeBearer;
|
|
43
|
-
const parsePermissions = (contextId, decodedToken) => {
|
|
44
|
-
if (!decodedToken) {
|
|
45
|
-
return [];
|
|
46
|
-
}
|
|
47
|
-
const { contexts } = decodedToken;
|
|
48
|
-
const activeContext = contexts.find((context) => context.id === contextId);
|
|
49
|
-
const permissionsValue = `${activeContext.permissions?.map((cp) => `${cp},`)}`;
|
|
50
|
-
return {
|
|
51
|
-
key: activeContext.entityId,
|
|
52
|
-
value: permissionsValue,
|
|
53
|
-
};
|
|
54
|
-
};
|
|
55
|
-
exports.parsePermissions = parsePermissions;
|
|
56
|
-
const getEntitiesFromContext = (contextId, decodedToken) => {
|
|
57
|
-
if (!decodedToken) {
|
|
58
|
-
return [];
|
|
59
|
-
}
|
|
60
|
-
let { contexts } = decodedToken;
|
|
61
|
-
if (contextId) {
|
|
62
|
-
contexts = contexts.filter((context) => context.id === contextId);
|
|
63
|
-
}
|
|
64
|
-
const attributes = {};
|
|
65
|
-
contexts.forEach((context) => {
|
|
66
|
-
const prop = CONTEXT_MAP_PROPS[context.subSystem || 'business'];
|
|
67
|
-
const permissions = (0, exports.parsePermissions)(context.id, decodedToken);
|
|
68
|
-
attributes[prop] || (attributes[prop] = {});
|
|
69
|
-
attributes[prop][permissions.key] = permissions.value;
|
|
70
|
-
});
|
|
71
|
-
return attributes;
|
|
72
|
-
};
|
|
73
|
-
exports.getEntitiesFromContext = getEntitiesFromContext;
|
|
74
|
-
const getContextAttributes = (contextId, decodedToken) => {
|
|
75
|
-
if (!decodedToken) {
|
|
76
|
-
return [];
|
|
77
|
-
}
|
|
78
|
-
let { contexts } = decodedToken;
|
|
79
|
-
if (contextId) {
|
|
80
|
-
contexts = contexts.filter((context) => context.id === contextId);
|
|
81
|
-
}
|
|
82
|
-
const attributes = {};
|
|
83
|
-
contexts.forEach((context) => {
|
|
84
|
-
CONTEXT_PROPS.forEach((prop) => {
|
|
85
|
-
if (context[prop]) {
|
|
86
|
-
const contextPropWrapped = [context[prop]];
|
|
87
|
-
attributes[prop] || (attributes[prop] = []);
|
|
88
|
-
attributes[prop] = attributes[prop].concat(contextPropWrapped);
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
return attributes;
|
|
93
|
-
};
|
|
94
|
-
exports.getContextAttributes = getContextAttributes;
|
|
95
|
-
const EMPTY_UUID = '00000000-0000-0000-0000-000000000000';
|
|
96
|
-
const FULL_UUID = 'ffffffff-ffff-ffff-ffff-ffffffffffff';
|
|
97
|
-
const VALID_CHARS_REGEX = '[0-9a-f]';
|
|
98
|
-
const UUID_VERSION_REGEX = '[1-8]';
|
|
99
|
-
const UUID_REGEX = new RegExp(`^(?:${VALID_CHARS_REGEX}{8}-${VALID_CHARS_REGEX}{4}-${UUID_VERSION_REGEX}${VALID_CHARS_REGEX}{3}-[89ab]${VALID_CHARS_REGEX}{3}-${VALID_CHARS_REGEX}{12}|${EMPTY_UUID}|${FULL_UUID})$`, 'i');
|
|
100
|
-
function validateUUID(uuid) {
|
|
101
|
-
return typeof uuid === 'string' && UUID_REGEX.test(uuid);
|
|
102
|
-
}
|
|
103
|
-
exports.validateUUID = validateUUID;
|