@stamhoofd/backend 2.83.4 → 2.84.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/index.ts +19 -4
- package/package.json +18 -14
- package/src/crons/amazon-ses.ts +26 -5
- package/src/crons/balance-emails.ts +18 -17
- package/src/email-recipient-loaders/registrations.ts +87 -0
- package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +5 -2
- package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +40 -40
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +28 -22
- package/src/endpoints/global/events/PatchEventsEndpoint.ts +81 -49
- package/src/endpoints/global/files/UploadFile.ts +11 -16
- package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +234 -0
- package/src/endpoints/global/groups/GetGroupsEndpoint.ts +117 -43
- package/src/endpoints/global/members/GetMembersEndpoint.test.ts +1054 -0
- package/src/endpoints/global/members/GetMembersEndpoint.ts +163 -141
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +6 -6
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +0 -16
- package/src/endpoints/global/members/helpers/validateGroupFilter.ts +73 -0
- package/src/endpoints/global/registration/GetPaymentRegistrations.ts +1 -2
- package/src/endpoints/global/registration/GetRegistrationsCountEndpoint.ts +43 -0
- package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +1016 -0
- package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +234 -0
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +5 -5
- package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +474 -554
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +191 -52
- package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +107 -9
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +89 -0
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +9 -6
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +88 -0
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +0 -6
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +10 -6
- package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +10 -25
- package/src/endpoints/organization/dashboard/payments/PatchBalanceItemsEndpoint.ts +0 -5
- package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +0 -5
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +4 -0
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +1 -0
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +44 -19
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +140 -25
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +40 -10
- package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.test.ts +2 -2
- package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.test.ts +2 -2
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +4 -1
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +2 -2
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +2 -2
- package/src/excel-loaders/members.ts +233 -232
- package/src/excel-loaders/payments.ts +1 -1
- package/src/excel-loaders/receivable-balances.ts +1 -1
- package/src/excel-loaders/registrations.ts +153 -0
- package/src/helpers/AdminPermissionChecker.ts +65 -37
- package/src/helpers/AuthenticatedStructures.ts +43 -3
- package/src/helpers/Context.ts +29 -1
- package/src/helpers/GlobalHelper.ts +3 -1
- package/src/helpers/GroupedThrottledQueue.test.ts +219 -0
- package/src/helpers/GroupedThrottledQueue.ts +108 -0
- package/src/helpers/LimitedFilteredRequestHelper.ts +26 -1
- package/src/helpers/MemberCharger.ts +0 -5
- package/src/helpers/MembershipCharger.ts +3 -9
- package/src/helpers/OrganizationCharger.ts +0 -5
- package/src/helpers/ThrottledQueue.test.ts +194 -0
- package/src/helpers/ThrottledQueue.ts +145 -0
- package/src/helpers/XlsxTransformerColumnHelper.ts +44 -1
- package/src/middleware/ContextMiddleware.ts +1 -1
- package/src/seeds/1728928974-update-cached-outstanding-balance-from-items.ts +2 -1
- package/src/seeds/1735577912-update-cached-outstanding-balance-from-items.ts +2 -1
- package/src/services/BalanceItemPaymentService.ts +1 -33
- package/src/services/BalanceItemService.ts +167 -48
- package/src/services/FileSignService.ts +18 -13
- package/src/services/MemberRecordStore.ts +28 -19
- package/src/services/PaymentReallocationService.test.ts +25 -14
- package/src/services/PaymentReallocationService.ts +29 -10
- package/src/services/PaymentService.ts +4 -16
- package/src/services/PlatformMembershipService.ts +8 -4
- package/src/services/RegistrationService.ts +66 -2
- package/src/sql-filters/base-registration-filter-compilers.ts +43 -0
- package/src/sql-filters/groups.ts +67 -0
- package/src/sql-filters/members.ts +33 -58
- package/src/sql-filters/organization-registration-periods.ts +8 -0
- package/src/sql-filters/registration-periods.ts +8 -0
- package/src/sql-filters/registrations.ts +11 -22
- package/src/sql-sorters/groups.ts +24 -0
- package/src/sql-sorters/organization-registration-periods.ts +24 -0
- package/src/sql-sorters/registration-periods.ts +47 -0
- package/src/sql-sorters/registrations.ts +77 -0
- package/tests/actions/patchOrganizationMember.ts +27 -0
- package/tests/actions/patchPaymentStatus.ts +45 -0
- package/tests/actions/patchUserMember.ts +27 -0
- package/tests/assertions/assertBalances.ts +49 -0
- package/tests/e2e/api-rate-limits.test.ts +5 -5
- package/tests/e2e/bundle-discounts.test.ts +4060 -0
- package/tests/e2e/charge-members.test.ts +27 -24
- package/tests/e2e/documents.test.ts +398 -0
- package/tests/e2e/register.test.ts +292 -312
- package/tests/helpers/PayconiqMocker.ts +55 -0
- package/tests/init/index.ts +5 -0
- package/tests/init/initAdmin.ts +14 -0
- package/tests/init/initBundleDiscount.ts +47 -0
- package/tests/init/initPayconiq.ts +9 -0
- package/tests/init/initPlatformAdmin.ts +13 -0
- package/tests/init/initStripe.ts +21 -0
- package/tests/jest.setup.ts +29 -0
- package/src/seeds-temporary/1736266448-recall-balance-item-price-paid.ts +0 -70
|
@@ -0,0 +1,1054 @@
|
|
|
1
|
+
import { Endpoint, Request } from '@simonbackx/simple-endpoints';
|
|
2
|
+
import { EventFactory, GroupFactory, MemberFactory, OrganizationFactory, RegistrationFactory, RegistrationPeriod, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
|
|
3
|
+
import { AccessRight, EventMeta, GroupType, LimitedFilteredRequest, NamedObject, PermissionLevel, PermissionRoleDetailed, Permissions, PermissionsResourceType, ResourcePermissions } from '@stamhoofd/structures';
|
|
4
|
+
import { STExpect, TestUtils } from '@stamhoofd/test-utils';
|
|
5
|
+
import { GetMembersEndpoint } from './GetMembersEndpoint';
|
|
6
|
+
import { testServer } from '../../../../tests/helpers/TestServer';
|
|
7
|
+
|
|
8
|
+
const baseUrl = `/members`;
|
|
9
|
+
const endpoint = new GetMembersEndpoint();
|
|
10
|
+
type EndpointType = typeof endpoint;
|
|
11
|
+
type Body = EndpointType extends Endpoint<any, any, infer B, any> ? B : never;
|
|
12
|
+
|
|
13
|
+
describe('Endpoint.GetMembersEndpoint', () => {
|
|
14
|
+
let period: RegistrationPeriod;
|
|
15
|
+
|
|
16
|
+
beforeEach(async () => {
|
|
17
|
+
TestUtils.setEnvironment('userMode', 'platform');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
beforeAll(async () => {
|
|
21
|
+
period = await new RegistrationPeriodFactory({
|
|
22
|
+
startDate: new Date(2023, 0, 1),
|
|
23
|
+
endDate: new Date(2023, 11, 31),
|
|
24
|
+
}).create();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('Permission checking', () => {
|
|
28
|
+
test('Allowed: Can fetch members for a given group', async () => {
|
|
29
|
+
// Setup
|
|
30
|
+
const role = PermissionRoleDetailed.create({
|
|
31
|
+
name: 'Test Role',
|
|
32
|
+
accessRights: [],
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const resources = new Map();
|
|
36
|
+
|
|
37
|
+
const organization = await new OrganizationFactory({ period, roles: [role] })
|
|
38
|
+
.create();
|
|
39
|
+
|
|
40
|
+
const user = await new UserFactory({
|
|
41
|
+
organization,
|
|
42
|
+
permissions: Permissions.create({
|
|
43
|
+
level: PermissionLevel.None,
|
|
44
|
+
roles: [
|
|
45
|
+
role,
|
|
46
|
+
],
|
|
47
|
+
resources,
|
|
48
|
+
}),
|
|
49
|
+
})
|
|
50
|
+
.create();
|
|
51
|
+
|
|
52
|
+
const token = await Token.createToken(user);
|
|
53
|
+
const member1 = await new MemberFactory({ }).create();
|
|
54
|
+
const member2 = await new MemberFactory({ }).create();
|
|
55
|
+
const group = await new GroupFactory({ organization, period }).create();
|
|
56
|
+
|
|
57
|
+
resources.set(
|
|
58
|
+
PermissionsResourceType.Groups, new Map([[
|
|
59
|
+
group.id,
|
|
60
|
+
ResourcePermissions.create({
|
|
61
|
+
level: PermissionLevel.Read,
|
|
62
|
+
}),
|
|
63
|
+
]]),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
await user.save();
|
|
67
|
+
|
|
68
|
+
await new RegistrationFactory({ member: member1, group }).create();
|
|
69
|
+
await new RegistrationFactory({ member: member2, group }).create();
|
|
70
|
+
|
|
71
|
+
// Try to request members for this group
|
|
72
|
+
const request = Request.get({
|
|
73
|
+
path: baseUrl,
|
|
74
|
+
host: organization.getApiHost(),
|
|
75
|
+
query: new LimitedFilteredRequest({
|
|
76
|
+
filter: {
|
|
77
|
+
registrations: {
|
|
78
|
+
$elemMatch: {
|
|
79
|
+
groupId: group.id,
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
limit: 10,
|
|
84
|
+
}),
|
|
85
|
+
headers: {
|
|
86
|
+
authorization: 'Bearer ' + token.accessToken,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
const response = await testServer.test(endpoint, request);
|
|
90
|
+
expect(response.status).toBe(200);
|
|
91
|
+
expect(response.body.results.members).toHaveLength(2);
|
|
92
|
+
|
|
93
|
+
// Check ids are matching without depending on ordering using jest extended
|
|
94
|
+
expect(response.body.results.members).toIncludeSameMembers([
|
|
95
|
+
expect.objectContaining({ id: member1.id }),
|
|
96
|
+
expect.objectContaining({ id: member2.id }),
|
|
97
|
+
]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('Not allowed: Cannot fetch members for a given group', async () => {
|
|
101
|
+
// Same test, but without giving the user permissions to read the group
|
|
102
|
+
// Setup
|
|
103
|
+
const role = PermissionRoleDetailed.create({
|
|
104
|
+
name: 'Test Role',
|
|
105
|
+
accessRights: [],
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const resources = new Map();
|
|
109
|
+
|
|
110
|
+
const organization = await new OrganizationFactory({ period, roles: [role] })
|
|
111
|
+
.create();
|
|
112
|
+
|
|
113
|
+
const user = await new UserFactory({
|
|
114
|
+
organization,
|
|
115
|
+
permissions: Permissions.create({
|
|
116
|
+
level: PermissionLevel.None,
|
|
117
|
+
roles: [
|
|
118
|
+
role,
|
|
119
|
+
],
|
|
120
|
+
resources,
|
|
121
|
+
}),
|
|
122
|
+
})
|
|
123
|
+
.create();
|
|
124
|
+
|
|
125
|
+
const token = await Token.createToken(user);
|
|
126
|
+
const member1 = await new MemberFactory({ }).create();
|
|
127
|
+
const member2 = await new MemberFactory({ }).create();
|
|
128
|
+
const group = await new GroupFactory({ organization, period }).create();
|
|
129
|
+
const group2 = await new GroupFactory({ organization, period }).create();
|
|
130
|
+
|
|
131
|
+
// Give permission to a different group
|
|
132
|
+
resources.set(
|
|
133
|
+
PermissionsResourceType.Groups, new Map([[
|
|
134
|
+
group2.id,
|
|
135
|
+
ResourcePermissions.create({
|
|
136
|
+
level: PermissionLevel.Read,
|
|
137
|
+
}),
|
|
138
|
+
]]),
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
await user.save();
|
|
142
|
+
|
|
143
|
+
await new RegistrationFactory({ member: member1, group }).create();
|
|
144
|
+
await new RegistrationFactory({ member: member2, group }).create();
|
|
145
|
+
|
|
146
|
+
// Try to request members for this group
|
|
147
|
+
const request = Request.get({
|
|
148
|
+
path: baseUrl,
|
|
149
|
+
host: organization.getApiHost(),
|
|
150
|
+
query: new LimitedFilteredRequest({
|
|
151
|
+
filter: {
|
|
152
|
+
registrations: {
|
|
153
|
+
$elemMatch: {
|
|
154
|
+
groupId: group.id,
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
limit: 10,
|
|
159
|
+
}),
|
|
160
|
+
headers: {
|
|
161
|
+
authorization: 'Bearer ' + token.accessToken,
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
await expect(testServer.test(endpoint, request)).rejects.toThrow(
|
|
165
|
+
STExpect.errorWithCode('permission_denied'),
|
|
166
|
+
);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test('Allowed: Can fetch members for multiple groups at the same time', async () => {
|
|
170
|
+
// Same test, but without giving the user permissions to read the group
|
|
171
|
+
// Setup
|
|
172
|
+
const role = PermissionRoleDetailed.create({
|
|
173
|
+
name: 'Test Role',
|
|
174
|
+
accessRights: [],
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const resources = new Map();
|
|
178
|
+
|
|
179
|
+
const organization = await new OrganizationFactory({ period, roles: [role] })
|
|
180
|
+
.create();
|
|
181
|
+
|
|
182
|
+
const user = await new UserFactory({
|
|
183
|
+
organization,
|
|
184
|
+
permissions: Permissions.create({
|
|
185
|
+
level: PermissionLevel.None,
|
|
186
|
+
roles: [
|
|
187
|
+
role,
|
|
188
|
+
],
|
|
189
|
+
resources,
|
|
190
|
+
}),
|
|
191
|
+
})
|
|
192
|
+
.create();
|
|
193
|
+
|
|
194
|
+
const token = await Token.createToken(user);
|
|
195
|
+
const member1 = await new MemberFactory({ }).create();
|
|
196
|
+
const member2 = await new MemberFactory({ }).create();
|
|
197
|
+
const group = await new GroupFactory({ organization, period }).create();
|
|
198
|
+
const group2 = await new GroupFactory({ organization, period }).create();
|
|
199
|
+
|
|
200
|
+
// Give permission to a different group
|
|
201
|
+
resources.set(
|
|
202
|
+
PermissionsResourceType.Groups, new Map([[
|
|
203
|
+
group.id,
|
|
204
|
+
ResourcePermissions.create({
|
|
205
|
+
level: PermissionLevel.Read,
|
|
206
|
+
}),
|
|
207
|
+
], [
|
|
208
|
+
group2.id,
|
|
209
|
+
ResourcePermissions.create({
|
|
210
|
+
level: PermissionLevel.Write,
|
|
211
|
+
}),
|
|
212
|
+
]]),
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
await user.save();
|
|
216
|
+
|
|
217
|
+
await new RegistrationFactory({ member: member1, group }).create();
|
|
218
|
+
await new RegistrationFactory({ member: member2, group: group2 }).create();
|
|
219
|
+
|
|
220
|
+
// Try to request members for this group
|
|
221
|
+
const request = Request.get({
|
|
222
|
+
path: baseUrl,
|
|
223
|
+
host: organization.getApiHost(),
|
|
224
|
+
query: new LimitedFilteredRequest({
|
|
225
|
+
filter: {
|
|
226
|
+
registrations: {
|
|
227
|
+
$elemMatch: {
|
|
228
|
+
groupId: {
|
|
229
|
+
$in: [group.id, group2.id],
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
limit: 10,
|
|
235
|
+
}),
|
|
236
|
+
headers: {
|
|
237
|
+
authorization: 'Bearer ' + token.accessToken,
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
const response = await testServer.test(endpoint, request);
|
|
241
|
+
expect(response.status).toBe(200);
|
|
242
|
+
expect(response.body.results.members).toHaveLength(2);
|
|
243
|
+
// Check ids are matching without depending on ordering using jest extended
|
|
244
|
+
expect(response.body.results.members).toIncludeSameMembers([
|
|
245
|
+
expect.objectContaining({ id: member1.id }),
|
|
246
|
+
expect.objectContaining({ id: member2.id }),
|
|
247
|
+
]);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
test('Not allowed: Cannot fetch members for multiple groups at the same time if no permissions for one of them', async () => {
|
|
251
|
+
// Same test, but without giving the user permissions to read the group
|
|
252
|
+
// Setup
|
|
253
|
+
const role = PermissionRoleDetailed.create({
|
|
254
|
+
name: 'Test Role',
|
|
255
|
+
accessRights: [],
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const resources = new Map();
|
|
259
|
+
|
|
260
|
+
const organization = await new OrganizationFactory({ period, roles: [role] })
|
|
261
|
+
.create();
|
|
262
|
+
|
|
263
|
+
const user = await new UserFactory({
|
|
264
|
+
organization,
|
|
265
|
+
permissions: Permissions.create({
|
|
266
|
+
level: PermissionLevel.None,
|
|
267
|
+
roles: [
|
|
268
|
+
role,
|
|
269
|
+
],
|
|
270
|
+
resources,
|
|
271
|
+
}),
|
|
272
|
+
})
|
|
273
|
+
.create();
|
|
274
|
+
|
|
275
|
+
const token = await Token.createToken(user);
|
|
276
|
+
const member1 = await new MemberFactory({ }).create();
|
|
277
|
+
const member2 = await new MemberFactory({ }).create();
|
|
278
|
+
const group = await new GroupFactory({ organization, period }).create();
|
|
279
|
+
const group2 = await new GroupFactory({ organization, period }).create();
|
|
280
|
+
|
|
281
|
+
// Only give permissions for one group
|
|
282
|
+
resources.set(
|
|
283
|
+
PermissionsResourceType.Groups, new Map([[
|
|
284
|
+
group.id,
|
|
285
|
+
ResourcePermissions.create({
|
|
286
|
+
level: PermissionLevel.Read,
|
|
287
|
+
}),
|
|
288
|
+
]]),
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
await user.save();
|
|
292
|
+
|
|
293
|
+
await new RegistrationFactory({ member: member1, group }).create();
|
|
294
|
+
await new RegistrationFactory({ member: member2, group: group2 }).create();
|
|
295
|
+
|
|
296
|
+
// Try to request members for this group
|
|
297
|
+
const request = Request.get({
|
|
298
|
+
path: baseUrl,
|
|
299
|
+
host: organization.getApiHost(),
|
|
300
|
+
query: new LimitedFilteredRequest({
|
|
301
|
+
filter: {
|
|
302
|
+
registrations: {
|
|
303
|
+
$elemMatch: {
|
|
304
|
+
groupId: {
|
|
305
|
+
$in: [group.id, group2.id],
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
limit: 10,
|
|
311
|
+
}),
|
|
312
|
+
headers: {
|
|
313
|
+
authorization: 'Bearer ' + token.accessToken,
|
|
314
|
+
},
|
|
315
|
+
});
|
|
316
|
+
await expect(testServer.test(endpoint, request)).rejects.toThrow(
|
|
317
|
+
STExpect.errorWithCode('permission_denied'),
|
|
318
|
+
);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
test('Allowed: Can fetch all members if permissions for at least one group', async () => {
|
|
322
|
+
// Same test, but without giving the user permissions to read the group
|
|
323
|
+
// Setup
|
|
324
|
+
const role = PermissionRoleDetailed.create({
|
|
325
|
+
name: 'Test Role',
|
|
326
|
+
accessRights: [],
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
const resources = new Map();
|
|
330
|
+
|
|
331
|
+
const organization = await new OrganizationFactory({ period, roles: [role] })
|
|
332
|
+
.create();
|
|
333
|
+
|
|
334
|
+
const user = await new UserFactory({
|
|
335
|
+
organization,
|
|
336
|
+
permissions: Permissions.create({
|
|
337
|
+
level: PermissionLevel.None,
|
|
338
|
+
roles: [
|
|
339
|
+
role,
|
|
340
|
+
],
|
|
341
|
+
resources,
|
|
342
|
+
}),
|
|
343
|
+
})
|
|
344
|
+
.create();
|
|
345
|
+
|
|
346
|
+
const token = await Token.createToken(user);
|
|
347
|
+
const member1 = await new MemberFactory({ }).create();
|
|
348
|
+
const member2 = await new MemberFactory({ }).create();
|
|
349
|
+
const member3 = await new MemberFactory({ }).create();
|
|
350
|
+
const group = await new GroupFactory({ organization, period }).create();
|
|
351
|
+
const group2 = await new GroupFactory({ organization, period }).create();
|
|
352
|
+
const group3 = await new GroupFactory({ organization, period }).create();
|
|
353
|
+
|
|
354
|
+
// Give permission for 2 / 3 groups
|
|
355
|
+
resources.set(
|
|
356
|
+
PermissionsResourceType.Groups, new Map([[
|
|
357
|
+
group.id,
|
|
358
|
+
ResourcePermissions.create({
|
|
359
|
+
level: PermissionLevel.Read,
|
|
360
|
+
}),
|
|
361
|
+
], [
|
|
362
|
+
group2.id,
|
|
363
|
+
ResourcePermissions.create({
|
|
364
|
+
level: PermissionLevel.Write,
|
|
365
|
+
}),
|
|
366
|
+
]]),
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
await user.save();
|
|
370
|
+
|
|
371
|
+
await new RegistrationFactory({ member: member1, group }).create();
|
|
372
|
+
await new RegistrationFactory({ member: member2, group: group2 }).create();
|
|
373
|
+
await new RegistrationFactory({ member: member3, group: group3 }).create();
|
|
374
|
+
|
|
375
|
+
// Try to request members for this group
|
|
376
|
+
const request = Request.get({
|
|
377
|
+
path: baseUrl,
|
|
378
|
+
host: organization.getApiHost(),
|
|
379
|
+
query: new LimitedFilteredRequest({
|
|
380
|
+
limit: 10,
|
|
381
|
+
}),
|
|
382
|
+
headers: {
|
|
383
|
+
authorization: 'Bearer ' + token.accessToken,
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
const response = await testServer.test(endpoint, request);
|
|
387
|
+
expect(response.status).toBe(200);
|
|
388
|
+
expect(response.body.results.members).toHaveLength(2);
|
|
389
|
+
// Check ids are matching without depending on ordering using jest extended
|
|
390
|
+
expect(response.body.results.members).toIncludeSameMembers([
|
|
391
|
+
expect.objectContaining({ id: member1.id }),
|
|
392
|
+
expect.objectContaining({ id: member2.id }),
|
|
393
|
+
]);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
test('Not allowed: Cannot fetch all members if no permissions for a single group', async () => {
|
|
397
|
+
// Same test, but without giving the user permissions to read the group
|
|
398
|
+
// Setup
|
|
399
|
+
const role = PermissionRoleDetailed.create({
|
|
400
|
+
name: 'Test Role',
|
|
401
|
+
accessRights: [AccessRight.WebshopScanTickets],
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
const resources = new Map();
|
|
405
|
+
|
|
406
|
+
const organization = await new OrganizationFactory({ period, roles: [role] })
|
|
407
|
+
.create();
|
|
408
|
+
|
|
409
|
+
const user = await new UserFactory({
|
|
410
|
+
organization,
|
|
411
|
+
permissions: Permissions.create({
|
|
412
|
+
level: PermissionLevel.None,
|
|
413
|
+
roles: [
|
|
414
|
+
role,
|
|
415
|
+
],
|
|
416
|
+
resources,
|
|
417
|
+
}),
|
|
418
|
+
})
|
|
419
|
+
.create();
|
|
420
|
+
|
|
421
|
+
const token = await Token.createToken(user);
|
|
422
|
+
const member1 = await new MemberFactory({ }).create();
|
|
423
|
+
const member2 = await new MemberFactory({ }).create();
|
|
424
|
+
const member3 = await new MemberFactory({ }).create();
|
|
425
|
+
const group = await new GroupFactory({ organization, period }).create();
|
|
426
|
+
const group2 = await new GroupFactory({ organization, period }).create();
|
|
427
|
+
const group3 = await new GroupFactory({ organization, period }).create();
|
|
428
|
+
|
|
429
|
+
await user.save();
|
|
430
|
+
|
|
431
|
+
await new RegistrationFactory({ member: member1, group }).create();
|
|
432
|
+
await new RegistrationFactory({ member: member2, group: group2 }).create();
|
|
433
|
+
await new RegistrationFactory({ member: member3, group: group3 }).create();
|
|
434
|
+
|
|
435
|
+
// Try to request members for this group
|
|
436
|
+
const request = Request.get({
|
|
437
|
+
path: baseUrl,
|
|
438
|
+
host: organization.getApiHost(),
|
|
439
|
+
query: new LimitedFilteredRequest({
|
|
440
|
+
limit: 10,
|
|
441
|
+
}),
|
|
442
|
+
headers: {
|
|
443
|
+
authorization: 'Bearer ' + token.accessToken,
|
|
444
|
+
},
|
|
445
|
+
});
|
|
446
|
+
await expect(testServer.test(endpoint, request)).rejects.toThrow(
|
|
447
|
+
STExpect.errorWithCode('permission_denied'),
|
|
448
|
+
);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
test('Allowed: A user inherits permissions for an event', async () => {
|
|
452
|
+
// Same test, but without giving the user permissions to read the group
|
|
453
|
+
// Setup
|
|
454
|
+
const role = PermissionRoleDetailed.create({
|
|
455
|
+
name: 'Test Role',
|
|
456
|
+
accessRights: [],
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
const resources = new Map();
|
|
460
|
+
|
|
461
|
+
const organization = await new OrganizationFactory({ period, roles: [role] })
|
|
462
|
+
.create();
|
|
463
|
+
|
|
464
|
+
const user = await new UserFactory({
|
|
465
|
+
organization,
|
|
466
|
+
permissions: Permissions.create({
|
|
467
|
+
level: PermissionLevel.None,
|
|
468
|
+
roles: [
|
|
469
|
+
role,
|
|
470
|
+
],
|
|
471
|
+
resources,
|
|
472
|
+
}),
|
|
473
|
+
})
|
|
474
|
+
.create();
|
|
475
|
+
|
|
476
|
+
const token = await Token.createToken(user);
|
|
477
|
+
const member1 = await new MemberFactory({ }).create();
|
|
478
|
+
const member2 = await new MemberFactory({ }).create();
|
|
479
|
+
|
|
480
|
+
const defaultGroup = await new GroupFactory({ organization, period }).create();
|
|
481
|
+
const group = await new GroupFactory({ organization, period, type: GroupType.EventRegistration }).create();
|
|
482
|
+
const event = await new EventFactory({
|
|
483
|
+
organization,
|
|
484
|
+
group,
|
|
485
|
+
startDate: period.startDate,
|
|
486
|
+
endDate: period.endDate,
|
|
487
|
+
meta: EventMeta.create({
|
|
488
|
+
groups: [
|
|
489
|
+
NamedObject.create({
|
|
490
|
+
id: defaultGroup.id,
|
|
491
|
+
name: defaultGroup.settings.name.toString(),
|
|
492
|
+
}),
|
|
493
|
+
],
|
|
494
|
+
}),
|
|
495
|
+
}).create();
|
|
496
|
+
|
|
497
|
+
// Give the user write permissions to all events targeted to the default group
|
|
498
|
+
resources.set(
|
|
499
|
+
PermissionsResourceType.Groups, new Map([[
|
|
500
|
+
defaultGroup.id,
|
|
501
|
+
ResourcePermissions.create({
|
|
502
|
+
level: PermissionLevel.None,
|
|
503
|
+
accessRights: [AccessRight.EventWrite],
|
|
504
|
+
}),
|
|
505
|
+
]]),
|
|
506
|
+
);
|
|
507
|
+
|
|
508
|
+
await user.save();
|
|
509
|
+
|
|
510
|
+
await new RegistrationFactory({ member: member1, group }).create();
|
|
511
|
+
await new RegistrationFactory({ member: member2, group }).create();
|
|
512
|
+
|
|
513
|
+
// Try to request members for this group
|
|
514
|
+
const request = Request.get({
|
|
515
|
+
path: baseUrl,
|
|
516
|
+
host: organization.getApiHost(),
|
|
517
|
+
query: new LimitedFilteredRequest({
|
|
518
|
+
filter: {
|
|
519
|
+
registrations: {
|
|
520
|
+
$elemMatch: {
|
|
521
|
+
groupId: group.id,
|
|
522
|
+
},
|
|
523
|
+
},
|
|
524
|
+
},
|
|
525
|
+
limit: 10,
|
|
526
|
+
}),
|
|
527
|
+
headers: {
|
|
528
|
+
authorization: 'Bearer ' + token.accessToken,
|
|
529
|
+
},
|
|
530
|
+
});
|
|
531
|
+
const response = await testServer.test(endpoint, request);
|
|
532
|
+
expect(response.status).toBe(200);
|
|
533
|
+
expect(response.body.results.members).toHaveLength(2);
|
|
534
|
+
// Check ids are matching without depending on ordering using jest extended
|
|
535
|
+
expect(response.body.results.members).toIncludeSameMembers([
|
|
536
|
+
expect.objectContaining({ id: member1.id }),
|
|
537
|
+
expect.objectContaining({ id: member2.id }),
|
|
538
|
+
]);
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
test('Allowed: A user inherits permissions for the waiting list of an event', async () => {
|
|
542
|
+
// Same test, but without giving the user permissions to read the group
|
|
543
|
+
// Setup
|
|
544
|
+
const role = PermissionRoleDetailed.create({
|
|
545
|
+
name: 'Test Role',
|
|
546
|
+
accessRights: [],
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
const resources = new Map();
|
|
550
|
+
|
|
551
|
+
const organization = await new OrganizationFactory({ period, roles: [role] })
|
|
552
|
+
.create();
|
|
553
|
+
|
|
554
|
+
const user = await new UserFactory({
|
|
555
|
+
organization,
|
|
556
|
+
permissions: Permissions.create({
|
|
557
|
+
level: PermissionLevel.None,
|
|
558
|
+
roles: [
|
|
559
|
+
role,
|
|
560
|
+
],
|
|
561
|
+
resources,
|
|
562
|
+
}),
|
|
563
|
+
})
|
|
564
|
+
.create();
|
|
565
|
+
|
|
566
|
+
const token = await Token.createToken(user);
|
|
567
|
+
const member1 = await new MemberFactory({ }).create();
|
|
568
|
+
const member2 = await new MemberFactory({ }).create();
|
|
569
|
+
const member3 = await new MemberFactory({ }).create();
|
|
570
|
+
|
|
571
|
+
const defaultGroup = await new GroupFactory({ organization, period }).create();
|
|
572
|
+
const waitingList = await new GroupFactory({ organization, period, type: GroupType.WaitingList }).create();
|
|
573
|
+
const group = await new GroupFactory({ organization, period, type: GroupType.EventRegistration, waitingListId: waitingList.id }).create();
|
|
574
|
+
|
|
575
|
+
const event = await new EventFactory({
|
|
576
|
+
organization,
|
|
577
|
+
group,
|
|
578
|
+
startDate: period.startDate,
|
|
579
|
+
endDate: period.endDate,
|
|
580
|
+
meta: EventMeta.create({
|
|
581
|
+
groups: [
|
|
582
|
+
NamedObject.create({
|
|
583
|
+
id: defaultGroup.id,
|
|
584
|
+
name: defaultGroup.settings.name.toString(),
|
|
585
|
+
}),
|
|
586
|
+
],
|
|
587
|
+
}),
|
|
588
|
+
}).create();
|
|
589
|
+
|
|
590
|
+
// Give the user write permissions to all events targeted to the default group
|
|
591
|
+
resources.set(
|
|
592
|
+
PermissionsResourceType.Groups, new Map([[
|
|
593
|
+
defaultGroup.id,
|
|
594
|
+
ResourcePermissions.create({
|
|
595
|
+
level: PermissionLevel.None,
|
|
596
|
+
accessRights: [AccessRight.EventWrite],
|
|
597
|
+
}),
|
|
598
|
+
]]),
|
|
599
|
+
);
|
|
600
|
+
|
|
601
|
+
await user.save();
|
|
602
|
+
|
|
603
|
+
await new RegistrationFactory({ member: member1, group: waitingList }).create();
|
|
604
|
+
await new RegistrationFactory({ member: member2, group: waitingList }).create();
|
|
605
|
+
await new RegistrationFactory({ member: member3, group }).create();
|
|
606
|
+
|
|
607
|
+
// Try to request members for this group
|
|
608
|
+
const request = Request.get({
|
|
609
|
+
path: baseUrl,
|
|
610
|
+
host: organization.getApiHost(),
|
|
611
|
+
query: new LimitedFilteredRequest({
|
|
612
|
+
filter: {
|
|
613
|
+
registrations: {
|
|
614
|
+
$elemMatch: {
|
|
615
|
+
groupId: waitingList.id,
|
|
616
|
+
},
|
|
617
|
+
},
|
|
618
|
+
},
|
|
619
|
+
limit: 10,
|
|
620
|
+
}),
|
|
621
|
+
headers: {
|
|
622
|
+
authorization: 'Bearer ' + token.accessToken,
|
|
623
|
+
},
|
|
624
|
+
});
|
|
625
|
+
const response = await testServer.test(endpoint, request);
|
|
626
|
+
expect(response.status).toBe(200);
|
|
627
|
+
expect(response.body.results.members).toHaveLength(2);
|
|
628
|
+
// Check ids are matching without depending on ordering using jest extended
|
|
629
|
+
expect(response.body.results.members).toIncludeSameMembers([
|
|
630
|
+
expect.objectContaining({ id: member1.id }),
|
|
631
|
+
expect.objectContaining({ id: member2.id }),
|
|
632
|
+
]);
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
test('Not allowed: A user cannot request registrations of an event if no permission to events', async () => {
|
|
636
|
+
// Same test, but without giving the user permissions to read the group
|
|
637
|
+
// Setup
|
|
638
|
+
const role = PermissionRoleDetailed.create({
|
|
639
|
+
name: 'Test Role',
|
|
640
|
+
accessRights: [],
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
const resources = new Map();
|
|
644
|
+
|
|
645
|
+
const organization = await new OrganizationFactory({ period, roles: [role] })
|
|
646
|
+
.create();
|
|
647
|
+
|
|
648
|
+
const user = await new UserFactory({
|
|
649
|
+
organization,
|
|
650
|
+
permissions: Permissions.create({
|
|
651
|
+
level: PermissionLevel.None,
|
|
652
|
+
roles: [
|
|
653
|
+
role,
|
|
654
|
+
],
|
|
655
|
+
resources,
|
|
656
|
+
}),
|
|
657
|
+
})
|
|
658
|
+
.create();
|
|
659
|
+
|
|
660
|
+
const token = await Token.createToken(user);
|
|
661
|
+
const member1 = await new MemberFactory({ }).create();
|
|
662
|
+
const member2 = await new MemberFactory({ }).create();
|
|
663
|
+
|
|
664
|
+
const defaultGroup = await new GroupFactory({ organization, period }).create();
|
|
665
|
+
const group = await new GroupFactory({ organization, period, type: GroupType.EventRegistration }).create();
|
|
666
|
+
const event = await new EventFactory({
|
|
667
|
+
organization,
|
|
668
|
+
group,
|
|
669
|
+
startDate: period.startDate,
|
|
670
|
+
endDate: period.endDate,
|
|
671
|
+
meta: EventMeta.create({
|
|
672
|
+
groups: [
|
|
673
|
+
NamedObject.create({
|
|
674
|
+
id: defaultGroup.id,
|
|
675
|
+
name: defaultGroup.settings.name.toString(),
|
|
676
|
+
}),
|
|
677
|
+
],
|
|
678
|
+
}),
|
|
679
|
+
}).create();
|
|
680
|
+
|
|
681
|
+
// The user can read members registered for default group, but not events for default group
|
|
682
|
+
resources.set(
|
|
683
|
+
PermissionsResourceType.Groups, new Map([[
|
|
684
|
+
defaultGroup.id,
|
|
685
|
+
ResourcePermissions.create({
|
|
686
|
+
level: PermissionLevel.Read,
|
|
687
|
+
accessRights: [],
|
|
688
|
+
}),
|
|
689
|
+
]]),
|
|
690
|
+
);
|
|
691
|
+
|
|
692
|
+
await user.save();
|
|
693
|
+
|
|
694
|
+
await new RegistrationFactory({ member: member1, group }).create();
|
|
695
|
+
await new RegistrationFactory({ member: member2, group }).create();
|
|
696
|
+
|
|
697
|
+
// Try to request members for this group
|
|
698
|
+
const request = Request.get({
|
|
699
|
+
path: baseUrl,
|
|
700
|
+
host: organization.getApiHost(),
|
|
701
|
+
query: new LimitedFilteredRequest({
|
|
702
|
+
filter: {
|
|
703
|
+
registrations: {
|
|
704
|
+
$elemMatch: {
|
|
705
|
+
groupId: group.id,
|
|
706
|
+
},
|
|
707
|
+
},
|
|
708
|
+
},
|
|
709
|
+
limit: 10,
|
|
710
|
+
}),
|
|
711
|
+
headers: {
|
|
712
|
+
authorization: 'Bearer ' + token.accessToken,
|
|
713
|
+
},
|
|
714
|
+
});
|
|
715
|
+
await expect(testServer.test(endpoint, request)).rejects.toThrow(
|
|
716
|
+
STExpect.errorWithCode('permission_denied'),
|
|
717
|
+
);
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
test('Not allowed: A user cannot request registrations of an event for all members if only access to events for a single group', async () => {
|
|
721
|
+
// Same test, but without giving the user permissions to read the group
|
|
722
|
+
// Setup
|
|
723
|
+
const role = PermissionRoleDetailed.create({
|
|
724
|
+
name: 'Test Role',
|
|
725
|
+
accessRights: [],
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
const resources = new Map();
|
|
729
|
+
|
|
730
|
+
const organization = await new OrganizationFactory({ period, roles: [role] })
|
|
731
|
+
.create();
|
|
732
|
+
|
|
733
|
+
const user = await new UserFactory({
|
|
734
|
+
organization,
|
|
735
|
+
permissions: Permissions.create({
|
|
736
|
+
level: PermissionLevel.None,
|
|
737
|
+
roles: [
|
|
738
|
+
role,
|
|
739
|
+
],
|
|
740
|
+
resources,
|
|
741
|
+
}),
|
|
742
|
+
})
|
|
743
|
+
.create();
|
|
744
|
+
|
|
745
|
+
const token = await Token.createToken(user);
|
|
746
|
+
const member1 = await new MemberFactory({ }).create();
|
|
747
|
+
const member2 = await new MemberFactory({ }).create();
|
|
748
|
+
|
|
749
|
+
const defaultGroup = await new GroupFactory({ organization, period }).create();
|
|
750
|
+
const group = await new GroupFactory({ organization, period, type: GroupType.EventRegistration }).create();
|
|
751
|
+
|
|
752
|
+
// Event for all members of the organization (so no permission to this event)
|
|
753
|
+
const event = await new EventFactory({
|
|
754
|
+
organization,
|
|
755
|
+
group,
|
|
756
|
+
startDate: period.startDate,
|
|
757
|
+
endDate: period.endDate,
|
|
758
|
+
}).create();
|
|
759
|
+
|
|
760
|
+
// The user can read members registered for default group, but not events for default group
|
|
761
|
+
resources.set(
|
|
762
|
+
PermissionsResourceType.Groups, new Map([[
|
|
763
|
+
defaultGroup.id,
|
|
764
|
+
ResourcePermissions.create({
|
|
765
|
+
level: PermissionLevel.Read,
|
|
766
|
+
accessRights: [AccessRight.EventWrite],
|
|
767
|
+
}),
|
|
768
|
+
]]),
|
|
769
|
+
);
|
|
770
|
+
|
|
771
|
+
await user.save();
|
|
772
|
+
|
|
773
|
+
await new RegistrationFactory({ member: member1, group }).create();
|
|
774
|
+
await new RegistrationFactory({ member: member2, group }).create();
|
|
775
|
+
|
|
776
|
+
// Try to request members for this group
|
|
777
|
+
const request = Request.get({
|
|
778
|
+
path: baseUrl,
|
|
779
|
+
host: organization.getApiHost(),
|
|
780
|
+
query: new LimitedFilteredRequest({
|
|
781
|
+
filter: {
|
|
782
|
+
registrations: {
|
|
783
|
+
$elemMatch: {
|
|
784
|
+
groupId: group.id,
|
|
785
|
+
},
|
|
786
|
+
},
|
|
787
|
+
},
|
|
788
|
+
limit: 10,
|
|
789
|
+
}),
|
|
790
|
+
headers: {
|
|
791
|
+
authorization: 'Bearer ' + token.accessToken,
|
|
792
|
+
},
|
|
793
|
+
});
|
|
794
|
+
await expect(testServer.test(endpoint, request)).rejects.toThrow(
|
|
795
|
+
STExpect.errorWithCode('permission_denied'),
|
|
796
|
+
);
|
|
797
|
+
});
|
|
798
|
+
|
|
799
|
+
test('Not allowed: A user cannot request registrations for the waiting list of an event if no permissions for event', async () => {
|
|
800
|
+
// Same test, but without giving the user permissions to read the group
|
|
801
|
+
// Setup
|
|
802
|
+
const role = PermissionRoleDetailed.create({
|
|
803
|
+
name: 'Test Role',
|
|
804
|
+
accessRights: [],
|
|
805
|
+
});
|
|
806
|
+
|
|
807
|
+
const resources = new Map();
|
|
808
|
+
|
|
809
|
+
const organization = await new OrganizationFactory({ period, roles: [role] })
|
|
810
|
+
.create();
|
|
811
|
+
|
|
812
|
+
const user = await new UserFactory({
|
|
813
|
+
organization,
|
|
814
|
+
permissions: Permissions.create({
|
|
815
|
+
level: PermissionLevel.None,
|
|
816
|
+
roles: [
|
|
817
|
+
role,
|
|
818
|
+
],
|
|
819
|
+
resources,
|
|
820
|
+
}),
|
|
821
|
+
})
|
|
822
|
+
.create();
|
|
823
|
+
|
|
824
|
+
const token = await Token.createToken(user);
|
|
825
|
+
const member1 = await new MemberFactory({ }).create();
|
|
826
|
+
const member2 = await new MemberFactory({ }).create();
|
|
827
|
+
const member3 = await new MemberFactory({ }).create();
|
|
828
|
+
|
|
829
|
+
const defaultGroup = await new GroupFactory({ organization, period }).create();
|
|
830
|
+
const waitingList = await new GroupFactory({ organization, period, type: GroupType.WaitingList }).create();
|
|
831
|
+
const group = await new GroupFactory({ organization, period, type: GroupType.EventRegistration, waitingListId: waitingList.id }).create();
|
|
832
|
+
|
|
833
|
+
const event = await new EventFactory({
|
|
834
|
+
organization,
|
|
835
|
+
group,
|
|
836
|
+
startDate: period.startDate,
|
|
837
|
+
endDate: period.endDate,
|
|
838
|
+
meta: EventMeta.create({
|
|
839
|
+
groups: [
|
|
840
|
+
NamedObject.create({
|
|
841
|
+
id: defaultGroup.id,
|
|
842
|
+
name: defaultGroup.settings.name.toString(),
|
|
843
|
+
}),
|
|
844
|
+
],
|
|
845
|
+
}),
|
|
846
|
+
}).create();
|
|
847
|
+
|
|
848
|
+
// The user can read members registered for default group, but not events for default group
|
|
849
|
+
resources.set(
|
|
850
|
+
PermissionsResourceType.Groups, new Map([[
|
|
851
|
+
defaultGroup.id,
|
|
852
|
+
ResourcePermissions.create({
|
|
853
|
+
level: PermissionLevel.Read,
|
|
854
|
+
accessRights: [],
|
|
855
|
+
}),
|
|
856
|
+
]]),
|
|
857
|
+
);
|
|
858
|
+
|
|
859
|
+
await user.save();
|
|
860
|
+
|
|
861
|
+
await new RegistrationFactory({ member: member1, group: waitingList }).create();
|
|
862
|
+
await new RegistrationFactory({ member: member2, group: waitingList }).create();
|
|
863
|
+
await new RegistrationFactory({ member: member3, group }).create();
|
|
864
|
+
|
|
865
|
+
// Try to request members for this group
|
|
866
|
+
const request = Request.get({
|
|
867
|
+
path: baseUrl,
|
|
868
|
+
host: organization.getApiHost(),
|
|
869
|
+
query: new LimitedFilteredRequest({
|
|
870
|
+
filter: {
|
|
871
|
+
registrations: {
|
|
872
|
+
$elemMatch: {
|
|
873
|
+
groupId: waitingList.id,
|
|
874
|
+
},
|
|
875
|
+
},
|
|
876
|
+
},
|
|
877
|
+
limit: 10,
|
|
878
|
+
}),
|
|
879
|
+
headers: {
|
|
880
|
+
authorization: 'Bearer ' + token.accessToken,
|
|
881
|
+
},
|
|
882
|
+
});
|
|
883
|
+
await expect(testServer.test(endpoint, request)).rejects.toThrow(
|
|
884
|
+
STExpect.errorWithCode('permission_denied'),
|
|
885
|
+
);
|
|
886
|
+
});
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
describe('Default filtering', () => {
|
|
890
|
+
test('A user without read permissions for all groups will only see members of membership groups', async () => {
|
|
891
|
+
// Same test, but without giving the user permissions to read the group
|
|
892
|
+
// Setup
|
|
893
|
+
const role = PermissionRoleDetailed.create({
|
|
894
|
+
name: 'Test Role',
|
|
895
|
+
accessRights: [],
|
|
896
|
+
});
|
|
897
|
+
|
|
898
|
+
const resources = new Map();
|
|
899
|
+
|
|
900
|
+
const organization = await new OrganizationFactory({ period, roles: [role] })
|
|
901
|
+
.create();
|
|
902
|
+
|
|
903
|
+
const user = await new UserFactory({
|
|
904
|
+
organization,
|
|
905
|
+
permissions: Permissions.create({
|
|
906
|
+
level: PermissionLevel.None,
|
|
907
|
+
roles: [
|
|
908
|
+
role,
|
|
909
|
+
],
|
|
910
|
+
resources,
|
|
911
|
+
}),
|
|
912
|
+
})
|
|
913
|
+
.create();
|
|
914
|
+
|
|
915
|
+
const token = await Token.createToken(user);
|
|
916
|
+
const member1 = await new MemberFactory({ }).create();
|
|
917
|
+
const member2 = await new MemberFactory({ }).create();
|
|
918
|
+
const member3 = await new MemberFactory({ }).create();
|
|
919
|
+
const member4 = await new MemberFactory({ }).create();
|
|
920
|
+
const group = await new GroupFactory({ organization, period }).create();
|
|
921
|
+
const group2 = await new GroupFactory({ organization, period }).create();
|
|
922
|
+
const group3 = await new GroupFactory({ organization, period }).create();
|
|
923
|
+
|
|
924
|
+
const group4 = await new GroupFactory({ organization, period, type: GroupType.EventRegistration }).create();
|
|
925
|
+
|
|
926
|
+
// Give permission for 2 / 3 groups + one event group
|
|
927
|
+
resources.set(
|
|
928
|
+
PermissionsResourceType.Groups, new Map([[
|
|
929
|
+
group.id,
|
|
930
|
+
ResourcePermissions.create({
|
|
931
|
+
level: PermissionLevel.Read,
|
|
932
|
+
}),
|
|
933
|
+
], [
|
|
934
|
+
group2.id,
|
|
935
|
+
ResourcePermissions.create({
|
|
936
|
+
level: PermissionLevel.Write,
|
|
937
|
+
}),
|
|
938
|
+
], [
|
|
939
|
+
group4.id,
|
|
940
|
+
ResourcePermissions.create({
|
|
941
|
+
level: PermissionLevel.Read,
|
|
942
|
+
}),
|
|
943
|
+
]]),
|
|
944
|
+
);
|
|
945
|
+
|
|
946
|
+
await user.save();
|
|
947
|
+
|
|
948
|
+
await new RegistrationFactory({ member: member1, group }).create();
|
|
949
|
+
await new RegistrationFactory({ member: member2, group: group2 }).create();
|
|
950
|
+
await new RegistrationFactory({ member: member3, group: group3 }).create();
|
|
951
|
+
await new RegistrationFactory({ member: member4, group: group4 }).create();
|
|
952
|
+
|
|
953
|
+
// Try to request all members
|
|
954
|
+
const request = Request.get({
|
|
955
|
+
path: baseUrl,
|
|
956
|
+
host: organization.getApiHost(),
|
|
957
|
+
query: new LimitedFilteredRequest({
|
|
958
|
+
limit: 10,
|
|
959
|
+
}),
|
|
960
|
+
headers: {
|
|
961
|
+
authorization: 'Bearer ' + token.accessToken,
|
|
962
|
+
},
|
|
963
|
+
});
|
|
964
|
+
|
|
965
|
+
// Response only includes members registered in a membership group, not the event group
|
|
966
|
+
const response = await testServer.test(endpoint, request);
|
|
967
|
+
expect(response.status).toBe(200);
|
|
968
|
+
expect(response.body.results.members).toHaveLength(2);
|
|
969
|
+
// Check ids are matching without depending on ordering using jest extended
|
|
970
|
+
expect(response.body.results.members).toIncludeSameMembers([
|
|
971
|
+
expect.objectContaining({ id: member1.id }),
|
|
972
|
+
expect.objectContaining({ id: member2.id }),
|
|
973
|
+
]);
|
|
974
|
+
});
|
|
975
|
+
|
|
976
|
+
test('A user with read permissions for all groups will also see members of event groups', async () => {
|
|
977
|
+
// Same test, but without giving the user permissions to read the group
|
|
978
|
+
// Setup
|
|
979
|
+
const role = PermissionRoleDetailed.create({
|
|
980
|
+
name: 'Test Role',
|
|
981
|
+
accessRights: [],
|
|
982
|
+
});
|
|
983
|
+
|
|
984
|
+
const resources = new Map();
|
|
985
|
+
|
|
986
|
+
const organization = await new OrganizationFactory({ period, roles: [role] })
|
|
987
|
+
.create();
|
|
988
|
+
|
|
989
|
+
const user = await new UserFactory({
|
|
990
|
+
organization,
|
|
991
|
+
permissions: Permissions.create({
|
|
992
|
+
level: PermissionLevel.None,
|
|
993
|
+
roles: [
|
|
994
|
+
role,
|
|
995
|
+
],
|
|
996
|
+
resources,
|
|
997
|
+
}),
|
|
998
|
+
})
|
|
999
|
+
.create();
|
|
1000
|
+
|
|
1001
|
+
const token = await Token.createToken(user);
|
|
1002
|
+
const member1 = await new MemberFactory({ }).create();
|
|
1003
|
+
const member2 = await new MemberFactory({ }).create();
|
|
1004
|
+
const member3 = await new MemberFactory({ }).create();
|
|
1005
|
+
const member4 = await new MemberFactory({ }).create();
|
|
1006
|
+
const group = await new GroupFactory({ organization, period }).create();
|
|
1007
|
+
const group2 = await new GroupFactory({ organization, period }).create();
|
|
1008
|
+
const group3 = await new GroupFactory({ organization, period }).create();
|
|
1009
|
+
|
|
1010
|
+
const group4 = await new GroupFactory({ organization, period, type: GroupType.EventRegistration }).create();
|
|
1011
|
+
|
|
1012
|
+
// Give permission to all groups
|
|
1013
|
+
resources.set(
|
|
1014
|
+
PermissionsResourceType.Groups, new Map([[
|
|
1015
|
+
'',
|
|
1016
|
+
ResourcePermissions.create({
|
|
1017
|
+
level: PermissionLevel.Read,
|
|
1018
|
+
}),
|
|
1019
|
+
]]),
|
|
1020
|
+
);
|
|
1021
|
+
|
|
1022
|
+
await user.save();
|
|
1023
|
+
|
|
1024
|
+
await new RegistrationFactory({ member: member1, group }).create();
|
|
1025
|
+
await new RegistrationFactory({ member: member2, group: group2 }).create();
|
|
1026
|
+
await new RegistrationFactory({ member: member3, group: group3 }).create();
|
|
1027
|
+
await new RegistrationFactory({ member: member4, group: group4 }).create();
|
|
1028
|
+
|
|
1029
|
+
// Try to request all members
|
|
1030
|
+
const request = Request.get({
|
|
1031
|
+
path: baseUrl,
|
|
1032
|
+
host: organization.getApiHost(),
|
|
1033
|
+
query: new LimitedFilteredRequest({
|
|
1034
|
+
limit: 10,
|
|
1035
|
+
}),
|
|
1036
|
+
headers: {
|
|
1037
|
+
authorization: 'Bearer ' + token.accessToken,
|
|
1038
|
+
},
|
|
1039
|
+
});
|
|
1040
|
+
|
|
1041
|
+
// Response only includes members registered in a membership group, not the event group
|
|
1042
|
+
const response = await testServer.test(endpoint, request);
|
|
1043
|
+
expect(response.status).toBe(200);
|
|
1044
|
+
expect(response.body.results.members).toHaveLength(4);
|
|
1045
|
+
// Check ids are matching without depending on ordering using jest extended
|
|
1046
|
+
expect(response.body.results.members).toIncludeSameMembers([
|
|
1047
|
+
expect.objectContaining({ id: member1.id }),
|
|
1048
|
+
expect.objectContaining({ id: member2.id }),
|
|
1049
|
+
expect.objectContaining({ id: member3.id }),
|
|
1050
|
+
expect.objectContaining({ id: member4.id }),
|
|
1051
|
+
]);
|
|
1052
|
+
});
|
|
1053
|
+
});
|
|
1054
|
+
});
|