@proteinjs/db 1.50.0 → 1.50.1

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/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.50.1](https://github.com/proteinjs/db/compare/@proteinjs/db@1.50.0...@proteinjs/db@1.50.1) (2026-09-30)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **db:** an undeclared db door mirrors the declared service door — the RPC runs both, so a service write door with no db mirror admitted the caller at the gate and refused them behind it ([35a3621](https://github.com/proteinjs/db/commit/35a362170d92b521b9104f8349f2e27d7bec98b8))
12
+
13
+
14
+
15
+
16
+
6
17
  # [1.50.0](https://github.com/proteinjs/db/compare/@proteinjs/db@1.49.1...@proteinjs/db@1.50.0) (2026-09-29)
7
18
 
8
19
 
@@ -63,6 +63,8 @@ export declare class TableAuth {
63
63
  */
64
64
  canDelete(table: Table<any>, api?: 'db' | 'service'): void;
65
65
  private canAccess;
66
+ /** The service block's door for `operation`, as the RPC gate reads it; a table with no service block declares none. */
67
+ private allowsServiceDoor;
66
68
  /** One identity against the current user; undefined (nothing declared) is not a grant. */
67
69
  private allows;
68
70
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TableAuth.d.ts","sourceRoot":"","sources":["../../../src/auth/TableAuth.ts"],"names":[],"mappings":"AAEA,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;;;;;;;;;OASG;IACH,UAAU,CACR,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,SAAS,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,EACnD,GAAG,GAAE,IAAI,GAAG,SAAgB,GAC3B,OAAO;IAQV;;;;;;OAMG;IACH,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO;IAQvD,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;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,GAAE,IAAI,GAAG,SAAgB,GAAG,IAAI;IAUhE,OAAO,CAAC,SAAS;IAqBjB,0FAA0F;IAC1F,OAAO,CAAC,MAAM;CAef"}
1
+ {"version":3,"file":"TableAuth.d.ts","sourceRoot":"","sources":["../../../src/auth/TableAuth.ts"],"names":[],"mappings":"AAEA,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;;;;;;;;;OASG;IACH,UAAU,CACR,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,SAAS,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,EACnD,GAAG,GAAE,IAAI,GAAG,SAAgB,GAC3B,OAAO;IAQV;;;;;;OAMG;IACH,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO;IAQvD,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;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,GAAE,IAAI,GAAG,SAAgB,GAAG,IAAI;IAUhE,OAAO,CAAC,SAAS;IAmCjB,uHAAuH;IACvH,OAAO,CAAC,iBAAiB;IASzB,0FAA0F;IAC1F,OAAO,CAAC,MAAM;CAef"}
@@ -119,8 +119,30 @@ var TableAuth = /** @class */ (function () {
119
119
  }
120
120
  // Within a declared block an undeclared operation stays closed to everyone (the block is
121
121
  // the whole declaration) — `allows` reads undefined as false, so the two doors are exactly
122
- // the ones the table wrote down.
123
- return this.allows(tableAuth.all) || this.allows(tableAuth[operation]);
122
+ // the ones the table wrote down...
123
+ if (this.allows(tableAuth.all) || this.allows(tableAuth[operation])) {
124
+ return true;
125
+ }
126
+ // ...except that a db door the block leaves UNDECLARED mirrors the door the table's SERVICE
127
+ // block declares for the same operation. The RPC runs both doors — the service gate
128
+ // (TableServiceAuth), then the inner Db's db-api re-check as the calling user — so a service
129
+ // door with no db mirror admitted the caller at the gate and refused them behind it, in the
130
+ // gate's own words ("db doors mirror service doors" was a rule tables hand-copied; the owner
131
+ // derives it). One-way: a service block that omits the door keeps the lock (the session /
132
+ // audit-trail pattern — no write door on either api, break-glass included), and a table with
133
+ // no service block keeps its db block as written.
134
+ return api === 'db' && tableAuth.all === undefined && tableAuth[operation] === undefined
135
+ ? this.allowsServiceDoor(table, operation)
136
+ : false;
137
+ };
138
+ /** The service block's door for `operation`, as the RPC gate reads it; a table with no service block declares none. */
139
+ TableAuth.prototype.allowsServiceDoor = function (table, operation) {
140
+ var _a;
141
+ var serviceAuth = (_a = table.auth) === null || _a === void 0 ? void 0 : _a.service;
142
+ if (!serviceAuth || Object.keys(serviceAuth).length == 0) {
143
+ return false;
144
+ }
145
+ return this.allows(serviceAuth.all) || this.allows(serviceAuth[operation]);
124
146
  };
125
147
  /** One identity against the current user; undefined (nothing declared) is not a grant. */
126
148
  TableAuth.prototype.allows = function (identity) {
@@ -1 +1 @@
1
- {"version":3,"file":"TableAuth.js","sourceRoot":"","sources":["../../../src/auth/TableAuth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TableAuth.js","sourceRoot":"","sources":["../../../src/auth/TableAuth.ts"],"names":[],"mappings":"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"}
@@ -107,4 +107,89 @@ describe('TableAuth operation doors keep their declared-block semantics', functi
107
107
  expect(new TableAuth_1.TableAuth().canPerform(new QueryOnlyTable(), 'insert')).toBe(false);
108
108
  });
109
109
  });
110
+ /**
111
+ * The RPC runs BOTH doors — the service gate (`TableServiceAuth`) and then the inner `Db`'s
112
+ * db-api re-check as the calling user — so a db door a table leaves UNDECLARED mirrors the door
113
+ * its service block declares for the same operation. "db doors mirror service doors" was a rule
114
+ * tables hand-copied; the owner derives it now: fifteen consumer tables opened `['admin']` writes
115
+ * on the service api over a query-only db block, and every one refused the admin at the inner
116
+ * check in the gate's own words — the gate admitted them, the re-check behind it did not, two
117
+ * verdicts for one caller. One-way: a service block that omits the door keeps the lock (the
118
+ * session / audit-trail pattern — no write door on either api, break-glass included), and a table
119
+ * with no service block keeps its db block as written (the pin above).
120
+ */
121
+ var ReadOpenWriteAdminTable = /** @class */ (function (_super) {
122
+ __extends(ReadOpenWriteAdminTable, _super);
123
+ function ReadOpenWriteAdminTable() {
124
+ var _this = _super !== null && _super.apply(this, arguments) || this;
125
+ _this.name = 'identity_read_open_write_admin_test';
126
+ _this.auth = {
127
+ db: { query: 'authenticated' },
128
+ service: { query: 'authenticated', insert: ['admin'], update: ['admin'], delete: ['admin'] },
129
+ };
130
+ _this.columns = (0, Record_1.withRecordColumns)({ title: new Columns_1.StringColumn('title') });
131
+ return _this;
132
+ }
133
+ return ReadOpenWriteAdminTable;
134
+ }(Table_1.Table));
135
+ var LockedLedgerTable = /** @class */ (function (_super) {
136
+ __extends(LockedLedgerTable, _super);
137
+ function LockedLedgerTable() {
138
+ var _this = _super !== null && _super.apply(this, arguments) || this;
139
+ _this.name = 'identity_locked_ledger_test';
140
+ _this.auth = {
141
+ db: { query: { permission: 'ledger' } },
142
+ service: { query: { permission: 'ledger' } },
143
+ };
144
+ _this.columns = (0, Record_1.withRecordColumns)({ title: new Columns_1.StringColumn('title') });
145
+ return _this;
146
+ }
147
+ return LockedLedgerTable;
148
+ }(Table_1.Table));
149
+ describe('TableAuth — an undeclared db door mirrors the declared service door', function () {
150
+ beforeEach(function () {
151
+ setMapping({ ledger: ['ledger'] });
152
+ });
153
+ afterEach(function () {
154
+ user_auth_1.UserAuth.userRepo = undefined;
155
+ user_auth_1.UserAuth.permissionRolesMapping = undefined;
156
+ });
157
+ test("an admin's write clears the ['admin'] service door AND the db-api re-check behind it", function () {
158
+ setUser(['admin']);
159
+ var table = new ReadOpenWriteAdminTable();
160
+ expect(function () { return new TableAuth_1.TableAuth().canUpdate(table, 'service'); }).not.toThrow();
161
+ expect(function () { return new TableAuth_1.TableAuth().canUpdate(table); }).not.toThrow();
162
+ expect(function () { return new TableAuth_1.TableAuth().canInsert(table); }).not.toThrow();
163
+ expect(function () { return new TableAuth_1.TableAuth().canDelete(table); }).not.toThrow();
164
+ expect(new TableAuth_1.TableAuth().canPerform(table, 'update', 'db')).toBe(true);
165
+ });
166
+ test('a signed-in non-admin is refused by name on both apis; the read door stays open', function () {
167
+ setUser(['ledger']);
168
+ var table = new ReadOpenWriteAdminTable();
169
+ expect(function () { return new TableAuth_1.TableAuth().canUpdate(table, 'service'); }).toThrow('User is not authorized to update records in table: identity_read_open_write_admin_test');
170
+ expect(function () { return new TableAuth_1.TableAuth().canUpdate(table); }).toThrow('User is not authorized to update records in table: identity_read_open_write_admin_test');
171
+ expect(function () { return new TableAuth_1.TableAuth().canQuery(table); }).not.toThrow();
172
+ });
173
+ test('a guest is refused every door', function () {
174
+ setGuest();
175
+ var table = new ReadOpenWriteAdminTable();
176
+ expect(function () { return new TableAuth_1.TableAuth().canQuery(table); }).toThrow('User is not authorized to query table: identity_read_open_write_admin_test');
177
+ expect(function () { return new TableAuth_1.TableAuth().canUpdate(table); }).toThrow();
178
+ expect(function () { return new TableAuth_1.TableAuth().canInsert(table, 'service'); }).toThrow();
179
+ });
180
+ test('one-way: a service block that omits the door keeps the lock on both apis, break-glass included', function () {
181
+ setUser(['admin']);
182
+ var table = new LockedLedgerTable();
183
+ expect(new TableAuth_1.TableAuth().canPerform(table, 'update', 'service')).toBe(false);
184
+ expect(new TableAuth_1.TableAuth().canPerform(table, 'update', 'db')).toBe(false);
185
+ expect(function () { return new TableAuth_1.TableAuth().canUpdate(table); }).toThrow('User is not authorized to update records in table: identity_locked_ledger_test');
186
+ expect(function () { return new TableAuth_1.TableAuth().canInsert(table, 'service'); }).toThrow();
187
+ expect(function () { return new TableAuth_1.TableAuth().canQuery(table); }).not.toThrow();
188
+ });
189
+ test('a table with no service block keeps its db block as written — admin included', function () {
190
+ setUser(['admin']);
191
+ expect(new TableAuth_1.TableAuth().canPerform(new QueryOnlyTable(), 'update', 'db')).toBe(false);
192
+ expect(function () { return new TableAuth_1.TableAuth().canUpdate(new QueryOnlyTable()); }).toThrow('User is not authorized to update records in table: identity_query_only_test');
193
+ });
194
+ });
110
195
  //# sourceMappingURL=TableAuthIdentity.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TableAuthIdentity.test.js","sourceRoot":"","sources":["../../test/TableAuthIdentity.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TableAuthIdentity.test.js","sourceRoot":"","sources":["../../test/TableAuthIdentity.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proteinjs/db",
3
- "version": "1.50.0",
3
+ "version": "1.50.1",
4
4
  "main": "./dist/generated/index.js",
5
5
  "types": "./dist/generated/index.d.ts",
6
6
  "exports": {
@@ -66,5 +66,5 @@
66
66
  "ts-jest": "29.1.1",
67
67
  "typescript": "5.2.2"
68
68
  },
69
- "gitHead": "3b2c70b4497cc965fa829726a88fdcd2e1f2377d"
69
+ "gitHead": "a324a92e60161ddf69fec4e17b646882fe830f85"
70
70
  }
@@ -132,8 +132,32 @@ export class TableAuth {
132
132
 
133
133
  // Within a declared block an undeclared operation stays closed to everyone (the block is
134
134
  // the whole declaration) — `allows` reads undefined as false, so the two doors are exactly
135
- // the ones the table wrote down.
136
- return this.allows(tableAuth.all) || this.allows(tableAuth[operation]);
135
+ // the ones the table wrote down...
136
+ if (this.allows(tableAuth.all) || this.allows(tableAuth[operation])) {
137
+ return true;
138
+ }
139
+
140
+ // ...except that a db door the block leaves UNDECLARED mirrors the door the table's SERVICE
141
+ // block declares for the same operation. The RPC runs both doors — the service gate
142
+ // (TableServiceAuth), then the inner Db's db-api re-check as the calling user — so a service
143
+ // door with no db mirror admitted the caller at the gate and refused them behind it, in the
144
+ // gate's own words ("db doors mirror service doors" was a rule tables hand-copied; the owner
145
+ // derives it). One-way: a service block that omits the door keeps the lock (the session /
146
+ // audit-trail pattern — no write door on either api, break-glass included), and a table with
147
+ // no service block keeps its db block as written.
148
+ return api === 'db' && tableAuth.all === undefined && tableAuth[operation] === undefined
149
+ ? this.allowsServiceDoor(table, operation)
150
+ : false;
151
+ }
152
+
153
+ /** The service block's door for `operation`, as the RPC gate reads it; a table with no service block declares none. */
154
+ private allowsServiceDoor(table: Table<any>, operation: 'query' | 'insert' | 'update' | 'delete'): boolean {
155
+ const serviceAuth = table.auth?.service;
156
+ if (!serviceAuth || Object.keys(serviceAuth).length == 0) {
157
+ return false;
158
+ }
159
+
160
+ return this.allows(serviceAuth.all) || this.allows(serviceAuth[operation]);
137
161
  }
138
162
 
139
163
  /** One identity against the current user; undefined (nothing declared) is not a grant. */
@@ -11,8 +11,9 @@ import { TableAuth } from '../src/auth/TableAuth';
11
11
  * - each identity form resolves against the current user; 'admin' is break-glass throughout;
12
12
  * - an UNDECLARED identity is admin-only (default-deny made explicit), never open;
13
13
  * - it fails CLOSED when no user can be resolved;
14
- * - the operation doors (`canPerform`) are byte-for-byte the pre-refactor semantics: within a
15
- * declared block an undeclared operation stays closed to everyone, admin included.
14
+ * - the operation doors (`canPerform`) keep the declared-block semantics: within a declared block
15
+ * an undeclared operation stays closed to everyone, admin included — unless the table's SERVICE
16
+ * block names that door, which the db door then mirrors (the last describe).
16
17
  *
17
18
  * `UserAuth` reads from a static repo; tests stub it directly per identity — no server needed.
18
19
  */
@@ -113,3 +114,95 @@ describe('TableAuth operation doors keep their declared-block semantics', () =>
113
114
  expect(new TableAuth().canPerform(new QueryOnlyTable(), 'insert')).toBe(false);
114
115
  });
115
116
  });
117
+
118
+ /**
119
+ * The RPC runs BOTH doors — the service gate (`TableServiceAuth`) and then the inner `Db`'s
120
+ * db-api re-check as the calling user — so a db door a table leaves UNDECLARED mirrors the door
121
+ * its service block declares for the same operation. "db doors mirror service doors" was a rule
122
+ * tables hand-copied; the owner derives it now: fifteen consumer tables opened `['admin']` writes
123
+ * on the service api over a query-only db block, and every one refused the admin at the inner
124
+ * check in the gate's own words — the gate admitted them, the re-check behind it did not, two
125
+ * verdicts for one caller. One-way: a service block that omits the door keeps the lock (the
126
+ * session / audit-trail pattern — no write door on either api, break-glass included), and a table
127
+ * with no service block keeps its db block as written (the pin above).
128
+ */
129
+ class ReadOpenWriteAdminTable extends Table<Doc> {
130
+ public name = 'identity_read_open_write_admin_test';
131
+ public auth: Table<Doc>['auth'] = {
132
+ db: { query: 'authenticated' },
133
+ service: { query: 'authenticated', insert: ['admin'], update: ['admin'], delete: ['admin'] },
134
+ };
135
+ public columns = withRecordColumns<Doc>({ title: new StringColumn('title') });
136
+ }
137
+
138
+ class LockedLedgerTable extends Table<Doc> {
139
+ public name = 'identity_locked_ledger_test';
140
+ public auth: Table<Doc>['auth'] = {
141
+ db: { query: { permission: 'ledger' } },
142
+ service: { query: { permission: 'ledger' } },
143
+ };
144
+ public columns = withRecordColumns<Doc>({ title: new StringColumn('title') });
145
+ }
146
+
147
+ describe('TableAuth — an undeclared db door mirrors the declared service door', () => {
148
+ beforeEach(() => {
149
+ setMapping({ ledger: ['ledger'] });
150
+ });
151
+
152
+ afterEach(() => {
153
+ (UserAuth as any).userRepo = undefined;
154
+ (UserAuth as any).permissionRolesMapping = undefined;
155
+ });
156
+
157
+ test("an admin's write clears the ['admin'] service door AND the db-api re-check behind it", () => {
158
+ setUser(['admin']);
159
+ const table = new ReadOpenWriteAdminTable();
160
+ expect(() => new TableAuth().canUpdate(table, 'service')).not.toThrow();
161
+ expect(() => new TableAuth().canUpdate(table)).not.toThrow();
162
+ expect(() => new TableAuth().canInsert(table)).not.toThrow();
163
+ expect(() => new TableAuth().canDelete(table)).not.toThrow();
164
+ expect(new TableAuth().canPerform(table, 'update', 'db')).toBe(true);
165
+ });
166
+
167
+ test('a signed-in non-admin is refused by name on both apis; the read door stays open', () => {
168
+ setUser(['ledger']);
169
+ const table = new ReadOpenWriteAdminTable();
170
+ expect(() => new TableAuth().canUpdate(table, 'service')).toThrow(
171
+ 'User is not authorized to update records in table: identity_read_open_write_admin_test'
172
+ );
173
+ expect(() => new TableAuth().canUpdate(table)).toThrow(
174
+ 'User is not authorized to update records in table: identity_read_open_write_admin_test'
175
+ );
176
+ expect(() => new TableAuth().canQuery(table)).not.toThrow();
177
+ });
178
+
179
+ test('a guest is refused every door', () => {
180
+ setGuest();
181
+ const table = new ReadOpenWriteAdminTable();
182
+ expect(() => new TableAuth().canQuery(table)).toThrow(
183
+ 'User is not authorized to query table: identity_read_open_write_admin_test'
184
+ );
185
+ expect(() => new TableAuth().canUpdate(table)).toThrow();
186
+ expect(() => new TableAuth().canInsert(table, 'service')).toThrow();
187
+ });
188
+
189
+ test('one-way: a service block that omits the door keeps the lock on both apis, break-glass included', () => {
190
+ setUser(['admin']);
191
+ const table = new LockedLedgerTable();
192
+ expect(new TableAuth().canPerform(table, 'update', 'service')).toBe(false);
193
+ expect(new TableAuth().canPerform(table, 'update', 'db')).toBe(false);
194
+ expect(() => new TableAuth().canUpdate(table)).toThrow(
195
+ 'User is not authorized to update records in table: identity_locked_ledger_test'
196
+ );
197
+ expect(() => new TableAuth().canInsert(table, 'service')).toThrow();
198
+ expect(() => new TableAuth().canQuery(table)).not.toThrow();
199
+ });
200
+
201
+ test('a table with no service block keeps its db block as written — admin included', () => {
202
+ setUser(['admin']);
203
+ expect(new TableAuth().canPerform(new QueryOnlyTable(), 'update', 'db')).toBe(false);
204
+ expect(() => new TableAuth().canUpdate(new QueryOnlyTable())).toThrow(
205
+ 'User is not authorized to update records in table: identity_query_only_test'
206
+ );
207
+ });
208
+ });