@stamhoofd/backend 2.118.1 → 2.120.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 +32 -22
- package/src/audit-logs/ModelLogger.ts +4 -2
- package/src/audit-logs/OrderLogger.ts +1 -1
- package/src/boot.ts +32 -14
- package/src/crons/balance-emails.ts +4 -2
- package/src/crons/clearExcelCache.test.ts +8 -8
- package/src/crons/update-cached-balances.ts +40 -14
- package/src/debug.ts +3 -2
- package/src/decoders/StringArrayDecoder.ts +1 -1
- package/src/decoders/StringNullableDecoder.ts +1 -1
- package/src/email-recipient-loaders/documents.ts +2 -1
- package/src/email-recipient-loaders/members.ts +2 -1
- package/src/email-recipient-loaders/orders.ts +2 -1
- package/src/email-recipient-loaders/payments.ts +6 -3
- package/src/email-recipient-loaders/receivable-balances.ts +2 -1
- package/src/email-recipient-loaders/registrations.ts +2 -1
- package/src/email-replacements/getEmailReplacementsForPayment.ts +8 -7
- package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +7 -6
- package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +3 -2
- package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +2 -1
- package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +4 -3
- package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +3 -2
- package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +7 -5
- package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +12 -10
- package/src/endpoints/admin/registrations/ChargeRegistrationsEndpoint.ts +4 -3
- package/src/endpoints/auth/CreateAdminEndpoint.ts +8 -6
- package/src/endpoints/auth/CreateTokenEndpoint.ts +14 -12
- package/src/endpoints/auth/DeleteTokenEndpoint.ts +2 -1
- package/src/endpoints/auth/DeleteUserEndpoint.ts +2 -1
- package/src/endpoints/auth/ForgotPasswordEndpoint.ts +5 -4
- package/src/endpoints/auth/GetOtherUserEndpoint.ts +3 -2
- package/src/endpoints/auth/GetUserEndpoint.ts +3 -2
- package/src/endpoints/auth/OpenIDConnectAuthTokenEndpoint.ts +2 -1
- package/src/endpoints/auth/OpenIDConnectCallbackEndpoint.ts +4 -2
- package/src/endpoints/auth/OpenIDConnectStartEndpoint.ts +3 -2
- package/src/endpoints/auth/PatchUserEndpoint.ts +15 -12
- package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +3 -2
- package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +3 -2
- package/src/endpoints/auth/SignupEndpoint.ts +5 -4
- package/src/endpoints/auth/VerifyEmailEndpoint.ts +6 -5
- package/src/endpoints/frontend/FrontendEnvironmentEndpoint.ts +3 -2
- package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +8 -5
- package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +5 -3
- package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +8 -5
- package/src/endpoints/global/billing/ActivatePackagesEndpoint.ts +9 -7
- package/src/endpoints/global/billing/DeactivatePackageEndpoint.ts +4 -3
- package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +4 -2
- package/src/endpoints/global/email/CreateEmailEndpoint.ts +9 -7
- package/src/endpoints/global/email/GetAdminEmailsEndpoint.test.ts +2 -1
- package/src/endpoints/global/email/GetAdminEmailsEndpoint.ts +22 -19
- package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +6 -4
- package/src/endpoints/global/email/GetEmailEndpoint.ts +4 -3
- package/src/endpoints/global/email/GetUserEmailsEndpoint.test.ts +3 -2
- package/src/endpoints/global/email/GetUserEmailsEndpoint.ts +7 -4
- package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +7 -5
- package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +11 -11
- package/src/endpoints/global/email/PatchEmailEndpoint.ts +14 -11
- package/src/endpoints/global/email-recipients/GetEmailRecipientsCountEndpoint.ts +3 -2
- package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.test.ts +2 -1
- package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.ts +8 -5
- package/src/endpoints/global/email-recipients/RetryEmailRecipientEndpoint.ts +7 -5
- package/src/endpoints/global/email-recipients/helpers/validateEmailRecipientFilter.ts +4 -3
- package/src/endpoints/global/events/GetEventNotificationsCountEndpoint.ts +3 -2
- package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +9 -6
- package/src/endpoints/global/events/GetEventsEndpoint.ts +7 -4
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +4 -2
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +17 -15
- package/src/endpoints/global/events/PatchEventsEndpoint.test.ts +4 -2
- package/src/endpoints/global/events/PatchEventsEndpoint.ts +28 -26
- package/src/endpoints/global/files/ExportToExcelEndpoint.ts +8 -5
- package/src/endpoints/global/files/GetFileCache.ts +5 -3
- package/src/endpoints/global/files/UploadFile.ts +10 -4
- package/src/endpoints/global/files/UploadImage.ts +4 -2
- package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +4 -2
- package/src/endpoints/global/groups/GetGroupsEndpoint.ts +8 -5
- package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +7 -5
- package/src/endpoints/global/members/GetMembersCountEndpoint.ts +3 -2
- package/src/endpoints/global/members/GetMembersEndpoint.test.ts +4 -2
- package/src/endpoints/global/members/GetMembersEndpoint.ts +10 -8
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +257 -6
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +162 -107
- package/src/endpoints/global/members/helpers/validateGroupFilter.ts +4 -3
- package/src/endpoints/global/members/shouldCheckIfMemberIsDuplicate.ts +3 -2
- package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +3 -2
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +3 -2
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +8 -7
- package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +5 -3
- package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +5 -3
- package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +8 -5
- package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +4 -2
- package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +2 -1
- package/src/endpoints/global/platform/GetPlatformEndpoint.ts +3 -2
- package/src/endpoints/global/platform/PatchPlatformEnpoint.test.ts +3 -2
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +7 -4
- package/src/endpoints/global/platform-memberships/GetPlatformMembershipsCountEndpoint.ts +47 -0
- package/src/endpoints/global/platform-memberships/GetPlatformMembershipsEndpoint.ts +206 -0
- package/src/endpoints/global/registration/GetRegistrationsCountEndpoint.ts +3 -2
- package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +2 -1
- package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +10 -7
- package/src/endpoints/global/registration/GetUserDetailedPayableBalanceEndpoint.ts +4 -2
- package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +4 -2
- package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +3 -2
- package/src/endpoints/global/registration/GetUserPayableBalanceEndpoint.ts +2 -1
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +5 -3
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +13 -9
- package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +50 -49
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +25 -22
- package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +8 -5
- package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +9 -7
- package/src/endpoints/global/sso/GetSSOEndpoint.ts +4 -2
- package/src/endpoints/global/sso/SetSSOEndpoint.ts +3 -2
- package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +4 -2
- package/src/endpoints/global/webshops/GetWebshopsCountEndpoint.ts +43 -0
- package/src/endpoints/global/webshops/GetWebshopsEndpoint.test.ts +808 -0
- package/src/endpoints/global/webshops/GetWebshopsEndpoint.ts +221 -0
- package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemEndpoint.ts +4 -3
- package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsEndpoint.ts +6 -4
- package/src/endpoints/organization/dashboard/balance-items/PatchBalanceItemsEndpoint.ts +15 -13
- package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableBalanceEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +3 -2
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +7 -4
- package/src/endpoints/organization/dashboard/documents/GetDocumentsCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +7 -4
- package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +9 -7
- package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.test.ts +4 -2
- package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.ts +7 -5
- package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +36 -1
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +13 -4
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +4 -2
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +7 -5
- package/src/endpoints/organization/dashboard/invoices/GetInvoicesCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/invoices/GetInvoicesEndpoint.ts +6 -4
- package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +5 -3
- package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +6 -3
- package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +4 -2
- package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +3 -2
- package/src/endpoints/organization/dashboard/organization/GetUitpasClientIdEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +5 -3
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +22 -19
- package/src/endpoints/organization/dashboard/organization/SearchUitpasOrganizersEndpoint.ts +5 -3
- package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +11 -9
- package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +8 -7
- package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +7 -5
- package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +18 -16
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +5 -3
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +2 -1
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +8 -5
- package/src/endpoints/organization/dashboard/registration-periods/MoveRegistrationPeriods.test.ts +4 -2
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.test.ts +4 -2
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +32 -29
- package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +6 -3
- package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +5 -3
- package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +5 -3
- package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +4 -3
- package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +4 -3
- package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.ts +6 -4
- package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +7 -6
- package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +7 -4
- package/src/endpoints/organization/dashboard/webshops/{GetWebshopTicketsCountEndpoint → GetWebshopTicketsCountEndpoint.ts} +7 -7
- package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +9 -6
- package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +6 -4
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +13 -12
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +5 -3
- package/src/endpoints/organization/dashboard/webshops/SearchUitpasEventsEndpoint.ts +6 -4
- package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +2 -1
- package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +6 -4
- package/src/endpoints/organization/shared/GetDocumentHtml.ts +4 -3
- package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +4 -3
- package/src/endpoints/organization/shared/GetUitpasNumberDetailsEndpoint.ts +3 -2
- package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +3 -2
- package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +4 -3
- package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +5 -4
- package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +4 -3
- package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +7 -5
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +4 -3
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +7 -3
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +11 -10
- package/src/endpoints/organization/webshops/RetrieveUitpasSocialTariffPriceEndpoint.ts +5 -4
- package/src/endpoints/system/HealthEndpoint.test.ts +44 -0
- package/src/endpoints/system/HealthEndpoint.ts +14 -6
- package/src/excel-loaders/balance-items.ts +19 -17
- package/src/excel-loaders/event-notifications.ts +15 -13
- package/src/excel-loaders/index.ts +1 -0
- package/src/excel-loaders/members.ts +45 -43
- package/src/excel-loaders/organizations.ts +26 -25
- package/src/excel-loaders/payments.ts +44 -42
- package/src/excel-loaders/platform-memberships.ts +202 -0
- package/src/excel-loaders/receivable-balances.ts +25 -23
- package/src/excel-loaders/registrations.ts +30 -28
- package/src/helpers/AddressValidator.test.ts +2 -1
- package/src/helpers/AddressValidator.ts +13 -10
- package/src/helpers/AdminPermissionChecker.ts +193 -95
- package/src/helpers/AuthenticatedStructures.ts +13 -11
- package/src/helpers/BuckarooHelper.ts +3 -2
- package/src/helpers/Context.ts +8 -6
- package/src/helpers/CookieHelper.ts +2 -2
- package/src/helpers/FileCache.ts +9 -9
- package/src/helpers/ForwardHandler.ts +3 -2
- package/src/helpers/GlobalHelper.ts +2 -0
- package/src/helpers/GroupBuilder.ts +2 -1
- package/src/helpers/GroupedThrottledQueue.test.ts +19 -19
- package/src/helpers/LimitedFilteredRequestHelper.ts +1 -1
- package/src/helpers/MemberCharger.ts +2 -1
- package/src/helpers/MemberUserSyncer.ts +6 -3
- package/src/helpers/MembershipCharger.ts +2 -2
- package/src/helpers/OrganizationCharger.ts +2 -1
- package/src/helpers/PeriodHelper.ts +2 -1
- package/src/helpers/SQLTranslatedString.ts +3 -2
- package/src/helpers/ServiceFeeHelper.ts +1 -1
- package/src/helpers/SetupStepUpdater.ts +6 -5
- package/src/helpers/StripeHelper.ts +9 -8
- package/src/helpers/TagHelper.test.ts +5 -5
- package/src/helpers/TagHelper.ts +2 -1
- package/src/helpers/TemporaryMemberAccess.ts +2 -1
- package/src/helpers/ThrottledQueue.test.ts +20 -20
- package/src/helpers/UitpasTokenRepository.ts +7 -7
- package/src/helpers/ViesHelper.ts +5 -4
- package/src/helpers/XlsxTransformerColumnHelper.ts +21 -19
- package/src/helpers/email-html-helpers.ts +13 -12
- package/src/helpers/fetchToAsyncIterator.ts +1 -1
- package/src/helpers/outstandingBalanceJoin.ts +2 -1
- package/src/helpers/updateMemberDetailsUitpasNumber.ts +5 -4
- package/src/middleware/ContextMiddleware.ts +1 -1
- package/src/migrate.ts +21 -4
- package/src/seeds/0000000003-default-email-templates.ts +1 -1
- package/src/seeds/0000000004-single-organization.ts +2 -1
- package/src/seeds/1752848561-groups-registration-periods.ts +3 -2
- package/src/seeds/1754560914-groups-prices.test.ts +2 -1
- package/src/seeds/1754560914-groups-prices.ts +2 -1
- package/src/seeds/1755790070-fill-email-recipient-errors.ts +6 -6
- package/src/seeds/1755876819-remove-duplicate-members.ts +2 -1
- package/src/seeds/1765896674-document-update-year.test.ts +2 -1
- package/src/seeds/1773754928-force-save-members.ts +15 -0
- package/src/services/AuditLogService.ts +3 -2
- package/src/services/BalanceItemPaymentService.ts +2 -2
- package/src/services/BalanceItemService.ts +2 -1
- package/src/services/BootChecksService.test.ts +33 -0
- package/src/services/BootChecksService.ts +21 -0
- package/src/services/DatabaseCollationService.test.ts +18 -0
- package/src/services/DatabaseCollationService.ts +81 -0
- package/src/services/DocumentService.ts +1 -1
- package/src/services/EventNotificationService.ts +5 -4
- package/src/services/FileSignService.ts +2 -2
- package/src/services/InvoiceService.ts +3 -3
- package/src/services/MemberNumberService.ts +6 -4
- package/src/services/MemberRecordStore.ts +28 -19
- package/src/services/PaymentReallocationService.test.ts +2 -1
- package/src/services/PaymentReallocationService.ts +2 -1
- package/src/services/PaymentService.ts +28 -26
- package/src/services/RegistrationService.ts +65 -3
- package/src/services/SSOService.ts +13 -9
- package/src/services/STPackageService.ts +7 -5
- package/src/services/StartupHealthService.ts +15 -0
- package/src/services/uitpas/PassholderEndpoints.ts +2 -2
- package/src/services/uitpas/UitpasService.ts +11 -8
- package/src/services/uitpas/cancelTicketSales.ts +1 -1
- package/src/services/uitpas/checkPermissionsFor.ts +9 -9
- package/src/services/uitpas/getSocialTariffForEvent.ts +4 -4
- package/src/services/uitpas/getSocialTariffForUitpasNumbers.ts +5 -5
- package/src/services/uitpas/handleUitpasResponse.ts +1 -1
- package/src/services/uitpas/registerTicketSales.ts +4 -4
- package/src/services/uitpas/searchUitpasEvents.ts +3 -3
- package/src/services/uitpas/searchUitpasOrganizers.ts +3 -3
- package/src/sql-filters/audit-logs.ts +2 -1
- package/src/sql-filters/balance-item-payments.ts +2 -1
- package/src/sql-filters/balance-items.ts +2 -1
- package/src/sql-filters/base-registration-filter-compilers.ts +6 -4
- package/src/sql-filters/document-templates.ts +2 -1
- package/src/sql-filters/documents.ts +2 -1
- package/src/sql-filters/email-recipients.ts +2 -1
- package/src/sql-filters/emails.ts +2 -1
- package/src/sql-filters/event-notifications.ts +2 -1
- package/src/sql-filters/events.ts +2 -1
- package/src/sql-filters/groups.ts +2 -1
- package/src/sql-filters/invoiced-balance-items.ts +2 -1
- package/src/sql-filters/invoices.ts +2 -1
- package/src/sql-filters/member-responsibility-records.ts +2 -1
- package/src/sql-filters/members.ts +8 -7
- package/src/sql-filters/orders.ts +3 -2
- package/src/sql-filters/organization-registration-periods.ts +2 -1
- package/src/sql-filters/organizations.ts +2 -1
- package/src/sql-filters/payments.ts +2 -1
- package/src/sql-filters/platform-memberships.ts +67 -0
- package/src/sql-filters/receivable-balances.ts +2 -1
- package/src/sql-filters/registration-periods.ts +2 -1
- package/src/sql-filters/registrations.ts +2 -1
- package/src/sql-filters/tickets.ts +2 -1
- package/src/sql-filters/users.ts +2 -1
- package/src/sql-filters/webshops.ts +38 -0
- package/src/sql-sorters/audit-logs.ts +3 -2
- package/src/sql-sorters/balance-items.ts +3 -2
- package/src/sql-sorters/document-templates.ts +3 -2
- package/src/sql-sorters/documents.ts +3 -2
- package/src/sql-sorters/email-recipients.ts +3 -2
- package/src/sql-sorters/emails.ts +3 -2
- package/src/sql-sorters/event-notifications.ts +3 -2
- package/src/sql-sorters/events.ts +3 -2
- package/src/sql-sorters/groups.ts +3 -2
- package/src/sql-sorters/invoices.ts +3 -2
- package/src/sql-sorters/members.ts +3 -2
- package/src/sql-sorters/orders.ts +3 -2
- package/src/sql-sorters/organization-registration-periods.ts +3 -2
- package/src/sql-sorters/organizations.ts +3 -2
- package/src/sql-sorters/payments.ts +3 -2
- package/src/sql-sorters/platform-memberships.ts +40 -0
- package/src/sql-sorters/receivable-balances.ts +3 -2
- package/src/sql-sorters/registration-periods.ts +3 -2
- package/src/sql-sorters/registrations.ts +3 -2
- package/src/sql-sorters/tickets.ts +3 -2
- package/src/sql-sorters/webshops.ts +40 -0
- package/tests/actions/patchOrganizationMember.ts +5 -4
- package/tests/actions/patchPaymentStatus.ts +2 -2
- package/tests/actions/patchUserMember.ts +6 -4
- package/tests/e2e/api-rate-limits.test.ts +4 -5
- package/tests/e2e/bundle-discounts.test.ts +3 -2
- package/tests/e2e/charge-members.test.ts +7 -5
- package/tests/e2e/documents.test.ts +3 -2
- package/tests/e2e/private-files.test.ts +11 -13
- package/tests/e2e/register.test.ts +6 -5
- package/tests/e2e/stock.test.ts +6 -8
- package/tests/e2e/tickets.test.ts +4 -2
- package/tests/helpers/StripeMocker.ts +3 -3
- package/tests/init/initAdmin.ts +4 -2
- package/tests/init/initBundleDiscount.ts +3 -2
- package/tests/init/initPayconiq.ts +1 -1
- package/tests/init/initPermissionRole.ts +4 -2
- package/tests/init/initPlatformRecordCategory.ts +1 -1
- package/tests/init/initStripe.ts +1 -1
- package/tests/vitest.global.setup.ts +26 -0
- package/tests/{jest.setup.ts → vitest.setup.ts} +4 -3
- package/tsconfig.build.json +17 -0
- package/tsconfig.json +10 -41
- package/tsconfig.test.json +17 -0
- package/vitest.config.js +13 -0
- package/eslint.config.mjs +0 -5
- package/jest.config.cjs +0 -27
- package/tests/jest.global.setup.ts +0 -33
- package/tests/toMatchMap.ts +0 -68
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { OneToManyRelation } from '@simonbackx/simple-database';
|
|
2
|
-
import { AutoEncoderPatchType, ConvertArrayToPatchableArray, Decoder,
|
|
3
|
-
import {
|
|
1
|
+
import type { OneToManyRelation } from '@simonbackx/simple-database';
|
|
2
|
+
import type { AutoEncoderPatchType, ConvertArrayToPatchableArray, Decoder, PatchableArrayAutoEncoder } from '@simonbackx/simple-encoding';
|
|
3
|
+
import { isEmptyPatch, isPatchableArray, PatchableArray, PatchableArrayDecoder, StringDecoder } from '@simonbackx/simple-encoding';
|
|
4
|
+
import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
|
|
5
|
+
import { Endpoint, Response } from '@simonbackx/simple-endpoints';
|
|
4
6
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
+
import type { MemberWithUsersRegistrationsAndGroups, Registration } from '@stamhoofd/models';
|
|
8
|
+
import { AuditLog, BalanceItem, Document, Group, Member, MemberFactory, MemberPlatformMembership, MemberResponsibilityRecord, mergeTwoMembers, Organization, Platform, RateLimiter, RegistrationPeriod, User } from '@stamhoofd/models';
|
|
9
|
+
import type { MemberResponsibility, MembersBlob } from '@stamhoofd/structures';
|
|
10
|
+
import { AuditLogReplacement, AuditLogReplacementType, AuditLogSource, AuditLogType, EmergencyContact, GroupType, MemberDetails, MemberWithRegistrationsBlob, Parent, PermissionLevel, PlatformMembershipTypeBehaviour, SetupStepType } from '@stamhoofd/structures';
|
|
7
11
|
import { Formatter } from '@stamhoofd/utility';
|
|
8
12
|
|
|
9
13
|
import { Email } from '@stamhoofd/email';
|
|
@@ -56,6 +60,18 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
56
60
|
return [false];
|
|
57
61
|
}
|
|
58
62
|
|
|
63
|
+
private static throwDuplicateMemberNumberError(error: unknown): never {
|
|
64
|
+
if (error && typeof error === 'object' && 'code' in error && error.code === 'ER_DUP_ENTRY' && 'message' in error && typeof error.message === 'string' && error.message.includes('memberNumber')) {
|
|
65
|
+
throw new SimpleError({
|
|
66
|
+
code: 'invalid_field',
|
|
67
|
+
message: 'Member number already in use',
|
|
68
|
+
human: $t('Dit lidnummer is al in gebruik'),
|
|
69
|
+
field: 'details.memberNumber',
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
|
|
59
75
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
60
76
|
const organization = await Context.setOptionalOrganizationScope();
|
|
61
77
|
await Context.authenticate();
|
|
@@ -111,7 +127,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
111
127
|
throw new SimpleError({
|
|
112
128
|
code: 'missing_organization',
|
|
113
129
|
message: 'Missing organization',
|
|
114
|
-
human: $t(`
|
|
130
|
+
human: $t(`%Di`),
|
|
115
131
|
statusCode: 400,
|
|
116
132
|
});
|
|
117
133
|
}
|
|
@@ -129,7 +145,12 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
129
145
|
}
|
|
130
146
|
}
|
|
131
147
|
|
|
132
|
-
|
|
148
|
+
try {
|
|
149
|
+
await member.save();
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
PatchOrganizationMembersEndpoint.throwDuplicateMemberNumberError(error);
|
|
153
|
+
}
|
|
133
154
|
members.push(member);
|
|
134
155
|
updateMembershipMemberIds.add(member.id);
|
|
135
156
|
|
|
@@ -148,9 +169,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
148
169
|
throw Context.auth.memberNotFoundOrNoAccess();
|
|
149
170
|
}
|
|
150
171
|
|
|
151
|
-
|
|
152
|
-
await PatchOrganizationMembersEndpoint.checkSecurityCode(member, securityCode, 'patch');
|
|
153
|
-
}
|
|
172
|
+
await PatchOrganizationMembersEndpoint.checkCanAccessMember(member, securityCode, 'patch');
|
|
154
173
|
|
|
155
174
|
patch = await Context.auth.filterMemberPatch(member, patch);
|
|
156
175
|
const originalDetails = member.details.clone();
|
|
@@ -162,7 +181,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
162
181
|
throw new SimpleError({
|
|
163
182
|
code: 'not_allowed',
|
|
164
183
|
message: 'Cannot override details',
|
|
165
|
-
human: $t(`
|
|
184
|
+
human: $t(`%Dj`),
|
|
166
185
|
field: 'details',
|
|
167
186
|
});
|
|
168
187
|
}
|
|
@@ -202,7 +221,12 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
202
221
|
}
|
|
203
222
|
}
|
|
204
223
|
|
|
205
|
-
|
|
224
|
+
try {
|
|
225
|
+
await member.save();
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
PatchOrganizationMembersEndpoint.throwDuplicateMemberNumberError(error);
|
|
229
|
+
}
|
|
206
230
|
|
|
207
231
|
// If parents changed or emergeny contacts: fetch family and merge data
|
|
208
232
|
if (patch.details && (!isEmptyPatch(patch.details?.parents) || !isEmptyPatch(patch.details?.emergencyContacts))) {
|
|
@@ -215,7 +239,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
215
239
|
// Update responsibilities
|
|
216
240
|
for (const patchResponsibility of patch.responsibilities.getPatches()) {
|
|
217
241
|
if (!Context.auth.hasPlatformFullAccess() && !(organization && await Context.auth.hasFullAccess(organization.id))) {
|
|
218
|
-
throw Context.auth.error($t(`
|
|
242
|
+
throw Context.auth.error($t(`%Dk`));
|
|
219
243
|
}
|
|
220
244
|
|
|
221
245
|
const responsibilityRecord = await MemberResponsibilityRecord.getByID(patchResponsibility.id);
|
|
@@ -223,21 +247,21 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
223
247
|
throw new SimpleError({
|
|
224
248
|
code: 'permission_denied',
|
|
225
249
|
message: "You don't have permissions to access this endpoint",
|
|
226
|
-
human: $t(`
|
|
250
|
+
human: $t(`%Dl`),
|
|
227
251
|
});
|
|
228
252
|
}
|
|
229
253
|
|
|
230
254
|
const responsibility = platform.config.responsibilities.find(r => r.id === patchResponsibility.responsibilityId);
|
|
231
255
|
|
|
232
256
|
if (responsibility && !responsibility.organizationBased && !Context.auth.hasPlatformFullAccess()) {
|
|
233
|
-
throw Context.auth.error($t(`
|
|
257
|
+
throw Context.auth.error($t(`%Dm`));
|
|
234
258
|
}
|
|
235
259
|
|
|
236
260
|
// Allow patching begin and end date
|
|
237
261
|
if (patchResponsibility.endDate !== undefined) {
|
|
238
262
|
if (responsibilityRecord.endDate) {
|
|
239
263
|
if (!Context.auth.hasPlatformFullAccess()) {
|
|
240
|
-
throw Context.auth.error($t(`
|
|
264
|
+
throw Context.auth.error($t(`%Dn`));
|
|
241
265
|
}
|
|
242
266
|
}
|
|
243
267
|
responsibilityRecord.endDate = patchResponsibility.endDate;
|
|
@@ -245,7 +269,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
245
269
|
|
|
246
270
|
if (patchResponsibility.startDate !== undefined) {
|
|
247
271
|
if (patchResponsibility.startDate.getTime() > Date.now() + 5 * 60 * 1000) {
|
|
248
|
-
throw Context.auth.error($t(`
|
|
272
|
+
throw Context.auth.error($t(`%Do`));
|
|
249
273
|
}
|
|
250
274
|
if (patchResponsibility.startDate.getTime() > Date.now()) {
|
|
251
275
|
patchResponsibility.startDate = new Date(); // force now
|
|
@@ -254,7 +278,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
254
278
|
const daysDiff = Math.abs((new Date().getTime() - patchResponsibility.startDate.getTime()) / (1000 * 60 * 60 * 24));
|
|
255
279
|
|
|
256
280
|
if (daysDiff > 60 && !Context.auth.hasPlatformFullAccess()) {
|
|
257
|
-
throw Context.auth.error($t(`
|
|
281
|
+
throw Context.auth.error($t(`%Dp`));
|
|
258
282
|
}
|
|
259
283
|
responsibilityRecord.startDate = patchResponsibility.startDate;
|
|
260
284
|
}
|
|
@@ -271,7 +295,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
271
295
|
// Create responsibilities
|
|
272
296
|
for (const { put } of patch.responsibilities.getPuts()) {
|
|
273
297
|
if (!Context.auth.hasPlatformFullAccess() && !(organization && await Context.auth.hasFullAccess(organization.id))) {
|
|
274
|
-
throw Context.auth.error($t(`
|
|
298
|
+
throw Context.auth.error($t(`%Dk`));
|
|
275
299
|
}
|
|
276
300
|
|
|
277
301
|
const platformResponsibility = platform.config.responsibilities.find(r => r.id === put.responsibilityId);
|
|
@@ -281,7 +305,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
281
305
|
throw new SimpleError({
|
|
282
306
|
code: 'invalid_field',
|
|
283
307
|
message: 'Invalid organization',
|
|
284
|
-
human: $t(`
|
|
308
|
+
human: $t(`%Dq`),
|
|
285
309
|
field: 'organizationId',
|
|
286
310
|
});
|
|
287
311
|
}
|
|
@@ -291,7 +315,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
291
315
|
throw new SimpleError({
|
|
292
316
|
code: 'invalid_field',
|
|
293
317
|
message: 'Invalid responsibility',
|
|
294
|
-
human: $t(`
|
|
318
|
+
human: $t(`%Dr`),
|
|
295
319
|
field: 'responsibilityId',
|
|
296
320
|
});
|
|
297
321
|
}
|
|
@@ -300,7 +324,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
300
324
|
throw new SimpleError({
|
|
301
325
|
code: 'invalid_field',
|
|
302
326
|
message: 'Invalid organization',
|
|
303
|
-
human: $t(`
|
|
327
|
+
human: $t(`%Ds`),
|
|
304
328
|
field: 'organizationId',
|
|
305
329
|
});
|
|
306
330
|
}
|
|
@@ -329,7 +353,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
329
353
|
throw new SimpleError({
|
|
330
354
|
code: 'invalid_field',
|
|
331
355
|
message: 'Invalid organization',
|
|
332
|
-
human: platformResponsibility ? $t('
|
|
356
|
+
human: platformResponsibility ? $t('%1B9') : $t('%8G'),
|
|
333
357
|
});
|
|
334
358
|
}
|
|
335
359
|
|
|
@@ -342,7 +366,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
342
366
|
throw new SimpleError({
|
|
343
367
|
code: 'invalid_field',
|
|
344
368
|
message: 'Invalid organization',
|
|
345
|
-
human: $t(`
|
|
369
|
+
human: $t(`%Dt`),
|
|
346
370
|
field: 'organizationId',
|
|
347
371
|
});
|
|
348
372
|
}
|
|
@@ -352,7 +376,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
352
376
|
throw new SimpleError({
|
|
353
377
|
code: 'invalid_field',
|
|
354
378
|
message: 'Missing groupId',
|
|
355
|
-
human: $t(`
|
|
379
|
+
human: $t(`%Du`),
|
|
356
380
|
field: 'groupId',
|
|
357
381
|
});
|
|
358
382
|
}
|
|
@@ -362,7 +386,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
362
386
|
throw new SimpleError({
|
|
363
387
|
code: 'invalid_field',
|
|
364
388
|
message: 'Invalid groupId',
|
|
365
|
-
human: $t(`
|
|
389
|
+
human: $t(`%Dv`),
|
|
366
390
|
field: 'groupId',
|
|
367
391
|
});
|
|
368
392
|
}
|
|
@@ -371,7 +395,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
371
395
|
throw new SimpleError({
|
|
372
396
|
code: 'invalid_field',
|
|
373
397
|
message: 'Invalid groupId',
|
|
374
|
-
human: $t(`
|
|
398
|
+
human: $t(`%Dw`),
|
|
375
399
|
field: 'groupId',
|
|
376
400
|
});
|
|
377
401
|
}
|
|
@@ -383,7 +407,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
383
407
|
model.endDate = put.endDate;
|
|
384
408
|
|
|
385
409
|
if (put.startDate.getTime() > Date.now() + 5 * 60 * 1000) {
|
|
386
|
-
throw Context.auth.error($t(`
|
|
410
|
+
throw Context.auth.error($t(`%Do`));
|
|
387
411
|
}
|
|
388
412
|
|
|
389
413
|
if (put.startDate.getTime() > Date.now()) {
|
|
@@ -391,7 +415,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
391
415
|
}
|
|
392
416
|
|
|
393
417
|
if (put.endDate && put.endDate > new Date(Date.now() + 60 * 1000)) {
|
|
394
|
-
throw Context.auth.error($t(`
|
|
418
|
+
throw Context.auth.error($t(`%Dx`));
|
|
395
419
|
}
|
|
396
420
|
|
|
397
421
|
model.startDate = put.startDate;
|
|
@@ -418,7 +442,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
418
442
|
throw new SimpleError({
|
|
419
443
|
code: 'invalid_field',
|
|
420
444
|
message: 'Invalid email',
|
|
421
|
-
human: $t(`
|
|
445
|
+
human: $t(`%Dy`),
|
|
422
446
|
});
|
|
423
447
|
}
|
|
424
448
|
|
|
@@ -435,7 +459,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
435
459
|
throw new SimpleError({
|
|
436
460
|
code: 'invalid_field',
|
|
437
461
|
message: 'Invalid period',
|
|
438
|
-
human: Context.i18n.$t(`
|
|
462
|
+
human: Context.i18n.$t(`%A9`),
|
|
439
463
|
field: 'periodId',
|
|
440
464
|
});
|
|
441
465
|
}
|
|
@@ -444,7 +468,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
444
468
|
throw new SimpleError({
|
|
445
469
|
code: 'invalid_field',
|
|
446
470
|
message: 'Invalid period',
|
|
447
|
-
human: Context.i18n.$t(
|
|
471
|
+
human: Context.i18n.$t(`%AA`, { period: period?.getBaseStructure().name }),
|
|
448
472
|
field: 'periodId',
|
|
449
473
|
});
|
|
450
474
|
}
|
|
@@ -454,13 +478,13 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
454
478
|
throw new SimpleError({
|
|
455
479
|
code: 'invalid_field',
|
|
456
480
|
message: 'Invalid organization',
|
|
457
|
-
human: $t(`
|
|
481
|
+
human: $t(`%Dz`),
|
|
458
482
|
field: 'organizationId',
|
|
459
483
|
});
|
|
460
484
|
}
|
|
461
485
|
|
|
462
486
|
if (!await Context.auth.hasFullAccess(put.organizationId)) {
|
|
463
|
-
throw Context.auth.error($t(`
|
|
487
|
+
throw Context.auth.error($t(`%E0`));
|
|
464
488
|
}
|
|
465
489
|
|
|
466
490
|
const putForOrganization = await Context.auth.getOrganization(put.organizationId);
|
|
@@ -472,7 +496,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
472
496
|
code: 'invalid_field',
|
|
473
497
|
field: 'membershipTypeId',
|
|
474
498
|
message: 'Invalid membership type',
|
|
475
|
-
human: $t(`
|
|
499
|
+
human: $t(`%E1`),
|
|
476
500
|
});
|
|
477
501
|
}
|
|
478
502
|
|
|
@@ -494,7 +518,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
494
518
|
code: 'invalid_field',
|
|
495
519
|
field: 'membershipTypeId',
|
|
496
520
|
message: 'Invalid membership type',
|
|
497
|
-
human: $t(`
|
|
521
|
+
human: $t(`%E2`),
|
|
498
522
|
});
|
|
499
523
|
}
|
|
500
524
|
|
|
@@ -541,7 +565,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
541
565
|
code: 'invalid_field',
|
|
542
566
|
field: 'startDate',
|
|
543
567
|
message: 'Overlapping memberships',
|
|
544
|
-
human: $t(`
|
|
568
|
+
human: $t(`%1NA`),
|
|
545
569
|
});
|
|
546
570
|
}
|
|
547
571
|
if (existing.locked) {
|
|
@@ -549,7 +573,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
549
573
|
code: 'invalid_field',
|
|
550
574
|
field: 'startDate',
|
|
551
575
|
message: 'Overlapping memberships',
|
|
552
|
-
human: $t(`
|
|
576
|
+
human: $t(`%1NB`),
|
|
553
577
|
});
|
|
554
578
|
}
|
|
555
579
|
if (!existing.generated) {
|
|
@@ -557,14 +581,14 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
557
581
|
code: 'invalid_field',
|
|
558
582
|
field: 'startDate',
|
|
559
583
|
message: 'Overlapping memberships',
|
|
560
|
-
human: $t(`
|
|
584
|
+
human: $t(`%1NC`),
|
|
561
585
|
});
|
|
562
586
|
}
|
|
563
587
|
throw new SimpleError({
|
|
564
588
|
code: 'invalid_field',
|
|
565
589
|
field: 'startDate',
|
|
566
590
|
message: 'Overlapping memberships',
|
|
567
|
-
human: $t(`
|
|
591
|
+
human: $t(`%1ND`),
|
|
568
592
|
});
|
|
569
593
|
}
|
|
570
594
|
else if (existing) {
|
|
@@ -596,12 +620,12 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
596
620
|
code: 'invalid_field',
|
|
597
621
|
field: 'id',
|
|
598
622
|
message: 'Invalid id',
|
|
599
|
-
human: $t(`
|
|
623
|
+
human: $t(`%E3`),
|
|
600
624
|
});
|
|
601
625
|
}
|
|
602
626
|
|
|
603
627
|
if (!await Context.auth.hasFullAccess(membership.organizationId)) {
|
|
604
|
-
throw Context.auth.error($t(`
|
|
628
|
+
throw Context.auth.error($t(`%E4`));
|
|
605
629
|
}
|
|
606
630
|
|
|
607
631
|
if (membership.periodId !== platform.periodId) {
|
|
@@ -611,7 +635,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
611
635
|
throw new SimpleError({
|
|
612
636
|
code: 'invalid_field',
|
|
613
637
|
message: 'Invalid period',
|
|
614
|
-
human: $t(`
|
|
638
|
+
human: $t(`%BZ`),
|
|
615
639
|
field: 'periodId',
|
|
616
640
|
});
|
|
617
641
|
}
|
|
@@ -620,7 +644,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
620
644
|
throw new SimpleError({
|
|
621
645
|
code: 'invalid_field',
|
|
622
646
|
message: 'Invalid period',
|
|
623
|
-
human: $t(`
|
|
647
|
+
human: $t(`%Ba`),
|
|
624
648
|
field: 'periodId',
|
|
625
649
|
});
|
|
626
650
|
}
|
|
@@ -633,11 +657,11 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
633
657
|
}
|
|
634
658
|
else {
|
|
635
659
|
if (p.locked === true) {
|
|
636
|
-
throw Context.auth.error($t('
|
|
660
|
+
throw Context.auth.error($t('%BX'));
|
|
637
661
|
}
|
|
638
662
|
|
|
639
663
|
if (p.locked === false) {
|
|
640
|
-
throw Context.auth.error($t('
|
|
664
|
+
throw Context.auth.error($t('%BY'));
|
|
641
665
|
}
|
|
642
666
|
}
|
|
643
667
|
|
|
@@ -654,12 +678,12 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
654
678
|
code: 'invalid_field',
|
|
655
679
|
field: 'id',
|
|
656
680
|
message: 'Invalid id',
|
|
657
|
-
human: $t(`
|
|
681
|
+
human: $t(`%E3`),
|
|
658
682
|
});
|
|
659
683
|
}
|
|
660
684
|
|
|
661
685
|
if (!await Context.auth.hasFullAccess(membership.organizationId)) {
|
|
662
|
-
throw Context.auth.error($t(`
|
|
686
|
+
throw Context.auth.error($t(`%E5`));
|
|
663
687
|
}
|
|
664
688
|
|
|
665
689
|
if (membership.periodId !== platform.periodId) {
|
|
@@ -669,7 +693,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
669
693
|
throw new SimpleError({
|
|
670
694
|
code: 'invalid_field',
|
|
671
695
|
message: 'Invalid period',
|
|
672
|
-
human: Context.i18n.$t(`
|
|
696
|
+
human: Context.i18n.$t(`%AB`),
|
|
673
697
|
field: 'periodId',
|
|
674
698
|
});
|
|
675
699
|
}
|
|
@@ -678,7 +702,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
678
702
|
throw new SimpleError({
|
|
679
703
|
code: 'invalid_field',
|
|
680
704
|
message: 'Invalid period',
|
|
681
|
-
human: Context.i18n.$t(
|
|
705
|
+
human: Context.i18n.$t(`%AC`, { period: period?.getBaseStructure().name }),
|
|
682
706
|
field: 'periodId',
|
|
683
707
|
});
|
|
684
708
|
}
|
|
@@ -689,14 +713,14 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
689
713
|
throw new SimpleError({
|
|
690
714
|
code: 'invalid_field',
|
|
691
715
|
message: 'Invalid invoice',
|
|
692
|
-
human: $t(`
|
|
716
|
+
human: $t(`%E6`),
|
|
693
717
|
});
|
|
694
718
|
}
|
|
695
719
|
|
|
696
720
|
throw new SimpleError({
|
|
697
721
|
code: 'invalid_field',
|
|
698
722
|
message: 'Invalid invoice',
|
|
699
|
-
human: $t(`
|
|
723
|
+
human: $t(`%E7`),
|
|
700
724
|
});
|
|
701
725
|
}
|
|
702
726
|
|
|
@@ -732,8 +756,10 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
732
756
|
] }).catch(console.error);
|
|
733
757
|
}
|
|
734
758
|
|
|
759
|
+
const r = await AuthenticatedStructures.membersBlob(members);
|
|
760
|
+
|
|
735
761
|
return new Response(
|
|
736
|
-
|
|
762
|
+
r,
|
|
737
763
|
);
|
|
738
764
|
}
|
|
739
765
|
|
|
@@ -746,7 +772,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
746
772
|
for (const id of ids) {
|
|
747
773
|
const member = await Member.getByIdWithUsersAndRegistrations(id);
|
|
748
774
|
if (!member || !await Context.auth.canDeleteMember(member)) {
|
|
749
|
-
throw Context.auth.error($t(`
|
|
775
|
+
throw Context.auth.error($t(`%E8`));
|
|
750
776
|
}
|
|
751
777
|
|
|
752
778
|
await MemberUserSyncer.onDeleteMember(member);
|
|
@@ -929,77 +955,102 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
929
955
|
}
|
|
930
956
|
}
|
|
931
957
|
|
|
932
|
-
static async checkSecurityCode(member: MemberWithUsersRegistrationsAndGroups, securityCode: string
|
|
933
|
-
|
|
934
|
-
|
|
958
|
+
private static async checkSecurityCode(member: MemberWithUsersRegistrationsAndGroups, securityCode: string) {
|
|
959
|
+
try {
|
|
960
|
+
securityCodeLimiter.track(member.details.name, 1);
|
|
935
961
|
}
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
Email.sendWebmaster({
|
|
942
|
-
subject: $t(`04cb945a-28aa-4f3e-95b3-16455cdd8892`),
|
|
943
|
-
text: $t(`5f7b1766-eb58-4471-bff7-60f3fc66fe41`) + ' ' + member.details.name + ' ' + $t(`7254f2f6-0d15-4e81-85cf-cff6438c9e98`) + ' ' + member.id + ')' + '\n\n' + e.message + '\n\nStamhoofd',
|
|
944
|
-
});
|
|
962
|
+
catch (e) {
|
|
963
|
+
Email.sendWebmaster({
|
|
964
|
+
subject: $t(`%E9`),
|
|
965
|
+
text: $t(`%EA`) + ' ' + member.details.name + ' ' + $t(`%1G`) + ' ' + member.id + ')' + '\n\n' + e.message + '\n\nStamhoofd',
|
|
966
|
+
});
|
|
945
967
|
|
|
968
|
+
throw new SimpleError({
|
|
969
|
+
code: 'too_many_tries',
|
|
970
|
+
message: 'Too many securityCodes limited',
|
|
971
|
+
human: $t(`%EB`),
|
|
972
|
+
field: 'details.securityCode',
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// Entered the security code, so we can link the user to the member
|
|
977
|
+
if (STAMHOOFD.environment !== 'development') {
|
|
978
|
+
if (!member.details.securityCode || securityCode !== member.details.securityCode) {
|
|
946
979
|
throw new SimpleError({
|
|
947
|
-
code: '
|
|
948
|
-
message: 'Too many securityCodes limited',
|
|
949
|
-
human: $t(`ddb1b9de-cc00-4960-ba36-fa70429cbac1`),
|
|
980
|
+
code: 'invalid_field',
|
|
950
981
|
field: 'details.securityCode',
|
|
982
|
+
message: 'Invalid security code',
|
|
983
|
+
human: Context.i18n.$t('%2i'),
|
|
984
|
+
statusCode: 400,
|
|
951
985
|
});
|
|
952
986
|
}
|
|
987
|
+
}
|
|
953
988
|
|
|
954
|
-
|
|
955
|
-
if (STAMHOOFD.environment !== 'development') {
|
|
956
|
-
if (!member.details.securityCode || securityCode !== member.details.securityCode) {
|
|
957
|
-
throw new SimpleError({
|
|
958
|
-
code: 'invalid_field',
|
|
959
|
-
field: 'details.securityCode',
|
|
960
|
-
message: 'Invalid security code',
|
|
961
|
-
human: Context.i18n.$t('49753d6a-7ca4-4145-8024-0be05a9ab063'),
|
|
962
|
-
statusCode: 400,
|
|
963
|
-
});
|
|
964
|
-
}
|
|
965
|
-
}
|
|
989
|
+
console.log('checkSecurityCode: security code is correct - for ' + member.id);
|
|
966
990
|
|
|
967
|
-
|
|
991
|
+
// Grant temporary access to this member without needing to enter the security code again
|
|
992
|
+
await Context.auth.temporarilyGrantMemberAccess(member, PermissionLevel.Full);
|
|
968
993
|
|
|
969
|
-
|
|
970
|
-
|
|
994
|
+
const log = new AuditLog();
|
|
995
|
+
|
|
996
|
+
// a member has multiple organizations, so this is difficult to determine - for now it is only visible in the admin panel
|
|
997
|
+
log.organizationId = member.organizationId;
|
|
971
998
|
|
|
972
|
-
|
|
999
|
+
log.type = AuditLogType.MemberSecurityCodeUsed;
|
|
1000
|
+
log.source = AuditLogSource.Anonymous;
|
|
973
1001
|
|
|
974
|
-
|
|
975
|
-
log.
|
|
1002
|
+
if (Context.user) {
|
|
1003
|
+
log.userId = Context.user.id;
|
|
1004
|
+
log.source = AuditLogSource.User;
|
|
1005
|
+
}
|
|
976
1006
|
|
|
977
|
-
|
|
978
|
-
|
|
1007
|
+
log.objectId = member.id;
|
|
1008
|
+
log.replacements = new Map([
|
|
1009
|
+
['m', AuditLogReplacement.create({
|
|
1010
|
+
value: member.details.name,
|
|
1011
|
+
type: AuditLogReplacementType.Member,
|
|
1012
|
+
id: member.id,
|
|
1013
|
+
})],
|
|
1014
|
+
]);
|
|
1015
|
+
await log.save();
|
|
1016
|
+
}
|
|
979
1017
|
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
1018
|
+
static async checkCanAccessMember(member: MemberWithUsersRegistrationsAndGroups, securityCode: string | null | undefined, type: 'put' | 'patch') {
|
|
1019
|
+
// do not check security code for user mode organization (throw error if not allowed)
|
|
1020
|
+
if (STAMHOOFD.userMode === 'organization') {
|
|
1021
|
+
if ((type === 'put' && await member.isSafeToMergeDuplicateWithoutSecurityCode()) || await Context.auth.canAccessMember(member, PermissionLevel.Write)) {
|
|
1022
|
+
console.log('checkSecurityCode: allowed for ' + member.id);
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
if (type === 'patch') {
|
|
1027
|
+
throw Context.auth.memberNotFoundOrNoAccess();
|
|
983
1028
|
}
|
|
984
1029
|
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1030
|
+
throw new SimpleError({
|
|
1031
|
+
code: 'known_member_missing_rights',
|
|
1032
|
+
message: 'Creating known member without sufficient access rights',
|
|
1033
|
+
// different message for userMode organization because security codes are not available in that mode
|
|
1034
|
+
human: $t(`{member} is al gekend in ons systeem, maar jouw e-mailadres niet. Neem contact op met de vereniging.`, { member: member.details.firstName }),
|
|
1035
|
+
statusCode: 400,
|
|
1036
|
+
});
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
if ((type === 'put' && await member.isSafeToMergeDuplicateWithoutSecurityCode()) || await Context.auth.canAccessMember(member, PermissionLevel.Write)) {
|
|
1040
|
+
console.log('checkSecurityCode: without security code: allowed for ' + member.id);
|
|
1041
|
+
}
|
|
1042
|
+
else if (securityCode) {
|
|
1043
|
+
await this.checkSecurityCode(member, securityCode);
|
|
994
1044
|
}
|
|
995
1045
|
else {
|
|
996
1046
|
if (type === 'patch') {
|
|
997
1047
|
throw Context.auth.memberNotFoundOrNoAccess();
|
|
998
1048
|
}
|
|
1049
|
+
|
|
999
1050
|
throw new SimpleError({
|
|
1000
1051
|
code: 'known_member_missing_rights',
|
|
1001
1052
|
message: 'Creating known member without sufficient access rights',
|
|
1002
|
-
human: $t(
|
|
1053
|
+
human: $t(`%1BA`, { member: member.details.firstName }),
|
|
1003
1054
|
statusCode: 400,
|
|
1004
1055
|
});
|
|
1005
1056
|
}
|
|
@@ -1027,7 +1078,11 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
1027
1078
|
// Check for duplicates and prevent creating a duplicate member by a user
|
|
1028
1079
|
const duplicate = await this.findExistingMember(member);
|
|
1029
1080
|
if (duplicate) {
|
|
1030
|
-
|
|
1081
|
+
console.error('duplicate detection');
|
|
1082
|
+
console.error(member.details.parents);
|
|
1083
|
+
console.error(duplicate.details.parents);
|
|
1084
|
+
|
|
1085
|
+
await this.checkCanAccessMember(duplicate, securityCode, type);
|
|
1031
1086
|
|
|
1032
1087
|
// Merge data
|
|
1033
1088
|
// NOTE: We use mergeTwoMembers instead of mergeMultipleMembers, because we should never safe 'member' , because that one does not exist in the database
|
|
@@ -1069,11 +1124,11 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
1069
1124
|
message: 'Maximum members reached',
|
|
1070
1125
|
human: responsibility.maximumMembers === 1
|
|
1071
1126
|
? (model.groupId
|
|
1072
|
-
? $t('
|
|
1073
|
-
: $t('
|
|
1127
|
+
? $t('%C5', { responsibility: responsibility.name })
|
|
1128
|
+
: $t('%C6', { responsibility: responsibility.name }))
|
|
1074
1129
|
: (model.groupId
|
|
1075
|
-
? $t('
|
|
1076
|
-
: $t('
|
|
1130
|
+
? $t('%C7', { count: responsibility.maximumMembers.toFixed(), responsibility: responsibility.name })
|
|
1131
|
+
: $t('%C8', { count: responsibility.maximumMembers.toFixed(), responsibility: responsibility.name })),
|
|
1077
1132
|
});
|
|
1078
1133
|
}
|
|
1079
1134
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
2
|
-
import {
|
|
2
|
+
import type { StamhoofdFilter, WrapperFilter } from '@stamhoofd/structures';
|
|
3
|
+
import { FilterWrapperMarker, PermissionLevel, unwrapFilter } from '@stamhoofd/structures';
|
|
3
4
|
import { Context } from '../../../../helpers/Context.js';
|
|
4
5
|
|
|
5
6
|
export async function validateGroupFilter({ filter, permissionLevel, key }: { filter: StamhoofdFilter; permissionLevel: PermissionLevel; key: string | null }) {
|
|
@@ -32,7 +33,7 @@ export async function validateGroupFilter({ filter, permissionLevel, key }: { fi
|
|
|
32
33
|
code: 'invalid_field',
|
|
33
34
|
field: 'filter',
|
|
34
35
|
message: 'You must filter on a group of the organization you are trying to access',
|
|
35
|
-
human: $t(`
|
|
36
|
+
human: $t(`%15e`),
|
|
36
37
|
});
|
|
37
38
|
}
|
|
38
39
|
|
|
@@ -63,7 +64,7 @@ export async function validateGroupFilter({ filter, permissionLevel, key }: { fi
|
|
|
63
64
|
if (permissionLevel !== PermissionLevel.Read || !group.settings.implicitlyAllowViewRegistrations) {
|
|
64
65
|
throw Context.auth.error({
|
|
65
66
|
message: 'You do not have access to this group',
|
|
66
|
-
human: $t(
|
|
67
|
+
human: $t(`%15f`, { groupName: group.settings.name }),
|
|
67
68
|
});
|
|
68
69
|
}
|
|
69
70
|
else {
|