@proteinjs/db 1.27.0 → 1.28.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/dist/generated/index.js +1 -1
- package/dist/generated/index.js.map +1 -1
- package/dist/generated/test/index.js +5 -5
- package/dist/generated/test/index.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/src/MigrationRunner.d.ts +9 -0
- package/dist/src/MigrationRunner.d.ts.map +1 -1
- package/dist/src/MigrationRunner.js +24 -10
- package/dist/src/MigrationRunner.js.map +1 -1
- package/dist/src/auth/TableAuth.d.ts +7 -1
- package/dist/src/auth/TableAuth.d.ts.map +1 -1
- package/dist/src/auth/TableAuth.js +7 -1
- package/dist/src/auth/TableAuth.js.map +1 -1
- package/dist/src/tables/MigrationTable.d.ts +7 -0
- package/dist/src/tables/MigrationTable.d.ts.map +1 -1
- package/dist/src/tables/MigrationTable.js +10 -0
- package/dist/src/tables/MigrationTable.js.map +1 -1
- package/dist/src/transaction/TransactionContextFactory.d.ts +1 -1
- package/dist/test/MigrationAuth.test.d.ts +2 -0
- package/dist/test/MigrationAuth.test.d.ts.map +1 -0
- package/dist/test/MigrationAuth.test.js +77 -0
- package/dist/test/MigrationAuth.test.js.map +1 -0
- package/dist/test/MigrationRunnerContainment.test.d.ts +2 -0
- package/dist/test/MigrationRunnerContainment.test.d.ts.map +1 -0
- package/dist/test/MigrationRunnerContainment.test.js +144 -0
- package/dist/test/MigrationRunnerContainment.test.js.map +1 -0
- package/dist/test/TableServiceAuth.test.js +67 -0
- package/dist/test/TableServiceAuth.test.js.map +1 -1
- package/dist/test/index.d.ts +1 -0
- package/dist/test/index.d.ts.map +1 -1
- package/dist/test/index.js +1 -0
- package/dist/test/index.js.map +1 -1
- package/dist/test/util/DbTestEnvironment.d.ts.map +1 -1
- package/dist/test/util/DbTestEnvironment.js +5 -0
- package/dist/test/util/DbTestEnvironment.js.map +1 -1
- package/dist/test/util/testUser.d.ts +5 -0
- package/dist/test/util/testUser.d.ts.map +1 -0
- package/dist/test/util/testUser.js +17 -0
- package/dist/test/util/testUser.js.map +1 -0
- package/generated/index.ts +18 -15
- package/generated/test/index.ts +44 -41
- package/index.ts +2 -0
- package/package.json +5 -6
- package/src/MigrationRunner.ts +20 -5
- package/src/auth/TableAuth.ts +13 -2
- package/src/tables/MigrationTable.ts +10 -0
- package/test/MigrationAuth.test.ts +87 -0
- package/test/MigrationRunnerContainment.test.ts +104 -0
- package/test/TableServiceAuth.test.ts +90 -1
- package/test/index.ts +2 -0
- package/test/util/DbTestEnvironment.ts +5 -0
- package/test/util/testUser.ts +27 -0
- package/LICENSE +0 -21
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../generated/test/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,+BAA6B;AAC7B,6BAA2B;AAC3B,iCAA+B;AAC/B,iCAA+B;AAC/B,iCAA+B;AAC/B,8BAA4B;AAC5B,gCAA8B;AAC9B,2BAAyB;AACzB,kBAAgB;AAChB,gBAAc;AAGd,4BAA4B;AAE5B,IAAM,WAAW,GAAG,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../generated/test/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,+BAA6B;AAC7B,6BAA2B;AAC3B,iCAA+B;AAC/B,iCAA+B;AAC/B,iCAA+B;AAC/B,8BAA4B;AAC5B,gCAA8B;AAC9B,2BAAyB;AACzB,kBAAgB;AAChB,gBAAc;AAGd,4BAA4B;AAE5B,IAAM,WAAW,GAAG,w5hGAAw5hG,CAAC;AAG76hG,4BAA4B;AAE5B,0FAAgF;AAChF,yCAAwC;AACxC,0FAA+E;AAC/E,0FAAgF;AAChF,0FAA+E;AAC/E,0FAAgF;AAChF,0FAA+E;AAC/E,0FAA2E;AAC3E,0FAA8E;AAC9E,0FAAmF;AACnF,2FAAkF;AAClF,2FAA6E;AAC7E,2FAA2E;AAC3E,sFAAyE;AACzE,wEAA0E;AAC1E,wEAA8E;AAC9E,4GAAiG;AACjG,4GAAwF;AACxF,4GAAwF;AACxF,4GAA8F;AAC9F,wFAA8E;AAC9E,wFAAqF;AACrF,wFAAiF;AACjF,sFAA4F;AAC5F,sFAAgG;AAChG,mCAAkC;AAClC,iEAAgE;AAChE,6DAA4D;AAC5D,2FAA0F;AAC1F,iFAAgF;AAChF,yEAAwE;AACxE,0EAAyE;AACzE,kEAAiE;AACjE,6EAA4E;AAC5E,2DAA0D;AAC1D,qEAAoE;AAEpE,IAAM,WAAW,GAAG;IACnB,8BAA8B,EAAE,wCAAc;IAC9C,qBAAqB,EAAE,aAAK;IAC5B,6BAA6B,EAAE,uCAAa;IAC5C,8BAA8B,EAAE,wCAAc;IAC9C,6BAA6B,EAAE,uCAAa;IAC5C,8BAA8B,EAAE,wCAAc;IAC9C,6BAA6B,EAAE,uCAAa;IAC5C,yBAAyB,EAAE,mCAAS;IACpC,4BAA4B,EAAE,sCAAY;IAC1C,iCAAiC,EAAE,2CAAiB;IACpD,gCAAgC,EAAE,2CAAgB;IAClD,2BAA2B,EAAE,sCAAW;IACxC,yBAAyB,EAAE,oCAAS;IACpC,yBAAyB,EAAE,iCAAS;IACpC,iCAAiC,EAAE,kCAAiB;IACpD,qCAAqC,EAAE,sCAAqB;IAC5D,sCAAsC,EAAE,yDAAsB;IAC9D,6BAA6B,EAAE,gDAAa;IAC5C,6BAA6B,EAAE,gDAAa;IAC5C,mCAAmC,EAAE,sDAAmB;IACxD,6BAA6B,EAAE,sCAAa;IAC5C,oCAAoC,EAAE,6CAAoB;IAC1D,gCAAgC,EAAE,yCAAgB;IAClD,4CAA4C,EAAE,oDAA4B;IAC1E,gDAAgD,EAAE,wDAAgC;IAClF,kBAAkB,EAAE,OAAE;IACtB,iCAAiC,EAAE,qCAAiB;IACpD,+BAA+B,EAAE,iCAAe;IAChD,wCAAwC,EAAE,mDAAwB;IAClE,mCAAmC,EAAE,yCAAmB;IACxD,+BAA+B,EAAE,iCAAe;IAChD,kCAAkC,EAAE,uCAAkB;IACtD,8BAA8B,EAAE,+BAAc;IAC9C,iCAAiC,EAAE,qCAAiB;IACpD,yBAAyB,EAAE,qBAAS;IACpC,8BAA8B,EAAE,+BAAc;CAC9C,CAAC;AAGF,kCAAkC;AAElC,oDAAyD;AACzD,6BAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAGjD,mDAAiC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export * from './src/UpdatePreserving';
|
|
|
11
11
|
export * from './src/reference/ReferenceCache';
|
|
12
12
|
export * from './src/RecordIterator';
|
|
13
13
|
export * from './src/source/SourceRecord';
|
|
14
|
+
export * from './src/source/SourceRecordRepo';
|
|
15
|
+
export * from './src/MigrationRunner';
|
|
14
16
|
export * from './src/QueryBuilderFactory';
|
|
15
17
|
export * from './src/TableWatcher';
|
|
16
18
|
export * from './src/transaction/Transaction';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC;AACnD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,6CAA6C,CAAC;AAE5D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAE1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAE5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,uCAAuC,CAAC;AACtD,cAAc,yCAAyC,CAAC;AAExD,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC;AACnD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,6CAA6C,CAAC;AAE5D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAE1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAE5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,uCAAuC,CAAC;AACtD,cAAc,yCAAyC,CAAC;AAExD,cAAc,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -27,6 +27,8 @@ __exportStar(require("./src/UpdatePreserving"), exports);
|
|
|
27
27
|
__exportStar(require("./src/reference/ReferenceCache"), exports);
|
|
28
28
|
__exportStar(require("./src/RecordIterator"), exports);
|
|
29
29
|
__exportStar(require("./src/source/SourceRecord"), exports);
|
|
30
|
+
__exportStar(require("./src/source/SourceRecordRepo"), exports);
|
|
31
|
+
__exportStar(require("./src/MigrationRunner"), exports);
|
|
30
32
|
__exportStar(require("./src/QueryBuilderFactory"), exports);
|
|
31
33
|
__exportStar(require("./src/TableWatcher"), exports);
|
|
32
34
|
__exportStar(require("./src/transaction/Transaction"), exports);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,8CAA4B;AAC5B,uDAAqC;AACrC,8DAA4C;AAC5C,gDAA8B;AAC9B,+CAA6B;AAC7B,iEAA+C;AAC/C,qEAAmD;AACnD,4DAA0C;AAC1C,yDAAuC;AACvC,iEAA+C;AAC/C,uDAAqC;AACrC,4DAA0C;AAC1C,4DAA0C;AAC1C,qDAAmC;AACnC,gEAA8C;AAC9C,sEAAoD;AACpD,8EAA4D;AAE5D,gEAA8C;AAC9C,8DAA4C;AAC5C,4DAA0C;AAE1C,sDAAoC;AACpC,8DAA4C;AAE5C,2DAAyC;AACzC,wEAAsD;AACtD,0EAAwD;AAExD,sDAAoC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,8CAA4B;AAC5B,uDAAqC;AACrC,8DAA4C;AAC5C,gDAA8B;AAC9B,+CAA6B;AAC7B,iEAA+C;AAC/C,qEAAmD;AACnD,4DAA0C;AAC1C,yDAAuC;AACvC,iEAA+C;AAC/C,uDAAqC;AACrC,4DAA0C;AAC1C,gEAA8C;AAC9C,wDAAsC;AACtC,4DAA0C;AAC1C,qDAAmC;AACnC,gEAA8C;AAC9C,sEAAoD;AACpD,8EAA4D;AAE5D,gEAA8C;AAC9C,8DAA4C;AAC5C,4DAA0C;AAE1C,sDAAoC;AACpC,8DAA4C;AAE5C,2DAAyC;AACzC,wEAAsD;AACtD,0EAAwD;AAExD,sDAAoC"}
|
|
@@ -4,7 +4,16 @@ export declare const getMigrationRunner: () => MigrationRunner;
|
|
|
4
4
|
export declare class MigrationRunner implements MigrationRunnerService {
|
|
5
5
|
private logger;
|
|
6
6
|
serviceMetadata: Service['serviceMetadata'];
|
|
7
|
+
/**
|
|
8
|
+
* The service dispatches this fire-and-forget (`doNotAwait`). The method is split along that
|
|
9
|
+
* seam: everything knowable before the run starts (a bogus id) throws synchronously — the only
|
|
10
|
+
* path on which an error can still reach the client (the executor wraps it into a
|
|
11
|
+
* ServiceError -> 400). The returned promise MAY REJECT (infrastructure failure while recording
|
|
12
|
+
* run state); the caller owns that rejection — on the service path the executor terminally
|
|
13
|
+
* observes every doNotAwait rejection (logs with method identity, never process death).
|
|
14
|
+
*/
|
|
7
15
|
runMigration(id: string): Promise<void>;
|
|
16
|
+
private runAndRecord;
|
|
8
17
|
private duration;
|
|
9
18
|
}
|
|
10
19
|
//# sourceMappingURL=MigrationRunner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MigrationRunner.d.ts","sourceRoot":"","sources":["../../src/MigrationRunner.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,sBAAsB,EAA6B,MAAM,mCAAmC,CAAC;AAEtG,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,eAAO,MAAM,kBAAkB,uBACyE,CAAC;AAEzG,qBAAa,eAAgB,YAAW,sBAAsB;IAC5D,OAAO,CAAC,MAAM,CAA+C;IACtD,eAAe,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAQhD;
|
|
1
|
+
{"version":3,"file":"MigrationRunner.d.ts","sourceRoot":"","sources":["../../src/MigrationRunner.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,sBAAsB,EAA6B,MAAM,mCAAmC,CAAC;AAEtG,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,eAAO,MAAM,kBAAkB,uBACyE,CAAC;AAEzG,qBAAa,eAAgB,YAAW,sBAAsB;IAC5D,OAAO,CAAC,MAAM,CAA+C;IACtD,eAAe,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAQhD;IAEF;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAUzB,YAAY;IA0B1B,OAAO,CAAC,QAAQ;CA4BjB"}
|
|
@@ -51,26 +51,37 @@ var MigrationRunner = /** @class */ (function () {
|
|
|
51
51
|
function MigrationRunner() {
|
|
52
52
|
this.logger = new logger_1.Logger({ name: this.constructor.name });
|
|
53
53
|
this.serviceMetadata = {
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
//
|
|
54
|
+
// Running migrations rides the abstract 'dev' PERMISSION (the developer-surface slug the
|
|
55
|
+
// db-ui dev pages also declare), resolved through the consumer app's PermissionRolesMapping.
|
|
56
|
+
// Admin still passes as break-glass. Matches the migration table's doors below the service.
|
|
57
57
|
auth: {
|
|
58
|
-
|
|
58
|
+
permission: 'dev',
|
|
59
59
|
},
|
|
60
60
|
doNotAwait: true,
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* The service dispatches this fire-and-forget (`doNotAwait`). The method is split along that
|
|
65
|
+
* seam: everything knowable before the run starts (a bogus id) throws synchronously — the only
|
|
66
|
+
* path on which an error can still reach the client (the executor wraps it into a
|
|
67
|
+
* ServiceError -> 400). The returned promise MAY REJECT (infrastructure failure while recording
|
|
68
|
+
* run state); the caller owns that rejection — on the service path the executor terminally
|
|
69
|
+
* observes every doNotAwait rejection (logs with method identity, never process death).
|
|
70
|
+
*/
|
|
63
71
|
MigrationRunner.prototype.runMigration = function (id) {
|
|
72
|
+
var migrationTable = new MigrationTable_1.MigrationTable();
|
|
73
|
+
var migration = new SourceRecordRepo_1.SourceRecordRepo().getSourceRecord(migrationTable.name, id);
|
|
74
|
+
if (!migration) {
|
|
75
|
+
throw new Error("Unable to find migration source record for id: ".concat(id));
|
|
76
|
+
}
|
|
77
|
+
return this.runAndRecord(migrationTable, migration);
|
|
78
|
+
};
|
|
79
|
+
MigrationRunner.prototype.runAndRecord = function (migrationTable, migration) {
|
|
64
80
|
return __awaiter(this, void 0, void 0, function () {
|
|
65
|
-
var
|
|
81
|
+
var db, _a, error_1;
|
|
66
82
|
return __generator(this, function (_b) {
|
|
67
83
|
switch (_b.label) {
|
|
68
84
|
case 0:
|
|
69
|
-
migrationTable = new MigrationTable_1.MigrationTable();
|
|
70
|
-
migration = new SourceRecordRepo_1.SourceRecordRepo().getSourceRecord(migrationTable.name, id);
|
|
71
|
-
if (!migration) {
|
|
72
|
-
throw new Error("Unable to find migration source record for id: ".concat(id));
|
|
73
|
-
}
|
|
74
85
|
db = (0, Db_1.getDb)();
|
|
75
86
|
migration.status = 'running';
|
|
76
87
|
migration.startTime = (0, moment_1.moment)();
|
|
@@ -89,6 +100,9 @@ var MigrationRunner = /** @class */ (function () {
|
|
|
89
100
|
return [3 /*break*/, 6];
|
|
90
101
|
case 4:
|
|
91
102
|
error_1 = _b.sent();
|
|
103
|
+
// Domain bookkeeping, not containment: a migration that throws is a run OUTCOME, recorded
|
|
104
|
+
// as failure status on the record. Only infrastructure failures (the db.update calls
|
|
105
|
+
// themselves) reject the returned promise.
|
|
92
106
|
migration.failureMessage = error_1.message;
|
|
93
107
|
migration.failureStack = error_1.stack;
|
|
94
108
|
migration.status = 'failure';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MigrationRunner.js","sourceRoot":"","sources":["../../src/MigrationRunner.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAA8C;AAC9C,2BAA6B;AAE7B,8DAA6D;AAC7D,4EAAsG;AACtG,0DAAoE;AAEpE,4CAA2C;AAEpC,IAAM,kBAAkB,GAAG;IAChC,OAAA,OAAO,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC,CAAE,IAAA,kDAAyB,GAAsB;AAAtG,CAAsG,CAAC;AAD5F,QAAA,kBAAkB,sBAC0E;AAEzG;IAAA;QACU,WAAM,GAAG,IAAI,eAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QACtD,oBAAe,GAA+B;YACnD,
|
|
1
|
+
{"version":3,"file":"MigrationRunner.js","sourceRoot":"","sources":["../../src/MigrationRunner.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,8 +3,14 @@ import { Table } from '../Table';
|
|
|
3
3
|
* @public all users, including guests (do not need to be logged in), do not need any roles
|
|
4
4
|
* @authenticated - users need to be logged in, do not need any roles
|
|
5
5
|
* @roles string[] - authenticated users, having at least one of these roles
|
|
6
|
+
* @permission - authenticated users holding an abstract permission slug, resolved to roles at
|
|
7
|
+
* runtime through the consumer app's `PermissionRolesMapping` (see `UserAuth.hasPermission`).
|
|
8
|
+
* Generic tables declare permissions; only the consumer names roles.
|
|
6
9
|
*/
|
|
7
|
-
export type
|
|
10
|
+
export type PermissionIdentity = {
|
|
11
|
+
permission: string;
|
|
12
|
+
};
|
|
13
|
+
export type Identity = 'public' | 'authenticated' | string[] | PermissionIdentity;
|
|
8
14
|
/**
|
|
9
15
|
* These Identities can perform these operations on this table.
|
|
10
16
|
* If omitted, defaults to requiring the 'admin' role (default deny)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableAuth.d.ts","sourceRoot":"","sources":["../../../src/auth/TableAuth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC
|
|
1
|
+
{"version":3,"file":"TableAuth.d.ts","sourceRoot":"","sources":["../../../src/auth/TableAuth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,eAAe,GAAG,MAAM,EAAE,GAAG,kBAAkB,CAAC;AAKlF;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,MAAM,CAAC,EAAE,QAAQ,CAAC;CACnB,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,SAAS;IAuBjB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,GAAE,IAAI,GAAG,SAAgB,GAAG,IAAI;IAM/D,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,GAAE,IAAI,GAAG,SAAgB,GAAG,IAAI;IAMhE,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,GAAE,IAAI,GAAG,SAAgB,GAAG,IAAI;IAMhE,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,GAAE,IAAI,GAAG,SAAgB,GAAG,IAAI;CAKjE"}
|
|
@@ -17,6 +17,9 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.TableAuth = exports.TableAuthError = void 0;
|
|
19
19
|
var user_auth_1 = require("@proteinjs/user-auth");
|
|
20
|
+
var isPermissionIdentity = function (identity) {
|
|
21
|
+
return !!identity && typeof identity === 'object' && !Array.isArray(identity) && typeof identity.permission === 'string';
|
|
22
|
+
};
|
|
20
23
|
/**
|
|
21
24
|
* A table-auth denial. The message names the table and operation and is safe to show the caller
|
|
22
25
|
* (it only echoes what they asked for). Name-tagged rather than relying on instanceof — the
|
|
@@ -49,7 +52,10 @@ var TableAuth = /** @class */ (function () {
|
|
|
49
52
|
(tableAuth.all === 'authenticated' && user_auth_1.UserAuth.isLoggedIn()) ||
|
|
50
53
|
(tableAuth[operation] === 'authenticated' && user_auth_1.UserAuth.isLoggedIn()) ||
|
|
51
54
|
(Array.isArray(tableAuth.all) && user_auth_1.UserAuth.hasRoles(tableAuth.all, 'at least one')) ||
|
|
52
|
-
(Array.isArray(tableAuth[operation]) && user_auth_1.UserAuth.hasRoles(tableAuth[operation], 'at least one'))
|
|
55
|
+
(Array.isArray(tableAuth[operation]) && user_auth_1.UserAuth.hasRoles(tableAuth[operation], 'at least one')) ||
|
|
56
|
+
(isPermissionIdentity(tableAuth.all) && user_auth_1.UserAuth.hasPermission(tableAuth.all.permission)) ||
|
|
57
|
+
(isPermissionIdentity(tableAuth[operation]) &&
|
|
58
|
+
user_auth_1.UserAuth.hasPermission(tableAuth[operation].permission)));
|
|
53
59
|
};
|
|
54
60
|
TableAuth.prototype.canQuery = function (table, api) {
|
|
55
61
|
if (api === void 0) { api = 'db'; }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableAuth.js","sourceRoot":"","sources":["../../../src/auth/TableAuth.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,kDAAgD;
|
|
1
|
+
{"version":3,"file":"TableAuth.js","sourceRoot":"","sources":["../../../src/auth/TableAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,13 @@ export interface Migration extends SourceRecord {
|
|
|
14
14
|
}
|
|
15
15
|
export declare class MigrationTable extends Table<Migration> {
|
|
16
16
|
name: string;
|
|
17
|
+
/**
|
|
18
|
+
* Both doors ride the 'dev' permission (consumer-mapped; admin passes as break-glass),
|
|
19
|
+
* matching MigrationRunner's serviceMetadata: the Migrations record table reads/edits via
|
|
20
|
+
* the service api, and the runner writes run state via the db api as the calling user.
|
|
21
|
+
* Boot-time source-record loading is a system path (getDbAsSystem) and bypasses doors.
|
|
22
|
+
*/
|
|
23
|
+
auth: Table<Migration>['auth'];
|
|
17
24
|
columns: {
|
|
18
25
|
id: import("../Table").Column<string, any>;
|
|
19
26
|
created: import("../Table").Column<Moment, any>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MigrationTable.d.ts","sourceRoot":"","sources":["../../../src/tables/MigrationTable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,YAAY,EAA2B,MAAM,wBAAwB,CAAC;AAE/E,MAAM,WAAW,SAAU,SAAQ,YAAY;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,GAAG,EAAE,MAAM,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;CAChC;AAED,qBAAa,cAAe,SAAQ,KAAK,CAAC,SAAS,CAAC;IAC3C,IAAI,SAAe;
|
|
1
|
+
{"version":3,"file":"MigrationTable.d.ts","sourceRoot":"","sources":["../../../src/tables/MigrationTable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,YAAY,EAA2B,MAAM,wBAAwB,CAAC;AAE/E,MAAM,WAAW,SAAU,SAAQ,YAAY;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,GAAG,EAAE,MAAM,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;CAChC;AAED,qBAAa,cAAe,SAAQ,KAAK,CAAC,SAAS,CAAC;IAC3C,IAAI,SAAe;IAC1B;;;;;OAKG;IACI,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAGnC;IACK,OAAO;;;;;;;;;;;;;;;;MASX;IACI,mBAAmB;;;;;MAKxB;CACH"}
|
|
@@ -60,6 +60,16 @@ var MigrationTable = /** @class */ (function (_super) {
|
|
|
60
60
|
function MigrationTable() {
|
|
61
61
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
62
62
|
_this.name = 'migration';
|
|
63
|
+
/**
|
|
64
|
+
* Both doors ride the 'dev' permission (consumer-mapped; admin passes as break-glass),
|
|
65
|
+
* matching MigrationRunner's serviceMetadata: the Migrations record table reads/edits via
|
|
66
|
+
* the service api, and the runner writes run state via the db api as the calling user.
|
|
67
|
+
* Boot-time source-record loading is a system path (getDbAsSystem) and bypasses doors.
|
|
68
|
+
*/
|
|
69
|
+
_this.auth = {
|
|
70
|
+
db: { all: { permission: 'dev' } },
|
|
71
|
+
service: { all: { permission: 'dev' } },
|
|
72
|
+
};
|
|
63
73
|
_this.columns = (0, SourceRecord_1.withSourceRecordColumns)({
|
|
64
74
|
description: new Columns_1.StringColumn('description', {}, 4000),
|
|
65
75
|
status: new Columns_1.StringColumn('status', { defaultValue: function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MigrationTable.js","sourceRoot":"","sources":["../../../src/tables/MigrationTable.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,sCAAwE;AACxE,kCAAiC;AACjC,uDAA+E;AAc/E;IAAoC,kCAAgB;IAApD;QAAA,
|
|
1
|
+
{"version":3,"file":"MigrationTable.js","sourceRoot":"","sources":["../../../src/tables/MigrationTable.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,sCAAwE;AACxE,kCAAiC;AACjC,uDAA+E;AAc/E;IAAoC,kCAAgB;IAApD;QAAA,qEA4BC;QA3BQ,UAAI,GAAG,WAAW,CAAC;QAC1B;;;;;WAKG;QACI,UAAI,GAA6B;YACtC,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE;YAClC,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE;SACxC,CAAC;QACK,aAAO,GAAG,IAAA,sCAAuB,EAAY;YAClD,WAAW,EAAE,IAAI,sBAAY,CAAC,aAAa,EAAE,EAAE,EAAE,IAAI,CAAC;YACtD,MAAM,EAAE,IAAI,sBAAY,CAAC,QAAQ,EAAE,EAAE,YAAY,EAAE;oBAAY,sBAAA,UAAU,EAAA;yBAAA,EAAE,CAAC;YAC5E,cAAc,EAAE,IAAI,sBAAY,CAAC,iBAAiB,EAAE,EAAE,EAAE,IAAI,CAAC;YAC7D,YAAY,EAAE,IAAI,sBAAY,CAAC,eAAe,EAAE,EAAE,EAAE,KAAK,CAAC;YAC1D,SAAS,EAAE,IAAI,wBAAc,CAAC,YAAY,CAAC;YAC3C,OAAO,EAAE,IAAI,wBAAc,CAAC,UAAU,CAAC;YACvC,QAAQ,EAAE,IAAI,sBAAY,CAAC,UAAU,CAAC;YACtC,MAAM,EAAE,IAAI,sBAAY,CAAC,QAAQ,CAAC;SACnC,CAAC,CAAC;QACI,yBAAmB,GAAG;YAC3B,8BAA8B,EAAE,IAAI;YACpC,EAAE,EAAE;gBACF,WAAW,EAAE,IAAI;aAClB;SACF,CAAC;;IACJ,CAAC;IAAD,qBAAC;AAAD,CAAC,AA5BD,CAAoC,aAAK,GA4BxC;AA5BY,wCAAc"}
|
|
@@ -5,7 +5,7 @@ export type PostCommitHook = () => void | Promise<void>;
|
|
|
5
5
|
export interface TransactionContextData {
|
|
6
6
|
currentTransaction?: any;
|
|
7
7
|
/**
|
|
8
|
-
|
|
8
|
+
* Hooks queued to run after the current transaction COMMITS — and never on rollback: a hook
|
|
9
9
|
* queued for a write that gets rolled back dies with the write. Seeded by `Db.runTransaction`
|
|
10
10
|
* on the ambient context so every `Db` instance created inside the transaction (table
|
|
11
11
|
* watchers, nested helpers) shares one queue; registered via `Db.runAfterCommit`, drained by
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MigrationAuth.test.d.ts","sourceRoot":"","sources":["../../test/MigrationAuth.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var user_auth_1 = require("@proteinjs/user-auth");
|
|
4
|
+
// Deep dist path on purpose: the package index doesn't export the auth gate (it is framework
|
|
5
|
+
// plumbing), but the test must exercise the REAL gate, not a re-implementation of its rules.
|
|
6
|
+
var ServiceAuth_1 = require("@proteinjs/service/dist/src/ServiceAuth");
|
|
7
|
+
var reflection_1 = require("@proteinjs/reflection");
|
|
8
|
+
var MigrationRunner_1 = require("../src/MigrationRunner");
|
|
9
|
+
var MigrationTable_1 = require("../src/tables/MigrationTable");
|
|
10
|
+
var TableAuth_1 = require("../src/auth/TableAuth");
|
|
11
|
+
var setUser = function (roles) {
|
|
12
|
+
user_auth_1.UserAuth.userRepo = {
|
|
13
|
+
getUser: function () { return ({ email: 'user@test.local', roles: roles }); },
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
var setMapping = function (mapping) {
|
|
17
|
+
user_auth_1.UserAuth.permissionRolesMapping = {
|
|
18
|
+
getRoles: function (permission) { return mapping[permission]; },
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
var canRunMigrations = function () {
|
|
22
|
+
var method = new reflection_1.Method('runMigration', undefined, true, false, false, false, 'public', []);
|
|
23
|
+
return ServiceAuth_1.ServiceAuth.canRunService(new MigrationRunner_1.MigrationRunner(), method, ['some-migration-id']);
|
|
24
|
+
};
|
|
25
|
+
describe('migrations ride the dev permission', function () {
|
|
26
|
+
beforeEach(function () {
|
|
27
|
+
setMapping({ dev: ['dev-crew'] });
|
|
28
|
+
});
|
|
29
|
+
afterEach(function () {
|
|
30
|
+
user_auth_1.UserAuth.userRepo = undefined;
|
|
31
|
+
user_auth_1.UserAuth.permissionRolesMapping = undefined;
|
|
32
|
+
});
|
|
33
|
+
it("a consumer-mapped dev-role holder can run migrations and use the migration table's doors", function () {
|
|
34
|
+
setUser(['dev-crew']);
|
|
35
|
+
expect(canRunMigrations()).toBe(true);
|
|
36
|
+
var auth = new TableAuth_1.TableAuth();
|
|
37
|
+
var table = new MigrationTable_1.MigrationTable();
|
|
38
|
+
var _loop_1 = function (api) {
|
|
39
|
+
expect(function () { return auth.canQuery(table, api); }).not.toThrow();
|
|
40
|
+
expect(function () { return auth.canUpdate(table, api); }).not.toThrow();
|
|
41
|
+
};
|
|
42
|
+
// The record-table page reads via the service api; the runner updates via the db api.
|
|
43
|
+
for (var _i = 0, _a = ['db', 'service']; _i < _a.length; _i++) {
|
|
44
|
+
var api = _a[_i];
|
|
45
|
+
_loop_1(api);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
it('a permissionless user is denied the service and both table doors', function () {
|
|
49
|
+
setUser(['ops-team']);
|
|
50
|
+
expect(canRunMigrations()).toBe(false);
|
|
51
|
+
var auth = new TableAuth_1.TableAuth();
|
|
52
|
+
var table = new MigrationTable_1.MigrationTable();
|
|
53
|
+
var _loop_2 = function (api) {
|
|
54
|
+
expect(function () { return auth.canQuery(table, api); }).toThrow('User is not authorized to query table: migration');
|
|
55
|
+
expect(function () { return auth.canUpdate(table, api); }).toThrow('User is not authorized to update records in table: migration');
|
|
56
|
+
};
|
|
57
|
+
for (var _i = 0, _a = ['db', 'service']; _i < _a.length; _i++) {
|
|
58
|
+
var api = _a[_i];
|
|
59
|
+
_loop_2(api);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
it('admin passes everything as break-glass', function () {
|
|
63
|
+
setUser(['admin']);
|
|
64
|
+
expect(canRunMigrations()).toBe(true);
|
|
65
|
+
var auth = new TableAuth_1.TableAuth();
|
|
66
|
+
var table = new MigrationTable_1.MigrationTable();
|
|
67
|
+
var _loop_3 = function (api) {
|
|
68
|
+
expect(function () { return auth.canQuery(table, api); }).not.toThrow();
|
|
69
|
+
expect(function () { return auth.canUpdate(table, api); }).not.toThrow();
|
|
70
|
+
};
|
|
71
|
+
for (var _i = 0, _a = ['db', 'service']; _i < _a.length; _i++) {
|
|
72
|
+
var api = _a[_i];
|
|
73
|
+
_loop_3(api);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
//# sourceMappingURL=MigrationAuth.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MigrationAuth.test.js","sourceRoot":"","sources":["../../test/MigrationAuth.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MigrationRunnerContainment.test.d.ts","sourceRoot":"","sources":["../../test/MigrationRunnerContainment.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,144 @@
|
|
|
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
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
// EnvInfo.isDev() requires a GlobalDataStorage implementation that only exists in a running app
|
|
40
|
+
// (same mock the @proteinjs/service executor suite uses).
|
|
41
|
+
jest.mock('@proteinjs/server-api', function () { return ({
|
|
42
|
+
EnvInfo: { isDev: function () { return true; } },
|
|
43
|
+
}); });
|
|
44
|
+
var logger_1 = require("@proteinjs/logger");
|
|
45
|
+
var reflection_1 = require("@proteinjs/reflection");
|
|
46
|
+
var serializer_1 = require("@proteinjs/serializer");
|
|
47
|
+
// Deep dist path on purpose: the package index doesn't export the executor (framework plumbing),
|
|
48
|
+
// but the executor check below must run the REAL BUILT owner of the doNotAwait seam.
|
|
49
|
+
var ServiceExecutor_1 = require("@proteinjs/service/dist/src/ServiceExecutor");
|
|
50
|
+
var MigrationRunner_1 = require("../src/MigrationRunner");
|
|
51
|
+
var MigrationTable_1 = require("../src/tables/MigrationTable");
|
|
52
|
+
var SourceRecordRepo_1 = require("../src/source/SourceRecordRepo");
|
|
53
|
+
var testUser_1 = require("./util/testUser");
|
|
54
|
+
/**
|
|
55
|
+
* This harness loads no reflection graph and registers no DefaultDbDriverFactory, so the body's
|
|
56
|
+
* FIRST db access (`new Db()` constructing its table-watcher runner) throws this. The specific
|
|
57
|
+
* message is a harness accident standing in for any mid-run infrastructure failure (db.update
|
|
58
|
+
* rejecting); the contract under test is that the failure escapes as a rejection at all.
|
|
59
|
+
*/
|
|
60
|
+
var infrastructureFailure = 'Unable to find type: @proteinjs/db/TableWatcher';
|
|
61
|
+
var plantMigration = function (id) {
|
|
62
|
+
var migration = {
|
|
63
|
+
id: id,
|
|
64
|
+
description: 'containment test migration',
|
|
65
|
+
run: function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
66
|
+
return [2 /*return*/, undefined];
|
|
67
|
+
}); }); },
|
|
68
|
+
};
|
|
69
|
+
new SourceRecordRepo_1.SourceRecordRepo().loadSourceRecord(new MigrationTable_1.MigrationTable().name, migration);
|
|
70
|
+
return migration;
|
|
71
|
+
};
|
|
72
|
+
describe('MigrationRunner containment (doNotAwait dispatch)', function () {
|
|
73
|
+
it('throws synchronously on a bogus migration id, not through the detached promise', function () {
|
|
74
|
+
var runner = new MigrationRunner_1.MigrationRunner();
|
|
75
|
+
expect(function () { return runner.runMigration('bogus-migration-id'); }).toThrow('Unable to find migration source record for id: bogus-migration-id');
|
|
76
|
+
});
|
|
77
|
+
it('rejects the detached promise on a mid-run infrastructure failure — the caller owns it', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
78
|
+
var runner;
|
|
79
|
+
return __generator(this, function (_a) {
|
|
80
|
+
switch (_a.label) {
|
|
81
|
+
case 0:
|
|
82
|
+
// The runner no longer swallows infrastructure failures: the rejection escapes to whoever
|
|
83
|
+
// holds the promise.
|
|
84
|
+
plantMigration('containment-test-migration');
|
|
85
|
+
runner = new MigrationRunner_1.MigrationRunner();
|
|
86
|
+
return [4 /*yield*/, expect(runner.runMigration('containment-test-migration')).rejects.toThrow(infrastructureFailure)];
|
|
87
|
+
case 1:
|
|
88
|
+
_a.sent();
|
|
89
|
+
return [2 /*return*/];
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}); });
|
|
93
|
+
it('through the real built executor, an infrastructure-failure rejection is terminally logged — not process death', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
94
|
+
var runner, method, _interface, executor, entries_1, errorEntry;
|
|
95
|
+
var _a, _b;
|
|
96
|
+
return __generator(this, function (_c) {
|
|
97
|
+
switch (_c.label) {
|
|
98
|
+
case 0:
|
|
99
|
+
// Admin identity passes the service's 'dev' permission as break-glass (MigrationAuth.test.ts
|
|
100
|
+
// pins the mapping itself).
|
|
101
|
+
(0, testUser_1.registerTestUser)();
|
|
102
|
+
_c.label = 1;
|
|
103
|
+
case 1:
|
|
104
|
+
_c.trys.push([1, , 5, 6]);
|
|
105
|
+
plantMigration('containment-test-migration-executor');
|
|
106
|
+
runner = new MigrationRunner_1.MigrationRunner();
|
|
107
|
+
method = new reflection_1.Method('runMigration', undefined, true, false, false, false, 'public', []);
|
|
108
|
+
_interface = new reflection_1.Interface('@proteinjs/db', 'MigrationRunnerService', [], [method]);
|
|
109
|
+
executor = new ServiceExecutor_1.ServiceExecutor(runner, _interface, method);
|
|
110
|
+
entries_1 = [];
|
|
111
|
+
executor.logger = new logger_1.Logger({
|
|
112
|
+
name: 'MigrationRunnerService.runMigration',
|
|
113
|
+
logWriter: { write: function (log) { return entries_1.push(log); } },
|
|
114
|
+
});
|
|
115
|
+
// The client response does not carry the failure — execute resolves immediately.
|
|
116
|
+
return [4 /*yield*/, expect(executor.execute(serializer_1.Serializer.serialize(['containment-test-migration-executor']))).resolves.toBeUndefined()];
|
|
117
|
+
case 2:
|
|
118
|
+
// The client response does not carry the failure — execute resolves immediately.
|
|
119
|
+
_c.sent();
|
|
120
|
+
// The detached rejection settles after the microtask queue drains; flush macrotasks so the
|
|
121
|
+
// executor's terminal catch has written its log entry. Were the rejection unobserved, jest
|
|
122
|
+
// would surface it as a failure here — and a bare node process would die.
|
|
123
|
+
return [4 /*yield*/, new Promise(function (resolve) { return setImmediate(resolve); })];
|
|
124
|
+
case 3:
|
|
125
|
+
// The detached rejection settles after the microtask queue drains; flush macrotasks so the
|
|
126
|
+
// executor's terminal catch has written its log entry. Were the rejection unobserved, jest
|
|
127
|
+
// would surface it as a failure here — and a bare node process would die.
|
|
128
|
+
_c.sent();
|
|
129
|
+
return [4 /*yield*/, new Promise(function (resolve) { return setImmediate(resolve); })];
|
|
130
|
+
case 4:
|
|
131
|
+
_c.sent();
|
|
132
|
+
errorEntry = entries_1.find(function (entry) { return entry.logLevel === 'error'; });
|
|
133
|
+
expect((_a = errorEntry === null || errorEntry === void 0 ? void 0 : errorEntry.error) === null || _a === void 0 ? void 0 : _a.message).toContain(infrastructureFailure);
|
|
134
|
+
expect((_b = errorEntry === null || errorEntry === void 0 ? void 0 : errorEntry.obj) === null || _b === void 0 ? void 0 : _b.functionName).toBe('MigrationRunnerService.runMigration');
|
|
135
|
+
return [3 /*break*/, 6];
|
|
136
|
+
case 5:
|
|
137
|
+
(0, testUser_1.clearTestUser)();
|
|
138
|
+
return [7 /*endfinally*/];
|
|
139
|
+
case 6: return [2 /*return*/];
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}); });
|
|
143
|
+
});
|
|
144
|
+
//# sourceMappingURL=MigrationRunnerContainment.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MigrationRunnerContainment.test.js","sourceRoot":"","sources":["../../test/MigrationRunnerContainment.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gGAAgG;AAChG,0DAA0D;AAC1D,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,cAAM,OAAA,CAAC;IACxC,OAAO,EAAE,EAAE,KAAK,EAAE,cAAM,OAAA,IAAI,EAAJ,CAAI,EAAE;CAC/B,CAAC,EAFuC,CAEvC,CAAC,CAAC;AAEJ,4CAAkE;AAClE,oDAA0D;AAC1D,oDAAmD;AACnD,iGAAiG;AACjG,qFAAqF;AACrF,+EAA8E;AAC9E,0DAAyD;AACzD,+DAAyE;AACzE,mEAAkE;AAClE,4CAAkE;AAmBlE;;;;;GAKG;AACH,IAAM,qBAAqB,GAAG,iDAAiD,CAAC;AAEhF,IAAM,cAAc,GAAG,UAAC,EAAU;IAChC,IAAM,SAAS,GAAG;QAChB,EAAE,IAAA;QACF,WAAW,EAAE,4BAA4B;QACzC,GAAG,EAAE;YAAY,sBAAA,SAAS,EAAA;iBAAA;KACd,CAAC;IACf,IAAI,mCAAgB,EAAE,CAAC,gBAAgB,CAAC,IAAI,+BAAc,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC9E,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,QAAQ,CAAC,mDAAmD,EAAE;IAC5D,EAAE,CAAC,gFAAgF,EAAE;QACnF,IAAM,MAAM,GAAG,IAAI,iCAAe,EAAE,CAAC;QACrC,MAAM,CAAC,cAAM,OAAA,MAAM,CAAC,YAAY,CAAC,oBAAoB,CAAC,EAAzC,CAAyC,CAAC,CAAC,OAAO,CAC7D,mEAAmE,CACpE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uFAAuF,EAAE;;;;;oBAC1F,0FAA0F;oBAC1F,qBAAqB;oBACrB,cAAc,CAAC,4BAA4B,CAAC,CAAC;oBAEvC,MAAM,GAAG,IAAI,iCAAe,EAAE,CAAC;oBACrC,qBAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,4BAA4B,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAA;;oBAAtG,SAAsG,CAAC;;;;SACxG,CAAC,CAAC;IAEH,EAAE,CAAC,+GAA+G,EAAE;;;;;;oBAClH,6FAA6F;oBAC7F,4BAA4B;oBAC5B,IAAA,2BAAgB,GAAE,CAAC;;;;oBAEjB,cAAc,CAAC,qCAAqC,CAAC,CAAC;oBAEhD,MAAM,GAAG,IAAI,iCAAe,EAAE,CAAC;oBAC/B,MAAM,GAAG,IAAI,mBAAM,CAAC,cAAc,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;oBACxF,UAAU,GAAG,IAAI,sBAAS,CAAC,eAAe,EAAE,wBAAwB,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;oBACpF,QAAQ,GAAG,IAAI,iCAAe,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;oBAC3D,YAAiB,EAAE,CAAC;oBACzB,QAAyC,CAAC,MAAM,GAAG,IAAI,eAAM,CAAC;wBAC7D,IAAI,EAAE,qCAAqC;wBAC3C,SAAS,EAAE,EAAE,KAAK,EAAE,UAAC,GAAQ,IAAK,OAAA,SAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAjB,CAAiB,EAAiC;qBACrF,CAAC,CAAC;oBAEH,iFAAiF;oBACjF,qBAAM,MAAM,CACV,QAAQ,CAAC,OAAO,CAAC,uBAAU,CAAC,SAAS,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC,CAChF,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAA;;oBAH1B,iFAAiF;oBACjF,SAE0B,CAAC;oBAC3B,2FAA2F;oBAC3F,2FAA2F;oBAC3F,0EAA0E;oBAC1E,qBAAM,IAAI,OAAO,CAAC,UAAC,OAAO,IAAK,OAAA,YAAY,CAAC,OAAO,CAAC,EAArB,CAAqB,CAAC,EAAA;;oBAHrD,2FAA2F;oBAC3F,2FAA2F;oBAC3F,0EAA0E;oBAC1E,SAAqD,CAAC;oBACtD,qBAAM,IAAI,OAAO,CAAC,UAAC,OAAO,IAAK,OAAA,YAAY,CAAC,OAAO,CAAC,EAArB,CAAqB,CAAC,EAAA;;oBAArD,SAAqD,CAAC;oBAEhD,UAAU,GAAG,SAAO,CAAC,IAAI,CAAC,UAAC,KAAK,IAAK,OAAA,KAAK,CAAC,QAAQ,KAAK,OAAO,EAA1B,CAA0B,CAAC,CAAC;oBACvE,MAAM,CAAC,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,KAAK,0CAAE,OAAO,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;oBACpE,MAAM,CAAC,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,GAAG,0CAAE,YAAY,CAAC,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;;;oBAElF,IAAA,wBAAa,GAAE,CAAC;;;;;SAEnB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -74,6 +74,30 @@ var NoAuthTable = /** @class */ (function (_super) {
|
|
|
74
74
|
}
|
|
75
75
|
return NoAuthTable;
|
|
76
76
|
}(Table_1.Table));
|
|
77
|
+
/**
|
|
78
|
+
* Mirrors the user table's shape: doors keyed to an abstract PERMISSION resolved through the
|
|
79
|
+
* consumer mapping, with a service-protected column reserved to a dedicated service.
|
|
80
|
+
*/
|
|
81
|
+
var PermissionGatedTable = /** @class */ (function (_super) {
|
|
82
|
+
__extends(PermissionGatedTable, _super);
|
|
83
|
+
function PermissionGatedTable() {
|
|
84
|
+
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
85
|
+
_this.name = 'permission_gated_test';
|
|
86
|
+
_this.auth = {
|
|
87
|
+
service: {
|
|
88
|
+
query: { permission: 'users' },
|
|
89
|
+
update: { permission: 'users' },
|
|
90
|
+
},
|
|
91
|
+
serviceProtectedColumns: ['owner'],
|
|
92
|
+
};
|
|
93
|
+
_this.columns = (0, Record_1.withRecordColumns)({
|
|
94
|
+
title: new Columns_1.StringColumn('title'),
|
|
95
|
+
owner: new Columns_1.StringColumn('owner'),
|
|
96
|
+
});
|
|
97
|
+
return _this;
|
|
98
|
+
}
|
|
99
|
+
return PermissionGatedTable;
|
|
100
|
+
}(Table_1.Table));
|
|
77
101
|
/** Read-only intent: only `query` granted (the canDelete-regression shape). */
|
|
78
102
|
var ReadOnlyTable = /** @class */ (function (_super) {
|
|
79
103
|
__extends(ReadOnlyTable, _super);
|
|
@@ -97,6 +121,11 @@ var setUser = function (roles) {
|
|
|
97
121
|
getUser: function () { return ({ email: 'user@test.local', roles: roles }); },
|
|
98
122
|
};
|
|
99
123
|
};
|
|
124
|
+
var setMapping = function (mapping) {
|
|
125
|
+
user_auth_1.UserAuth.permissionRolesMapping = {
|
|
126
|
+
getRoles: function (permission) { return mapping[permission]; },
|
|
127
|
+
};
|
|
128
|
+
};
|
|
100
129
|
var auth = function () { return new TableServiceAuth_1.TableServiceAuth(); };
|
|
101
130
|
/** A denial must be a client-safe ServiceError naming the table and operation. */
|
|
102
131
|
var expectDenied = function (fn, message) {
|
|
@@ -138,6 +167,44 @@ describe('TableServiceAuth — per-operation service grants', function () {
|
|
|
138
167
|
expectDenied(function () { return auth().canAccess('delete', [table, { id: 'x' }]); }, 'User is not authorized to delete records from table: read_only_test');
|
|
139
168
|
});
|
|
140
169
|
});
|
|
170
|
+
describe('TableServiceAuth — permission-keyed doors (the user table shape)', function () {
|
|
171
|
+
afterEach(function () {
|
|
172
|
+
user_auth_1.UserAuth.userRepo = undefined;
|
|
173
|
+
user_auth_1.UserAuth.permissionRolesMapping = undefined;
|
|
174
|
+
});
|
|
175
|
+
it("grants a holder of the consumer's mapped role; denies without the role", function () {
|
|
176
|
+
var table = new PermissionGatedTable();
|
|
177
|
+
setMapping({ users: ['support'] });
|
|
178
|
+
setUser(['support']);
|
|
179
|
+
expect(auth().canAccess('query', [table, {}])).toBe(true);
|
|
180
|
+
expect(auth().canAccess('update', [table, { id: 'x', title: 't' }])).toBe(true);
|
|
181
|
+
setUser(['dev']);
|
|
182
|
+
expectDenied(function () { return auth().canAccess('query', [table, {}]); }, 'User is not authorized to query table: permission_gated_test');
|
|
183
|
+
});
|
|
184
|
+
it('denies everyone but admin when no mapping is registered (default deny)', function () {
|
|
185
|
+
var table = new PermissionGatedTable();
|
|
186
|
+
setUser(['support']);
|
|
187
|
+
expectDenied(function () { return auth().canAccess('query', [table, {}]); }, 'User is not authorized to query table: permission_gated_test');
|
|
188
|
+
setUser(['admin']);
|
|
189
|
+
expect(auth().canAccess('query', [table, {}])).toBe(true);
|
|
190
|
+
});
|
|
191
|
+
it('operations without a grant stay closed even for permission holders (and admin)', function () {
|
|
192
|
+
var table = new PermissionGatedTable();
|
|
193
|
+
setMapping({ users: ['support'] });
|
|
194
|
+
setUser(['support']);
|
|
195
|
+
expectDenied(function () { return auth().canAccess('insert', [table, { title: 't' }]); }, 'User is not authorized to insert records into table: permission_gated_test');
|
|
196
|
+
// An auth block with no grant for the operation is a deliberate lock, not an admin default —
|
|
197
|
+
// the audit-table shape (role_grant_event) depends on this.
|
|
198
|
+
setUser(['admin']);
|
|
199
|
+
expectDenied(function () { return auth().canAccess('delete', [table, { id: 'x' }]); }, 'User is not authorized to delete records from table: permission_gated_test');
|
|
200
|
+
});
|
|
201
|
+
it('the protected column stays unwritable even for a permission holder with the update grant', function () {
|
|
202
|
+
var table = new PermissionGatedTable();
|
|
203
|
+
setMapping({ users: ['support'] });
|
|
204
|
+
setUser(['support']);
|
|
205
|
+
expectDenied(function () { return auth().canAccess('update', [table, { id: 'x', owner: 'someone' }]); }, "Column 'owner' cannot be written via the db service on table: permission_gated_test");
|
|
206
|
+
});
|
|
207
|
+
});
|
|
141
208
|
describe('TableServiceAuth — default deny (no auth block)', function () {
|
|
142
209
|
afterEach(function () {
|
|
143
210
|
user_auth_1.UserAuth.userRepo = undefined;
|