@stamhoofd/backend 2.81.0 → 2.83.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/package.json +10 -10
- package/src/audit-logs/GroupLogger.ts +3 -3
- package/src/audit-logs/MemberResponsibilityRecordLogger.ts +1 -1
- package/src/audit-logs/OrderLogger.ts +1 -1
- package/src/audit-logs/RegistrationLogger.ts +1 -1
- package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +4 -4
- package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +1 -1
- package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +5 -5
- package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +1 -1
- package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +8 -8
- package/src/endpoints/auth/CreateAdminEndpoint.ts +2 -2
- package/src/endpoints/auth/CreateTokenEndpoint.ts +10 -10
- package/src/endpoints/auth/ForgotPasswordEndpoint.ts +2 -2
- package/src/endpoints/auth/PatchUserEndpoint.ts +9 -9
- package/src/endpoints/auth/SignupEndpoint.ts +2 -2
- package/src/endpoints/auth/VerifyEmailEndpoint.ts +3 -3
- package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +1 -1
- package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +1 -1
- package/src/endpoints/global/email/GetEmailEndpoint.ts +1 -1
- package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +1 -1
- package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +139 -0
- package/src/endpoints/global/email/PatchEmailEndpoint.ts +30 -7
- package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +1 -1
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +16 -35
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +1 -1
- package/src/endpoints/global/events/PatchEventsEndpoint.ts +22 -16
- package/src/endpoints/global/files/ExportToExcelEndpoint.ts +1 -1
- package/src/endpoints/global/files/UploadFile.ts +14 -2
- package/src/endpoints/global/files/UploadImage.ts +2 -2
- package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +2 -2
- package/src/endpoints/global/members/GetMembersEndpoint.ts +1 -1
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +19 -19
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +34 -34
- package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +1 -1
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +5 -5
- package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +5 -1
- package/src/endpoints/global/platform/GetPlatformEndpoint.test.ts +68 -0
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +1 -1
- package/src/endpoints/global/registration/GetPaymentRegistrations.ts +2 -2
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +15 -17
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +4 -4
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +37 -37
- package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +2 -2
- package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +1 -1
- package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +5 -5
- package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplateEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +3 -3
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +9 -9
- package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +4 -4
- package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/payments/PatchBalanceItemsEndpoint.ts +11 -11
- package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +13 -13
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +16 -16
- package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.test.ts +106 -0
- package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +16 -3
- package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.test.ts +247 -0
- package/src/endpoints/{auth → organization/dashboard/users}/PatchApiUserEndpoint.ts +25 -6
- package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +4 -4
- package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +8 -8
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +1 -1
- package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +1 -1
- package/src/endpoints/organization/shared/GetDocumentHtml.ts +2 -2
- package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +1 -1
- package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.test.ts +5 -0
- package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +1 -1
- package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +2 -2
- package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +1 -1
- package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +3 -3
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +6 -1
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +1 -1
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +10 -8
- package/src/excel-loaders/event-notifications.ts +11 -11
- package/src/excel-loaders/members.ts +34 -34
- package/src/excel-loaders/organizations.ts +23 -23
- package/src/excel-loaders/payments.ts +39 -39
- package/src/excel-loaders/receivable-balances.ts +21 -21
- package/src/helpers/AddressValidator.ts +6 -6
- package/src/helpers/AdminPermissionChecker.ts +7 -4
- package/src/helpers/AuthenticatedStructures.ts +16 -8
- package/src/helpers/BuckarooHelper.ts +1 -1
- package/src/helpers/CheckSettlements.ts +1 -1
- package/src/helpers/Context.ts +31 -15
- package/src/helpers/FileCache.ts +7 -7
- package/src/helpers/ForwardHandler.ts +1 -1
- package/src/helpers/GlobalHelper.ts +6 -4
- package/src/helpers/MembershipCharger.ts +2 -2
- package/src/helpers/SetupStepUpdater.ts +1 -1
- package/src/helpers/StripeHelper.ts +18 -7
- package/src/helpers/XlsxTransformerColumnHelper.ts +18 -18
- package/src/services/DocumentService.ts +1 -1
- package/src/services/EventNotificationService.ts +1 -1
- package/src/services/MemberNumberService.ts +3 -3
- package/src/services/SSOService.ts +5 -5
- package/src/sql-filters/members.ts +1 -1
- package/tests/e2e/api-rate-limits.test.ts +188 -0
- package/tests/e2e/private-files.test.ts +3 -3
- package/tests/helpers/StripeMocker.ts +7 -1
- /package/src/endpoints/global/platform/{GetPlatformEnpoint.ts → GetPlatformEndpoint.ts} +0 -0
|
@@ -2,8 +2,8 @@ import { Database } from '@simonbackx/simple-database';
|
|
|
2
2
|
import { PatchableArray, PatchableArrayAutoEncoder, PatchMap } from '@simonbackx/simple-encoding';
|
|
3
3
|
import { Endpoint, Request } from '@simonbackx/simple-endpoints';
|
|
4
4
|
import { GroupFactory, MemberFactory, OrganizationFactory, OrganizationTagFactory, Platform, RegistrationFactory, Token, UserFactory } from '@stamhoofd/models';
|
|
5
|
-
import { Address, Country, EmergencyContact, MemberDetails, MemberWithRegistrationsBlob, OrganizationMetaData, OrganizationRecordsConfiguration, Parent, PatchAnswers, PermissionLevel, Permissions, PermissionsResourceType, RecordCategory, RecordSettings, RecordTextAnswer, ResourcePermissions, ReviewTime, ReviewTimes } from '@stamhoofd/structures';
|
|
6
|
-
import { TestUtils } from '@stamhoofd/test-utils';
|
|
5
|
+
import { Address, Country, EmergencyContact, MemberDetails, MemberWithRegistrationsBlob, OrganizationMetaData, OrganizationRecordsConfiguration, Parent, PatchAnswers, PermissionLevel, Permissions, PermissionsResourceType, RecordCategory, RecordSettings, RecordTextAnswer, ResourcePermissions, ReviewTime, ReviewTimes, TranslatedString } from '@stamhoofd/structures';
|
|
6
|
+
import { SHExpect, TestUtils } from '@stamhoofd/test-utils';
|
|
7
7
|
import { testServer } from '../../../../tests/helpers/TestServer';
|
|
8
8
|
import { PatchOrganizationMembersEndpoint } from './PatchOrganizationMembersEndpoint';
|
|
9
9
|
|
|
@@ -16,8 +16,6 @@ const firstName = 'John';
|
|
|
16
16
|
const lastName = 'Doe';
|
|
17
17
|
const birthDay = { year: 1993, month: 4, day: 5 };
|
|
18
18
|
|
|
19
|
-
const errorWithCode = (code: string) => expect.objectContaining({ code }) as jest.Constructable;
|
|
20
|
-
|
|
21
19
|
describe('Endpoint.PatchOrganizationMembersEndpoint', () => {
|
|
22
20
|
beforeEach(async () => {
|
|
23
21
|
TestUtils.setEnvironment('userMode', 'platform');
|
|
@@ -59,7 +57,7 @@ describe('Endpoint.PatchOrganizationMembersEndpoint', () => {
|
|
|
59
57
|
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
60
58
|
await expect(testServer.test(endpoint, request))
|
|
61
59
|
.rejects
|
|
62
|
-
.toThrow(errorWithCode('known_member_missing_rights'));
|
|
60
|
+
.toThrow(SHExpect.errorWithCode('known_member_missing_rights'));
|
|
63
61
|
});
|
|
64
62
|
|
|
65
63
|
test('The security code is not a requirement for members without additional data', async () => {
|
|
@@ -219,7 +217,7 @@ describe('Endpoint.PatchOrganizationMembersEndpoint', () => {
|
|
|
219
217
|
|
|
220
218
|
const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
|
|
221
219
|
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
222
|
-
await expect(testServer.test(endpoint, request)).rejects.toThrow(errorWithCode('not_found'));
|
|
220
|
+
await expect(testServer.test(endpoint, request)).rejects.toThrow(SHExpect.errorWithCode('not_found'));
|
|
223
221
|
});
|
|
224
222
|
|
|
225
223
|
test('An admin can edit members registered in its own organization', async () => {
|
|
@@ -359,12 +357,12 @@ describe('Endpoint.PatchOrganizationMembersEndpoint', () => {
|
|
|
359
357
|
describe('Record answers', () => {
|
|
360
358
|
test('An admin can set records of its own organization', async () => {
|
|
361
359
|
const commentsRecord = RecordSettings.create({
|
|
362
|
-
name: 'Opmerkingen',
|
|
360
|
+
name: TranslatedString.create('Opmerkingen'),
|
|
363
361
|
externalPermissionLevel: PermissionLevel.Read, // this should be ignored since we are an admin
|
|
364
362
|
});
|
|
365
363
|
|
|
366
364
|
const recordCategory = RecordCategory.create({
|
|
367
|
-
name: 'Medische fiche',
|
|
365
|
+
name: TranslatedString.create('Medische fiche'),
|
|
368
366
|
records: [
|
|
369
367
|
commentsRecord,
|
|
370
368
|
],
|
|
@@ -428,11 +426,11 @@ describe('Endpoint.PatchOrganizationMembersEndpoint', () => {
|
|
|
428
426
|
|
|
429
427
|
test('An admin with read only record category permission cannot set the records in that category', async () => {
|
|
430
428
|
const commentsRecord = RecordSettings.create({
|
|
431
|
-
name: 'Opmerkingen',
|
|
429
|
+
name: TranslatedString.create('Opmerkingen'),
|
|
432
430
|
});
|
|
433
431
|
|
|
434
432
|
const recordCategory = RecordCategory.create({
|
|
435
|
-
name: 'Medische fiche',
|
|
433
|
+
name: TranslatedString.create('Medische fiche'),
|
|
436
434
|
records: [
|
|
437
435
|
commentsRecord,
|
|
438
436
|
],
|
|
@@ -495,16 +493,16 @@ describe('Endpoint.PatchOrganizationMembersEndpoint', () => {
|
|
|
495
493
|
|
|
496
494
|
const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
|
|
497
495
|
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
498
|
-
await expect(testServer.test(endpoint, request)).rejects.toThrow(errorWithCode('permission_denied'));
|
|
496
|
+
await expect(testServer.test(endpoint, request)).rejects.toThrow(SHExpect.errorWithCode('permission_denied'));
|
|
499
497
|
});
|
|
500
498
|
|
|
501
499
|
test('An admin without record category permission cannot set the records in that category', async () => {
|
|
502
500
|
const commentsRecord = RecordSettings.create({
|
|
503
|
-
name: 'Opmerkingen',
|
|
501
|
+
name: TranslatedString.create('Opmerkingen'),
|
|
504
502
|
});
|
|
505
503
|
|
|
506
504
|
const recordCategory = RecordCategory.create({
|
|
507
|
-
name: 'Medische fiche',
|
|
505
|
+
name: TranslatedString.create('Medische fiche'),
|
|
508
506
|
records: [
|
|
509
507
|
commentsRecord,
|
|
510
508
|
],
|
|
@@ -564,16 +562,16 @@ describe('Endpoint.PatchOrganizationMembersEndpoint', () => {
|
|
|
564
562
|
|
|
565
563
|
const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
|
|
566
564
|
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
567
|
-
await expect(testServer.test(endpoint, request)).rejects.toThrow(errorWithCode('permission_denied'));
|
|
565
|
+
await expect(testServer.test(endpoint, request)).rejects.toThrow(SHExpect.errorWithCode('permission_denied'));
|
|
568
566
|
});
|
|
569
567
|
|
|
570
568
|
test('An admin can set records of the platform', async () => {
|
|
571
569
|
const commentsRecord = RecordSettings.create({
|
|
572
|
-
name: 'Opmerkingen',
|
|
570
|
+
name: TranslatedString.create('Opmerkingen'),
|
|
573
571
|
});
|
|
574
572
|
|
|
575
573
|
const recordCategory = RecordCategory.create({
|
|
576
|
-
name: 'Medische fiche',
|
|
574
|
+
name: TranslatedString.create('Medische fiche'),
|
|
577
575
|
records: [
|
|
578
576
|
commentsRecord,
|
|
579
577
|
],
|
|
@@ -647,11 +645,11 @@ describe('Endpoint.PatchOrganizationMembersEndpoint', () => {
|
|
|
647
645
|
|
|
648
646
|
test('[Regression] A platform admin with tag-access to an organization can change platform records', async () => {
|
|
649
647
|
const commentsRecord = RecordSettings.create({
|
|
650
|
-
name: 'Opmerkingen',
|
|
648
|
+
name: TranslatedString.create('Opmerkingen'),
|
|
651
649
|
});
|
|
652
650
|
|
|
653
651
|
const recordCategory = RecordCategory.create({
|
|
654
|
-
name: 'Medische fiche',
|
|
652
|
+
name: TranslatedString.create('Medische fiche'),
|
|
655
653
|
records: [
|
|
656
654
|
commentsRecord,
|
|
657
655
|
],
|
|
@@ -1458,7 +1456,9 @@ describe('Endpoint.PatchOrganizationMembersEndpoint', () => {
|
|
|
1458
1456
|
await member3.refresh();
|
|
1459
1457
|
|
|
1460
1458
|
// Check all parents equal
|
|
1461
|
-
const expectedParent = parent3
|
|
1459
|
+
const expectedParent = parent3.patch({
|
|
1460
|
+
createdAt: parent1.createdAt, // parent1 created at can be 1ms smaller, and oldest will be used
|
|
1461
|
+
});
|
|
1462
1462
|
|
|
1463
1463
|
expect(member1.details.parents).toEqual([expectedParent]);
|
|
1464
1464
|
expect(member2.details.parents).toEqual([expectedParent]);
|
|
@@ -122,7 +122,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
122
122
|
throw new SimpleError({
|
|
123
123
|
code: 'missing_organization',
|
|
124
124
|
message: 'Missing organization',
|
|
125
|
-
human:
|
|
125
|
+
human: $t(`2bb4647b-a3b8-453e-8b75-41c290910fc8`),
|
|
126
126
|
statusCode: 400,
|
|
127
127
|
});
|
|
128
128
|
}
|
|
@@ -173,7 +173,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
173
173
|
throw new SimpleError({
|
|
174
174
|
code: 'not_allowed',
|
|
175
175
|
message: 'Cannot override details',
|
|
176
|
-
human:
|
|
176
|
+
human: $t(`b66ef4c3-9931-4fc3-9da1-c023857684fa`),
|
|
177
177
|
field: 'details',
|
|
178
178
|
});
|
|
179
179
|
}
|
|
@@ -218,7 +218,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
218
218
|
// Update responsibilities
|
|
219
219
|
for (const patchResponsibility of patch.responsibilities.getPatches()) {
|
|
220
220
|
if (!Context.auth.hasPlatformFullAccess() && !(organization && await Context.auth.hasFullAccess(organization.id))) {
|
|
221
|
-
throw Context.auth.error(
|
|
221
|
+
throw Context.auth.error($t(`1d1b5807-af39-400b-8dea-2f222ee668ae`));
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
const responsibilityRecord = await MemberResponsibilityRecord.getByID(patchResponsibility.id);
|
|
@@ -226,21 +226,21 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
226
226
|
throw new SimpleError({
|
|
227
227
|
code: 'permission_denied',
|
|
228
228
|
message: "You don't have permissions to access this endpoint",
|
|
229
|
-
human:
|
|
229
|
+
human: $t(`738fc35a-da77-4e1a-8233-9ff651781f65`),
|
|
230
230
|
});
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
const responsibility = platform.config.responsibilities.find(r => r.id === patchResponsibility.responsibilityId);
|
|
234
234
|
|
|
235
235
|
if (responsibility && !responsibility.organizationBased && !Context.auth.hasPlatformFullAccess()) {
|
|
236
|
-
throw Context.auth.error(
|
|
236
|
+
throw Context.auth.error($t(`e2ceec71-367c-4cfd-98f3-b0ec0c83e2c2`));
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
// Allow patching begin and end date
|
|
240
240
|
if (patchResponsibility.endDate !== undefined) {
|
|
241
241
|
if (responsibilityRecord.endDate) {
|
|
242
242
|
if (!Context.auth.hasPlatformFullAccess()) {
|
|
243
|
-
throw Context.auth.error(
|
|
243
|
+
throw Context.auth.error($t(`fd88b6ba-1f0b-4e82-9c5b-7c7a3ac8f4fa`));
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
246
|
responsibilityRecord.endDate = patchResponsibility.endDate;
|
|
@@ -248,7 +248,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
248
248
|
|
|
249
249
|
if (patchResponsibility.startDate !== undefined) {
|
|
250
250
|
if (patchResponsibility.startDate.getTime() > Date.now() + 5 * 60 * 1000) {
|
|
251
|
-
throw Context.auth.error(
|
|
251
|
+
throw Context.auth.error($t(`84c2346e-40b2-4b38-9b2d-e1fcba6f1202`));
|
|
252
252
|
}
|
|
253
253
|
if (patchResponsibility.startDate.getTime() > Date.now()) {
|
|
254
254
|
patchResponsibility.startDate = new Date(); // force now
|
|
@@ -257,7 +257,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
257
257
|
const daysDiff = Math.abs((new Date().getTime() - patchResponsibility.startDate.getTime()) / (1000 * 60 * 60 * 24));
|
|
258
258
|
|
|
259
259
|
if (daysDiff > 60 && !Context.auth.hasPlatformFullAccess()) {
|
|
260
|
-
throw Context.auth.error(
|
|
260
|
+
throw Context.auth.error($t(`dc0c8bff-7b16-4597-adfb-cd6a4d7d4bf1`));
|
|
261
261
|
}
|
|
262
262
|
responsibilityRecord.startDate = patchResponsibility.startDate;
|
|
263
263
|
}
|
|
@@ -274,7 +274,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
274
274
|
// Create responsibilities
|
|
275
275
|
for (const { put } of patch.responsibilities.getPuts()) {
|
|
276
276
|
if (!Context.auth.hasPlatformFullAccess() && !(organization && await Context.auth.hasFullAccess(organization.id))) {
|
|
277
|
-
throw Context.auth.error(
|
|
277
|
+
throw Context.auth.error($t(`1d1b5807-af39-400b-8dea-2f222ee668ae`));
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
const platformResponsibility = platform.config.responsibilities.find(r => r.id === put.responsibilityId);
|
|
@@ -284,7 +284,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
284
284
|
throw new SimpleError({
|
|
285
285
|
code: 'invalid_field',
|
|
286
286
|
message: 'Invalid organization',
|
|
287
|
-
human:
|
|
287
|
+
human: $t(`31757907-4cdd-4f0e-bb9d-cba9c1d997e4`),
|
|
288
288
|
field: 'organizationId',
|
|
289
289
|
});
|
|
290
290
|
}
|
|
@@ -294,7 +294,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
294
294
|
throw new SimpleError({
|
|
295
295
|
code: 'invalid_field',
|
|
296
296
|
message: 'Invalid responsibility',
|
|
297
|
-
human:
|
|
297
|
+
human: $t(`03114785-acf5-4bba-a3b5-15d3ac4ae17c`),
|
|
298
298
|
field: 'responsibilityId',
|
|
299
299
|
});
|
|
300
300
|
}
|
|
@@ -303,7 +303,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
303
303
|
throw new SimpleError({
|
|
304
304
|
code: 'invalid_field',
|
|
305
305
|
message: 'Invalid organization',
|
|
306
|
-
human:
|
|
306
|
+
human: $t(`ed22b0bb-8ae7-4ef0-a139-1bc11b2a719e`),
|
|
307
307
|
field: 'organizationId',
|
|
308
308
|
});
|
|
309
309
|
}
|
|
@@ -345,7 +345,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
345
345
|
throw new SimpleError({
|
|
346
346
|
code: 'invalid_field',
|
|
347
347
|
message: 'Invalid organization',
|
|
348
|
-
human:
|
|
348
|
+
human: $t(`aa39f949-6fe5-4ed2-acb7-ff3d138cf243`),
|
|
349
349
|
field: 'organizationId',
|
|
350
350
|
});
|
|
351
351
|
}
|
|
@@ -355,7 +355,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
355
355
|
throw new SimpleError({
|
|
356
356
|
code: 'invalid_field',
|
|
357
357
|
message: 'Missing groupId',
|
|
358
|
-
human:
|
|
358
|
+
human: $t(`8bfe005a-a98a-48d6-afbf-bcca487b064b`),
|
|
359
359
|
field: 'groupId',
|
|
360
360
|
});
|
|
361
361
|
}
|
|
@@ -365,7 +365,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
365
365
|
throw new SimpleError({
|
|
366
366
|
code: 'invalid_field',
|
|
367
367
|
message: 'Invalid groupId',
|
|
368
|
-
human:
|
|
368
|
+
human: $t(`ca86d6ef-990e-42a4-834c-1c94622c95ef`),
|
|
369
369
|
field: 'groupId',
|
|
370
370
|
});
|
|
371
371
|
}
|
|
@@ -374,7 +374,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
374
374
|
throw new SimpleError({
|
|
375
375
|
code: 'invalid_field',
|
|
376
376
|
message: 'Invalid groupId',
|
|
377
|
-
human:
|
|
377
|
+
human: $t(`aed1d5e3-1d42-46d4-a9c1-ac13bdffc2bd`),
|
|
378
378
|
field: 'groupId',
|
|
379
379
|
});
|
|
380
380
|
}
|
|
@@ -386,7 +386,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
386
386
|
model.endDate = put.endDate;
|
|
387
387
|
|
|
388
388
|
if (put.startDate.getTime() > Date.now() + 5 * 60 * 1000) {
|
|
389
|
-
throw Context.auth.error(
|
|
389
|
+
throw Context.auth.error($t(`84c2346e-40b2-4b38-9b2d-e1fcba6f1202`));
|
|
390
390
|
}
|
|
391
391
|
|
|
392
392
|
if (put.startDate.getTime() > Date.now()) {
|
|
@@ -394,7 +394,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
394
394
|
}
|
|
395
395
|
|
|
396
396
|
if (put.endDate && put.endDate > new Date(Date.now() + 60 * 1000)) {
|
|
397
|
-
throw Context.auth.error(
|
|
397
|
+
throw Context.auth.error($t(`5c6106e8-6785-4f72-b0c7-00a940240019`));
|
|
398
398
|
}
|
|
399
399
|
|
|
400
400
|
model.startDate = put.startDate;
|
|
@@ -421,7 +421,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
421
421
|
throw new SimpleError({
|
|
422
422
|
code: 'invalid_field',
|
|
423
423
|
message: 'Invalid email',
|
|
424
|
-
human:
|
|
424
|
+
human: $t(`dcb9cd60-ddfe-403d-bfb7-d1c7b63e2fdf`),
|
|
425
425
|
});
|
|
426
426
|
}
|
|
427
427
|
|
|
@@ -457,13 +457,13 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
457
457
|
throw new SimpleError({
|
|
458
458
|
code: 'invalid_field',
|
|
459
459
|
message: 'Invalid organization',
|
|
460
|
-
human:
|
|
460
|
+
human: $t(`601c15e5-cfb0-4c34-af03-7dfc55e39d36`),
|
|
461
461
|
field: 'organizationId',
|
|
462
462
|
});
|
|
463
463
|
}
|
|
464
464
|
|
|
465
465
|
if (!await Context.auth.hasFullAccess(put.organizationId)) {
|
|
466
|
-
throw Context.auth.error(
|
|
466
|
+
throw Context.auth.error($t(`9c632c7f-242e-44a1-b8ad-335b613075d8`));
|
|
467
467
|
}
|
|
468
468
|
|
|
469
469
|
const putForOrganization = await Context.auth.getOrganization(put.organizationId);
|
|
@@ -475,7 +475,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
475
475
|
code: 'invalid_field',
|
|
476
476
|
field: 'membershipTypeId',
|
|
477
477
|
message: 'Invalid membership type',
|
|
478
|
-
human:
|
|
478
|
+
human: $t(`fa79b34e-deef-4379-9c80-8795b0f5eaa3`),
|
|
479
479
|
});
|
|
480
480
|
}
|
|
481
481
|
|
|
@@ -497,7 +497,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
497
497
|
code: 'invalid_field',
|
|
498
498
|
field: 'membershipTypeId',
|
|
499
499
|
message: 'Invalid membership type',
|
|
500
|
-
human:
|
|
500
|
+
human: $t(`a17551ff-5097-4f09-a8bb-19fe377f2b98`),
|
|
501
501
|
});
|
|
502
502
|
}
|
|
503
503
|
|
|
@@ -543,7 +543,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
543
543
|
code: 'invalid_field',
|
|
544
544
|
field: 'startDate',
|
|
545
545
|
message: 'Invalid start date',
|
|
546
|
-
human:
|
|
546
|
+
human: $t(`faf8b6bb-2727-4d2f-847f-203cf3979dfb`),
|
|
547
547
|
});
|
|
548
548
|
}
|
|
549
549
|
|
|
@@ -561,12 +561,12 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
561
561
|
code: 'invalid_field',
|
|
562
562
|
field: 'id',
|
|
563
563
|
message: 'Invalid id',
|
|
564
|
-
human:
|
|
564
|
+
human: $t(`ee79372d-c14d-41ab-afb1-336acbe52687`),
|
|
565
565
|
});
|
|
566
566
|
}
|
|
567
567
|
|
|
568
568
|
if (!await Context.auth.hasFullAccess(membership.organizationId)) {
|
|
569
|
-
throw Context.auth.error(
|
|
569
|
+
throw Context.auth.error($t(`fa5797d7-dafb-469a-a75c-b3b8a6a08737`));
|
|
570
570
|
}
|
|
571
571
|
|
|
572
572
|
if (membership.periodId !== platform.periodId) {
|
|
@@ -619,12 +619,12 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
619
619
|
code: 'invalid_field',
|
|
620
620
|
field: 'id',
|
|
621
621
|
message: 'Invalid id',
|
|
622
|
-
human:
|
|
622
|
+
human: $t(`ee79372d-c14d-41ab-afb1-336acbe52687`),
|
|
623
623
|
});
|
|
624
624
|
}
|
|
625
625
|
|
|
626
626
|
if (!await Context.auth.hasFullAccess(membership.organizationId)) {
|
|
627
|
-
throw Context.auth.error(
|
|
627
|
+
throw Context.auth.error($t(`c3cca571-d543-4ca7-9da1-1e5570f5063a`));
|
|
628
628
|
}
|
|
629
629
|
|
|
630
630
|
if (membership.periodId !== platform.periodId) {
|
|
@@ -654,14 +654,14 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
654
654
|
throw new SimpleError({
|
|
655
655
|
code: 'invalid_field',
|
|
656
656
|
message: 'Invalid invoice',
|
|
657
|
-
human:
|
|
657
|
+
human: $t(`be7d7286-9c3f-41f9-9378-b028754c8533`),
|
|
658
658
|
});
|
|
659
659
|
}
|
|
660
660
|
|
|
661
661
|
throw new SimpleError({
|
|
662
662
|
code: 'invalid_field',
|
|
663
663
|
message: 'Invalid invoice',
|
|
664
|
-
human:
|
|
664
|
+
human: $t(`1a7b41da-9bd3-4019-9ed4-39e742f99f41`),
|
|
665
665
|
});
|
|
666
666
|
}
|
|
667
667
|
|
|
@@ -709,7 +709,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
709
709
|
for (const id of ids) {
|
|
710
710
|
const member = await Member.getWithRegistrations(id);
|
|
711
711
|
if (!member || !await Context.auth.canDeleteMember(member)) {
|
|
712
|
-
throw Context.auth.error(
|
|
712
|
+
throw Context.auth.error($t(`39f5696c-3755-429f-b0da-a0ca920ed11e`));
|
|
713
713
|
}
|
|
714
714
|
|
|
715
715
|
await MemberUserSyncer.onDeleteMember(member);
|
|
@@ -901,14 +901,14 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
901
901
|
}
|
|
902
902
|
catch (e) {
|
|
903
903
|
Email.sendWebmaster({
|
|
904
|
-
subject:
|
|
905
|
-
text:
|
|
904
|
+
subject: $t(`04cb945a-28aa-4f3e-95b3-16455cdd8892`),
|
|
905
|
+
text: $t(`5f7b1766-eb58-4471-bff7-60f3fc66fe41`) + ' ' + member.details.name + ' ' + $t(`7254f2f6-0d15-4e81-85cf-cff6438c9e98`) + ' ' + member.id + ')' + '\n\n' + e.message + '\n\nStamhoofd',
|
|
906
906
|
});
|
|
907
907
|
|
|
908
908
|
throw new SimpleError({
|
|
909
909
|
code: 'too_many_tries',
|
|
910
910
|
message: 'Too many securityCodes limited',
|
|
911
|
-
human:
|
|
911
|
+
human: $t(`ddb1b9de-cc00-4960-ba36-fa70429cbac1`),
|
|
912
912
|
field: 'details.securityCode',
|
|
913
913
|
});
|
|
914
914
|
}
|
|
@@ -36,7 +36,7 @@ export class CheckRegisterCodeEndpoint extends Endpoint<Params, Query, Body, Res
|
|
|
36
36
|
throw new SimpleError({
|
|
37
37
|
code: 'invalid_code',
|
|
38
38
|
message: 'Invalid code',
|
|
39
|
-
human:
|
|
39
|
+
human: $t(`d46c176d-780c-4484-a510-7fcbe0e31555`),
|
|
40
40
|
field: 'registerCode',
|
|
41
41
|
});
|
|
42
42
|
}
|
|
@@ -31,7 +31,7 @@ export class CreateOrganizationEndpoint extends Endpoint<Params, Query, Body, Re
|
|
|
31
31
|
throw new SimpleError({
|
|
32
32
|
code: 'invalid_field',
|
|
33
33
|
message: 'Not allowed',
|
|
34
|
-
human:
|
|
34
|
+
human: $t(`a010c110-bf4e-4c12-a324-6b84c992e728`),
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -40,7 +40,7 @@ export class CreateOrganizationEndpoint extends Endpoint<Params, Query, Body, Re
|
|
|
40
40
|
throw new SimpleError({
|
|
41
41
|
code: 'invalid_field',
|
|
42
42
|
message: 'Should not be empty',
|
|
43
|
-
human:
|
|
43
|
+
human: $t(`3f37782a-c07f-457d-994f-f1cc075cff44`),
|
|
44
44
|
field: 'organization.name',
|
|
45
45
|
});
|
|
46
46
|
}
|
|
@@ -48,7 +48,7 @@ export class CreateOrganizationEndpoint extends Endpoint<Params, Query, Body, Re
|
|
|
48
48
|
throw new SimpleError({
|
|
49
49
|
code: 'invalid_field',
|
|
50
50
|
message: 'Field is too short',
|
|
51
|
-
human:
|
|
51
|
+
human: $t(`0e82abec-5467-45d8-ba89-9b9fd10c085d`),
|
|
52
52
|
field: 'organization.name',
|
|
53
53
|
});
|
|
54
54
|
}
|
|
@@ -59,7 +59,7 @@ export class CreateOrganizationEndpoint extends Endpoint<Params, Query, Body, Re
|
|
|
59
59
|
throw new SimpleError({
|
|
60
60
|
code: 'invalid_field',
|
|
61
61
|
message: 'Field is too long',
|
|
62
|
-
human:
|
|
62
|
+
human: $t(`c4d225ea-8e41-4829-bf0c-bc04755492de`),
|
|
63
63
|
field: 'organization.name',
|
|
64
64
|
});
|
|
65
65
|
}
|
|
@@ -69,7 +69,7 @@ export class CreateOrganizationEndpoint extends Endpoint<Params, Query, Body, Re
|
|
|
69
69
|
throw new SimpleError({
|
|
70
70
|
code: 'name_taken',
|
|
71
71
|
message: 'An organization with the same name already exists',
|
|
72
|
-
human:
|
|
72
|
+
human: $t(`19e5262f-9dc1-40d9-b905-bda8462b6046`),
|
|
73
73
|
field: 'name',
|
|
74
74
|
});
|
|
75
75
|
}
|
|
@@ -52,6 +52,11 @@ export class StripeWebookEndpoint extends Endpoint<Params, Query, Body, Response
|
|
|
52
52
|
|
|
53
53
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
54
54
|
console.log('Received Stripe Webhook', request.body.type);
|
|
55
|
+
const secret = request.body.account ? STAMHOOFD.STRIPE_CONNECT_ENDPOINT_SECRET : STAMHOOFD.STRIPE_ENDPOINT_SECRET;
|
|
56
|
+
|
|
57
|
+
if (!secret) {
|
|
58
|
+
throw StripeHelper.notConfiguredError;
|
|
59
|
+
}
|
|
55
60
|
|
|
56
61
|
// Verify webhook signature and extract the event.
|
|
57
62
|
// See https://stripe.com/docs/webhooks/signatures for more information.
|
|
@@ -66,7 +71,6 @@ export class StripeWebookEndpoint extends Endpoint<Params, Query, Body, Response
|
|
|
66
71
|
statusCode: 400,
|
|
67
72
|
});
|
|
68
73
|
}
|
|
69
|
-
const secret = request.body.account ? STAMHOOFD.STRIPE_CONNECT_ENDPOINT_SECRET : STAMHOOFD.STRIPE_ENDPOINT_SECRET;
|
|
70
74
|
event = await stripe.webhooks.constructEventAsync(await request.request.bodyPromise!, sig, secret);
|
|
71
75
|
}
|
|
72
76
|
catch (err) {
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Request } from '@simonbackx/simple-endpoints';
|
|
2
|
+
import { Token, UserFactory } from '@stamhoofd/models';
|
|
3
|
+
import { PermissionLevel, Permissions, Version } from '@stamhoofd/structures';
|
|
4
|
+
|
|
5
|
+
import { TestUtils } from '@stamhoofd/test-utils';
|
|
6
|
+
import { testServer } from '../../../../tests/helpers/TestServer';
|
|
7
|
+
import { GetPlatformEndpoint } from './GetPlatformEndpoint';
|
|
8
|
+
|
|
9
|
+
describe('Endpoint.GetPlatformEndpoint', () => {
|
|
10
|
+
const endpoint = new GetPlatformEndpoint();
|
|
11
|
+
|
|
12
|
+
const getPlatform = async (token?: Token) => {
|
|
13
|
+
const request = Request.buildJson('GET', `/v${Version}/platform`);
|
|
14
|
+
if (token) {
|
|
15
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
16
|
+
}
|
|
17
|
+
return await testServer.test(endpoint, request);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
beforeEach(async () => {
|
|
21
|
+
TestUtils.setEnvironment('userMode', 'platform');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('Should return platform without private config if not authenticated', async () => {
|
|
25
|
+
const platform = await getPlatform();
|
|
26
|
+
expect(platform.body.privateConfig).toBeNull();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('Should return platform without private config if no platform access', async () => {
|
|
30
|
+
const user = await new UserFactory({
|
|
31
|
+
globalPermissions: Permissions.create({
|
|
32
|
+
level: PermissionLevel.None,
|
|
33
|
+
}),
|
|
34
|
+
})
|
|
35
|
+
.create();
|
|
36
|
+
|
|
37
|
+
const token = await Token.createToken(user);
|
|
38
|
+
const platform = await getPlatform(token);
|
|
39
|
+
expect(platform.body.privateConfig).toBeNull();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('Should return platform with private config if authenticated and has platform access', async () => {
|
|
43
|
+
const user = await new UserFactory({
|
|
44
|
+
globalPermissions: Permissions.create({
|
|
45
|
+
level: PermissionLevel.Full,
|
|
46
|
+
}),
|
|
47
|
+
})
|
|
48
|
+
.create();
|
|
49
|
+
|
|
50
|
+
const token = await Token.createToken(user);
|
|
51
|
+
const platform = await getPlatform(token);
|
|
52
|
+
expect(platform.body.privateConfig).not.toBeNull();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('Should throw if invalid token', async () => {
|
|
56
|
+
const user = await new UserFactory({
|
|
57
|
+
globalPermissions: Permissions.create({
|
|
58
|
+
level: PermissionLevel.Full,
|
|
59
|
+
}),
|
|
60
|
+
})
|
|
61
|
+
.create();
|
|
62
|
+
|
|
63
|
+
const token = await Token.createToken(user);
|
|
64
|
+
token.accessToken = 'invalid-token';
|
|
65
|
+
await token.save();
|
|
66
|
+
await expect(getPlatform(token)).rejects.toThrow('The access token is invalid');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -161,7 +161,7 @@ export class PatchPlatformEndpoint extends Endpoint<
|
|
|
161
161
|
throw new SimpleError({
|
|
162
162
|
code: 'cannot_set_locked_period',
|
|
163
163
|
message: 'Platform period cannot be set to a locked period',
|
|
164
|
-
human:
|
|
164
|
+
human: $t(`fdd15119-b950-4282-9413-fd6973afde07`),
|
|
165
165
|
});
|
|
166
166
|
}
|
|
167
167
|
platform.periodId = period.id;
|
|
@@ -33,7 +33,7 @@ export class GetPaymentRegistrations extends Endpoint<Params, Query, Body, Respo
|
|
|
33
33
|
if (!payment) {
|
|
34
34
|
throw new SimpleError({
|
|
35
35
|
code: '',
|
|
36
|
-
message:
|
|
36
|
+
message: $t(`35b369bd-5766-41d1-8da3-3d362e316c1a`),
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
const registrations = await Member.getRegistrationWithMembersForPayment(payment.id);
|
|
@@ -45,7 +45,7 @@ export class GetPaymentRegistrations extends Endpoint<Params, Query, Body, Respo
|
|
|
45
45
|
if (!authorizedMembers.includes(registration.member.id)) {
|
|
46
46
|
throw new SimpleError({
|
|
47
47
|
code: '',
|
|
48
|
-
message:
|
|
48
|
+
message: $t(`35b369bd-5766-41d1-8da3-3d362e316c1a`),
|
|
49
49
|
});
|
|
50
50
|
}
|
|
51
51
|
}
|