@autofleet/zehut 2.0.3 → 3.0.0-beta.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/lib/app-auth.js +6 -15
- package/lib/check-permission.js +1 -1
- package/lib/index.d.ts +8 -1
- package/lib/index.js +9 -2
- package/lib/secret-getter.test.js +21 -27
- package/lib/test-helpers/index.js +3 -4
- package/lib/tracer.d.ts +6 -1
- package/lib/tracer.js +7 -1
- package/lib/user/ApiUser.js +56 -73
- package/lib/user/api-user-flows.test.js +19 -28
- package/lib/user/index.js +20 -30
- package/lib/utils.js +1 -2
- package/package.json +2 -6
package/lib/app-auth.js
CHANGED
|
@@ -1,21 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.getClientSecret = exports.decodeAppBearer = void 0;
|
|
13
4
|
const services_1 = require("./services");
|
|
14
|
-
exports.decodeAppBearer = (bearer, appId) =>
|
|
15
|
-
const { data: decoded } =
|
|
5
|
+
exports.decodeAppBearer = async (bearer, appId) => {
|
|
6
|
+
const { data: decoded } = await services_1.AutofleetApiNetwork.post('/api/v1/auth', { bearer, appId });
|
|
16
7
|
return decoded;
|
|
17
|
-
}
|
|
18
|
-
exports.getClientSecret = (appId) =>
|
|
19
|
-
const { data: secret } =
|
|
8
|
+
};
|
|
9
|
+
exports.getClientSecret = async (appId) => {
|
|
10
|
+
const { data: secret } = await services_1.AutofleetApiNetwork.get(`/api/v1/auth/client-secret/${appId}`);
|
|
20
11
|
return secret;
|
|
21
|
-
}
|
|
12
|
+
};
|
package/lib/check-permission.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
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
|
-
exports.getUser = () =>
|
|
5
|
+
exports.getUser = () => tracer_1.getCurrentTrace()?.context?.get('userObject');
|
|
6
6
|
exports.isUserExist = () => {
|
|
7
7
|
const u = exports.getUser();
|
|
8
8
|
return u && u.id;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import User, { middleware, eagerLoadPermissionsMiddleware, middlewareWithDecode, getDecodedBearer, appMiddleware } from './user';
|
|
2
|
+
import { newTrace, traceTypes } from './tracer';
|
|
2
3
|
import { checkFleetPermission, checkBusinessModelPermission, checkDemandSourcePermission, isUserExist, getUser } from './check-permission';
|
|
3
4
|
import { UnauthorizedAccessError } from './errors';
|
|
4
5
|
import { getRefreshTokenSecret, getTokenSecret } from './secret-getter';
|
|
@@ -6,8 +7,14 @@ declare const getCurrentPayload: () => any;
|
|
|
6
7
|
declare const enableTracing: ({ outbreakOptions }?: {
|
|
7
8
|
outbreakOptions?: {};
|
|
8
9
|
}) => void;
|
|
9
|
-
export { enableTracing, User, middleware, middlewareWithDecode, eagerLoadPermissionsMiddleware, getCurrentPayload, getDecodedBearer, checkFleetPermission, checkBusinessModelPermission, checkDemandSourcePermission, isUserExist, getUser, getRefreshTokenSecret, getTokenSecret, UnauthorizedAccessError, appMiddleware, };
|
|
10
|
+
export { traceTypes, newTrace, enableTracing, User, middleware, middlewareWithDecode, eagerLoadPermissionsMiddleware, getCurrentPayload, getDecodedBearer, checkFleetPermission, checkBusinessModelPermission, checkDemandSourcePermission, isUserExist, getUser, getRefreshTokenSecret, getTokenSecret, UnauthorizedAccessError, appMiddleware, };
|
|
10
11
|
declare const _default: {
|
|
12
|
+
traceTypes: {
|
|
13
|
+
HTTP_REQUEST: string;
|
|
14
|
+
WEB_SOCKET: string;
|
|
15
|
+
RABBIT: string;
|
|
16
|
+
};
|
|
17
|
+
newTrace: (type: any) => import("./tracer").Trace;
|
|
11
18
|
User: typeof User;
|
|
12
19
|
middleware: (options?: {
|
|
13
20
|
eagerLoadUserPermissions?: boolean;
|
package/lib/index.js
CHANGED
|
@@ -22,7 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
22
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.appMiddleware = exports.UnauthorizedAccessError = exports.getTokenSecret = exports.getRefreshTokenSecret = exports.getUser = exports.isUserExist = exports.checkDemandSourcePermission = exports.checkBusinessModelPermission = exports.checkFleetPermission = exports.getDecodedBearer = exports.getCurrentPayload = exports.eagerLoadPermissionsMiddleware = exports.middlewareWithDecode = exports.middleware = exports.User = exports.enableTracing = void 0;
|
|
25
|
+
exports.appMiddleware = exports.UnauthorizedAccessError = exports.getTokenSecret = exports.getRefreshTokenSecret = exports.getUser = exports.isUserExist = exports.checkDemandSourcePermission = exports.checkBusinessModelPermission = exports.checkFleetPermission = exports.getDecodedBearer = exports.getCurrentPayload = exports.eagerLoadPermissionsMiddleware = exports.middlewareWithDecode = exports.middleware = exports.User = exports.enableTracing = exports.newTrace = exports.traceTypes = void 0;
|
|
26
26
|
const outbreak_1 = __importDefault(require("@autofleet/outbreak"));
|
|
27
27
|
const user_1 = __importStar(require("./user"));
|
|
28
28
|
exports.User = user_1.default;
|
|
@@ -32,6 +32,8 @@ Object.defineProperty(exports, "middlewareWithDecode", { enumerable: true, get:
|
|
|
32
32
|
Object.defineProperty(exports, "getDecodedBearer", { enumerable: true, get: function () { return user_1.getDecodedBearer; } });
|
|
33
33
|
Object.defineProperty(exports, "appMiddleware", { enumerable: true, get: function () { return user_1.appMiddleware; } });
|
|
34
34
|
const tracer_1 = require("./tracer");
|
|
35
|
+
Object.defineProperty(exports, "newTrace", { enumerable: true, get: function () { return tracer_1.newTrace; } });
|
|
36
|
+
Object.defineProperty(exports, "traceTypes", { enumerable: true, get: function () { return tracer_1.traceTypes; } });
|
|
35
37
|
const check_permission_1 = require("./check-permission");
|
|
36
38
|
Object.defineProperty(exports, "checkFleetPermission", { enumerable: true, get: function () { return check_permission_1.checkFleetPermission; } });
|
|
37
39
|
Object.defineProperty(exports, "checkBusinessModelPermission", { enumerable: true, get: function () { return check_permission_1.checkBusinessModelPermission; } });
|
|
@@ -46,11 +48,16 @@ Object.defineProperty(exports, "getTokenSecret", { enumerable: true, get: functi
|
|
|
46
48
|
const getCurrentPayload = tracer_1.getCurrentTrace;
|
|
47
49
|
exports.getCurrentPayload = getCurrentPayload;
|
|
48
50
|
const enableTracing = ({ outbreakOptions = {} } = {}) => {
|
|
49
|
-
outbreak_1.default(
|
|
51
|
+
outbreak_1.default({
|
|
52
|
+
headersPrefix: 'x-af',
|
|
53
|
+
...outbreakOptions,
|
|
54
|
+
});
|
|
50
55
|
tracer_1.enable();
|
|
51
56
|
};
|
|
52
57
|
exports.enableTracing = enableTracing;
|
|
53
58
|
exports.default = {
|
|
59
|
+
traceTypes: tracer_1.traceTypes,
|
|
60
|
+
newTrace: tracer_1.newTrace,
|
|
54
61
|
User: user_1.default,
|
|
55
62
|
middleware: user_1.middleware,
|
|
56
63
|
middlewareWithDecode: user_1.middlewareWithDecode,
|
|
@@ -18,22 +18,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
24
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
25
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
26
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
27
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
|
-
});
|
|
29
|
-
};
|
|
30
21
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
31
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
23
|
};
|
|
33
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
25
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
35
26
|
const moment_1 = __importDefault(require("moment"));
|
|
36
|
-
const sleep = (ms) =>
|
|
27
|
+
const sleep = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
37
28
|
process.env.NODE_ENV = 'node-common-test';
|
|
38
29
|
describe('secret getter tests', () => {
|
|
39
30
|
const testSecrets = {
|
|
@@ -44,47 +35,50 @@ describe('secret getter tests', () => {
|
|
|
44
35
|
};
|
|
45
36
|
beforeEach(() => {
|
|
46
37
|
jest.resetModules();
|
|
47
|
-
process.env =
|
|
38
|
+
process.env = {
|
|
39
|
+
...(process.env || {}),
|
|
40
|
+
...testSecrets,
|
|
41
|
+
}; // Make a copy
|
|
48
42
|
});
|
|
49
|
-
it('test get new refresh token secret when after deprecation timestamp', () =>
|
|
43
|
+
it('test get new refresh token secret when after deprecation timestamp', async () => {
|
|
50
44
|
process.env.DEPRECATION_UNIX_TIMESTAMP = moment_1.default().subtract(1, 'days').unix().toString();
|
|
51
|
-
const { getTokenSecret } =
|
|
45
|
+
const { getTokenSecret } = await Promise.resolve().then(() => __importStar(require('./secret-getter')));
|
|
52
46
|
const token = jsonwebtoken_1.default.sign({
|
|
53
47
|
exp: moment_1.default().unix() + (60 * 60 * 24 * 365),
|
|
54
48
|
}, testSecrets.JWT_NEW_SECRET);
|
|
55
49
|
const result = getTokenSecret(token);
|
|
56
50
|
expect(result).toBe(testSecrets.JWT_NEW_SECRET);
|
|
57
|
-
})
|
|
58
|
-
it('test get old refresh token secret when before deprecation timestamp', () =>
|
|
51
|
+
});
|
|
52
|
+
it('test get old refresh token secret when before deprecation timestamp', async () => {
|
|
59
53
|
process.env.DEPRECATION_UNIX_TIMESTAMP = moment_1.default().add(1, 'days').unix().toString();
|
|
60
|
-
const { getTokenSecret } =
|
|
54
|
+
const { getTokenSecret } = await Promise.resolve().then(() => __importStar(require('./secret-getter')));
|
|
61
55
|
const token = jsonwebtoken_1.default.sign({
|
|
62
56
|
exp: moment_1.default().unix() + (60 * 60 * 24 * 365),
|
|
63
57
|
}, testSecrets.DEPRECATED_JWT_SECRET);
|
|
64
58
|
const result = getTokenSecret(token);
|
|
65
59
|
expect(result).toBe(testSecrets.DEPRECATED_JWT_SECRET);
|
|
66
|
-
})
|
|
67
|
-
it('test get old refresh token secret when after deprecation timestamp, but token is from before', () =>
|
|
60
|
+
});
|
|
61
|
+
it('test get old refresh token secret when after deprecation timestamp, but token is from before', async () => {
|
|
68
62
|
const token = jsonwebtoken_1.default.sign({
|
|
69
63
|
exp: moment_1.default().unix() + (60 * 60 * 24 * 365),
|
|
70
64
|
}, testSecrets.DEPRECATED_JWT_SECRET);
|
|
71
65
|
process.env.DEPRECATION_UNIX_TIMESTAMP = moment_1.default().add(10, 'seconds').unix().toString();
|
|
72
|
-
const { getTokenSecret } =
|
|
73
|
-
|
|
66
|
+
const { getTokenSecret } = await Promise.resolve().then(() => __importStar(require('./secret-getter')));
|
|
67
|
+
await sleep(1000);
|
|
74
68
|
const result = getTokenSecret(token);
|
|
75
69
|
expect(result).toBe(testSecrets.DEPRECATED_JWT_SECRET);
|
|
76
|
-
})
|
|
77
|
-
it('test malformed token returns new secret', () =>
|
|
78
|
-
const { getTokenSecret } =
|
|
70
|
+
});
|
|
71
|
+
it('test malformed token returns new secret', async () => {
|
|
72
|
+
const { getTokenSecret } = await Promise.resolve().then(() => __importStar(require('./secret-getter')));
|
|
79
73
|
const token = 'shit';
|
|
80
74
|
const result = getTokenSecret(token);
|
|
81
75
|
expect(result).toBe(testSecrets.JWT_NEW_SECRET);
|
|
82
|
-
})
|
|
83
|
-
it('test malformed token returns new secret even before deprecation time', () =>
|
|
76
|
+
});
|
|
77
|
+
it('test malformed token returns new secret even before deprecation time', async () => {
|
|
84
78
|
process.env.DEPRECATION_UNIX_TIMESTAMP = moment_1.default().add(10, 'day').unix().toString();
|
|
85
|
-
const { getTokenSecret } =
|
|
79
|
+
const { getTokenSecret } = await Promise.resolve().then(() => __importStar(require('./secret-getter')));
|
|
86
80
|
const token = 'shit';
|
|
87
81
|
const result = getTokenSecret(token);
|
|
88
82
|
expect(result).toBe(testSecrets.JWT_NEW_SECRET);
|
|
89
|
-
})
|
|
83
|
+
});
|
|
90
84
|
});
|
|
@@ -14,14 +14,13 @@ exports.setIdentityNock = (userAttributes) => {
|
|
|
14
14
|
.reply(200, userAttributes.permissions);
|
|
15
15
|
};
|
|
16
16
|
exports.mockRequestAndUser = (app, userCustomAttributes) => {
|
|
17
|
-
var _a, _b, _c;
|
|
18
17
|
const agent = supertest_1.default.agent(app);
|
|
19
18
|
const userAttributes = {
|
|
20
19
|
id: userCustomAttributes.id || uuid_1.v4(),
|
|
21
20
|
permissions: {
|
|
22
|
-
businessModels:
|
|
23
|
-
fleets:
|
|
24
|
-
demandSources:
|
|
21
|
+
businessModels: userCustomAttributes?.permissions?.businessModels || {},
|
|
22
|
+
fleets: userCustomAttributes?.permissions?.fleets || {},
|
|
23
|
+
demandSources: userCustomAttributes?.permissions?.demandSources || {},
|
|
25
24
|
},
|
|
26
25
|
};
|
|
27
26
|
agent.set('x-af-user-id', userAttributes.id);
|
package/lib/tracer.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ declare const tracer: {
|
|
|
3
3
|
currentTrace: any;
|
|
4
4
|
traces: {};
|
|
5
5
|
};
|
|
6
|
-
declare class Trace {
|
|
6
|
+
export declare class Trace {
|
|
7
7
|
id: string;
|
|
8
8
|
type: string;
|
|
9
9
|
context: Map<string, any>;
|
|
@@ -12,4 +12,9 @@ declare class Trace {
|
|
|
12
12
|
export declare const newTrace: (type: any) => Trace;
|
|
13
13
|
export declare const enable: () => asyncHooks.AsyncHook;
|
|
14
14
|
export declare const getCurrentTrace: () => any;
|
|
15
|
+
export declare const traceTypes: {
|
|
16
|
+
HTTP_REQUEST: string;
|
|
17
|
+
WEB_SOCKET: string;
|
|
18
|
+
RABBIT: string;
|
|
19
|
+
};
|
|
15
20
|
export default tracer;
|
package/lib/tracer.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getCurrentTrace = exports.enable = exports.newTrace = void 0;
|
|
6
|
+
exports.traceTypes = exports.getCurrentTrace = exports.enable = exports.newTrace = exports.Trace = void 0;
|
|
7
7
|
const async_hooks_1 = __importDefault(require("async_hooks"));
|
|
8
8
|
const uuid_1 = require("uuid");
|
|
9
9
|
const prevStates = {};
|
|
@@ -45,6 +45,7 @@ class Trace {
|
|
|
45
45
|
this.context = new Map();
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
+
exports.Trace = Trace;
|
|
48
49
|
exports.newTrace = (type) => {
|
|
49
50
|
tracer.currentTrace = new Trace(type);
|
|
50
51
|
tracer.traces[async_hooks_1.default.executionAsyncId()] = tracer.currentTrace;
|
|
@@ -52,4 +53,9 @@ exports.newTrace = (type) => {
|
|
|
52
53
|
};
|
|
53
54
|
exports.enable = () => hook.enable();
|
|
54
55
|
exports.getCurrentTrace = () => tracer.currentTrace || {};
|
|
56
|
+
exports.traceTypes = {
|
|
57
|
+
HTTP_REQUEST: 'httpRequest',
|
|
58
|
+
WEB_SOCKET: 'webSocket',
|
|
59
|
+
RABBIT: 'rabbit',
|
|
60
|
+
};
|
|
55
61
|
exports.default = tracer;
|
package/lib/user/ApiUser.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -34,38 +25,34 @@ class ApiUser {
|
|
|
34
25
|
this.accountType = accountType;
|
|
35
26
|
}
|
|
36
27
|
}
|
|
37
|
-
getUserPermissions() {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (this.privatePermissions) {
|
|
43
|
-
return this.privatePermissions;
|
|
44
|
-
}
|
|
45
|
-
const { data } = yield services_1.IdentityNetwork.get(`/api/v1/users/${this.id}/authorization-payload`);
|
|
46
|
-
this.accountType = data.accountType;
|
|
47
|
-
this.privatePermissions = data;
|
|
28
|
+
async getUserPermissions() {
|
|
29
|
+
if (!this.id) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (this.privatePermissions) {
|
|
48
33
|
return this.privatePermissions;
|
|
49
|
-
}
|
|
34
|
+
}
|
|
35
|
+
const { data } = await services_1.IdentityNetwork.get(`/api/v1/users/${this.id}/authorization-payload`);
|
|
36
|
+
this.accountType = data.accountType;
|
|
37
|
+
this.privatePermissions = data;
|
|
38
|
+
return this.privatePermissions;
|
|
50
39
|
}
|
|
51
|
-
useCustomPermissionLoader(customPermissionLoader) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (this.privatePermissions) {
|
|
57
|
-
return this.privatePermissions;
|
|
58
|
-
}
|
|
59
|
-
const cachedResult = userCache.get(this.id);
|
|
60
|
-
if (cachedResult) {
|
|
61
|
-
this.privatePermissions = cachedResult;
|
|
62
|
-
return cachedResult;
|
|
63
|
-
}
|
|
64
|
-
const data = yield customPermissionLoader(this.id);
|
|
65
|
-
userCache.set(this.id, data);
|
|
66
|
-
this.privatePermissions = data;
|
|
40
|
+
async useCustomPermissionLoader(customPermissionLoader) {
|
|
41
|
+
if (!this.id) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (this.privatePermissions) {
|
|
67
45
|
return this.privatePermissions;
|
|
68
|
-
}
|
|
46
|
+
}
|
|
47
|
+
const cachedResult = userCache.get(this.id);
|
|
48
|
+
if (cachedResult) {
|
|
49
|
+
this.privatePermissions = cachedResult;
|
|
50
|
+
return cachedResult;
|
|
51
|
+
}
|
|
52
|
+
const data = await customPermissionLoader(this.id);
|
|
53
|
+
userCache.set(this.id, data);
|
|
54
|
+
this.privatePermissions = data;
|
|
55
|
+
return this.privatePermissions;
|
|
69
56
|
}
|
|
70
57
|
get businessModels() {
|
|
71
58
|
return this.getUserProperty('businessModels');
|
|
@@ -123,18 +110,16 @@ class ApiUser {
|
|
|
123
110
|
currentUserTrace.context.set(exports.ELEVATED_PERMISSIONS_HEADER, JSON.stringify(this.elevatedPermissions));
|
|
124
111
|
};
|
|
125
112
|
}
|
|
126
|
-
getUserPermissionsLegacy() {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (this.privatePermissionsLegacy) {
|
|
132
|
-
return this.privatePermissionsLegacy;
|
|
133
|
-
}
|
|
134
|
-
const { data } = yield services_1.IdentityNetwork.get(`/api/v1/users/${this.id}/authorization-payload-legacy`);
|
|
135
|
-
this.privatePermissionsLegacy = data;
|
|
113
|
+
async getUserPermissionsLegacy() {
|
|
114
|
+
if (!this.id) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (this.privatePermissionsLegacy) {
|
|
136
118
|
return this.privatePermissionsLegacy;
|
|
137
|
-
}
|
|
119
|
+
}
|
|
120
|
+
const { data } = await services_1.IdentityNetwork.get(`/api/v1/users/${this.id}/authorization-payload-legacy`);
|
|
121
|
+
this.privatePermissionsLegacy = data;
|
|
122
|
+
return this.privatePermissionsLegacy;
|
|
138
123
|
}
|
|
139
124
|
get permissionsLegacy() {
|
|
140
125
|
if (!this.privatePermissionsLegacy) {
|
|
@@ -142,31 +127,29 @@ class ApiUser {
|
|
|
142
127
|
}
|
|
143
128
|
return this.privatePermissionsLegacy;
|
|
144
129
|
}
|
|
145
|
-
getUserAppPermissions(appId, clientSecret) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
},
|
|
165
|
-
});
|
|
166
|
-
userCache.set(this.id, data);
|
|
167
|
-
this.appPermission[appId] = data;
|
|
168
|
-
return this.appPermission[appId];
|
|
130
|
+
async getUserAppPermissions(appId, clientSecret) {
|
|
131
|
+
if (!this.id || !appId || !clientSecret) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const currentAppPermission = this.appPermission[appId];
|
|
135
|
+
if (currentAppPermission) {
|
|
136
|
+
return currentAppPermission;
|
|
137
|
+
}
|
|
138
|
+
const cachedResult = userCache.get(`${this.id}:${appId}`);
|
|
139
|
+
if (cachedResult) {
|
|
140
|
+
this.appPermission[appId] = cachedResult;
|
|
141
|
+
return cachedResult;
|
|
142
|
+
}
|
|
143
|
+
const { data } = await services_1.AutofleetApiNetwork.post(`/api/v1/apps/${appId}/get-user-payload`, {
|
|
144
|
+
userId: this.id,
|
|
145
|
+
}, {
|
|
146
|
+
headers: {
|
|
147
|
+
'x-autofleet-apps-secret': clientSecret,
|
|
148
|
+
},
|
|
169
149
|
});
|
|
150
|
+
userCache.set(this.id, data);
|
|
151
|
+
this.appPermission[appId] = data;
|
|
152
|
+
return this.appPermission[appId];
|
|
170
153
|
}
|
|
171
154
|
}
|
|
172
155
|
exports.default = ApiUser;
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -17,19 +8,19 @@ const express_1 = __importDefault(require("express"));
|
|
|
17
8
|
const axios_1 = __importDefault(require("axios"));
|
|
18
9
|
const index_1 = require("../index");
|
|
19
10
|
const index_2 = require("./index");
|
|
20
|
-
const generateApp = (addEndpoints, port) =>
|
|
11
|
+
const generateApp = async (addEndpoints, port) => {
|
|
21
12
|
const app = express_1.default();
|
|
22
13
|
addEndpoints(app);
|
|
23
|
-
const server =
|
|
14
|
+
const server = await new Promise((resolve) => {
|
|
24
15
|
const s = app.listen(port, () => {
|
|
25
16
|
console.log('Listen on port', port);
|
|
26
17
|
resolve(s);
|
|
27
18
|
});
|
|
28
19
|
});
|
|
29
20
|
return () => server.close();
|
|
30
|
-
}
|
|
21
|
+
};
|
|
31
22
|
describe('E2E', () => {
|
|
32
|
-
it('Basic functionality', () =>
|
|
23
|
+
it('Basic functionality', async () => {
|
|
33
24
|
let server2TraceId = null;
|
|
34
25
|
const [uuid1, uuid2] = [uuid_1.v4(), uuid_1.v4()];
|
|
35
26
|
index_1.enableTracing({
|
|
@@ -37,9 +28,9 @@ describe('E2E', () => {
|
|
|
37
28
|
headersPrefix: 'x-af-',
|
|
38
29
|
},
|
|
39
30
|
});
|
|
40
|
-
const closeServer1 =
|
|
31
|
+
const closeServer1 = await generateApp((app) => {
|
|
41
32
|
app.use(index_2.middleware());
|
|
42
|
-
app.get('/', (req, res) =>
|
|
33
|
+
app.get('/', async (req, res) => {
|
|
43
34
|
const user = index_1.getUser();
|
|
44
35
|
const closeElevation1 = user.elevatePermissions({
|
|
45
36
|
businessModels: {
|
|
@@ -51,15 +42,15 @@ describe('E2E', () => {
|
|
|
51
42
|
[uuid2]: ['vehicle:write'],
|
|
52
43
|
},
|
|
53
44
|
});
|
|
54
|
-
const { data: res1 } =
|
|
45
|
+
const { data: res1 } = await axios_1.default.post('http://localhost:8082');
|
|
55
46
|
closeElevation1();
|
|
56
|
-
const { data: res2 } =
|
|
47
|
+
const { data: res2 } = await axios_1.default.post('http://localhost:8082');
|
|
57
48
|
closeElevation2();
|
|
58
49
|
res.json([res1, res2]);
|
|
59
|
-
})
|
|
50
|
+
});
|
|
60
51
|
}, 8089);
|
|
61
52
|
const server2NumberOfPermissions = [];
|
|
62
|
-
const closeServer2 =
|
|
53
|
+
const closeServer2 = await generateApp((app) => {
|
|
63
54
|
app.use(index_2.middleware());
|
|
64
55
|
app.post('/', (req, res) => {
|
|
65
56
|
const user = index_1.getUser();
|
|
@@ -77,7 +68,7 @@ describe('E2E', () => {
|
|
|
77
68
|
});
|
|
78
69
|
});
|
|
79
70
|
}, 8082);
|
|
80
|
-
const { data: [res1, res2], headers } =
|
|
71
|
+
const { data: [res1, res2], headers } = await axios_1.default.get('http://localhost:8089', {
|
|
81
72
|
headers: {
|
|
82
73
|
'x-af-header': 'testHeader',
|
|
83
74
|
'x-af-id': 'my-wakanda-id',
|
|
@@ -94,17 +85,17 @@ describe('E2E', () => {
|
|
|
94
85
|
expect(JSON.parse(res1.addedPermissions).businessModels[uuid2]).toBeDefined();
|
|
95
86
|
expect(JSON.parse(res2.addedPermissions).businessModels[uuid1]).not.toBeDefined();
|
|
96
87
|
expect(JSON.parse(res2.addedPermissions).businessModels[uuid2]).toBeDefined();
|
|
97
|
-
})
|
|
98
|
-
it('Should throw in case of invalid UUID', () =>
|
|
88
|
+
});
|
|
89
|
+
it('Should throw in case of invalid UUID', async () => {
|
|
99
90
|
let error = null;
|
|
100
91
|
index_1.enableTracing({
|
|
101
92
|
outbreakOptions: {
|
|
102
93
|
headersPrefix: 'x-af-',
|
|
103
94
|
},
|
|
104
95
|
});
|
|
105
|
-
const closeServer1 =
|
|
96
|
+
const closeServer1 = await generateApp((app) => {
|
|
106
97
|
app.use(index_2.middleware());
|
|
107
|
-
app.get('/', (req, res) =>
|
|
98
|
+
app.get('/', async (req, res) => {
|
|
108
99
|
const user = index_1.getUser();
|
|
109
100
|
try {
|
|
110
101
|
const closeElevation1 = user.elevatePermissions({
|
|
@@ -112,16 +103,16 @@ describe('E2E', () => {
|
|
|
112
103
|
nnn: ['vehicle:write'],
|
|
113
104
|
},
|
|
114
105
|
});
|
|
115
|
-
|
|
106
|
+
await axios_1.default.post('http://localhost:8082');
|
|
116
107
|
closeElevation1();
|
|
117
108
|
}
|
|
118
109
|
catch (e) {
|
|
119
110
|
error = e;
|
|
120
111
|
}
|
|
121
112
|
res.json({ status: 'ok' });
|
|
122
|
-
})
|
|
113
|
+
});
|
|
123
114
|
}, 8089);
|
|
124
|
-
|
|
115
|
+
await axios_1.default.get('http://localhost:8089', {
|
|
125
116
|
headers: {
|
|
126
117
|
'x-af-header': 'testHeader',
|
|
127
118
|
'x-af-id': 'my-wakanda-id',
|
|
@@ -130,5 +121,5 @@ describe('E2E', () => {
|
|
|
130
121
|
});
|
|
131
122
|
closeServer1();
|
|
132
123
|
expect(error.message).toEqual('Entity id on elevatePermissions is not a valid UUID, provided: nnn');
|
|
133
|
-
})
|
|
124
|
+
});
|
|
134
125
|
});
|
package/lib/user/index.js
CHANGED
|
@@ -18,15 +18,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
24
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
25
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
26
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
27
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
|
-
});
|
|
29
|
-
};
|
|
30
21
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
31
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
23
|
};
|
|
@@ -38,7 +29,7 @@ const tracer_1 = require("../tracer");
|
|
|
38
29
|
const app_auth_1 = require("../app-auth");
|
|
39
30
|
const appDoesNotExist_1 = __importDefault(require("../exceptions/appDoesNotExist"));
|
|
40
31
|
const utils_1 = require("../utils");
|
|
41
|
-
exports.middleware = (options = {}) => (req, res, next) =>
|
|
32
|
+
exports.middleware = (options = {}) => async (req, res, next) => {
|
|
42
33
|
try {
|
|
43
34
|
const { eagerLoadUserPermissions, eagerLoadUserPermissionsLegacy, customPermissionLoader, } = options;
|
|
44
35
|
const userId = req.headers['x-af-user-id'];
|
|
@@ -52,14 +43,14 @@ exports.middleware = (options = {}) => (req, res, next) => __awaiter(void 0, voi
|
|
|
52
43
|
const userObject = new ApiUser_1.default(userId, 'user', elevatedPermissionsFromHeader);
|
|
53
44
|
if (eagerLoadUserPermissions) {
|
|
54
45
|
if (customPermissionLoader) {
|
|
55
|
-
|
|
46
|
+
await userObject.useCustomPermissionLoader(customPermissionLoader);
|
|
56
47
|
}
|
|
57
48
|
else {
|
|
58
|
-
|
|
49
|
+
await userObject.getUserPermissions();
|
|
59
50
|
}
|
|
60
51
|
}
|
|
61
52
|
if (eagerLoadUserPermissionsLegacy) {
|
|
62
|
-
|
|
53
|
+
await userObject.getUserPermissionsLegacy();
|
|
63
54
|
}
|
|
64
55
|
req.user = userObject;
|
|
65
56
|
trace.context.set('userObject', userObject);
|
|
@@ -73,15 +64,14 @@ exports.middleware = (options = {}) => (req, res, next) => __awaiter(void 0, voi
|
|
|
73
64
|
error: 'cannot authenticate user',
|
|
74
65
|
});
|
|
75
66
|
}
|
|
76
|
-
}
|
|
77
|
-
exports.middlewareWithDecode = (options = {}) => (req, res, next) =>
|
|
78
|
-
var _a, _b;
|
|
67
|
+
};
|
|
68
|
+
exports.middlewareWithDecode = (options = {}) => async (req, res, next) => {
|
|
79
69
|
const { eagerLoadUserPermissions, eagerLoadUserPermissionsLegacy, returnErrorIfNoToken, } = options;
|
|
80
70
|
const trace = tracer_1.newTrace('userPayload');
|
|
81
71
|
let decoded;
|
|
82
72
|
if (req.headers.authorization) {
|
|
83
73
|
try {
|
|
84
|
-
decoded =
|
|
74
|
+
decoded = await utils_1.decodeBearer(req.headers.authorization);
|
|
85
75
|
}
|
|
86
76
|
catch (e) {
|
|
87
77
|
if (e instanceof jsonwebtoken_1.TokenExpiredError) {
|
|
@@ -104,16 +94,16 @@ exports.middlewareWithDecode = (options = {}) => (req, res, next) => __awaiter(v
|
|
|
104
94
|
}
|
|
105
95
|
return;
|
|
106
96
|
}
|
|
107
|
-
const userId =
|
|
97
|
+
const userId = decoded?.user?.id;
|
|
108
98
|
if (userId) {
|
|
109
99
|
req.headers['X-AF-USER-ID'] = userId;
|
|
110
100
|
}
|
|
111
|
-
const userObject = new ApiUser_1.default(userId,
|
|
101
|
+
const userObject = new ApiUser_1.default(userId, decoded?.user?.accountType);
|
|
112
102
|
if (eagerLoadUserPermissions) {
|
|
113
|
-
|
|
103
|
+
await userObject.getUserPermissions();
|
|
114
104
|
}
|
|
115
105
|
if (eagerLoadUserPermissionsLegacy) {
|
|
116
|
-
|
|
106
|
+
await userObject.getUserPermissionsLegacy();
|
|
117
107
|
}
|
|
118
108
|
req.user = userObject;
|
|
119
109
|
trace.context.set('userObject', userObject);
|
|
@@ -129,8 +119,8 @@ exports.middlewareWithDecode = (options = {}) => (req, res, next) => __awaiter(v
|
|
|
129
119
|
}
|
|
130
120
|
// eslint-disable-next-line consistent-return
|
|
131
121
|
return next();
|
|
132
|
-
}
|
|
133
|
-
exports.appMiddleware = (options) => (req, res, next) =>
|
|
122
|
+
};
|
|
123
|
+
exports.appMiddleware = (options) => async (req, res, next) => {
|
|
134
124
|
const { appId, clientSecret, } = options;
|
|
135
125
|
const trace = tracer_1.newTrace('userPayload');
|
|
136
126
|
let decoded;
|
|
@@ -141,7 +131,7 @@ exports.appMiddleware = (options) => (req, res, next) => __awaiter(void 0, void
|
|
|
141
131
|
});
|
|
142
132
|
}
|
|
143
133
|
try {
|
|
144
|
-
decoded =
|
|
134
|
+
decoded = await app_auth_1.decodeAppBearer(req.headers.authorization, appId);
|
|
145
135
|
if (!decoded) {
|
|
146
136
|
throw new appDoesNotExist_1.default();
|
|
147
137
|
}
|
|
@@ -170,7 +160,7 @@ exports.appMiddleware = (options) => (req, res, next) => __awaiter(void 0, void
|
|
|
170
160
|
errors: ['Server error while parsing token'],
|
|
171
161
|
});
|
|
172
162
|
}
|
|
173
|
-
const userId = decoded
|
|
163
|
+
const userId = decoded?.userId;
|
|
174
164
|
if (userId) {
|
|
175
165
|
req.headers['X-AF-USER-ID'] = userId;
|
|
176
166
|
}
|
|
@@ -178,7 +168,7 @@ exports.appMiddleware = (options) => (req, res, next) => __awaiter(void 0, void
|
|
|
178
168
|
if (appId) {
|
|
179
169
|
req.headers['x-autofleet-apps-secret'] = clientSecret;
|
|
180
170
|
// Won't work until we find a better solution for identity ms
|
|
181
|
-
|
|
171
|
+
await userObject.getUserAppPermissions(appId, clientSecret);
|
|
182
172
|
}
|
|
183
173
|
req.user = userObject;
|
|
184
174
|
trace.context.set('userObject', userObject);
|
|
@@ -186,11 +176,11 @@ exports.appMiddleware = (options) => (req, res, next) => __awaiter(void 0, void
|
|
|
186
176
|
// Added in order to support outbreak.
|
|
187
177
|
req.headers['x-af-user-permissions'] = userObject;
|
|
188
178
|
return next();
|
|
189
|
-
}
|
|
190
|
-
exports.eagerLoadPermissionsMiddleware = (req, res, next) =>
|
|
191
|
-
|
|
179
|
+
};
|
|
180
|
+
exports.eagerLoadPermissionsMiddleware = async (req, res, next) => {
|
|
181
|
+
await req.user.getUserPermissions();
|
|
192
182
|
return next();
|
|
193
|
-
}
|
|
183
|
+
};
|
|
194
184
|
exports.getDecodedBearer = (req) => {
|
|
195
185
|
if (req.headers.authorization) {
|
|
196
186
|
return utils_1.decodeBearer(req.headers.authorization);
|
package/lib/utils.js
CHANGED
|
@@ -36,13 +36,12 @@ exports.decodeBearer = (bearer, appSecret) => {
|
|
|
36
36
|
return decoded;
|
|
37
37
|
};
|
|
38
38
|
exports.parsePermissions = (contextId, decodedToken) => {
|
|
39
|
-
var _a;
|
|
40
39
|
if (!decodedToken) {
|
|
41
40
|
return [];
|
|
42
41
|
}
|
|
43
42
|
const contexts = decodedToken.contexts;
|
|
44
43
|
const activeContext = contexts.find((context) => context.id === contextId);
|
|
45
|
-
const permissionsValue = `${
|
|
44
|
+
const permissionsValue = `${activeContext.permissions?.map((cp) => `${cp},`)}`;
|
|
46
45
|
return {
|
|
47
46
|
key: activeContext.entityId,
|
|
48
47
|
value: permissionsValue,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/zehut",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-beta.0",
|
|
4
4
|
"description": "manage user's identity",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -12,10 +12,6 @@
|
|
|
12
12
|
"test-auto": "jest --watch --runInBand",
|
|
13
13
|
"linter": "./node_modules/.bin/eslint ."
|
|
14
14
|
},
|
|
15
|
-
"jest": {
|
|
16
|
-
"verbose": true,
|
|
17
|
-
"testURL": "http://localhost/"
|
|
18
|
-
},
|
|
19
15
|
"repository": {
|
|
20
16
|
"type": "git",
|
|
21
17
|
"url": "git+ssh://git@gitlab.com/AutoFleet/zehut.git"
|
|
@@ -46,7 +42,7 @@
|
|
|
46
42
|
"eslint": "^7.13.0",
|
|
47
43
|
"eslint-config-airbnb-typescript": "^12.0.0",
|
|
48
44
|
"eslint-plugin-import": "^2.22.1",
|
|
49
|
-
"jest": "^
|
|
45
|
+
"jest": "^24.9.0",
|
|
50
46
|
"ts-jest": "^25.4.0",
|
|
51
47
|
"typescript": "^3.9.5"
|
|
52
48
|
},
|