@nymphjs/tilmeld 1.0.0-beta.13 → 1.0.0-beta.131

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.
Files changed (105) hide show
  1. package/CHANGELOG.md +604 -0
  2. package/README.md +21 -5
  3. package/dist/AbleObject.d.ts +15 -0
  4. package/dist/AbleObject.js +18 -6
  5. package/dist/AbleObject.js.map +1 -1
  6. package/dist/Group.d.ts +183 -19
  7. package/dist/Group.js +814 -440
  8. package/dist/Group.js.map +1 -1
  9. package/dist/Group.testArtifacts.d.ts +3 -0
  10. package/dist/Group.testArtifacts.js +120 -0
  11. package/dist/Group.testArtifacts.js.map +1 -0
  12. package/dist/Tilmeld.d.ts +241 -12
  13. package/dist/Tilmeld.js +725 -286
  14. package/dist/Tilmeld.js.map +1 -1
  15. package/dist/Tilmeld.types.d.ts +5 -5
  16. package/dist/Tilmeld.types.js +1 -2
  17. package/dist/User.d.ts +396 -26
  18. package/dist/User.js +1955 -1058
  19. package/dist/User.js.map +1 -1
  20. package/dist/User.testArtifacts.d.ts +3 -0
  21. package/dist/User.testArtifacts.js +175 -0
  22. package/dist/User.testArtifacts.js.map +1 -0
  23. package/dist/conf/defaults.d.ts +1 -1
  24. package/dist/conf/defaults.js +196 -141
  25. package/dist/conf/defaults.js.map +1 -1
  26. package/dist/conf/index.d.ts +355 -2
  27. package/dist/conf/index.js +2 -8
  28. package/dist/conf/index.js.map +1 -1
  29. package/dist/decorators/index.d.ts +2 -0
  30. package/dist/decorators/index.js +3 -0
  31. package/dist/decorators/index.js.map +1 -0
  32. package/dist/decorators/requireAbility.d.ts +10 -0
  33. package/dist/decorators/requireAbility.js +21 -0
  34. package/dist/decorators/requireAbility.js.map +1 -0
  35. package/dist/decorators/requireAuthentication.d.ts +8 -0
  36. package/dist/decorators/requireAuthentication.js +16 -0
  37. package/dist/decorators/requireAuthentication.js.map +1 -0
  38. package/dist/enforceTilmeld.d.ts +3 -0
  39. package/dist/enforceTilmeld.js +18 -0
  40. package/dist/enforceTilmeld.js.map +1 -0
  41. package/dist/errors/AccessControlError.d.ts +2 -1
  42. package/dist/errors/AccessControlError.js +3 -6
  43. package/dist/errors/AccessControlError.js.map +1 -1
  44. package/dist/errors/BadDataError.d.ts +2 -1
  45. package/dist/errors/BadDataError.js +3 -6
  46. package/dist/errors/BadDataError.js.map +1 -1
  47. package/dist/errors/BadEmailError.d.ts +2 -1
  48. package/dist/errors/BadEmailError.js +3 -6
  49. package/dist/errors/BadEmailError.js.map +1 -1
  50. package/dist/errors/BadUsernameError.d.ts +2 -1
  51. package/dist/errors/BadUsernameError.js +3 -6
  52. package/dist/errors/BadUsernameError.js.map +1 -1
  53. package/dist/errors/CouldNotChangeDefaultPrimaryGroupError.js +1 -5
  54. package/dist/errors/CouldNotChangeDefaultPrimaryGroupError.js.map +1 -1
  55. package/dist/errors/EmailChangeRateLimitExceededError.js +1 -5
  56. package/dist/errors/EmailChangeRateLimitExceededError.js.map +1 -1
  57. package/dist/errors/index.d.ts +6 -6
  58. package/dist/errors/index.js +6 -22
  59. package/dist/errors/index.js.map +1 -1
  60. package/dist/index.d.ts +12 -10
  61. package/dist/index.js +17 -35
  62. package/dist/index.js.map +1 -1
  63. package/dist/testArtifacts.d.ts +23 -0
  64. package/dist/testArtifacts.js +1317 -0
  65. package/dist/testArtifacts.js.map +1 -0
  66. package/dist/tilmeldJoiProps.d.ts +3 -3
  67. package/dist/tilmeldJoiProps.js +13 -18
  68. package/dist/tilmeldJoiProps.js.map +1 -1
  69. package/jest.config.js +31 -5
  70. package/package.json +49 -36
  71. package/src/AbleObject.ts +2 -2
  72. package/src/Group.testArtifacts.ts +159 -0
  73. package/src/Group.ts +647 -241
  74. package/src/Tilmeld.ts +550 -315
  75. package/src/Tilmeld.types.ts +5 -5
  76. package/src/User.testArtifacts.ts +226 -0
  77. package/src/User.ts +1657 -637
  78. package/src/conf/defaults.ts +172 -109
  79. package/src/conf/index.ts +370 -2
  80. package/src/decorators/index.ts +2 -0
  81. package/src/decorators/requireAbility.ts +26 -0
  82. package/src/decorators/requireAuthentication.ts +19 -0
  83. package/src/enforceTilmeld.ts +20 -0
  84. package/src/errors/AccessControlError.ts +4 -2
  85. package/src/errors/BadDataError.ts +4 -2
  86. package/src/errors/BadEmailError.ts +4 -2
  87. package/src/errors/BadUsernameError.ts +4 -2
  88. package/src/errors/index.ts +6 -6
  89. package/src/index.ts +13 -10
  90. package/src/testArtifacts.ts +2098 -0
  91. package/src/tilmeldJoiProps.ts +8 -23
  92. package/tsconfig.json +6 -3
  93. package/typedoc.json +4 -0
  94. package/dist/Group.test.d.ts +0 -1
  95. package/dist/Group.test.js +0 -48
  96. package/dist/Group.test.js.map +0 -1
  97. package/dist/User.test.d.ts +0 -1
  98. package/dist/User.test.js +0 -51
  99. package/dist/User.test.js.map +0 -1
  100. package/dist/conf/d.d.ts +0 -55
  101. package/dist/conf/d.js +0 -3
  102. package/dist/conf/d.js.map +0 -1
  103. package/src/Group.test.ts +0 -58
  104. package/src/User.test.ts +0 -61
  105. package/src/conf/d.ts +0 -303
@@ -0,0 +1,1317 @@
1
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
2
+ var useValue = arguments.length > 2;
3
+ for (var i = 0; i < initializers.length; i++) {
4
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
5
+ }
6
+ return useValue ? value : void 0;
7
+ };
8
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
+ var _, done = false;
14
+ for (var i = decorators.length - 1; i >= 0; i--) {
15
+ var context = {};
16
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
+ if (kind === "accessor") {
21
+ if (result === void 0) continue;
22
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
+ if (_ = accept(result.get)) descriptor.get = _;
24
+ if (_ = accept(result.set)) descriptor.set = _;
25
+ if (_ = accept(result.init)) initializers.unshift(_);
26
+ }
27
+ else if (_ = accept(result)) {
28
+ if (kind === "field") initializers.unshift(_);
29
+ else descriptor[key] = _;
30
+ }
31
+ }
32
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
+ done = true;
34
+ };
35
+ import { Entity, Nymph, HttpError, TilmeldAccessLevels, TilmeldAccessRequest, } from '@nymphjs/nymph';
36
+ import Tilmeld from './Tilmeld.js';
37
+ import { requireAbility, requireAuthentication } from './decorators/index.js';
38
+ import { AccessControlError } from './errors/index.js';
39
+ import { UserTest } from './User.testArtifacts.js';
40
+ import { GroupTest } from './Group.testArtifacts.js';
41
+ /**
42
+ * This class is a test class that extends the Entity class.
43
+ */
44
+ let TestModel = (() => {
45
+ let _classSuper = Entity;
46
+ let _instanceExtraInitializers = [];
47
+ let _$testRequireAuthenticationDecorator_decorators;
48
+ let _$testRequireAuthenticationDecoratorAsync_decorators;
49
+ let _$testRequireAbilityDecorator_decorators;
50
+ let _$testRequireAbilityDecoratorAsync_decorators;
51
+ return class TestModel extends _classSuper {
52
+ static {
53
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
54
+ _$testRequireAuthenticationDecorator_decorators = [requireAuthentication];
55
+ _$testRequireAuthenticationDecoratorAsync_decorators = [requireAuthentication];
56
+ _$testRequireAbilityDecorator_decorators = [requireAbility('test-ability')];
57
+ _$testRequireAbilityDecoratorAsync_decorators = [requireAbility('test-ability')];
58
+ __esDecorate(this, null, _$testRequireAuthenticationDecorator_decorators, { kind: "method", name: "$testRequireAuthenticationDecorator", static: false, private: false, access: { has: obj => "$testRequireAuthenticationDecorator" in obj, get: obj => obj.$testRequireAuthenticationDecorator }, metadata: _metadata }, null, _instanceExtraInitializers);
59
+ __esDecorate(this, null, _$testRequireAuthenticationDecoratorAsync_decorators, { kind: "method", name: "$testRequireAuthenticationDecoratorAsync", static: false, private: false, access: { has: obj => "$testRequireAuthenticationDecoratorAsync" in obj, get: obj => obj.$testRequireAuthenticationDecoratorAsync }, metadata: _metadata }, null, _instanceExtraInitializers);
60
+ __esDecorate(this, null, _$testRequireAbilityDecorator_decorators, { kind: "method", name: "$testRequireAbilityDecorator", static: false, private: false, access: { has: obj => "$testRequireAbilityDecorator" in obj, get: obj => obj.$testRequireAbilityDecorator }, metadata: _metadata }, null, _instanceExtraInitializers);
61
+ __esDecorate(this, null, _$testRequireAbilityDecoratorAsync_decorators, { kind: "method", name: "$testRequireAbilityDecoratorAsync", static: false, private: false, access: { has: obj => "$testRequireAbilityDecoratorAsync" in obj, get: obj => obj.$testRequireAbilityDecoratorAsync }, metadata: _metadata }, null, _instanceExtraInitializers);
62
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
63
+ }
64
+ static ETYPE = 'tilmeld_test_model';
65
+ static class = 'TestModel';
66
+ /**
67
+ * This should only be used by the backend.
68
+ */
69
+ $skipAcWhenDeleting = (__runInitializers(this, _instanceExtraInitializers), false);
70
+ $testRequireAuthenticationDecorator() {
71
+ return true;
72
+ }
73
+ async $testRequireAuthenticationDecoratorAsync() {
74
+ return true;
75
+ }
76
+ $testRequireAbilityDecorator() {
77
+ return true;
78
+ }
79
+ async $testRequireAbilityDecoratorAsync() {
80
+ return true;
81
+ }
82
+ /*
83
+ * This should *never* be accessible on the client.
84
+ */
85
+ async $deleteSkipAC() {
86
+ this.$skipAcWhenDeleting = true;
87
+ return await this.$delete();
88
+ }
89
+ $tilmeldDeleteSkipAC() {
90
+ if (this.$skipAcWhenDeleting) {
91
+ this.$skipAcWhenDeleting = false;
92
+ return true;
93
+ }
94
+ return false;
95
+ }
96
+ };
97
+ })();
98
+ export { TestModel };
99
+ const TestModelClass = TestModel;
100
+ export function TilmeldTest(nymphBase, describe, it) {
101
+ const tilmeld = new Tilmeld({
102
+ appName: 'My App',
103
+ appUrl: 'http://localhost:8080',
104
+ cookieDomain: 'localhost',
105
+ cookiePath: '/',
106
+ setupPath: '/user',
107
+ emailUsernames: false,
108
+ domainSupport: true,
109
+ verifyRedirect: 'http://localhost:8080',
110
+ verifyChangeRedirect: 'http://localhost:8080',
111
+ cancelChangeRedirect: 'http://localhost:8080',
112
+ jwtSecret: 'shhhhh',
113
+ sendEmail: async (_tilmeld, _options, _user) => {
114
+ return true;
115
+ },
116
+ });
117
+ const nymph = new Nymph(nymphBase.config, nymphBase.driver, tilmeld);
118
+ describe('Tilmeld', () => {
119
+ UserTest(nymph, tilmeld, describe, it);
120
+ GroupTest(nymph, tilmeld, describe, it);
121
+ const User = tilmeld.User;
122
+ const Group = tilmeld.Group;
123
+ const TestModel = nymph.addEntityClass(TestModelClass);
124
+ async function deleteTestData() {
125
+ let all = await nymph.getEntities({
126
+ class: TestModel,
127
+ });
128
+ expect(Array.isArray(all)).toEqual(true);
129
+ for (const cur of all) {
130
+ await cur.$deleteSkipAC();
131
+ }
132
+ all = await nymph.getEntities({ class: TestModel });
133
+ expect(all.length).toEqual(0);
134
+ all = await nymph.getEntities({ class: User });
135
+ expect(Array.isArray(all)).toEqual(true);
136
+ for (const cur of all) {
137
+ await cur.$deleteSkipAC();
138
+ }
139
+ all = await nymph.getEntities({ class: User });
140
+ expect(all.length).toEqual(0);
141
+ all = await nymph.getEntities({ class: Group });
142
+ expect(Array.isArray(all)).toEqual(true);
143
+ for (const cur of all) {
144
+ await cur.$deleteSkipAC();
145
+ }
146
+ all = await nymph.getEntities({ class: Group });
147
+ expect(all.length).toEqual(0);
148
+ }
149
+ async function makeUsers() {
150
+ const admin = await User.factoryUsername('admin');
151
+ const bob = await User.factoryUsername('bob');
152
+ const alice = await User.factoryUsername('alice');
153
+ const abgroup = await Group.factoryGroupname('abgroup');
154
+ if (admin.guid == null) {
155
+ admin.username = 'admin';
156
+ admin.email = 'admin@localhost';
157
+ admin.nameFirst = 'Admin';
158
+ admin.nameLast = 'User';
159
+ admin.name = 'Admin User';
160
+ admin.$password('password');
161
+ admin.$grant('system/admin');
162
+ await admin.$saveSkipAC();
163
+ }
164
+ if (abgroup.guid == null) {
165
+ abgroup.groupname = 'abgroup';
166
+ abgroup.email = 'abgroup@localhost';
167
+ abgroup.name = 'AB Group';
168
+ await abgroup.$saveSkipAC();
169
+ }
170
+ if (bob.guid == null) {
171
+ bob.username = 'bob';
172
+ bob.email = 'bob@localhost';
173
+ bob.nameFirst = 'Bob';
174
+ bob.nameLast = 'User';
175
+ bob.name = 'Bob User';
176
+ bob.$password('password');
177
+ bob.$addGroup(abgroup);
178
+ await bob.$saveSkipAC();
179
+ }
180
+ if (alice.guid == null) {
181
+ alice.username = 'alice';
182
+ alice.email = 'alice@localhost';
183
+ alice.nameFirst = 'Alice';
184
+ alice.nameLast = 'User';
185
+ alice.name = 'Alice User';
186
+ alice.$password('password');
187
+ alice.$addGroup(abgroup);
188
+ await alice.$saveSkipAC();
189
+ }
190
+ return { admin, bob, alice, abgroup };
191
+ }
192
+ it('delete old test data', async () => {
193
+ await deleteTestData();
194
+ });
195
+ it('users can log in', async () => {
196
+ const { admin, bob, alice } = await makeUsers();
197
+ let result = await admin.$login({
198
+ username: 'admin',
199
+ password: 'password',
200
+ });
201
+ expect(result.result).toEqual(true);
202
+ expect(admin.$is(User.current())).toEqual(true);
203
+ result = await admin.$logout();
204
+ expect(result.result).toEqual(true);
205
+ expect(User.current()).toBeNull();
206
+ result = await bob.$login({
207
+ username: 'bob',
208
+ password: 'password',
209
+ });
210
+ expect(result.result).toEqual(true);
211
+ expect(bob.$is(User.current())).toEqual(true);
212
+ result = await bob.$logout();
213
+ expect(result.result).toEqual(true);
214
+ expect(User.current()).toBeNull();
215
+ result = await alice.$login({
216
+ username: 'alice',
217
+ password: 'password',
218
+ });
219
+ expect(result.result).toEqual(true);
220
+ expect(alice.$is(User.current())).toEqual(true);
221
+ result = await alice.$logout();
222
+ expect(result.result).toEqual(true);
223
+ expect(User.current()).toBeNull();
224
+ });
225
+ it('creates tables for test model', async () => {
226
+ const testEntity = await nymph.getEntity({ class: TestModel });
227
+ expect(testEntity).toBeNull();
228
+ });
229
+ it('user ownership, group ownership, and access controls are added on entities', async () => {
230
+ const { bob } = await makeUsers();
231
+ await tilmeld.fillSession(bob);
232
+ const bobsEntity = await TestModel.factory();
233
+ bobsEntity.name = "Bob's Entity";
234
+ await bobsEntity.$save();
235
+ expect(bobsEntity.guid).not.toBeNull();
236
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
237
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
238
+ expect(testEntityBob).not.toBeNull();
239
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
240
+ expect(testEntityBob?.user?.$is(bob)).toEqual(true);
241
+ expect(testEntityBob?.group?.$is(bob.group)).toEqual(true);
242
+ expect(testEntityBob?.acUser).toEqual(TilmeldAccessLevels.FULL_ACCESS);
243
+ expect(testEntityBob?.acGroup).toEqual(TilmeldAccessLevels.READ_ACCESS);
244
+ expect(testEntityBob?.acOther).toEqual(TilmeldAccessLevels.NO_ACCESS);
245
+ expect(testEntityBob?.acRead).toEqual([]);
246
+ expect(testEntityBob?.acWrite).toEqual([]);
247
+ expect(testEntityBob?.acFull).toEqual([]);
248
+ });
249
+ it('require authentication decorator', async () => {
250
+ const { bob } = await makeUsers();
251
+ await tilmeld.fillSession(bob);
252
+ const bobsEntity = await TestModel.factory();
253
+ bobsEntity.name = "Bob's Entity";
254
+ await bobsEntity.$save();
255
+ expect(bobsEntity.$testRequireAuthenticationDecorator()).toEqual(true);
256
+ expect(await bobsEntity.$testRequireAuthenticationDecoratorAsync()).toEqual(true);
257
+ tilmeld.clearSession();
258
+ try {
259
+ bobsEntity.$testRequireAuthenticationDecorator();
260
+ throw new Error('Should have thrown.');
261
+ }
262
+ catch (e) {
263
+ expect(e).toBeInstanceOf(HttpError);
264
+ expect(e.status).toEqual(403);
265
+ expect(e.message).toEqual('Forbidden');
266
+ }
267
+ try {
268
+ await bobsEntity.$testRequireAuthenticationDecoratorAsync();
269
+ throw new Error('Should have thrown.');
270
+ }
271
+ catch (e) {
272
+ expect(e).toBeInstanceOf(HttpError);
273
+ expect(e.status).toEqual(403);
274
+ expect(e.message).toEqual('Forbidden');
275
+ }
276
+ });
277
+ it('require ability decorator', async () => {
278
+ const { bob } = await makeUsers();
279
+ await tilmeld.fillSession(bob);
280
+ const bobsEntity = await TestModel.factory();
281
+ bobsEntity.name = "Bob's Entity";
282
+ await bobsEntity.$save();
283
+ try {
284
+ bobsEntity.$testRequireAbilityDecorator();
285
+ throw new Error('Should have thrown.');
286
+ }
287
+ catch (e) {
288
+ expect(e).toBeInstanceOf(HttpError);
289
+ expect(e.status).toEqual(403);
290
+ expect(e.message).toEqual('Forbidden');
291
+ }
292
+ try {
293
+ await bobsEntity.$testRequireAbilityDecoratorAsync();
294
+ throw new Error('Should have thrown.');
295
+ }
296
+ catch (e) {
297
+ expect(e).toBeInstanceOf(HttpError);
298
+ expect(e.status).toEqual(403);
299
+ expect(e.message).toEqual('Forbidden');
300
+ }
301
+ tilmeld.clearSession();
302
+ try {
303
+ bobsEntity.$testRequireAbilityDecorator();
304
+ throw new Error('Should have thrown.');
305
+ }
306
+ catch (e) {
307
+ expect(e).toBeInstanceOf(HttpError);
308
+ expect(e.status).toEqual(403);
309
+ expect(e.message).toEqual('Forbidden');
310
+ }
311
+ try {
312
+ await bobsEntity.$testRequireAbilityDecoratorAsync();
313
+ throw new Error('Should have thrown.');
314
+ }
315
+ catch (e) {
316
+ expect(e).toBeInstanceOf(HttpError);
317
+ expect(e.status).toEqual(403);
318
+ expect(e.message).toEqual('Forbidden');
319
+ }
320
+ bob.$grant('test-ability');
321
+ await tilmeld.fillSession(bob);
322
+ expect(bobsEntity.$testRequireAbilityDecorator()).toEqual(true);
323
+ expect(await bobsEntity.$testRequireAbilityDecoratorAsync()).toEqual(true);
324
+ });
325
+ it("alice can't access an entity owned by bob", async () => {
326
+ const { bob, alice } = await makeUsers();
327
+ await tilmeld.fillSession(bob);
328
+ const bobsEntity = await TestModel.factory();
329
+ bobsEntity.name = "Bob's Entity";
330
+ await bobsEntity.$save();
331
+ expect(bobsEntity.guid).not.toBeNull();
332
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
333
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
334
+ expect(testEntityBob).not.toBeNull();
335
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
336
+ tilmeld.clearSession();
337
+ await tilmeld.fillSession(alice);
338
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
339
+ expect(testEntityAlice).toBeNull();
340
+ });
341
+ it("alice can't write to an entity she doesn't have write permission for", async () => {
342
+ const { bob, alice } = await makeUsers();
343
+ await tilmeld.fillSession(bob);
344
+ const bobsEntity = await TestModel.factory();
345
+ bobsEntity.name = "Bob's Entity";
346
+ bobsEntity.acRead = [alice.guid ?? ''];
347
+ await bobsEntity.$save();
348
+ expect(bobsEntity.guid).not.toBeNull();
349
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
350
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
351
+ expect(testEntityBob).not.toBeNull();
352
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
353
+ tilmeld.clearSession();
354
+ await tilmeld.fillSession(alice);
355
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
356
+ expect(testEntityAlice).not.toBeNull();
357
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
358
+ if (testEntityAlice == null) {
359
+ throw new Error();
360
+ }
361
+ testEntityAlice.name = "Haha! It's mine now!";
362
+ try {
363
+ await testEntityAlice.$save();
364
+ throw new Error('It should have thrown AccessControlError.');
365
+ }
366
+ catch (e) {
367
+ expect(e).toBeInstanceOf(AccessControlError);
368
+ }
369
+ expect(await testEntityAlice.$refresh()).toEqual(true);
370
+ expect(testEntityAlice.name).toEqual("Bob's Entity");
371
+ });
372
+ it('alice can write to an entity she has write permission for', async () => {
373
+ const { bob, alice } = await makeUsers();
374
+ await tilmeld.fillSession(bob);
375
+ const bobsEntity = await TestModel.factory();
376
+ bobsEntity.name = "Bob's Entity";
377
+ bobsEntity.acWrite = [alice.guid ?? ''];
378
+ await bobsEntity.$save();
379
+ expect(bobsEntity.guid).not.toBeNull();
380
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
381
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
382
+ expect(testEntityBob).not.toBeNull();
383
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
384
+ tilmeld.clearSession();
385
+ await tilmeld.fillSession(alice);
386
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
387
+ expect(testEntityAlice).not.toBeNull();
388
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
389
+ if (testEntityAlice == null) {
390
+ throw new Error();
391
+ }
392
+ testEntityAlice.name = "Haha! It's mine now!";
393
+ await testEntityAlice.$save();
394
+ expect(await testEntityAlice.$refresh()).toEqual(true);
395
+ expect(testEntityAlice.name).toEqual("Haha! It's mine now!");
396
+ });
397
+ it("alice can't delete an entity she doesn't have full permission for", async () => {
398
+ const { bob, alice } = await makeUsers();
399
+ await tilmeld.fillSession(bob);
400
+ const bobsEntity = await TestModel.factory();
401
+ bobsEntity.name = "Bob's Entity";
402
+ bobsEntity.acWrite = [alice.guid ?? ''];
403
+ await bobsEntity.$save();
404
+ expect(bobsEntity.guid).not.toBeNull();
405
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
406
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
407
+ expect(testEntityBob).not.toBeNull();
408
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
409
+ tilmeld.clearSession();
410
+ await tilmeld.fillSession(alice);
411
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
412
+ expect(testEntityAlice).not.toBeNull();
413
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
414
+ if (testEntityAlice == null) {
415
+ throw new Error();
416
+ }
417
+ try {
418
+ await testEntityAlice.$delete();
419
+ throw new Error('It should have thrown AccessControlError.');
420
+ }
421
+ catch (e) {
422
+ expect(e).toBeInstanceOf(AccessControlError);
423
+ }
424
+ expect(await testEntityAlice.$refresh()).toEqual(true);
425
+ expect(testEntityAlice.guid).toEqual(bobsEntity.guid);
426
+ });
427
+ it('alice can delete an entity she has full permission for', async () => {
428
+ const { bob, alice } = await makeUsers();
429
+ await tilmeld.fillSession(bob);
430
+ const bobsEntity = await TestModel.factory();
431
+ bobsEntity.name = "Bob's Entity";
432
+ bobsEntity.acFull = [alice.guid ?? ''];
433
+ await bobsEntity.$save();
434
+ expect(bobsEntity.guid).not.toBeNull();
435
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
436
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
437
+ expect(testEntityBob).not.toBeNull();
438
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
439
+ tilmeld.clearSession();
440
+ await tilmeld.fillSession(alice);
441
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
442
+ expect(testEntityAlice).not.toBeNull();
443
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
444
+ if (testEntityAlice == null) {
445
+ throw new Error();
446
+ }
447
+ await testEntityAlice.$delete();
448
+ const verifyEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
449
+ expect(verifyEntityAlice).toBeNull();
450
+ });
451
+ it('alice can access an entity her group has permission for', async () => {
452
+ const { bob, alice, abgroup } = await makeUsers();
453
+ await tilmeld.fillSession(bob);
454
+ const bobsEntity = await TestModel.factory();
455
+ bobsEntity.name = "Bob's Entity";
456
+ bobsEntity.acRead = [abgroup.guid ?? ''];
457
+ await bobsEntity.$save();
458
+ expect(bobsEntity.guid).not.toBeNull();
459
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
460
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
461
+ expect(testEntityBob).not.toBeNull();
462
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
463
+ tilmeld.clearSession();
464
+ await tilmeld.fillSession(alice);
465
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
466
+ expect(testEntityAlice).not.toBeNull();
467
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
468
+ });
469
+ it("alice can't write to an entity her group doesn't have write permission for", async () => {
470
+ const { bob, alice, abgroup } = await makeUsers();
471
+ await tilmeld.fillSession(bob);
472
+ const bobsEntity = await TestModel.factory();
473
+ bobsEntity.name = "Bob's Entity";
474
+ bobsEntity.acRead = [abgroup.guid ?? ''];
475
+ await bobsEntity.$save();
476
+ expect(bobsEntity.guid).not.toBeNull();
477
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
478
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
479
+ expect(testEntityBob).not.toBeNull();
480
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
481
+ tilmeld.clearSession();
482
+ await tilmeld.fillSession(alice);
483
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
484
+ expect(testEntityAlice).not.toBeNull();
485
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
486
+ if (testEntityAlice == null) {
487
+ throw new Error();
488
+ }
489
+ testEntityAlice.name = "Haha! It's mine now!";
490
+ try {
491
+ await testEntityAlice.$save();
492
+ throw new Error('It should have thrown AccessControlError.');
493
+ }
494
+ catch (e) {
495
+ expect(e).toBeInstanceOf(AccessControlError);
496
+ }
497
+ expect(await testEntityAlice.$refresh()).toEqual(true);
498
+ expect(testEntityAlice.name).toEqual("Bob's Entity");
499
+ });
500
+ it('alice can write to an entity her group has write permission for', async () => {
501
+ const { bob, alice, abgroup } = await makeUsers();
502
+ await tilmeld.fillSession(bob);
503
+ const bobsEntity = await TestModel.factory();
504
+ bobsEntity.name = "Bob's Entity";
505
+ bobsEntity.acWrite = [abgroup.guid ?? ''];
506
+ await bobsEntity.$save();
507
+ expect(bobsEntity.guid).not.toBeNull();
508
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
509
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
510
+ expect(testEntityBob).not.toBeNull();
511
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
512
+ tilmeld.clearSession();
513
+ await tilmeld.fillSession(alice);
514
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
515
+ expect(testEntityAlice).not.toBeNull();
516
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
517
+ if (testEntityAlice == null) {
518
+ throw new Error();
519
+ }
520
+ testEntityAlice.name = "Haha! It's mine now!";
521
+ await testEntityAlice.$save();
522
+ expect(await testEntityAlice.$refresh()).toEqual(true);
523
+ expect(testEntityAlice.name).toEqual("Haha! It's mine now!");
524
+ });
525
+ it("alice can't delete an entity her group doesn't have full permission for", async () => {
526
+ const { bob, alice, abgroup } = await makeUsers();
527
+ await tilmeld.fillSession(bob);
528
+ const bobsEntity = await TestModel.factory();
529
+ bobsEntity.name = "Bob's Entity";
530
+ bobsEntity.acWrite = [abgroup.guid ?? ''];
531
+ await bobsEntity.$save();
532
+ expect(bobsEntity.guid).not.toBeNull();
533
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
534
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
535
+ expect(testEntityBob).not.toBeNull();
536
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
537
+ tilmeld.clearSession();
538
+ await tilmeld.fillSession(alice);
539
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
540
+ expect(testEntityAlice).not.toBeNull();
541
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
542
+ if (testEntityAlice == null) {
543
+ throw new Error();
544
+ }
545
+ try {
546
+ await testEntityAlice.$delete();
547
+ throw new Error('It should have thrown AccessControlError.');
548
+ }
549
+ catch (e) {
550
+ expect(e).toBeInstanceOf(AccessControlError);
551
+ }
552
+ expect(await testEntityAlice.$refresh()).toEqual(true);
553
+ expect(testEntityAlice.guid).toEqual(bobsEntity.guid);
554
+ });
555
+ it('alice can delete an entity her group has full permission for', async () => {
556
+ const { bob, alice, abgroup } = await makeUsers();
557
+ await tilmeld.fillSession(bob);
558
+ const bobsEntity = await TestModel.factory();
559
+ bobsEntity.name = "Bob's Entity";
560
+ bobsEntity.acFull = [abgroup.guid ?? ''];
561
+ await bobsEntity.$save();
562
+ expect(bobsEntity.guid).not.toBeNull();
563
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
564
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
565
+ expect(testEntityBob).not.toBeNull();
566
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
567
+ tilmeld.clearSession();
568
+ await tilmeld.fillSession(alice);
569
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
570
+ expect(testEntityAlice).not.toBeNull();
571
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
572
+ if (testEntityAlice == null) {
573
+ throw new Error();
574
+ }
575
+ await testEntityAlice.$delete();
576
+ const verifyEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
577
+ expect(verifyEntityAlice).toBeNull();
578
+ });
579
+ it('alice can access an entity her primary group has permission for', async () => {
580
+ const { bob, alice } = await makeUsers();
581
+ await tilmeld.fillSession(bob);
582
+ const bobsEntity = await TestModel.factory();
583
+ bobsEntity.name = "Bob's Entity";
584
+ bobsEntity.group = alice.group;
585
+ await bobsEntity.$save();
586
+ expect(bobsEntity.guid).not.toBeNull();
587
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
588
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
589
+ expect(testEntityBob).not.toBeNull();
590
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
591
+ tilmeld.clearSession();
592
+ await tilmeld.fillSession(alice);
593
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
594
+ expect(testEntityAlice).not.toBeNull();
595
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
596
+ });
597
+ it("alice can't write to an entity her primary group doesn't have write permission for", async () => {
598
+ const { bob, alice } = await makeUsers();
599
+ await tilmeld.fillSession(bob);
600
+ const bobsEntity = await TestModel.factory();
601
+ bobsEntity.name = "Bob's Entity";
602
+ bobsEntity.group = alice.group;
603
+ await bobsEntity.$save();
604
+ expect(bobsEntity.guid).not.toBeNull();
605
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
606
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
607
+ expect(testEntityBob).not.toBeNull();
608
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
609
+ tilmeld.clearSession();
610
+ await tilmeld.fillSession(alice);
611
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
612
+ expect(testEntityAlice).not.toBeNull();
613
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
614
+ if (testEntityAlice == null) {
615
+ throw new Error();
616
+ }
617
+ testEntityAlice.name = "Haha! It's mine now!";
618
+ try {
619
+ await testEntityAlice.$save();
620
+ throw new Error('It should have thrown AccessControlError.');
621
+ }
622
+ catch (e) {
623
+ expect(e).toBeInstanceOf(AccessControlError);
624
+ }
625
+ expect(await testEntityAlice.$refresh()).toEqual(true);
626
+ expect(testEntityAlice.name).toEqual("Bob's Entity");
627
+ });
628
+ it('alice can write to an entity her primary group has write permission for', async () => {
629
+ const { bob, alice } = await makeUsers();
630
+ await tilmeld.fillSession(bob);
631
+ const bobsEntity = await TestModel.factory();
632
+ bobsEntity.name = "Bob's Entity";
633
+ bobsEntity.group = alice.group;
634
+ bobsEntity.acGroup = TilmeldAccessLevels.WRITE_ACCESS;
635
+ await bobsEntity.$save();
636
+ expect(bobsEntity.guid).not.toBeNull();
637
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
638
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
639
+ expect(testEntityBob).not.toBeNull();
640
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
641
+ tilmeld.clearSession();
642
+ await tilmeld.fillSession(alice);
643
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
644
+ expect(testEntityAlice).not.toBeNull();
645
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
646
+ if (testEntityAlice == null) {
647
+ throw new Error();
648
+ }
649
+ testEntityAlice.name = "Haha! It's mine now!";
650
+ await testEntityAlice.$save();
651
+ expect(await testEntityAlice.$refresh()).toEqual(true);
652
+ expect(testEntityAlice.name).toEqual("Haha! It's mine now!");
653
+ });
654
+ it("alice can't delete an entity her primary group doesn't have full permission for", async () => {
655
+ const { bob, alice } = await makeUsers();
656
+ await tilmeld.fillSession(bob);
657
+ const bobsEntity = await TestModel.factory();
658
+ bobsEntity.name = "Bob's Entity";
659
+ bobsEntity.group = alice.group;
660
+ bobsEntity.acGroup = TilmeldAccessLevels.WRITE_ACCESS;
661
+ await bobsEntity.$save();
662
+ expect(bobsEntity.guid).not.toBeNull();
663
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
664
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
665
+ expect(testEntityBob).not.toBeNull();
666
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
667
+ tilmeld.clearSession();
668
+ await tilmeld.fillSession(alice);
669
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
670
+ expect(testEntityAlice).not.toBeNull();
671
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
672
+ if (testEntityAlice == null) {
673
+ throw new Error();
674
+ }
675
+ try {
676
+ await testEntityAlice.$delete();
677
+ throw new Error('It should have thrown AccessControlError.');
678
+ }
679
+ catch (e) {
680
+ expect(e).toBeInstanceOf(AccessControlError);
681
+ }
682
+ expect(await testEntityAlice.$refresh()).toEqual(true);
683
+ expect(testEntityAlice.guid).toEqual(bobsEntity.guid);
684
+ });
685
+ it('alice can delete an entity her primary group has full permission for', async () => {
686
+ const { bob, alice } = await makeUsers();
687
+ await tilmeld.fillSession(bob);
688
+ const bobsEntity = await TestModel.factory();
689
+ bobsEntity.name = "Bob's Entity";
690
+ bobsEntity.group = alice.group;
691
+ bobsEntity.acGroup = TilmeldAccessLevels.FULL_ACCESS;
692
+ await bobsEntity.$save();
693
+ expect(bobsEntity.guid).not.toBeNull();
694
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
695
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
696
+ expect(testEntityBob).not.toBeNull();
697
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
698
+ tilmeld.clearSession();
699
+ await tilmeld.fillSession(alice);
700
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
701
+ expect(testEntityAlice).not.toBeNull();
702
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
703
+ if (testEntityAlice == null) {
704
+ throw new Error();
705
+ }
706
+ await testEntityAlice.$delete();
707
+ const verifyEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
708
+ expect(verifyEntityAlice).toBeNull();
709
+ });
710
+ it('alice can access an entity everyone has permission for', async () => {
711
+ const { bob, alice } = await makeUsers();
712
+ await tilmeld.fillSession(bob);
713
+ const bobsEntity = await TestModel.factory();
714
+ bobsEntity.name = "Bob's Entity";
715
+ bobsEntity.acOther = TilmeldAccessLevels.READ_ACCESS;
716
+ await bobsEntity.$save();
717
+ expect(bobsEntity.guid).not.toBeNull();
718
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
719
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
720
+ expect(testEntityBob).not.toBeNull();
721
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
722
+ tilmeld.clearSession();
723
+ await tilmeld.fillSession(alice);
724
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
725
+ expect(testEntityAlice).not.toBeNull();
726
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
727
+ });
728
+ it("alice can't write to an entity everyone doesn't have write permission for", async () => {
729
+ const { bob, alice } = await makeUsers();
730
+ await tilmeld.fillSession(bob);
731
+ const bobsEntity = await TestModel.factory();
732
+ bobsEntity.name = "Bob's Entity";
733
+ bobsEntity.acOther = TilmeldAccessLevels.READ_ACCESS;
734
+ await bobsEntity.$save();
735
+ expect(bobsEntity.guid).not.toBeNull();
736
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
737
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
738
+ expect(testEntityBob).not.toBeNull();
739
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
740
+ tilmeld.clearSession();
741
+ await tilmeld.fillSession(alice);
742
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
743
+ expect(testEntityAlice).not.toBeNull();
744
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
745
+ if (testEntityAlice == null) {
746
+ throw new Error();
747
+ }
748
+ testEntityAlice.name = "Haha! It's mine now!";
749
+ try {
750
+ await testEntityAlice.$save();
751
+ throw new Error('It should have thrown AccessControlError.');
752
+ }
753
+ catch (e) {
754
+ expect(e).toBeInstanceOf(AccessControlError);
755
+ }
756
+ expect(await testEntityAlice.$refresh()).toEqual(true);
757
+ expect(testEntityAlice.name).toEqual("Bob's Entity");
758
+ });
759
+ it('alice can write to an entity everyone has write permission for', async () => {
760
+ const { bob, alice } = await makeUsers();
761
+ await tilmeld.fillSession(bob);
762
+ const bobsEntity = await TestModel.factory();
763
+ bobsEntity.name = "Bob's Entity";
764
+ bobsEntity.acOther = TilmeldAccessLevels.WRITE_ACCESS;
765
+ await bobsEntity.$save();
766
+ expect(bobsEntity.guid).not.toBeNull();
767
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
768
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
769
+ expect(testEntityBob).not.toBeNull();
770
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
771
+ tilmeld.clearSession();
772
+ await tilmeld.fillSession(alice);
773
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
774
+ expect(testEntityAlice).not.toBeNull();
775
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
776
+ if (testEntityAlice == null) {
777
+ throw new Error();
778
+ }
779
+ testEntityAlice.name = "Haha! It's mine now!";
780
+ await testEntityAlice.$save();
781
+ expect(await testEntityAlice.$refresh()).toEqual(true);
782
+ expect(testEntityAlice.name).toEqual("Haha! It's mine now!");
783
+ });
784
+ it("alice can't delete an entity everyone doesn't have full permission for", async () => {
785
+ const { bob, alice } = await makeUsers();
786
+ await tilmeld.fillSession(bob);
787
+ const bobsEntity = await TestModel.factory();
788
+ bobsEntity.name = "Bob's Entity";
789
+ bobsEntity.acOther = TilmeldAccessLevels.WRITE_ACCESS;
790
+ await bobsEntity.$save();
791
+ expect(bobsEntity.guid).not.toBeNull();
792
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
793
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
794
+ expect(testEntityBob).not.toBeNull();
795
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
796
+ tilmeld.clearSession();
797
+ await tilmeld.fillSession(alice);
798
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
799
+ expect(testEntityAlice).not.toBeNull();
800
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
801
+ if (testEntityAlice == null) {
802
+ throw new Error();
803
+ }
804
+ try {
805
+ await testEntityAlice.$delete();
806
+ throw new Error('It should have thrown AccessControlError.');
807
+ }
808
+ catch (e) {
809
+ expect(e).toBeInstanceOf(AccessControlError);
810
+ }
811
+ expect(await testEntityAlice.$refresh()).toEqual(true);
812
+ expect(testEntityAlice.guid).toEqual(bobsEntity.guid);
813
+ });
814
+ it('alice can delete an entity everyone has full permission for', async () => {
815
+ const { bob, alice } = await makeUsers();
816
+ await tilmeld.fillSession(bob);
817
+ const bobsEntity = await TestModel.factory();
818
+ bobsEntity.name = "Bob's Entity";
819
+ bobsEntity.acOther = TilmeldAccessLevels.FULL_ACCESS;
820
+ await bobsEntity.$save();
821
+ expect(bobsEntity.guid).not.toBeNull();
822
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
823
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
824
+ expect(testEntityBob).not.toBeNull();
825
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
826
+ tilmeld.clearSession();
827
+ await tilmeld.fillSession(alice);
828
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
829
+ expect(testEntityAlice).not.toBeNull();
830
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
831
+ if (testEntityAlice == null) {
832
+ throw new Error();
833
+ }
834
+ await testEntityAlice.$delete();
835
+ const verifyEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
836
+ expect(verifyEntityAlice).toBeNull();
837
+ });
838
+ it('a clear session can delete an entity everyone has full permission for', async () => {
839
+ const { bob } = await makeUsers();
840
+ await tilmeld.fillSession(bob);
841
+ const bobsEntity = await TestModel.factory();
842
+ bobsEntity.name = "Bob's Entity";
843
+ bobsEntity.acOther = TilmeldAccessLevels.FULL_ACCESS;
844
+ await bobsEntity.$save();
845
+ expect(bobsEntity.guid).not.toBeNull();
846
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
847
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
848
+ expect(testEntityBob).not.toBeNull();
849
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
850
+ tilmeld.clearSession();
851
+ const testEntityNobody = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
852
+ expect(testEntityNobody).not.toBeNull();
853
+ expect(testEntityNobody?.guid).toEqual(bobsEntity.guid);
854
+ if (testEntityNobody == null) {
855
+ throw new Error();
856
+ }
857
+ await testEntityNobody.$delete();
858
+ const verifyEntityNobody = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
859
+ expect(verifyEntityNobody).toBeNull();
860
+ });
861
+ it('allows skip ac deletions', async () => {
862
+ const allEntities = [
863
+ ...(await nymph.getEntities({ class: TestModel, skipAc: true })),
864
+ ...(await nymph.getEntities({ class: User, skipAc: true })),
865
+ ...(await nymph.getEntities({ class: Group, skipAc: true })),
866
+ ];
867
+ for (let entity of allEntities) {
868
+ await entity.$deleteSkipAC();
869
+ }
870
+ });
871
+ it('entity can be retrieved by queries on ac properties', async () => {
872
+ const { bob, alice } = await makeUsers();
873
+ await tilmeld.fillSession(bob);
874
+ const bobsEntity = await TestModel.factory();
875
+ bobsEntity.name = "Bob's Entity";
876
+ bobsEntity.acRead = [
877
+ alice.guid ?? '',
878
+ bob.guid ?? '',
879
+ ...(bob.group ? [bob.group.guid ?? ''] : []),
880
+ ];
881
+ bobsEntity.acWrite = [alice.guid ?? '', bob.guid ?? ''];
882
+ bobsEntity.acFull = [bob.guid ?? ''];
883
+ await bobsEntity.$save();
884
+ expect(bobsEntity.guid).not.toBeNull();
885
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
886
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
887
+ expect(testEntityBob).not.toBeNull();
888
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
889
+ tilmeld.clearSession();
890
+ await tilmeld.fillSession(alice);
891
+ // Equals queries.
892
+ let testEntityAlice = await nymph.getEntity({ class: TestModel }, {
893
+ type: '&',
894
+ guid: bobsEntity.guid || '',
895
+ equal: ['user', bob.guid],
896
+ });
897
+ expect(testEntityAlice).not.toBeNull();
898
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
899
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
900
+ type: '&',
901
+ guid: bobsEntity.guid || '',
902
+ equal: ['user', '000000000000000000000000'],
903
+ });
904
+ expect(testEntityAlice).toBeNull();
905
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
906
+ type: '&',
907
+ guid: bobsEntity.guid || '',
908
+ equal: ['group', bob.group?.guid],
909
+ });
910
+ expect(testEntityAlice).not.toBeNull();
911
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
912
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
913
+ type: '&',
914
+ guid: bobsEntity.guid || '',
915
+ equal: ['group', '000000000000000000000000'],
916
+ });
917
+ expect(testEntityAlice).toBeNull();
918
+ // Contains queries.
919
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
920
+ type: '&',
921
+ guid: bobsEntity.guid || '',
922
+ contain: ['user', bob.guid],
923
+ });
924
+ expect(testEntityAlice).not.toBeNull();
925
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
926
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
927
+ type: '&',
928
+ guid: bobsEntity.guid || '',
929
+ contain: ['user', '000000000000000000000000'],
930
+ });
931
+ expect(testEntityAlice).toBeNull();
932
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
933
+ type: '&',
934
+ guid: bobsEntity.guid || '',
935
+ contain: ['group', bob.group?.guid],
936
+ });
937
+ expect(testEntityAlice).not.toBeNull();
938
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
939
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
940
+ type: '&',
941
+ guid: bobsEntity.guid || '',
942
+ contain: ['group', '000000000000000000000000'],
943
+ });
944
+ expect(testEntityAlice).toBeNull();
945
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
946
+ type: '&',
947
+ guid: bobsEntity.guid || '',
948
+ contain: ['acRead', alice.guid],
949
+ });
950
+ expect(testEntityAlice).not.toBeNull();
951
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
952
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
953
+ type: '&',
954
+ guid: bobsEntity.guid || '',
955
+ contain: ['acRead', '000000000000000000000000'],
956
+ });
957
+ expect(testEntityAlice).toBeNull();
958
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
959
+ type: '&',
960
+ guid: bobsEntity.guid || '',
961
+ contain: ['acWrite', bob.guid],
962
+ });
963
+ expect(testEntityAlice).not.toBeNull();
964
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
965
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
966
+ type: '&',
967
+ guid: bobsEntity.guid || '',
968
+ contain: ['acWrite', '000000000000000000000000'],
969
+ });
970
+ expect(testEntityAlice).toBeNull();
971
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
972
+ type: '&',
973
+ guid: bobsEntity.guid || '',
974
+ contain: ['acFull', bob.guid],
975
+ });
976
+ expect(testEntityAlice).not.toBeNull();
977
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
978
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
979
+ type: '&',
980
+ guid: bobsEntity.guid || '',
981
+ contain: ['acFull', '000000000000000000000000'],
982
+ });
983
+ expect(testEntityAlice).toBeNull();
984
+ // Ref queries.
985
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
986
+ type: '&',
987
+ guid: bobsEntity.guid || '',
988
+ ref: ['user', bob],
989
+ });
990
+ expect(testEntityAlice).not.toBeNull();
991
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
992
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
993
+ type: '&',
994
+ guid: bobsEntity.guid || '',
995
+ ref: ['user', '000000000000000000000000'],
996
+ });
997
+ expect(testEntityAlice).toBeNull();
998
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
999
+ type: '&',
1000
+ guid: bobsEntity.guid || '',
1001
+ ref: ['group', bob.group ?? ''],
1002
+ });
1003
+ expect(testEntityAlice).not.toBeNull();
1004
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
1005
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
1006
+ type: '&',
1007
+ guid: bobsEntity.guid || '',
1008
+ ref: ['group', '000000000000000000000000'],
1009
+ });
1010
+ expect(testEntityAlice).toBeNull();
1011
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
1012
+ type: '&',
1013
+ guid: bobsEntity.guid || '',
1014
+ ref: ['acRead', alice],
1015
+ });
1016
+ expect(testEntityAlice).not.toBeNull();
1017
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
1018
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
1019
+ type: '&',
1020
+ guid: bobsEntity.guid || '',
1021
+ ref: ['acRead', '000000000000000000000000'],
1022
+ });
1023
+ expect(testEntityAlice).toBeNull();
1024
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
1025
+ type: '&',
1026
+ guid: bobsEntity.guid || '',
1027
+ ref: ['acWrite', bob],
1028
+ });
1029
+ expect(testEntityAlice).not.toBeNull();
1030
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
1031
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
1032
+ type: '&',
1033
+ guid: bobsEntity.guid || '',
1034
+ ref: ['acWrite', '000000000000000000000000'],
1035
+ });
1036
+ expect(testEntityAlice).toBeNull();
1037
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
1038
+ type: '&',
1039
+ guid: bobsEntity.guid || '',
1040
+ ref: ['acFull', bob],
1041
+ });
1042
+ expect(testEntityAlice).not.toBeNull();
1043
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
1044
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
1045
+ type: '&',
1046
+ guid: bobsEntity.guid || '',
1047
+ ref: ['acFull', '000000000000000000000000'],
1048
+ });
1049
+ expect(testEntityAlice).toBeNull();
1050
+ // QRef queries.
1051
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
1052
+ type: '&',
1053
+ guid: bobsEntity.guid || '',
1054
+ qref: [
1055
+ 'user',
1056
+ [
1057
+ { class: User },
1058
+ { type: '&', equal: ['username', bob.username ?? ''] },
1059
+ ],
1060
+ ],
1061
+ });
1062
+ expect(testEntityAlice).not.toBeNull();
1063
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
1064
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
1065
+ type: '&',
1066
+ guid: bobsEntity.guid || '',
1067
+ qref: [
1068
+ 'user',
1069
+ [{ class: User }, { type: '&', equal: ['username', 'pickle'] }],
1070
+ ],
1071
+ });
1072
+ expect(testEntityAlice).toBeNull();
1073
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
1074
+ type: '&',
1075
+ guid: bobsEntity.guid || '',
1076
+ qref: [
1077
+ 'acRead',
1078
+ [
1079
+ { class: User },
1080
+ { type: '&', equal: ['username', alice.username ?? ''] },
1081
+ ],
1082
+ ],
1083
+ });
1084
+ expect(testEntityAlice).not.toBeNull();
1085
+ expect(testEntityAlice?.guid).toEqual(bobsEntity.guid);
1086
+ testEntityAlice = await nymph.getEntity({ class: TestModel }, {
1087
+ type: '&',
1088
+ guid: bobsEntity.guid || '',
1089
+ qref: [
1090
+ 'acRead',
1091
+ [{ class: User }, { type: '&', equal: ['username', 'pickle'] }],
1092
+ ],
1093
+ });
1094
+ expect(testEntityAlice).toBeNull();
1095
+ });
1096
+ it('alice can access an entity with an access request', async () => {
1097
+ const { bob, alice } = await makeUsers();
1098
+ await tilmeld.fillSession(alice);
1099
+ const alicesEntity = await TestModel.factory();
1100
+ alicesEntity.name = "Alice's Entity";
1101
+ await alicesEntity.$save();
1102
+ expect(alicesEntity.guid).not.toBeNull();
1103
+ expect(alice.$is(alicesEntity.user)).toEqual(true);
1104
+ const testEntityAlice = await nymph.getEntity({ class: TestModel, acRequest: TilmeldAccessRequest.USER_OWNED }, { type: '&', guid: alicesEntity.guid || '' });
1105
+ expect(testEntityAlice).not.toBeNull();
1106
+ expect(testEntityAlice?.guid).toEqual(alicesEntity.guid);
1107
+ tilmeld.clearSession();
1108
+ });
1109
+ it("access request for user owned doesn't return group owned entity", async () => {
1110
+ const { bob, alice } = await makeUsers();
1111
+ await tilmeld.fillSession(bob);
1112
+ const bobsEntity = await TestModel.factory();
1113
+ bobsEntity.name = "Bob's Entity";
1114
+ bobsEntity.group = alice.group;
1115
+ await bobsEntity.$save();
1116
+ expect(bobsEntity.guid).not.toBeNull();
1117
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
1118
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1119
+ expect(testEntityBob).not.toBeNull();
1120
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
1121
+ tilmeld.clearSession();
1122
+ await tilmeld.fillSession(alice);
1123
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1124
+ expect(testEntityAlice).not.toBeNull();
1125
+ const testFailureEntityAlice = await nymph.getEntity({ class: TestModel, acRequest: TilmeldAccessRequest.USER_OWNED }, { type: '&', guid: bobsEntity.guid || '' });
1126
+ expect(testFailureEntityAlice).toBeNull();
1127
+ const testSuccessEntityAlice = await nymph.getEntity({
1128
+ class: TestModel,
1129
+ acRequest: TilmeldAccessRequest.PRIMARY_GROUP_OWNED,
1130
+ }, { type: '&', guid: bobsEntity.guid || '' });
1131
+ expect(testSuccessEntityAlice).not.toBeNull();
1132
+ });
1133
+ it("access request for user owned doesn't return acOther accessible entity", async () => {
1134
+ const { bob, alice } = await makeUsers();
1135
+ await tilmeld.fillSession(bob);
1136
+ const bobsEntity = await TestModel.factory();
1137
+ bobsEntity.name = "Bob's Entity";
1138
+ bobsEntity.acOther = TilmeldAccessLevels.READ_ACCESS;
1139
+ await bobsEntity.$save();
1140
+ expect(bobsEntity.guid).not.toBeNull();
1141
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
1142
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1143
+ expect(testEntityBob).not.toBeNull();
1144
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
1145
+ tilmeld.clearSession();
1146
+ await tilmeld.fillSession(alice);
1147
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1148
+ expect(testEntityAlice).not.toBeNull();
1149
+ const testFailureEntityAlice = await nymph.getEntity({ class: TestModel, acRequest: TilmeldAccessRequest.USER_OWNED }, { type: '&', guid: bobsEntity.guid || '' });
1150
+ expect(testFailureEntityAlice).toBeNull();
1151
+ const testSuccessEntityAlice = await nymph.getEntity({ class: TestModel, acRequest: TilmeldAccessRequest.OTHER_ACCESSIBLE }, { type: '&', guid: bobsEntity.guid || '' });
1152
+ expect(testSuccessEntityAlice).not.toBeNull();
1153
+ });
1154
+ it("access request for user owned doesn't return user acRead accessible entity", async () => {
1155
+ const { bob, alice } = await makeUsers();
1156
+ await tilmeld.fillSession(bob);
1157
+ const bobsEntity = await TestModel.factory();
1158
+ bobsEntity.name = "Bob's Entity";
1159
+ bobsEntity.acRead = [alice.guid ?? ''];
1160
+ await bobsEntity.$save();
1161
+ expect(bobsEntity.guid).not.toBeNull();
1162
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
1163
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1164
+ expect(testEntityBob).not.toBeNull();
1165
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
1166
+ tilmeld.clearSession();
1167
+ await tilmeld.fillSession(alice);
1168
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1169
+ expect(testEntityAlice).not.toBeNull();
1170
+ const testFailureEntityAlice = await nymph.getEntity({ class: TestModel, acRequest: TilmeldAccessRequest.USER_OWNED }, { type: '&', guid: bobsEntity.guid || '' });
1171
+ expect(testFailureEntityAlice).toBeNull();
1172
+ const testSuccessEntityAlice = await nymph.getEntity({ class: TestModel, acRequest: TilmeldAccessRequest.USER_ACCESSIBLE }, { type: '&', guid: bobsEntity.guid || '' });
1173
+ expect(testSuccessEntityAlice).not.toBeNull();
1174
+ });
1175
+ it("access request for user owned doesn't return group acRead accessible entity", async () => {
1176
+ const { bob, alice } = await makeUsers();
1177
+ await tilmeld.fillSession(bob);
1178
+ const bobsEntity = await TestModel.factory();
1179
+ bobsEntity.name = "Bob's Entity";
1180
+ bobsEntity.acWrite = [alice.group?.guid ?? ''];
1181
+ await bobsEntity.$save();
1182
+ expect(bobsEntity.guid).not.toBeNull();
1183
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
1184
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1185
+ expect(testEntityBob).not.toBeNull();
1186
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
1187
+ tilmeld.clearSession();
1188
+ await tilmeld.fillSession(alice);
1189
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1190
+ expect(testEntityAlice).not.toBeNull();
1191
+ const testFailureEntityAlice = await nymph.getEntity({ class: TestModel, acRequest: TilmeldAccessRequest.USER_OWNED }, { type: '&', guid: bobsEntity.guid || '' });
1192
+ expect(testFailureEntityAlice).toBeNull();
1193
+ const testSuccessEntityAlice = await nymph.getEntity({
1194
+ class: TestModel,
1195
+ acRequest: TilmeldAccessRequest.PRIMARY_GROUP_ACCESSIBLE,
1196
+ }, { type: '&', guid: bobsEntity.guid || '' });
1197
+ expect(testSuccessEntityAlice).not.toBeNull();
1198
+ });
1199
+ it("access request for user owned doesn't return secondary group owned entity", async () => {
1200
+ const { bob, alice, abgroup } = await makeUsers();
1201
+ await tilmeld.fillSession(bob);
1202
+ const bobsEntity = await TestModel.factory();
1203
+ bobsEntity.name = "Bob's Entity";
1204
+ bobsEntity.group = abgroup;
1205
+ await bobsEntity.$save();
1206
+ expect(bobsEntity.guid).not.toBeNull();
1207
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
1208
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1209
+ expect(testEntityBob).not.toBeNull();
1210
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
1211
+ tilmeld.clearSession();
1212
+ await tilmeld.fillSession(alice);
1213
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1214
+ expect(testEntityAlice).not.toBeNull();
1215
+ const testFailureEntityAlice = await nymph.getEntity({ class: TestModel, acRequest: TilmeldAccessRequest.USER_OWNED }, { type: '&', guid: bobsEntity.guid || '' });
1216
+ expect(testFailureEntityAlice).toBeNull();
1217
+ const testSuccessEntityAlice = await nymph.getEntity({
1218
+ class: TestModel,
1219
+ acRequest: TilmeldAccessRequest.SECONDARY_GROUP_OWNED,
1220
+ }, { type: '&', guid: bobsEntity.guid || '' });
1221
+ expect(testSuccessEntityAlice).not.toBeNull();
1222
+ });
1223
+ it("access request for user owned doesn't return secondary group accessible entity", async () => {
1224
+ const { bob, alice, abgroup } = await makeUsers();
1225
+ await tilmeld.fillSession(bob);
1226
+ const bobsEntity = await TestModel.factory();
1227
+ bobsEntity.name = "Bob's Entity";
1228
+ bobsEntity.acFull = [abgroup.guid ?? ''];
1229
+ await bobsEntity.$save();
1230
+ expect(bobsEntity.guid).not.toBeNull();
1231
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
1232
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1233
+ expect(testEntityBob).not.toBeNull();
1234
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
1235
+ tilmeld.clearSession();
1236
+ await tilmeld.fillSession(alice);
1237
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1238
+ expect(testEntityAlice).not.toBeNull();
1239
+ const testFailureEntityAlice = await nymph.getEntity({ class: TestModel, acRequest: TilmeldAccessRequest.USER_OWNED }, { type: '&', guid: bobsEntity.guid || '' });
1240
+ expect(testFailureEntityAlice).toBeNull();
1241
+ const testSuccessEntityAlice = await nymph.getEntity({
1242
+ class: TestModel,
1243
+ acRequest: TilmeldAccessRequest.SECONDARY_GROUP_ACCESSIBLE,
1244
+ }, { type: '&', guid: bobsEntity.guid || '' });
1245
+ expect(testSuccessEntityAlice).not.toBeNull();
1246
+ // Test or-ing two levels together.
1247
+ const testSuccessEntityAlice2 = await nymph.getEntity({
1248
+ class: TestModel,
1249
+ acRequest: TilmeldAccessRequest.SECONDARY_GROUP_ACCESSIBLE |
1250
+ TilmeldAccessRequest.PRIMARY_GROUP_ACCESSIBLE,
1251
+ }, { type: '&', guid: bobsEntity.guid || '' });
1252
+ expect(testSuccessEntityAlice2).not.toBeNull();
1253
+ });
1254
+ it('access request for entity still works when filtering user owned entities manually', async () => {
1255
+ const { bob, alice } = await makeUsers();
1256
+ await tilmeld.fillSession(bob);
1257
+ const bobsEntity = await TestModel.factory();
1258
+ bobsEntity.name = "Bob's Entity";
1259
+ bobsEntity.acFull = [alice.guid ?? ''];
1260
+ await bobsEntity.$save();
1261
+ expect(bobsEntity.guid).not.toBeNull();
1262
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
1263
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1264
+ expect(testEntityBob).not.toBeNull();
1265
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
1266
+ tilmeld.clearSession();
1267
+ await tilmeld.fillSession(alice);
1268
+ const alicesEntity = await TestModel.factory();
1269
+ alicesEntity.name = "Alice's Entity";
1270
+ await alicesEntity.$save();
1271
+ expect(alicesEntity.guid).not.toBeNull();
1272
+ expect(alice.$is(alicesEntity.user)).toEqual(true);
1273
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1274
+ expect(testEntityAlice).not.toBeNull();
1275
+ const testWithoutFiltering = await nymph.getEntities({ class: TestModel, acRequest: TilmeldAccessRequest.USER_OWNED }, { type: '|', guid: [alicesEntity.guid || '', bobsEntity.guid || ''] });
1276
+ expect(testWithoutFiltering.length).toEqual(1);
1277
+ expect(testWithoutFiltering[0].guid).toEqual(alicesEntity?.guid || '');
1278
+ const testWithFiltering = await nymph.getEntities({
1279
+ class: TestModel,
1280
+ acRequest: TilmeldAccessRequest.USER_OWNED,
1281
+ }, { type: '|', guid: [alicesEntity.guid || '', bobsEntity.guid || ''] }, { type: '!&', ref: ['user', alice] });
1282
+ expect(testWithFiltering.length).toEqual(0);
1283
+ const testInclusive = await nymph.getEntities({ class: TestModel });
1284
+ const testInclusiveWithFiltering = await nymph.getEntities({ class: TestModel }, { type: '!&', ref: ['user', alice] });
1285
+ expect(testInclusiveWithFiltering.length).toBeGreaterThanOrEqual(1);
1286
+ const guids = testInclusiveWithFiltering.map((entity) => entity.guid);
1287
+ expect(guids).not.toContain(alicesEntity?.guid || '');
1288
+ expect(guids).toContain(bobsEntity?.guid || '');
1289
+ const allDefaultGuids = testInclusive.map((entity) => entity.guid);
1290
+ for (let guid of guids) {
1291
+ expect(allDefaultGuids).toContain(guid);
1292
+ }
1293
+ });
1294
+ it("access request for invalid access control doesn't return any inaccessible entities", async () => {
1295
+ const { bob, alice, abgroup } = await makeUsers();
1296
+ await tilmeld.fillSession(bob);
1297
+ const bobsEntity = await TestModel.factory();
1298
+ bobsEntity.name = "Bob's Entity";
1299
+ await bobsEntity.$save();
1300
+ expect(bobsEntity.guid).not.toBeNull();
1301
+ expect(bob.$is(bobsEntity.user)).toEqual(true);
1302
+ const testEntityBob = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1303
+ expect(testEntityBob).not.toBeNull();
1304
+ expect(testEntityBob?.guid).toEqual(bobsEntity.guid);
1305
+ tilmeld.clearSession();
1306
+ await tilmeld.fillSession(alice);
1307
+ const testEntityAlice = await nymph.getEntity({ class: TestModel }, { type: '&', guid: bobsEntity.guid || '' });
1308
+ expect(testEntityAlice).toBeNull();
1309
+ const testFailureEntityAlice = await nymph.getEntity({ class: TestModel, acRequest: TilmeldAccessRequest.UNOWNED * 2 }, { type: '&', guid: bobsEntity.guid || '' });
1310
+ expect(testFailureEntityAlice).toBeNull();
1311
+ });
1312
+ it('delete test data again', async () => {
1313
+ await deleteTestData();
1314
+ });
1315
+ });
1316
+ }
1317
+ //# sourceMappingURL=testArtifacts.js.map