@autofleet/zehut 3.0.1-beta3 → 3.0.2
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/lib/app-auth.js +4 -2
- package/lib/check-permission.js +17 -12
- package/lib/errors.d.ts +1 -1
- package/lib/errors.js +1 -1
- package/lib/index.js +7 -3
- package/lib/secret-getter.js +7 -5
- package/lib/secret-getter.test.js +16 -10
- package/lib/test-helpers/index.d.ts +1 -1
- package/lib/test-helpers/index.js +7 -5
- package/lib/tracer.js +7 -4
- package/lib/user/ApiUser.d.ts +3 -2
- package/lib/user/ApiUser.js +10 -6
- package/lib/user/api-user-flows.test.js +12 -12
- package/lib/user/index.js +26 -16
- package/lib/utils.js +19 -10
- package/package.json +11 -9
package/lib/app-auth.js
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getClientSecret = exports.decodeAppBearer = void 0;
|
|
4
4
|
const services_1 = require("./services");
|
|
5
|
-
|
|
5
|
+
const decodeAppBearer = async (bearer, appId) => {
|
|
6
6
|
const { data: decoded } = await services_1.AutofleetApiNetwork.post('/api/v1/auth', { bearer, appId });
|
|
7
7
|
return decoded;
|
|
8
8
|
};
|
|
9
|
-
exports.
|
|
9
|
+
exports.decodeAppBearer = decodeAppBearer;
|
|
10
|
+
const getClientSecret = async (appId) => {
|
|
10
11
|
const { data: secret } = await services_1.AutofleetApiNetwork.get(`/api/v1/auth/client-secret/${appId}`);
|
|
11
12
|
return secret;
|
|
12
13
|
};
|
|
14
|
+
exports.getClientSecret = getClientSecret;
|
package/lib/check-permission.js
CHANGED
|
@@ -2,29 +2,34 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.checkDemandSourcePermission = exports.checkBusinessModelPermission = exports.checkFleetPermission = exports.isUserExist = exports.getUser = void 0;
|
|
4
4
|
const tracer_1 = require("./tracer");
|
|
5
|
-
|
|
6
|
-
exports.
|
|
7
|
-
|
|
5
|
+
const getUser = () => (0, tracer_1.getCurrentTrace)()?.context?.get('userObject');
|
|
6
|
+
exports.getUser = getUser;
|
|
7
|
+
const isUserExist = () => {
|
|
8
|
+
const u = (0, exports.getUser)();
|
|
8
9
|
return u && u.id;
|
|
9
10
|
};
|
|
10
|
-
exports.
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
exports.isUserExist = isUserExist;
|
|
12
|
+
const checkFleetPermission = (fleetId) => {
|
|
13
|
+
if ((0, exports.isUserExist)()) {
|
|
14
|
+
const user = (0, exports.getUser)();
|
|
13
15
|
return !user || Object.keys(user.permissions.fleets).includes(fleetId);
|
|
14
16
|
}
|
|
15
17
|
return true;
|
|
16
18
|
};
|
|
17
|
-
exports.
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
exports.checkFleetPermission = checkFleetPermission;
|
|
20
|
+
const checkBusinessModelPermission = (businessModelId) => {
|
|
21
|
+
if ((0, exports.isUserExist)()) {
|
|
22
|
+
const user = (0, exports.getUser)();
|
|
20
23
|
return !user || Object.keys(user.permissions.businessModels).includes(businessModelId);
|
|
21
24
|
}
|
|
22
25
|
return true;
|
|
23
26
|
};
|
|
24
|
-
exports.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
exports.checkBusinessModelPermission = checkBusinessModelPermission;
|
|
28
|
+
const checkDemandSourcePermission = (demandSourceId) => {
|
|
29
|
+
if ((0, exports.isUserExist)()) {
|
|
30
|
+
const user = (0, exports.getUser)();
|
|
27
31
|
return !user || Object.keys(user.permissions.demandSources).includes(demandSourceId);
|
|
28
32
|
}
|
|
29
33
|
return true;
|
|
30
34
|
};
|
|
35
|
+
exports.checkDemandSourcePermission = checkDemandSourcePermission;
|
package/lib/errors.d.ts
CHANGED
package/lib/errors.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.UnauthorizedAccessError = void 0;
|
|
4
4
|
// eslint-disable-next-line import/prefer-default-export
|
|
5
5
|
class UnauthorizedAccessError extends Error {
|
|
6
|
-
constructor(user = null, message) {
|
|
6
|
+
constructor(user = null, message = 'UnauthorizedAccessError') {
|
|
7
7
|
super(message);
|
|
8
8
|
this.name = 'UnauthorizedAccessError';
|
|
9
9
|
this.user = user;
|
package/lib/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
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);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -14,7 +18,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
14
18
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
19
|
if (mod && mod.__esModule) return mod;
|
|
16
20
|
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
22
|
__setModuleDefault(result, mod);
|
|
19
23
|
return result;
|
|
20
24
|
};
|
|
@@ -52,7 +56,7 @@ const enableTracing = ({ outbreakOptions = {} } = {}) => {
|
|
|
52
56
|
headersPrefix: 'x-af',
|
|
53
57
|
...outbreakOptions,
|
|
54
58
|
});
|
|
55
|
-
tracer_1.enable();
|
|
59
|
+
(0, tracer_1.enable)();
|
|
56
60
|
};
|
|
57
61
|
exports.enableTracing = enableTracing;
|
|
58
62
|
exports.default = {
|
package/lib/secret-getter.js
CHANGED
|
@@ -8,15 +8,15 @@ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
|
8
8
|
const moment_1 = __importDefault(require("moment"));
|
|
9
9
|
const { DEPRECATED_JWT_SECRET, JWT_NEW_SECRET, DEPRECATED_REFRESH_JWT_SECRET, REFRESH_JWT_SECRET, DEPRECATION_UNIX_TIMESTAMP, } = process.env;
|
|
10
10
|
const getRelevantSecret = (token, deprecatedSecret, newSecret) => {
|
|
11
|
-
const deprecationTime = moment_1.default(parseInt(DEPRECATION_UNIX_TIMESTAMP, 10) * 1000);
|
|
11
|
+
const deprecationTime = (0, moment_1.default)(parseInt(DEPRECATION_UNIX_TIMESTAMP, 10) * 1000);
|
|
12
12
|
try {
|
|
13
13
|
let unixTime;
|
|
14
14
|
if (token) {
|
|
15
15
|
const { iat } = jsonwebtoken_1.default.decode(token);
|
|
16
|
-
unixTime = moment_1.default(iat * 1000);
|
|
16
|
+
unixTime = (0, moment_1.default)(iat * 1000);
|
|
17
17
|
}
|
|
18
18
|
else {
|
|
19
|
-
unixTime = moment_1.default();
|
|
19
|
+
unixTime = (0, moment_1.default)();
|
|
20
20
|
}
|
|
21
21
|
return unixTime.isBefore(deprecationTime) ? deprecatedSecret : newSecret;
|
|
22
22
|
}
|
|
@@ -24,5 +24,7 @@ const getRelevantSecret = (token, deprecatedSecret, newSecret) => {
|
|
|
24
24
|
return newSecret;
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
|
-
|
|
28
|
-
exports.
|
|
27
|
+
const getRefreshTokenSecret = (token) => getRelevantSecret(token, DEPRECATED_REFRESH_JWT_SECRET, REFRESH_JWT_SECRET);
|
|
28
|
+
exports.getRefreshTokenSecret = getRefreshTokenSecret;
|
|
29
|
+
const getTokenSecret = (token) => getRelevantSecret(token, DEPRECATED_JWT_SECRET, JWT_NEW_SECRET);
|
|
30
|
+
exports.getTokenSecret = getTokenSecret;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
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);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -14,7 +18,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
14
18
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
19
|
if (mod && mod.__esModule) return mod;
|
|
16
20
|
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
22
|
__setModuleDefault(result, mod);
|
|
19
23
|
return result;
|
|
20
24
|
};
|
|
@@ -24,7 +28,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
24
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
29
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
26
30
|
const moment_1 = __importDefault(require("moment"));
|
|
27
|
-
const sleep = async (ms) => new Promise((resolve) =>
|
|
31
|
+
const sleep = async (ms) => new Promise((resolve) => {
|
|
32
|
+
setTimeout(resolve, ms);
|
|
33
|
+
});
|
|
28
34
|
process.env.NODE_ENV = 'node-common-test';
|
|
29
35
|
describe('secret getter tests', () => {
|
|
30
36
|
const testSecrets = {
|
|
@@ -41,28 +47,28 @@ describe('secret getter tests', () => {
|
|
|
41
47
|
}; // Make a copy
|
|
42
48
|
});
|
|
43
49
|
it('test get new refresh token secret when after deprecation timestamp', async () => {
|
|
44
|
-
process.env.DEPRECATION_UNIX_TIMESTAMP = moment_1.default().subtract(1, 'days').unix().toString();
|
|
50
|
+
process.env.DEPRECATION_UNIX_TIMESTAMP = (0, moment_1.default)().subtract(1, 'days').unix().toString();
|
|
45
51
|
const { getTokenSecret } = await Promise.resolve().then(() => __importStar(require('./secret-getter')));
|
|
46
52
|
const token = jsonwebtoken_1.default.sign({
|
|
47
|
-
exp: moment_1.default().unix() + (60 * 60 * 24 * 365),
|
|
53
|
+
exp: (0, moment_1.default)().unix() + (60 * 60 * 24 * 365),
|
|
48
54
|
}, testSecrets.JWT_NEW_SECRET);
|
|
49
55
|
const result = getTokenSecret(token);
|
|
50
56
|
expect(result).toBe(testSecrets.JWT_NEW_SECRET);
|
|
51
57
|
});
|
|
52
58
|
it('test get old refresh token secret when before deprecation timestamp', async () => {
|
|
53
|
-
process.env.DEPRECATION_UNIX_TIMESTAMP = moment_1.default().add(1, 'days').unix().toString();
|
|
59
|
+
process.env.DEPRECATION_UNIX_TIMESTAMP = (0, moment_1.default)().add(1, 'days').unix().toString();
|
|
54
60
|
const { getTokenSecret } = await Promise.resolve().then(() => __importStar(require('./secret-getter')));
|
|
55
61
|
const token = jsonwebtoken_1.default.sign({
|
|
56
|
-
exp: moment_1.default().unix() + (60 * 60 * 24 * 365),
|
|
62
|
+
exp: (0, moment_1.default)().unix() + (60 * 60 * 24 * 365),
|
|
57
63
|
}, testSecrets.DEPRECATED_JWT_SECRET);
|
|
58
64
|
const result = getTokenSecret(token);
|
|
59
65
|
expect(result).toBe(testSecrets.DEPRECATED_JWT_SECRET);
|
|
60
66
|
});
|
|
61
67
|
it('test get old refresh token secret when after deprecation timestamp, but token is from before', async () => {
|
|
62
68
|
const token = jsonwebtoken_1.default.sign({
|
|
63
|
-
exp: moment_1.default().unix() + (60 * 60 * 24 * 365),
|
|
69
|
+
exp: (0, moment_1.default)().unix() + (60 * 60 * 24 * 365),
|
|
64
70
|
}, testSecrets.DEPRECATED_JWT_SECRET);
|
|
65
|
-
process.env.DEPRECATION_UNIX_TIMESTAMP = moment_1.default().add(10, 'seconds').unix().toString();
|
|
71
|
+
process.env.DEPRECATION_UNIX_TIMESTAMP = (0, moment_1.default)().add(10, 'seconds').unix().toString();
|
|
66
72
|
const { getTokenSecret } = await Promise.resolve().then(() => __importStar(require('./secret-getter')));
|
|
67
73
|
await sleep(1000);
|
|
68
74
|
const result = getTokenSecret(token);
|
|
@@ -75,7 +81,7 @@ describe('secret getter tests', () => {
|
|
|
75
81
|
expect(result).toBe(testSecrets.JWT_NEW_SECRET);
|
|
76
82
|
});
|
|
77
83
|
it('test malformed token returns new secret even before deprecation time', async () => {
|
|
78
|
-
process.env.DEPRECATION_UNIX_TIMESTAMP = moment_1.default().add(10, 'day').unix().toString();
|
|
84
|
+
process.env.DEPRECATION_UNIX_TIMESTAMP = (0, moment_1.default)().add(10, 'day').unix().toString();
|
|
79
85
|
const { getTokenSecret } = await Promise.resolve().then(() => __importStar(require('./secret-getter')));
|
|
80
86
|
const token = 'shit';
|
|
81
87
|
const result = getTokenSecret(token);
|
|
@@ -8,15 +8,16 @@ const supertest_1 = __importDefault(require("supertest"));
|
|
|
8
8
|
const nock_1 = __importDefault(require("nock"));
|
|
9
9
|
const http_1 = __importDefault(require("http"));
|
|
10
10
|
const uuid_1 = require("uuid");
|
|
11
|
-
|
|
12
|
-
nock_1.default(`http://${process.env.IDENTITY_MS_SERVICE_HOST}`)
|
|
11
|
+
const setIdentityNock = (userAttributes) => {
|
|
12
|
+
(0, nock_1.default)(`http://${process.env.IDENTITY_MS_SERVICE_HOST}`)
|
|
13
13
|
.get(`/api/v1/users/${userAttributes.id}/authorization-payload`)
|
|
14
14
|
.reply(200, userAttributes.permissions);
|
|
15
15
|
};
|
|
16
|
-
exports.
|
|
16
|
+
exports.setIdentityNock = setIdentityNock;
|
|
17
|
+
const mockRequestAndUser = (app, userCustomAttributes) => {
|
|
17
18
|
const agent = supertest_1.default.agent(app);
|
|
18
19
|
const userAttributes = {
|
|
19
|
-
id: userCustomAttributes.id || uuid_1.v4(),
|
|
20
|
+
id: userCustomAttributes.id || (0, uuid_1.v4)(),
|
|
20
21
|
permissions: {
|
|
21
22
|
businessModels: userCustomAttributes?.permissions?.businessModels || {},
|
|
22
23
|
fleets: userCustomAttributes?.permissions?.fleets || {},
|
|
@@ -24,10 +25,11 @@ exports.mockRequestAndUser = (app, userCustomAttributes) => {
|
|
|
24
25
|
},
|
|
25
26
|
};
|
|
26
27
|
agent.set('x-af-user-id', userAttributes.id);
|
|
27
|
-
exports.setIdentityNock(userAttributes);
|
|
28
|
+
(0, exports.setIdentityNock)(userAttributes);
|
|
28
29
|
const agentObject = {};
|
|
29
30
|
http_1.default.METHODS.forEach((method) => {
|
|
30
31
|
agentObject[method.toLowerCase()] = (path) => agent[method.toLowerCase()](path).set('x-af-user-id', userAttributes.id);
|
|
31
32
|
});
|
|
32
33
|
return agentObject;
|
|
33
34
|
};
|
|
35
|
+
exports.mockRequestAndUser = mockRequestAndUser;
|
package/lib/tracer.js
CHANGED
|
@@ -40,19 +40,22 @@ const hook = async_hooks_1.default.createHook({
|
|
|
40
40
|
});
|
|
41
41
|
class Trace {
|
|
42
42
|
constructor(type) {
|
|
43
|
-
this.id = uuid_1.v1();
|
|
43
|
+
this.id = (0, uuid_1.v1)();
|
|
44
44
|
this.type = type;
|
|
45
45
|
this.context = new Map();
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
exports.Trace = Trace;
|
|
49
|
-
|
|
49
|
+
const newTrace = (type) => {
|
|
50
50
|
tracer.currentTrace = new Trace(type);
|
|
51
51
|
tracer.traces[async_hooks_1.default.executionAsyncId()] = tracer.currentTrace;
|
|
52
52
|
return tracer.currentTrace;
|
|
53
53
|
};
|
|
54
|
-
exports.
|
|
55
|
-
|
|
54
|
+
exports.newTrace = newTrace;
|
|
55
|
+
const enable = () => hook.enable();
|
|
56
|
+
exports.enable = enable;
|
|
57
|
+
const getCurrentTrace = () => tracer.currentTrace || {};
|
|
58
|
+
exports.getCurrentTrace = getCurrentTrace;
|
|
56
59
|
exports.traceTypes = {
|
|
57
60
|
HTTP_REQUEST: 'httpRequest',
|
|
58
61
|
WEB_SOCKET: 'webSocket',
|
package/lib/user/ApiUser.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type AccountType = 'client' | 'user' | 'service';
|
|
2
2
|
interface EntityPermissions {
|
|
3
3
|
[key: string]: string[];
|
|
4
4
|
}
|
|
@@ -7,6 +7,7 @@ export interface UserPayload {
|
|
|
7
7
|
businessModels: EntityPermissions;
|
|
8
8
|
fleets: EntityPermissions;
|
|
9
9
|
demandSources: EntityPermissions;
|
|
10
|
+
accountType?: AccountType;
|
|
10
11
|
contexts?: EntityPermissions;
|
|
11
12
|
createdAt?: string;
|
|
12
13
|
}
|
|
@@ -17,7 +18,7 @@ export interface PartialUserPayload {
|
|
|
17
18
|
vehicles?: EntityPermissions;
|
|
18
19
|
drivers?: EntityPermissions;
|
|
19
20
|
}
|
|
20
|
-
export
|
|
21
|
+
export type CustomPermissionLoader = (string: any) => Promise<UserPayload>;
|
|
21
22
|
export default class ApiUser {
|
|
22
23
|
id: string | undefined;
|
|
23
24
|
privatePermissions: UserPayload | undefined;
|
package/lib/user/ApiUser.js
CHANGED
|
@@ -32,7 +32,11 @@ class ApiUser {
|
|
|
32
32
|
if (this.privatePermissions) {
|
|
33
33
|
return this.privatePermissions;
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
let data = userCache.get(this.id);
|
|
36
|
+
if (!data) {
|
|
37
|
+
({ data } = await services_1.IdentityNetwork.get(`/api/v1/users/${this.id}/authorization-payload`));
|
|
38
|
+
userCache.set(this.id, data);
|
|
39
|
+
}
|
|
36
40
|
this.accountType = data.accountType;
|
|
37
41
|
this.privatePermissions = data;
|
|
38
42
|
return this.privatePermissions;
|
|
@@ -76,7 +80,7 @@ class ApiUser {
|
|
|
76
80
|
demandSources: {},
|
|
77
81
|
};
|
|
78
82
|
[...this.privateElevatedPermissionsHash.values()].forEach((p) => {
|
|
79
|
-
permissions = merge_deep_1.default(permissions, p);
|
|
83
|
+
permissions = (0, merge_deep_1.default)(permissions, p);
|
|
80
84
|
});
|
|
81
85
|
return permissions;
|
|
82
86
|
}
|
|
@@ -84,20 +88,20 @@ class ApiUser {
|
|
|
84
88
|
if (!this.privatePermissions) {
|
|
85
89
|
throw new Error('Cannot get permissions without calling (async) getUserPermissions before');
|
|
86
90
|
}
|
|
87
|
-
const permissions = merge_deep_1.default(this.privatePermissions, this.elevatedPermissions);
|
|
91
|
+
const permissions = (0, merge_deep_1.default)(this.privatePermissions, this.elevatedPermissions);
|
|
88
92
|
return permissions;
|
|
89
93
|
}
|
|
90
94
|
elevatePermissions(addedPermissions) {
|
|
91
|
-
const elevationId = uuid_1.v4();
|
|
95
|
+
const elevationId = (0, uuid_1.v4)();
|
|
92
96
|
// Validate that the added permissions are valid UUIDs
|
|
93
97
|
Object.keys(addedPermissions).forEach((entityType) => {
|
|
94
98
|
Object.keys(addedPermissions[entityType]).forEach((entityId) => {
|
|
95
|
-
if (!uuid_1.validate(entityId)) {
|
|
99
|
+
if (!(0, uuid_1.validate)(entityId)) {
|
|
96
100
|
throw new Error(`Entity id on elevatePermissions is not a valid UUID, provided: ${entityId}`);
|
|
97
101
|
}
|
|
98
102
|
});
|
|
99
103
|
});
|
|
100
|
-
const currentUserTrace = outbreak_1.getCurrentContext();
|
|
104
|
+
const currentUserTrace = (0, outbreak_1.getCurrentContext)();
|
|
101
105
|
if (!currentUserTrace) {
|
|
102
106
|
throw new Error('Cannot find current user cross services trace');
|
|
103
107
|
}
|
|
@@ -9,7 +9,7 @@ const axios_1 = __importDefault(require("axios"));
|
|
|
9
9
|
const index_1 = require("../index");
|
|
10
10
|
const index_2 = require("./index");
|
|
11
11
|
const generateApp = async (addEndpoints, port) => {
|
|
12
|
-
const app = express_1.default();
|
|
12
|
+
const app = (0, express_1.default)();
|
|
13
13
|
addEndpoints(app);
|
|
14
14
|
const server = await new Promise((resolve) => {
|
|
15
15
|
const s = app.listen(port, () => {
|
|
@@ -22,16 +22,16 @@ const generateApp = async (addEndpoints, port) => {
|
|
|
22
22
|
describe('E2E', () => {
|
|
23
23
|
it('Basic functionality', async () => {
|
|
24
24
|
let server2TraceId = null;
|
|
25
|
-
const [uuid1, uuid2] = [uuid_1.v4(), uuid_1.v4()];
|
|
26
|
-
index_1.enableTracing({
|
|
25
|
+
const [uuid1, uuid2] = [(0, uuid_1.v4)(), (0, uuid_1.v4)()];
|
|
26
|
+
(0, index_1.enableTracing)({
|
|
27
27
|
outbreakOptions: {
|
|
28
28
|
headersPrefix: 'x-af-',
|
|
29
29
|
},
|
|
30
30
|
});
|
|
31
31
|
const closeServer1 = await generateApp((app) => {
|
|
32
|
-
app.use(index_2.middleware());
|
|
32
|
+
app.use((0, index_2.middleware)());
|
|
33
33
|
app.get('/', async (req, res) => {
|
|
34
|
-
const user = index_1.getUser();
|
|
34
|
+
const user = (0, index_1.getUser)();
|
|
35
35
|
const closeElevation1 = user.elevatePermissions({
|
|
36
36
|
businessModels: {
|
|
37
37
|
[uuid1]: ['vehicle:write'],
|
|
@@ -51,9 +51,9 @@ describe('E2E', () => {
|
|
|
51
51
|
}, 8089);
|
|
52
52
|
const server2NumberOfPermissions = [];
|
|
53
53
|
const closeServer2 = await generateApp((app) => {
|
|
54
|
-
app.use(index_2.middleware());
|
|
54
|
+
app.use((0, index_2.middleware)());
|
|
55
55
|
app.post('/', (req, res) => {
|
|
56
|
-
const user = index_1.getUser();
|
|
56
|
+
const user = (0, index_1.getUser)();
|
|
57
57
|
user.privatePermissions = {
|
|
58
58
|
businessModels: {},
|
|
59
59
|
fleets: {},
|
|
@@ -72,7 +72,7 @@ describe('E2E', () => {
|
|
|
72
72
|
headers: {
|
|
73
73
|
'x-af-header': 'testHeader',
|
|
74
74
|
'x-af-id': 'my-wakanda-id',
|
|
75
|
-
'x-af-user-id': uuid_1.v4(),
|
|
75
|
+
'x-af-user-id': (0, uuid_1.v4)(),
|
|
76
76
|
},
|
|
77
77
|
});
|
|
78
78
|
closeServer1();
|
|
@@ -88,15 +88,15 @@ describe('E2E', () => {
|
|
|
88
88
|
});
|
|
89
89
|
it('Should throw in case of invalid UUID', async () => {
|
|
90
90
|
let error = null;
|
|
91
|
-
index_1.enableTracing({
|
|
91
|
+
(0, index_1.enableTracing)({
|
|
92
92
|
outbreakOptions: {
|
|
93
93
|
headersPrefix: 'x-af-',
|
|
94
94
|
},
|
|
95
95
|
});
|
|
96
96
|
const closeServer1 = await generateApp((app) => {
|
|
97
|
-
app.use(index_2.middleware());
|
|
97
|
+
app.use((0, index_2.middleware)());
|
|
98
98
|
app.get('/', async (req, res) => {
|
|
99
|
-
const user = index_1.getUser();
|
|
99
|
+
const user = (0, index_1.getUser)();
|
|
100
100
|
try {
|
|
101
101
|
const closeElevation1 = user.elevatePermissions({
|
|
102
102
|
businessModels: {
|
|
@@ -116,7 +116,7 @@ describe('E2E', () => {
|
|
|
116
116
|
headers: {
|
|
117
117
|
'x-af-header': 'testHeader',
|
|
118
118
|
'x-af-id': 'my-wakanda-id',
|
|
119
|
-
'x-af-user-id': uuid_1.v4(),
|
|
119
|
+
'x-af-user-id': (0, uuid_1.v4)(),
|
|
120
120
|
},
|
|
121
121
|
});
|
|
122
122
|
closeServer1();
|
package/lib/user/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
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);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -14,7 +18,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
14
18
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
19
|
if (mod && mod.__esModule) return mod;
|
|
16
20
|
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
22
|
__setModuleDefault(result, mod);
|
|
19
23
|
return result;
|
|
20
24
|
};
|
|
@@ -29,11 +33,11 @@ const tracer_1 = require("../tracer");
|
|
|
29
33
|
const app_auth_1 = require("../app-auth");
|
|
30
34
|
const appDoesNotExist_1 = __importDefault(require("../exceptions/appDoesNotExist"));
|
|
31
35
|
const utils_1 = require("../utils");
|
|
32
|
-
|
|
36
|
+
const middleware = (options = {}) => async (req, res, next) => {
|
|
33
37
|
try {
|
|
34
38
|
const { eagerLoadUserPermissions, eagerLoadUserPermissionsLegacy, customPermissionLoader, } = options;
|
|
35
39
|
const userId = req.headers['x-af-user-id'];
|
|
36
|
-
const trace = tracer_1.newTrace('userPayload');
|
|
40
|
+
const trace = (0, tracer_1.newTrace)('userPayload');
|
|
37
41
|
if (!userId) {
|
|
38
42
|
return next();
|
|
39
43
|
}
|
|
@@ -65,13 +69,14 @@ exports.middleware = (options = {}) => async (req, res, next) => {
|
|
|
65
69
|
});
|
|
66
70
|
}
|
|
67
71
|
};
|
|
68
|
-
exports.
|
|
72
|
+
exports.middleware = middleware;
|
|
73
|
+
const middlewareWithDecode = (options = {}) => async (req, res, next) => {
|
|
69
74
|
const { eagerLoadUserPermissions, eagerLoadUserPermissionsLegacy, returnErrorIfNoToken, } = options;
|
|
70
|
-
const trace = tracer_1.newTrace('userPayload');
|
|
75
|
+
const trace = (0, tracer_1.newTrace)('userPayload');
|
|
71
76
|
let decoded;
|
|
72
77
|
if (req.headers.authorization) {
|
|
73
78
|
try {
|
|
74
|
-
decoded = await utils_1.decodeBearer(req.headers.authorization);
|
|
79
|
+
decoded = await (0, utils_1.decodeBearer)(req.headers.authorization);
|
|
75
80
|
}
|
|
76
81
|
catch (e) {
|
|
77
82
|
if (e instanceof jsonwebtoken_1.TokenExpiredError) {
|
|
@@ -120,9 +125,10 @@ exports.middlewareWithDecode = (options = {}) => async (req, res, next) => {
|
|
|
120
125
|
// eslint-disable-next-line consistent-return
|
|
121
126
|
return next();
|
|
122
127
|
};
|
|
123
|
-
exports.
|
|
128
|
+
exports.middlewareWithDecode = middlewareWithDecode;
|
|
129
|
+
const appMiddleware = (options) => async (req, res, next) => {
|
|
124
130
|
const { appId, clientSecret, } = options;
|
|
125
|
-
const trace = tracer_1.newTrace('userPayload');
|
|
131
|
+
const trace = (0, tracer_1.newTrace)('userPayload');
|
|
126
132
|
let decoded;
|
|
127
133
|
if (!req.headers.authorization) {
|
|
128
134
|
res.status(401);
|
|
@@ -131,7 +137,7 @@ exports.appMiddleware = (options) => async (req, res, next) => {
|
|
|
131
137
|
});
|
|
132
138
|
}
|
|
133
139
|
try {
|
|
134
|
-
decoded = await app_auth_1.decodeAppBearer(req.headers.authorization, appId);
|
|
140
|
+
decoded = await (0, app_auth_1.decodeAppBearer)(req.headers.authorization, appId);
|
|
135
141
|
if (!decoded) {
|
|
136
142
|
throw new appDoesNotExist_1.default();
|
|
137
143
|
}
|
|
@@ -172,28 +178,32 @@ exports.appMiddleware = (options) => async (req, res, next) => {
|
|
|
172
178
|
}
|
|
173
179
|
req.user = userObject;
|
|
174
180
|
trace.context.set('userObject', userObject);
|
|
175
|
-
trace.context.set('accessToken', utils_1.getAuthFromBearer(req.headers.authorization));
|
|
181
|
+
trace.context.set('accessToken', (0, utils_1.getAuthFromBearer)(req.headers.authorization));
|
|
176
182
|
// Added in order to support outbreak.
|
|
177
183
|
req.headers['x-af-user-permissions'] = userObject;
|
|
178
184
|
return next();
|
|
179
185
|
};
|
|
180
|
-
exports.
|
|
186
|
+
exports.appMiddleware = appMiddleware;
|
|
187
|
+
const eagerLoadPermissionsMiddleware = async (req, res, next) => {
|
|
181
188
|
await req.user.getUserPermissions();
|
|
182
189
|
return next();
|
|
183
190
|
};
|
|
184
|
-
exports.
|
|
191
|
+
exports.eagerLoadPermissionsMiddleware = eagerLoadPermissionsMiddleware;
|
|
192
|
+
const getDecodedBearer = (req) => {
|
|
185
193
|
if (req.headers.authorization) {
|
|
186
|
-
return utils_1.decodeBearer(req.headers.authorization);
|
|
194
|
+
return (0, utils_1.decodeBearer)(req.headers.authorization);
|
|
187
195
|
}
|
|
188
196
|
return null;
|
|
189
197
|
};
|
|
190
|
-
exports.
|
|
198
|
+
exports.getDecodedBearer = getDecodedBearer;
|
|
199
|
+
const createOrSetRabbitTrace = async (trace, userId) => {
|
|
191
200
|
const userObject = new ApiUser_1.default(userId);
|
|
192
201
|
await userObject.getUserPermissions();
|
|
193
202
|
if (!trace) {
|
|
194
203
|
// eslint-disable-next-line no-param-reassign
|
|
195
|
-
trace = tracer_1.newTrace(tracer_1.traceTypes.RABBIT);
|
|
204
|
+
trace = (0, tracer_1.newTrace)(tracer_1.traceTypes.RABBIT);
|
|
196
205
|
}
|
|
197
206
|
trace.context.set('userObject', userObject);
|
|
198
207
|
};
|
|
208
|
+
exports.createOrSetRabbitTrace = createOrSetRabbitTrace;
|
|
199
209
|
exports.default = ApiUser_1.default;
|
package/lib/utils.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
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);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -14,7 +18,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
14
18
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
19
|
if (mod && mod.__esModule) return mod;
|
|
16
20
|
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
22
|
__setModuleDefault(result, mod);
|
|
19
23
|
return result;
|
|
20
24
|
};
|
|
@@ -29,13 +33,15 @@ const CONTEXT_MAP_PROPS = {
|
|
|
29
33
|
business: 'businessModels',
|
|
30
34
|
demand: 'demandSources',
|
|
31
35
|
};
|
|
32
|
-
|
|
33
|
-
exports.
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
+
const getAuthFromBearer = (bearer) => bearer.replace('Bearer ', '');
|
|
37
|
+
exports.getAuthFromBearer = getAuthFromBearer;
|
|
38
|
+
const decodeBearer = (bearer, appSecret) => {
|
|
39
|
+
const token = (0, exports.getAuthFromBearer)(bearer);
|
|
40
|
+
const decoded = jwt.verify(token, appSecret || (0, secret_getter_1.getTokenSecret)(token));
|
|
36
41
|
return decoded;
|
|
37
42
|
};
|
|
38
|
-
exports.
|
|
43
|
+
exports.decodeBearer = decodeBearer;
|
|
44
|
+
const parsePermissions = (contextId, decodedToken) => {
|
|
39
45
|
if (!decodedToken) {
|
|
40
46
|
return [];
|
|
41
47
|
}
|
|
@@ -47,7 +53,8 @@ exports.parsePermissions = (contextId, decodedToken) => {
|
|
|
47
53
|
value: permissionsValue,
|
|
48
54
|
};
|
|
49
55
|
};
|
|
50
|
-
exports.
|
|
56
|
+
exports.parsePermissions = parsePermissions;
|
|
57
|
+
const getEntitiesFromContext = (contextId, decodedToken) => {
|
|
51
58
|
if (!decodedToken) {
|
|
52
59
|
return [];
|
|
53
60
|
}
|
|
@@ -58,7 +65,7 @@ exports.getEntitiesFromContext = (contextId, decodedToken) => {
|
|
|
58
65
|
const attributes = {};
|
|
59
66
|
contexts.forEach((context) => {
|
|
60
67
|
const prop = CONTEXT_MAP_PROPS[context.subSystem || 'business'];
|
|
61
|
-
const permissions = exports.parsePermissions(context.id, decodedToken);
|
|
68
|
+
const permissions = (0, exports.parsePermissions)(context.id, decodedToken);
|
|
62
69
|
// eslint-disable-next-line no-unused-expressions
|
|
63
70
|
attributes[prop]
|
|
64
71
|
? attributes[prop][permissions.key] = permissions.value
|
|
@@ -66,7 +73,8 @@ exports.getEntitiesFromContext = (contextId, decodedToken) => {
|
|
|
66
73
|
});
|
|
67
74
|
return attributes;
|
|
68
75
|
};
|
|
69
|
-
exports.
|
|
76
|
+
exports.getEntitiesFromContext = getEntitiesFromContext;
|
|
77
|
+
const getContextAttributes = (contextId, decodedToken) => {
|
|
70
78
|
if (!decodedToken) {
|
|
71
79
|
return [];
|
|
72
80
|
}
|
|
@@ -88,3 +96,4 @@ exports.getContextAttributes = (contextId, decodedToken) => {
|
|
|
88
96
|
});
|
|
89
97
|
return attributes;
|
|
90
98
|
};
|
|
99
|
+
exports.getContextAttributes = getContextAttributes;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/zehut",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "manage user's identity",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@autofleet/network": "^1.4.2",
|
|
27
27
|
"@autofleet/outbreak": "0.2.1",
|
|
28
|
-
"@types/jest": "^22.0.0",
|
|
29
28
|
"axios": "^0.27.2",
|
|
30
29
|
"express": "^4.18.1",
|
|
31
30
|
"jsonwebtoken": "^8.5.1",
|
|
@@ -38,13 +37,16 @@
|
|
|
38
37
|
"uuid": "^8.3.2"
|
|
39
38
|
},
|
|
40
39
|
"devDependencies": {
|
|
41
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
42
|
-
"eslint": "^
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "^6.5.0",
|
|
41
|
+
"@typescript-eslint/parser": "^6.5.0",
|
|
42
|
+
"@types/jest": "^29.5.4",
|
|
43
|
+
"@types/node": "^16.14.2",
|
|
44
|
+
"eslint": "^8.48.0",
|
|
45
|
+
"eslint-config-airbnb-typescript": "^17.1.0",
|
|
46
|
+
"eslint-plugin-import": "^2.28.1",
|
|
47
|
+
"jest": "^29.6.4",
|
|
48
|
+
"ts-jest": "^29.1.1",
|
|
49
|
+
"typescript": "^4.9.5"
|
|
48
50
|
},
|
|
49
51
|
"files": [
|
|
50
52
|
"lib/**/*"
|