@nextage/nx-frame-be 1.0.44 → 1.0.45
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/build/common/base/__test__/before-get-contract.test.d.ts +16 -0
- package/build/common/base/__test__/before-get-contract.test.js +90 -0
- package/build/common/base/base.model.js +5 -2
- package/build/common/crypto/index.d.ts +1 -0
- package/build/common/crypto/index.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*********************************************************************************************
|
|
2
|
+
* *
|
|
3
|
+
* BEFOREGET CONTRACT *
|
|
4
|
+
* *
|
|
5
|
+
* `beforeGet` is declared `Promise<FilterParams>`, so the filter it returns is part of the *
|
|
6
|
+
* contract. `get` used to await it and throw the result away, handing `findOne` the object *
|
|
7
|
+
* it had built itself - which worked only because every override in existence MUTATES its *
|
|
8
|
+
* argument. *
|
|
9
|
+
* *
|
|
10
|
+
* That difference is invisible at compile time and silent at run time, and it is the whole *
|
|
11
|
+
* point of this file: an override written in pure style - `return { ...filter, tenantId }`, *
|
|
12
|
+
* the shape the signature invites - compiled, passed review, and read across every tenant. *
|
|
13
|
+
* These tests state that BOTH styles scope the read. *
|
|
14
|
+
* *
|
|
15
|
+
*********************************************************************************************/
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*********************************************************************************************
|
|
3
|
+
* *
|
|
4
|
+
* BEFOREGET CONTRACT *
|
|
5
|
+
* *
|
|
6
|
+
* `beforeGet` is declared `Promise<FilterParams>`, so the filter it returns is part of the *
|
|
7
|
+
* contract. `get` used to await it and throw the result away, handing `findOne` the object *
|
|
8
|
+
* it had built itself - which worked only because every override in existence MUTATES its *
|
|
9
|
+
* argument. *
|
|
10
|
+
* *
|
|
11
|
+
* That difference is invisible at compile time and silent at run time, and it is the whole *
|
|
12
|
+
* point of this file: an override written in pure style - `return { ...filter, tenantId }`, *
|
|
13
|
+
* the shape the signature invites - compiled, passed review, and read across every tenant. *
|
|
14
|
+
* These tests state that BOTH styles scope the read. *
|
|
15
|
+
* *
|
|
16
|
+
*********************************************************************************************/
|
|
17
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
18
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
19
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
20
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
21
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
22
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
23
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
const base_model_1 = require("../base.model");
|
|
28
|
+
const mongo_utils_1 = require("../mongo-utils");
|
|
29
|
+
/** Scopes the read the way every override in the wild does today: by MUTATING the filter. */
|
|
30
|
+
class MutatingModel extends base_model_1.BaseModel {
|
|
31
|
+
beforeGet() {
|
|
32
|
+
return __awaiter(this, arguments, void 0, function* (filter = {}, context = {}) {
|
|
33
|
+
filter.tenantId = context.tenantId;
|
|
34
|
+
return filter;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Scopes the read in pure style - the shape the `Promise<FilterParams>` signature invites. */
|
|
39
|
+
class PureModel extends base_model_1.BaseModel {
|
|
40
|
+
beforeGet() {
|
|
41
|
+
return __awaiter(this, arguments, void 0, function* (filter = {}, context = {}) {
|
|
42
|
+
return Object.assign(Object.assign({}, filter), { tenantId: context.tenantId });
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const schema = {
|
|
47
|
+
code: { type: String, required: true },
|
|
48
|
+
tenantId: { type: String, required: true },
|
|
49
|
+
};
|
|
50
|
+
const mutating = (0, mongo_utils_1.createModel)({
|
|
51
|
+
name: 'BeforeGetMutating',
|
|
52
|
+
modelName: 'BeforeGetMutating',
|
|
53
|
+
collection: 'beforeGetMutating',
|
|
54
|
+
classDef: MutatingModel,
|
|
55
|
+
modelParams: {},
|
|
56
|
+
schema
|
|
57
|
+
}, true);
|
|
58
|
+
const pure = (0, mongo_utils_1.createModel)({
|
|
59
|
+
name: 'BeforeGetPure',
|
|
60
|
+
modelName: 'BeforeGetPure',
|
|
61
|
+
collection: 'beforeGetPure',
|
|
62
|
+
classDef: PureModel,
|
|
63
|
+
modelParams: {},
|
|
64
|
+
schema
|
|
65
|
+
}, true);
|
|
66
|
+
describe('BaseModel.get honours the filter beforeGet returns', () => {
|
|
67
|
+
const owner = { tenantId: 'tenant-a' };
|
|
68
|
+
const outsider = { tenantId: 'tenant-b' };
|
|
69
|
+
let mutatingId;
|
|
70
|
+
let pureId;
|
|
71
|
+
// Inserted per test: the shared setup empties every collection before each one.
|
|
72
|
+
beforeEach(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
73
|
+
const a = yield mutating.mgModel.collection.insertOne({ code: 'A', tenantId: owner.tenantId });
|
|
74
|
+
const b = yield pure.mgModel.collection.insertOne({ code: 'B', tenantId: owner.tenantId });
|
|
75
|
+
mutatingId = a.insertedId.toString();
|
|
76
|
+
pureId = b.insertedId.toString();
|
|
77
|
+
}));
|
|
78
|
+
it('denies a foreign read when the override MUTATES the filter', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
79
|
+
expect(yield mutating.get(mutatingId, outsider)).toBeNull();
|
|
80
|
+
}));
|
|
81
|
+
// The one that used to pass in silence: the filter handed to `findOne` was the untouched
|
|
82
|
+
// `{ _id }`, so another tenant's document came back in full.
|
|
83
|
+
it('denies a foreign read when the override RETURNS a new filter', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
84
|
+
expect(yield pure.get(pureId, outsider)).toBeNull();
|
|
85
|
+
}));
|
|
86
|
+
it('still finds the document for its own tenant, in both styles', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
87
|
+
expect(yield mutating.get(mutatingId, owner)).not.toBeNull();
|
|
88
|
+
expect(yield pure.get(pureId, owner)).not.toBeNull();
|
|
89
|
+
}));
|
|
90
|
+
});
|
|
@@ -213,8 +213,11 @@ class BaseModel extends events_1.EventEmitter {
|
|
|
213
213
|
return __awaiter(this, arguments, void 0, function* (id, context = {}) {
|
|
214
214
|
if (!id)
|
|
215
215
|
return null;
|
|
216
|
-
|
|
217
|
-
|
|
216
|
+
// The RETURNED filter is the one that counts. This used to discard it and query with
|
|
217
|
+
// the object built here, which worked only because every override mutates its argument:
|
|
218
|
+
// one written in pure style - `return { ...filter, tenantId }`, the shape this very
|
|
219
|
+
// signature invites - compiled, read across every tenant, and said nothing.
|
|
220
|
+
const filter = yield this.beforeGet({ _id: (0, mongo_utils_1.toObjectId)(id) }, context);
|
|
218
221
|
return this.mgModel.findOne(filter, null, { session: context === null || context === void 0 ? void 0 : context.session });
|
|
219
222
|
});
|
|
220
223
|
}
|
|
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./crypto.interfaces"), exports);
|
|
18
|
+
__exportStar(require("./crypto.constants"), exports);
|
|
18
19
|
__exportStar(require("./crypto.classes"), exports);
|
|
19
20
|
__exportStar(require("./crypto.utils"), exports);
|
|
20
21
|
__exportStar(require("./crypto-legacy"), exports);
|