@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.
Files changed (362) hide show
  1. package/package.json +32 -22
  2. package/src/audit-logs/ModelLogger.ts +4 -2
  3. package/src/audit-logs/OrderLogger.ts +1 -1
  4. package/src/boot.ts +32 -14
  5. package/src/crons/balance-emails.ts +4 -2
  6. package/src/crons/clearExcelCache.test.ts +8 -8
  7. package/src/crons/update-cached-balances.ts +40 -14
  8. package/src/debug.ts +3 -2
  9. package/src/decoders/StringArrayDecoder.ts +1 -1
  10. package/src/decoders/StringNullableDecoder.ts +1 -1
  11. package/src/email-recipient-loaders/documents.ts +2 -1
  12. package/src/email-recipient-loaders/members.ts +2 -1
  13. package/src/email-recipient-loaders/orders.ts +2 -1
  14. package/src/email-recipient-loaders/payments.ts +6 -3
  15. package/src/email-recipient-loaders/receivable-balances.ts +2 -1
  16. package/src/email-recipient-loaders/registrations.ts +2 -1
  17. package/src/email-replacements/getEmailReplacementsForPayment.ts +8 -7
  18. package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +7 -6
  19. package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +3 -2
  20. package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +2 -1
  21. package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +4 -3
  22. package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +3 -2
  23. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +7 -5
  24. package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +12 -10
  25. package/src/endpoints/admin/registrations/ChargeRegistrationsEndpoint.ts +4 -3
  26. package/src/endpoints/auth/CreateAdminEndpoint.ts +8 -6
  27. package/src/endpoints/auth/CreateTokenEndpoint.ts +14 -12
  28. package/src/endpoints/auth/DeleteTokenEndpoint.ts +2 -1
  29. package/src/endpoints/auth/DeleteUserEndpoint.ts +2 -1
  30. package/src/endpoints/auth/ForgotPasswordEndpoint.ts +5 -4
  31. package/src/endpoints/auth/GetOtherUserEndpoint.ts +3 -2
  32. package/src/endpoints/auth/GetUserEndpoint.ts +3 -2
  33. package/src/endpoints/auth/OpenIDConnectAuthTokenEndpoint.ts +2 -1
  34. package/src/endpoints/auth/OpenIDConnectCallbackEndpoint.ts +4 -2
  35. package/src/endpoints/auth/OpenIDConnectStartEndpoint.ts +3 -2
  36. package/src/endpoints/auth/PatchUserEndpoint.ts +15 -12
  37. package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +3 -2
  38. package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +3 -2
  39. package/src/endpoints/auth/SignupEndpoint.ts +5 -4
  40. package/src/endpoints/auth/VerifyEmailEndpoint.ts +6 -5
  41. package/src/endpoints/frontend/FrontendEnvironmentEndpoint.ts +3 -2
  42. package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +8 -5
  43. package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +5 -3
  44. package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +8 -5
  45. package/src/endpoints/global/billing/ActivatePackagesEndpoint.ts +9 -7
  46. package/src/endpoints/global/billing/DeactivatePackageEndpoint.ts +4 -3
  47. package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +4 -2
  48. package/src/endpoints/global/email/CreateEmailEndpoint.ts +9 -7
  49. package/src/endpoints/global/email/GetAdminEmailsEndpoint.test.ts +2 -1
  50. package/src/endpoints/global/email/GetAdminEmailsEndpoint.ts +22 -19
  51. package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +6 -4
  52. package/src/endpoints/global/email/GetEmailEndpoint.ts +4 -3
  53. package/src/endpoints/global/email/GetUserEmailsEndpoint.test.ts +3 -2
  54. package/src/endpoints/global/email/GetUserEmailsEndpoint.ts +7 -4
  55. package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +7 -5
  56. package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +11 -11
  57. package/src/endpoints/global/email/PatchEmailEndpoint.ts +14 -11
  58. package/src/endpoints/global/email-recipients/GetEmailRecipientsCountEndpoint.ts +3 -2
  59. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.test.ts +2 -1
  60. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.ts +8 -5
  61. package/src/endpoints/global/email-recipients/RetryEmailRecipientEndpoint.ts +7 -5
  62. package/src/endpoints/global/email-recipients/helpers/validateEmailRecipientFilter.ts +4 -3
  63. package/src/endpoints/global/events/GetEventNotificationsCountEndpoint.ts +3 -2
  64. package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +9 -6
  65. package/src/endpoints/global/events/GetEventsEndpoint.ts +7 -4
  66. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +4 -2
  67. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +17 -15
  68. package/src/endpoints/global/events/PatchEventsEndpoint.test.ts +4 -2
  69. package/src/endpoints/global/events/PatchEventsEndpoint.ts +28 -26
  70. package/src/endpoints/global/files/ExportToExcelEndpoint.ts +8 -5
  71. package/src/endpoints/global/files/GetFileCache.ts +5 -3
  72. package/src/endpoints/global/files/UploadFile.ts +10 -4
  73. package/src/endpoints/global/files/UploadImage.ts +4 -2
  74. package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +4 -2
  75. package/src/endpoints/global/groups/GetGroupsEndpoint.ts +8 -5
  76. package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +7 -5
  77. package/src/endpoints/global/members/GetMembersCountEndpoint.ts +3 -2
  78. package/src/endpoints/global/members/GetMembersEndpoint.test.ts +4 -2
  79. package/src/endpoints/global/members/GetMembersEndpoint.ts +10 -8
  80. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +257 -6
  81. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +162 -107
  82. package/src/endpoints/global/members/helpers/validateGroupFilter.ts +4 -3
  83. package/src/endpoints/global/members/shouldCheckIfMemberIsDuplicate.ts +3 -2
  84. package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +3 -2
  85. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +3 -2
  86. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +8 -7
  87. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +5 -3
  88. package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +5 -3
  89. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +8 -5
  90. package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +4 -2
  91. package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +2 -1
  92. package/src/endpoints/global/platform/GetPlatformEndpoint.ts +3 -2
  93. package/src/endpoints/global/platform/PatchPlatformEnpoint.test.ts +3 -2
  94. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +7 -4
  95. package/src/endpoints/global/platform-memberships/GetPlatformMembershipsCountEndpoint.ts +47 -0
  96. package/src/endpoints/global/platform-memberships/GetPlatformMembershipsEndpoint.ts +206 -0
  97. package/src/endpoints/global/registration/GetRegistrationsCountEndpoint.ts +3 -2
  98. package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +2 -1
  99. package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +10 -7
  100. package/src/endpoints/global/registration/GetUserDetailedPayableBalanceEndpoint.ts +4 -2
  101. package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +4 -2
  102. package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +3 -2
  103. package/src/endpoints/global/registration/GetUserPayableBalanceEndpoint.ts +2 -1
  104. package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +5 -3
  105. package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +13 -9
  106. package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +50 -49
  107. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +25 -22
  108. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +8 -5
  109. package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +9 -7
  110. package/src/endpoints/global/sso/GetSSOEndpoint.ts +4 -2
  111. package/src/endpoints/global/sso/SetSSOEndpoint.ts +3 -2
  112. package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +4 -2
  113. package/src/endpoints/global/webshops/GetWebshopsCountEndpoint.ts +43 -0
  114. package/src/endpoints/global/webshops/GetWebshopsEndpoint.test.ts +808 -0
  115. package/src/endpoints/global/webshops/GetWebshopsEndpoint.ts +221 -0
  116. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemEndpoint.ts +4 -3
  117. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsCountEndpoint.ts +3 -2
  118. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsEndpoint.ts +6 -4
  119. package/src/endpoints/organization/dashboard/balance-items/PatchBalanceItemsEndpoint.ts +15 -13
  120. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +4 -2
  121. package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableBalanceEndpoint.ts +4 -2
  122. package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +2 -1
  123. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +3 -2
  124. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesCountEndpoint.ts +3 -2
  125. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +7 -4
  126. package/src/endpoints/organization/dashboard/documents/GetDocumentsCountEndpoint.ts +3 -2
  127. package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +7 -4
  128. package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +9 -7
  129. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.test.ts +4 -2
  130. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.ts +7 -5
  131. package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +3 -2
  132. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +36 -1
  133. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +13 -4
  134. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +4 -2
  135. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +7 -5
  136. package/src/endpoints/organization/dashboard/invoices/GetInvoicesCountEndpoint.ts +3 -2
  137. package/src/endpoints/organization/dashboard/invoices/GetInvoicesEndpoint.ts +6 -4
  138. package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +5 -3
  139. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +4 -2
  140. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +6 -3
  141. package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +4 -2
  142. package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +2 -1
  143. package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +2 -1
  144. package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +4 -2
  145. package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +3 -2
  146. package/src/endpoints/organization/dashboard/organization/GetUitpasClientIdEndpoint.ts +2 -1
  147. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +5 -3
  148. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +22 -19
  149. package/src/endpoints/organization/dashboard/organization/SearchUitpasOrganizersEndpoint.ts +5 -3
  150. package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +11 -9
  151. package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +8 -7
  152. package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +2 -1
  153. package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +3 -2
  154. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +7 -5
  155. package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +18 -16
  156. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +2 -1
  157. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesCountEndpoint.ts +3 -2
  158. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +5 -3
  159. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +2 -1
  160. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +8 -5
  161. package/src/endpoints/organization/dashboard/registration-periods/MoveRegistrationPeriods.test.ts +4 -2
  162. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.test.ts +4 -2
  163. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +32 -29
  164. package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +6 -3
  165. package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +3 -2
  166. package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +3 -2
  167. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +5 -3
  168. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +2 -1
  169. package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +5 -3
  170. package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +3 -2
  171. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +4 -3
  172. package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +4 -3
  173. package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +3 -2
  174. package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +2 -1
  175. package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.ts +6 -4
  176. package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +7 -6
  177. package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +3 -2
  178. package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +4 -2
  179. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersCountEndpoint.ts +3 -2
  180. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +7 -4
  181. package/src/endpoints/organization/dashboard/webshops/{GetWebshopTicketsCountEndpoint → GetWebshopTicketsCountEndpoint.ts} +7 -7
  182. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +9 -6
  183. package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +4 -2
  184. package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +6 -4
  185. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +13 -12
  186. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +4 -2
  187. package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +5 -3
  188. package/src/endpoints/organization/dashboard/webshops/SearchUitpasEventsEndpoint.ts +6 -4
  189. package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +2 -1
  190. package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +6 -4
  191. package/src/endpoints/organization/shared/GetDocumentHtml.ts +4 -3
  192. package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +4 -3
  193. package/src/endpoints/organization/shared/GetUitpasNumberDetailsEndpoint.ts +3 -2
  194. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +3 -2
  195. package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +4 -3
  196. package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +5 -4
  197. package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +4 -3
  198. package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +7 -5
  199. package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +4 -3
  200. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +7 -3
  201. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +11 -10
  202. package/src/endpoints/organization/webshops/RetrieveUitpasSocialTariffPriceEndpoint.ts +5 -4
  203. package/src/endpoints/system/HealthEndpoint.test.ts +44 -0
  204. package/src/endpoints/system/HealthEndpoint.ts +14 -6
  205. package/src/excel-loaders/balance-items.ts +19 -17
  206. package/src/excel-loaders/event-notifications.ts +15 -13
  207. package/src/excel-loaders/index.ts +1 -0
  208. package/src/excel-loaders/members.ts +45 -43
  209. package/src/excel-loaders/organizations.ts +26 -25
  210. package/src/excel-loaders/payments.ts +44 -42
  211. package/src/excel-loaders/platform-memberships.ts +202 -0
  212. package/src/excel-loaders/receivable-balances.ts +25 -23
  213. package/src/excel-loaders/registrations.ts +30 -28
  214. package/src/helpers/AddressValidator.test.ts +2 -1
  215. package/src/helpers/AddressValidator.ts +13 -10
  216. package/src/helpers/AdminPermissionChecker.ts +193 -95
  217. package/src/helpers/AuthenticatedStructures.ts +13 -11
  218. package/src/helpers/BuckarooHelper.ts +3 -2
  219. package/src/helpers/Context.ts +8 -6
  220. package/src/helpers/CookieHelper.ts +2 -2
  221. package/src/helpers/FileCache.ts +9 -9
  222. package/src/helpers/ForwardHandler.ts +3 -2
  223. package/src/helpers/GlobalHelper.ts +2 -0
  224. package/src/helpers/GroupBuilder.ts +2 -1
  225. package/src/helpers/GroupedThrottledQueue.test.ts +19 -19
  226. package/src/helpers/LimitedFilteredRequestHelper.ts +1 -1
  227. package/src/helpers/MemberCharger.ts +2 -1
  228. package/src/helpers/MemberUserSyncer.ts +6 -3
  229. package/src/helpers/MembershipCharger.ts +2 -2
  230. package/src/helpers/OrganizationCharger.ts +2 -1
  231. package/src/helpers/PeriodHelper.ts +2 -1
  232. package/src/helpers/SQLTranslatedString.ts +3 -2
  233. package/src/helpers/ServiceFeeHelper.ts +1 -1
  234. package/src/helpers/SetupStepUpdater.ts +6 -5
  235. package/src/helpers/StripeHelper.ts +9 -8
  236. package/src/helpers/TagHelper.test.ts +5 -5
  237. package/src/helpers/TagHelper.ts +2 -1
  238. package/src/helpers/TemporaryMemberAccess.ts +2 -1
  239. package/src/helpers/ThrottledQueue.test.ts +20 -20
  240. package/src/helpers/UitpasTokenRepository.ts +7 -7
  241. package/src/helpers/ViesHelper.ts +5 -4
  242. package/src/helpers/XlsxTransformerColumnHelper.ts +21 -19
  243. package/src/helpers/email-html-helpers.ts +13 -12
  244. package/src/helpers/fetchToAsyncIterator.ts +1 -1
  245. package/src/helpers/outstandingBalanceJoin.ts +2 -1
  246. package/src/helpers/updateMemberDetailsUitpasNumber.ts +5 -4
  247. package/src/middleware/ContextMiddleware.ts +1 -1
  248. package/src/migrate.ts +21 -4
  249. package/src/seeds/0000000003-default-email-templates.ts +1 -1
  250. package/src/seeds/0000000004-single-organization.ts +2 -1
  251. package/src/seeds/1752848561-groups-registration-periods.ts +3 -2
  252. package/src/seeds/1754560914-groups-prices.test.ts +2 -1
  253. package/src/seeds/1754560914-groups-prices.ts +2 -1
  254. package/src/seeds/1755790070-fill-email-recipient-errors.ts +6 -6
  255. package/src/seeds/1755876819-remove-duplicate-members.ts +2 -1
  256. package/src/seeds/1765896674-document-update-year.test.ts +2 -1
  257. package/src/seeds/1773754928-force-save-members.ts +15 -0
  258. package/src/services/AuditLogService.ts +3 -2
  259. package/src/services/BalanceItemPaymentService.ts +2 -2
  260. package/src/services/BalanceItemService.ts +2 -1
  261. package/src/services/BootChecksService.test.ts +33 -0
  262. package/src/services/BootChecksService.ts +21 -0
  263. package/src/services/DatabaseCollationService.test.ts +18 -0
  264. package/src/services/DatabaseCollationService.ts +81 -0
  265. package/src/services/DocumentService.ts +1 -1
  266. package/src/services/EventNotificationService.ts +5 -4
  267. package/src/services/FileSignService.ts +2 -2
  268. package/src/services/InvoiceService.ts +3 -3
  269. package/src/services/MemberNumberService.ts +6 -4
  270. package/src/services/MemberRecordStore.ts +28 -19
  271. package/src/services/PaymentReallocationService.test.ts +2 -1
  272. package/src/services/PaymentReallocationService.ts +2 -1
  273. package/src/services/PaymentService.ts +28 -26
  274. package/src/services/RegistrationService.ts +65 -3
  275. package/src/services/SSOService.ts +13 -9
  276. package/src/services/STPackageService.ts +7 -5
  277. package/src/services/StartupHealthService.ts +15 -0
  278. package/src/services/uitpas/PassholderEndpoints.ts +2 -2
  279. package/src/services/uitpas/UitpasService.ts +11 -8
  280. package/src/services/uitpas/cancelTicketSales.ts +1 -1
  281. package/src/services/uitpas/checkPermissionsFor.ts +9 -9
  282. package/src/services/uitpas/getSocialTariffForEvent.ts +4 -4
  283. package/src/services/uitpas/getSocialTariffForUitpasNumbers.ts +5 -5
  284. package/src/services/uitpas/handleUitpasResponse.ts +1 -1
  285. package/src/services/uitpas/registerTicketSales.ts +4 -4
  286. package/src/services/uitpas/searchUitpasEvents.ts +3 -3
  287. package/src/services/uitpas/searchUitpasOrganizers.ts +3 -3
  288. package/src/sql-filters/audit-logs.ts +2 -1
  289. package/src/sql-filters/balance-item-payments.ts +2 -1
  290. package/src/sql-filters/balance-items.ts +2 -1
  291. package/src/sql-filters/base-registration-filter-compilers.ts +6 -4
  292. package/src/sql-filters/document-templates.ts +2 -1
  293. package/src/sql-filters/documents.ts +2 -1
  294. package/src/sql-filters/email-recipients.ts +2 -1
  295. package/src/sql-filters/emails.ts +2 -1
  296. package/src/sql-filters/event-notifications.ts +2 -1
  297. package/src/sql-filters/events.ts +2 -1
  298. package/src/sql-filters/groups.ts +2 -1
  299. package/src/sql-filters/invoiced-balance-items.ts +2 -1
  300. package/src/sql-filters/invoices.ts +2 -1
  301. package/src/sql-filters/member-responsibility-records.ts +2 -1
  302. package/src/sql-filters/members.ts +8 -7
  303. package/src/sql-filters/orders.ts +3 -2
  304. package/src/sql-filters/organization-registration-periods.ts +2 -1
  305. package/src/sql-filters/organizations.ts +2 -1
  306. package/src/sql-filters/payments.ts +2 -1
  307. package/src/sql-filters/platform-memberships.ts +67 -0
  308. package/src/sql-filters/receivable-balances.ts +2 -1
  309. package/src/sql-filters/registration-periods.ts +2 -1
  310. package/src/sql-filters/registrations.ts +2 -1
  311. package/src/sql-filters/tickets.ts +2 -1
  312. package/src/sql-filters/users.ts +2 -1
  313. package/src/sql-filters/webshops.ts +38 -0
  314. package/src/sql-sorters/audit-logs.ts +3 -2
  315. package/src/sql-sorters/balance-items.ts +3 -2
  316. package/src/sql-sorters/document-templates.ts +3 -2
  317. package/src/sql-sorters/documents.ts +3 -2
  318. package/src/sql-sorters/email-recipients.ts +3 -2
  319. package/src/sql-sorters/emails.ts +3 -2
  320. package/src/sql-sorters/event-notifications.ts +3 -2
  321. package/src/sql-sorters/events.ts +3 -2
  322. package/src/sql-sorters/groups.ts +3 -2
  323. package/src/sql-sorters/invoices.ts +3 -2
  324. package/src/sql-sorters/members.ts +3 -2
  325. package/src/sql-sorters/orders.ts +3 -2
  326. package/src/sql-sorters/organization-registration-periods.ts +3 -2
  327. package/src/sql-sorters/organizations.ts +3 -2
  328. package/src/sql-sorters/payments.ts +3 -2
  329. package/src/sql-sorters/platform-memberships.ts +40 -0
  330. package/src/sql-sorters/receivable-balances.ts +3 -2
  331. package/src/sql-sorters/registration-periods.ts +3 -2
  332. package/src/sql-sorters/registrations.ts +3 -2
  333. package/src/sql-sorters/tickets.ts +3 -2
  334. package/src/sql-sorters/webshops.ts +40 -0
  335. package/tests/actions/patchOrganizationMember.ts +5 -4
  336. package/tests/actions/patchPaymentStatus.ts +2 -2
  337. package/tests/actions/patchUserMember.ts +6 -4
  338. package/tests/e2e/api-rate-limits.test.ts +4 -5
  339. package/tests/e2e/bundle-discounts.test.ts +3 -2
  340. package/tests/e2e/charge-members.test.ts +7 -5
  341. package/tests/e2e/documents.test.ts +3 -2
  342. package/tests/e2e/private-files.test.ts +11 -13
  343. package/tests/e2e/register.test.ts +6 -5
  344. package/tests/e2e/stock.test.ts +6 -8
  345. package/tests/e2e/tickets.test.ts +4 -2
  346. package/tests/helpers/StripeMocker.ts +3 -3
  347. package/tests/init/initAdmin.ts +4 -2
  348. package/tests/init/initBundleDiscount.ts +3 -2
  349. package/tests/init/initPayconiq.ts +1 -1
  350. package/tests/init/initPermissionRole.ts +4 -2
  351. package/tests/init/initPlatformRecordCategory.ts +1 -1
  352. package/tests/init/initStripe.ts +1 -1
  353. package/tests/vitest.global.setup.ts +26 -0
  354. package/tests/{jest.setup.ts → vitest.setup.ts} +4 -3
  355. package/tsconfig.build.json +17 -0
  356. package/tsconfig.json +10 -41
  357. package/tsconfig.test.json +17 -0
  358. package/vitest.config.js +13 -0
  359. package/eslint.config.mjs +0 -5
  360. package/jest.config.cjs +0 -27
  361. package/tests/jest.global.setup.ts +0 -33
  362. package/tests/toMatchMap.ts +0 -68
@@ -1,8 +1,12 @@
1
- import { AutoEncoderPatchType, PatchMap } from '@simonbackx/simple-encoding';
1
+ import type { AutoEncoderPatchType } from '@simonbackx/simple-encoding';
2
+ import { PatchMap } from '@simonbackx/simple-encoding';
2
3
  import { isSimpleError, isSimpleErrors, SimpleError } from '@simonbackx/simple-errors';
3
- import { BalanceItem, CachedBalance, Document, Email, EmailTemplate, Event, EventNotification, Group, Member, MemberPlatformMembership, MemberWithRegistrations, MemberWithUsers, MemberWithUsersAndRegistrations, MemberWithUsersRegistrationsAndGroups, Order, Organization, OrganizationRegistrationPeriod, Payment, Registration, User, Webshop } from '@stamhoofd/models';
4
- import { AccessRight, EmailTemplate as EmailTemplateStruct, EventPermissionChecker, FinancialSupportSettings, GroupCategory, GroupStatus, GroupType, MemberWithRegistrationsBlob, PermissionLevel, PermissionsResourceType, Platform as PlatformStruct, ReceivableBalanceType, RecordSettings, ResourcePermissions, UitpasNumberDetails, UitpasSocialTariff, UitpasSocialTariffStatus } from '@stamhoofd/structures';
4
+ import type { BalanceItem, Document, Email, EmailTemplate, MemberWithUsers, MemberWithUsersAndRegistrations, MemberWithUsersRegistrationsAndGroups, Order, OrganizationRegistrationPeriod, User } from '@stamhoofd/models';
5
+ import { CachedBalance, Event, EventNotification, Group, Member, MemberPlatformMembership, Organization, Payment, Registration, Webshop } from '@stamhoofd/models';
6
+ import type { GroupCategory, MemberWithRegistrationsBlob, Platform as PlatformStruct, RecordAnswer, RecordSettings, ResourcePermissions } from '@stamhoofd/structures';
7
+ import { AccessRight, EmailTemplate as EmailTemplateStruct, EventPermissionChecker, FinancialSupportSettings, GroupStatus, GroupType, PermissionLevel, PermissionsResourceType, ReceivableBalanceType, UitpasNumberDetails, UitpasSocialTariff, UitpasSocialTariffStatus } from '@stamhoofd/structures';
5
8
  import { Formatter } from '@stamhoofd/utility';
9
+ import type { RecordCacheEntry } from '../services/MemberRecordStore.js';
6
10
  import { MemberRecordStore } from '../services/MemberRecordStore.js';
7
11
  import { addTemporaryMemberAccess, hasTemporaryMemberAccess } from './TemporaryMemberAccess.js';
8
12
 
@@ -11,7 +15,7 @@ import { addTemporaryMemberAccess, hasTemporaryMemberAccess } from './TemporaryM
11
15
  * This helps when dependencies of permissions change, such as parent categories for groups
12
16
  */
13
17
  export class AdminPermissionChecker {
14
- organization: Organization | null;
18
+ readonly organization: Organization | null;
15
19
  user: User;
16
20
  /**
17
21
  * The member that is linked to this user = is this user
@@ -21,6 +25,7 @@ export class AdminPermissionChecker {
21
25
 
22
26
  organizationCache: Map<string, Organization | Promise<Organization | undefined>> = new Map();
23
27
  groupsCache: Map<string, Group | null | Promise<Group | null>> = new Map();
28
+ webshopsCache: Map<string, Webshop | null | Promise<Webshop | null>> = new Map();
24
29
 
25
30
  constructor(user: User, platform: PlatformStruct, organization?: Organization) {
26
31
  this.user = user;
@@ -74,7 +79,6 @@ export class AdminPermissionChecker {
74
79
  return await cache;
75
80
  }
76
81
 
77
- console.log('Get group', groupId);
78
82
  const promise = Group.select()
79
83
  .where('id', groupId)
80
84
  .first(false);
@@ -106,7 +110,6 @@ export class AdminPermissionChecker {
106
110
  }
107
111
 
108
112
  if (remainingIds.length > 0) {
109
- console.log('Get groups', remainingIds);
110
113
  const promise = Group.select()
111
114
  .where('id', remainingIds)
112
115
  .fetch();
@@ -125,6 +128,22 @@ export class AdminPermissionChecker {
125
128
  return cached;
126
129
  }
127
130
 
131
+ async getWebshop(webshopId: string): Promise<Webshop | null> {
132
+ const cache = this.webshopsCache.get(webshopId);
133
+ if (cache !== undefined) {
134
+ return await cache;
135
+ }
136
+
137
+ const promise = Webshop.select()
138
+ .where('id', webshopId)
139
+ .first(false);
140
+
141
+ this.webshopsCache.set(webshopId, promise);
142
+ const webshop = await promise;
143
+ this.webshopsCache.set(webshopId, webshop);
144
+ return webshop;
145
+ }
146
+
128
147
  cacheGroup(group: Group) {
129
148
  this.groupsCache.set(group.id, group);
130
149
  }
@@ -141,7 +160,7 @@ export class AdminPermissionChecker {
141
160
  }
142
161
 
143
162
  error(humanOrData?: string | { message: string; human?: string }): SimpleError {
144
- const human = typeof humanOrData === 'string' ? humanOrData : (humanOrData?.human ?? $t(`ab071f11-e05b-4bd9-9370-cd4f220c1b54`));
163
+ const human = typeof humanOrData === 'string' ? humanOrData : (humanOrData?.human ?? $t(`%Fg`));
145
164
  const message = typeof humanOrData === 'string' ? humanOrData : (humanOrData?.message ?? 'You do not have permissions for this action');
146
165
 
147
166
  return new SimpleError({
@@ -153,14 +172,14 @@ export class AdminPermissionChecker {
153
172
  }
154
173
 
155
174
  memberNotFoundOrNoAccess(): SimpleError {
156
- return this.notFoundOrNoAccess($t('d24814a3-aedc-4569-9ab3-f854027c4e9f'));
175
+ return this.notFoundOrNoAccess($t('%CA'));
157
176
  }
158
177
 
159
178
  notFoundOrNoAccess(message?: string): SimpleError {
160
179
  return new SimpleError({
161
180
  code: 'not_found',
162
181
  message: 'Resource not found or no access',
163
- human: message ?? $t(`8a8bb10d-9a78-48d0-8589-65d95331530e`),
182
+ human: message ?? $t(`%Fh`),
164
183
  statusCode: 404,
165
184
  });
166
185
  }
@@ -799,7 +818,7 @@ export class AdminPermissionChecker {
799
818
  }
800
819
 
801
820
  if (template.webshopId) {
802
- const webshop = await Webshop.getByID(template.webshopId);
821
+ const webshop = await this.getWebshop(template.webshopId);
803
822
  if (!webshop || !(await this.canAccessWebshop(webshop, PermissionLevel.Full))) {
804
823
  return false;
805
824
  }
@@ -808,7 +827,7 @@ export class AdminPermissionChecker {
808
827
  }
809
828
 
810
829
  if (template.groupId) {
811
- const group = await Group.getByID(template.groupId);
830
+ const group = await this.getGroup(template.groupId);
812
831
  if (!group || !(await this.canAccessGroup(group, PermissionLevel.Full))) {
813
832
  return false;
814
833
  }
@@ -1255,8 +1274,33 @@ export class AdminPermissionChecker {
1255
1274
  return false;
1256
1275
  }
1257
1276
 
1277
+ private async getSingleRecord(id: string): Promise<RecordCacheEntry | null> {
1278
+ // For userMode organization the records should not be cached
1279
+ if (STAMHOOFD.userMode === 'organization') {
1280
+ if (this.organization) {
1281
+ for (const recordCategory of this.organization.meta.recordsConfiguration.recordCategories) {
1282
+ for (const record of recordCategory.getAllRecords()) {
1283
+ if (id === record.id) {
1284
+ return {
1285
+ record,
1286
+ rootCategoryId: recordCategory.id,
1287
+ organizationId: this.organization.id
1288
+ }
1289
+ }
1290
+ }
1291
+ }
1292
+ return null;
1293
+ }
1294
+ // should never get called if no organization
1295
+ console.error('getRecord called without an organization');
1296
+ return null;
1297
+ }
1298
+
1299
+ return MemberRecordStore.getRecord(id);
1300
+ }
1301
+
1258
1302
  async canFilterMembersOnRecordId(recordId: string): Promise<{ canAccess: false; record: RecordSettings | null } | { canAccess: true; record: RecordSettings }> {
1259
- const record = await MemberRecordStore.getRecord(recordId);
1303
+ const record = await this.getSingleRecord(recordId);
1260
1304
  if (!record) {
1261
1305
  return {
1262
1306
  canAccess: false,
@@ -1322,87 +1366,142 @@ export class AdminPermissionChecker {
1322
1366
  };
1323
1367
  }
1324
1368
 
1325
- async checkRecordAccess(member: MemberWithUsersRegistrationsAndGroups, recordId: string, level: PermissionLevel = PermissionLevel.Read): Promise<{ canAccess: false; record: RecordSettings | null } | { canAccess: true; record: RecordSettings }> {
1326
- const record = await MemberRecordStore.getRecord(recordId);
1327
- if (!record) {
1328
- return {
1329
- canAccess: false,
1330
- record: null,
1331
- };
1369
+ private async loopRecordAnswerSettingsAccess<T extends RecordAnswer | AutoEncoderPatchType<RecordAnswer>>({member, level, recordAnswers, callback }:
1370
+ {
1371
+ member: MemberWithUsersRegistrationsAndGroups,
1372
+ level: PermissionLevel,
1373
+ recordAnswers: PatchMap<string, T | null | undefined> | Map<string, T>
1374
+ callback: (result: { canAccess: false; record: RecordSettings | null } | { canAccess: true; record: RecordSettings }, entry: [keys: string, value: T | null | undefined]) => void
1375
+ }): Promise<void>
1376
+ {
1377
+ if (STAMHOOFD.userMode !== 'platform') {
1378
+ let organization = this.organization;
1379
+
1380
+ if (!organization) {
1381
+ // normally this should not happen
1382
+ console.error('loopRecordAnswerSettingsAccess called without an organization set');
1383
+ let organizationId = member.organizationId;
1384
+
1385
+ if (!organizationId) {
1386
+ if (member.registrations.length === 0) {
1387
+ // no access to any records (theoretically a global admin should have access, but normally this case should not happen)
1388
+ for (const entry of recordAnswers.entries()) {
1389
+ callback({canAccess: false, record: null}, entry);
1390
+ }
1391
+ return;
1392
+ }
1393
+
1394
+ // in userMode organization a member can only be linked to 1 organization
1395
+ organizationId = member.registrations[0].organizationId;
1396
+ }
1397
+
1398
+ organization = await this.getOrganization(organizationId);
1399
+ }
1400
+
1401
+ const organizationId = organization.id;
1402
+ const map = new Map<string, RecordCacheEntry>()
1403
+
1404
+ // create map
1405
+ for (const category of organization.meta.recordsConfiguration.recordCategories) {
1406
+ const rootCategoryId = category.id;
1407
+
1408
+ for (const record of category.getAllRecords()) {
1409
+ map.set(record.id, {
1410
+ record,
1411
+ organizationId,
1412
+ rootCategoryId,
1413
+ });
1414
+ }
1415
+ }
1416
+
1417
+ for (const entry of recordAnswers.entries()) {
1418
+ const key = entry[0];
1419
+ const cachedRecordEntry = map.get(key);
1420
+ if (cachedRecordEntry) {
1421
+ const canAccess = await this.checkRecordAccess({
1422
+ member,
1423
+ record: cachedRecordEntry.record,
1424
+ organizationId: cachedRecordEntry.organizationId,
1425
+ rootCategoryId: cachedRecordEntry.rootCategoryId,
1426
+ level
1427
+ });
1428
+ callback({canAccess, record: cachedRecordEntry.record}, entry);
1429
+ } else {
1430
+ callback({canAccess: false, record: null}, entry);
1431
+ }
1432
+ }
1433
+
1434
+ return;
1332
1435
  }
1333
1436
 
1334
- if (!this.checkScope(record.organizationId)) {
1335
- return {
1336
- canAccess: false,
1337
- record: record.record,
1338
- };
1437
+ // userMode platform
1438
+ for (const entry of recordAnswers.entries()) {
1439
+ const key = entry[0];
1440
+ const cachedRecordEntry = await MemberRecordStore.getRecord(key);
1441
+ if (cachedRecordEntry) {
1442
+ const canAccess = await this.checkRecordAccess({
1443
+ member,
1444
+ record: cachedRecordEntry.record,
1445
+ organizationId: cachedRecordEntry.organizationId,
1446
+ rootCategoryId: cachedRecordEntry.rootCategoryId,
1447
+ level
1448
+ });
1449
+ callback({canAccess, record: cachedRecordEntry.record}, entry);
1450
+ } else {
1451
+ callback({canAccess: false, record: null}, entry);
1452
+ }
1453
+ }
1454
+ }
1455
+
1456
+ private async checkRecordAccess({member, level, record, organizationId, rootCategoryId}: {member: MemberWithUsersRegistrationsAndGroups, record: RecordSettings, organizationId: string | null, rootCategoryId: string, level: PermissionLevel}): Promise<boolean> {
1457
+ if (!this.checkScope(organizationId)) {
1458
+ return false
1339
1459
  }
1340
1460
 
1341
1461
  const isUserManager = this.isUserManager(member);
1342
1462
  if (isUserManager) {
1343
- if (record.record.checkPermissionForUserManager(level)) {
1344
- return {
1345
- canAccess: true,
1346
- record: record.record,
1347
- };
1463
+ if (record.checkPermissionForUserManager(level)) {
1464
+ return true;
1348
1465
  }
1349
1466
  }
1350
1467
 
1351
1468
  if (!this.user.permissions) {
1352
- return {
1353
- canAccess: false,
1354
- record: record.record,
1355
- };
1469
+ return false;
1356
1470
  }
1357
1471
 
1358
- if (record.organizationId) {
1359
- const organizationPermissions = await this.getOrganizationPermissions(record.organizationId);
1360
- if (organizationPermissions && organizationPermissions.hasResourceAccess(PermissionsResourceType.RecordCategories, record.rootCategoryId, level)) {
1361
- return {
1362
- canAccess: true,
1363
- record: record.record,
1364
- };
1472
+ if (organizationId) {
1473
+ const organizationPermissions = await this.getOrganizationPermissions(organizationId);
1474
+ if (organizationPermissions && organizationPermissions.hasResourceAccess(PermissionsResourceType.RecordCategories, rootCategoryId, level)) {
1475
+ return true;
1365
1476
  }
1366
1477
  }
1367
1478
  else {
1368
1479
  // Also check current scoped organization
1369
1480
  if (this.organization) {
1370
1481
  const organizationPermissions = await this.getOrganizationPermissions(this.organization.id);
1371
- if (organizationPermissions && organizationPermissions.hasResourceAccess(PermissionsResourceType.RecordCategories, record.rootCategoryId, level)) {
1372
- return {
1373
- canAccess: true,
1374
- record: record.record,
1375
- };
1482
+ if (organizationPermissions && organizationPermissions.hasResourceAccess(PermissionsResourceType.RecordCategories, rootCategoryId, level)) {
1483
+ return true;
1376
1484
  }
1377
1485
  }
1378
1486
  }
1379
1487
 
1380
1488
  // 2. Check platform permissions
1381
- if (this.platformPermissions?.hasResourceAccess(PermissionsResourceType.RecordCategories, record.rootCategoryId, level)) {
1382
- return {
1383
- canAccess: true,
1384
- record: record.record,
1385
- };
1489
+ if (this.platformPermissions?.hasResourceAccess(PermissionsResourceType.RecordCategories, rootCategoryId, level)) {
1490
+ return true;
1386
1491
  }
1387
1492
 
1388
1493
  // All member access, means also having access to record categories of non-registered members
1389
1494
  if (this.canAccessAllPlatformMembers(level)) { // needs to be full to also inherit record category access
1390
- return {
1391
- canAccess: true,
1392
- record: record.record,
1393
- };
1495
+ return true;
1394
1496
  }
1395
1497
 
1396
1498
  if (hasTemporaryMemberAccess(this.user.id, member.id, PermissionLevel.Full)) {
1397
1499
  // You created this member, so temporary can read all records in order to set the member up correctly
1398
- return {
1399
- canAccess: true,
1400
- record: record.record,
1401
- };
1500
+ return true;
1402
1501
  }
1403
1502
 
1404
1503
  // It is possible that this is a platform admin (or an admin that has access to multiple organizations), and inherits automatic permissions for tags. So'll need to loop all the organizations where this member has an active registration for
1405
- if (!record.organizationId && !this.organization) {
1504
+ if (!organizationId && !this.organization) {
1406
1505
  const checkedOrganizations = new Map<string, boolean>();
1407
1506
  for (const registration of member.registrations) {
1408
1507
  const permissions = checkedOrganizations.get(registration.organizationId);
@@ -1410,22 +1509,16 @@ export class AdminPermissionChecker {
1410
1509
  // Checking the organization permissions is faster (and less data lookups required), so we do that first before doing the more expensive registration access check
1411
1510
  if (permissions !== undefined) {
1412
1511
  if (permissions === true && await this.canAccessRegistration(registration, level)) {
1413
- return {
1414
- canAccess: true,
1415
- record: record.record,
1416
- };
1512
+ return true;
1417
1513
  }
1418
1514
  continue;
1419
1515
  }
1420
1516
 
1421
1517
  const organizationPermissions = await this.getOrganizationPermissions(registration.organizationId);
1422
- if (organizationPermissions && organizationPermissions.hasResourceAccess(PermissionsResourceType.RecordCategories, record.rootCategoryId, level)) {
1518
+ if (organizationPermissions && organizationPermissions.hasResourceAccess(PermissionsResourceType.RecordCategories, rootCategoryId, level)) {
1423
1519
  checkedOrganizations.set(registration.organizationId, true);
1424
1520
  if (await this.canAccessRegistration(registration, level)) {
1425
- return {
1426
- canAccess: true,
1427
- record: record.record,
1428
- };
1521
+ return true;
1429
1522
  }
1430
1523
  }
1431
1524
  else {
@@ -1434,10 +1527,7 @@ export class AdminPermissionChecker {
1434
1527
  }
1435
1528
  }
1436
1529
 
1437
- return {
1438
- canAccess: false,
1439
- record: record.record,
1440
- };
1530
+ return false;
1441
1531
  }
1442
1532
 
1443
1533
  /**
@@ -1458,18 +1548,22 @@ export class AdminPermissionChecker {
1458
1548
  async filterMemberData(member: MemberWithUsersRegistrationsAndGroups, data: MemberWithRegistrationsBlob, options?: { forAdminCartCalculation?: boolean }): Promise<MemberWithRegistrationsBlob> {
1459
1549
  const cloned = data.clone();
1460
1550
 
1461
- for (const [key, value] of cloned.details.recordAnswers.entries()) {
1462
- const { canAccess, record } = await this.checkRecordAccess(member, key, PermissionLevel.Read);
1463
- if (!canAccess) {
1464
- cloned.details.recordAnswers.delete(key);
1465
- }
1466
- else {
1467
- if (value) {
1468
- // Force update
1469
- value.settings = record;
1551
+ await this.loopRecordAnswerSettingsAccess({
1552
+ member,
1553
+ level: PermissionLevel.Read,
1554
+ recordAnswers: cloned.details.recordAnswers,
1555
+ callback: ({ canAccess, record }, [key, value]) => {
1556
+ if (!canAccess) {
1557
+ cloned.details.recordAnswers.delete(key);
1558
+ }
1559
+ else {
1560
+ if (value) {
1561
+ // Force update
1562
+ value.settings = record;
1563
+ }
1470
1564
  }
1471
1565
  }
1472
- }
1566
+ });
1473
1567
 
1474
1568
  const isUserManager = this.isUserManager(member);
1475
1569
  if (isUserManager) {
@@ -1597,21 +1691,25 @@ export class AdminPermissionChecker {
1597
1691
  });
1598
1692
  }
1599
1693
 
1600
- for (const [key, value] of data.details.recordAnswers.entries()) {
1601
- const { canAccess, record } = await this.checkRecordAccess(member, key, PermissionLevel.Write);
1602
- if (!canAccess) {
1603
- throw new SimpleError({
1604
- code: 'permission_denied',
1605
- message: $t('0823202f-8c46-445b-9b49-f171e1ae85ac', { name: record?.name ?? 'deze vraag' }),
1606
- statusCode: 400,
1607
- });
1608
- }
1694
+ await this.loopRecordAnswerSettingsAccess({
1695
+ member,
1696
+ level: PermissionLevel.Write,
1697
+ recordAnswers: data.details.recordAnswers,
1698
+ callback: ({canAccess, record}, [_key, value]) => {
1699
+ if (!canAccess) {
1700
+ throw new SimpleError({
1701
+ code: 'permission_denied',
1702
+ message: $t('%Ff', { name: record?.name ?? 'deze vraag' }),
1703
+ statusCode: 400,
1704
+ });
1705
+ }
1609
1706
 
1610
- // Force set the value settings
1611
- if (value) {
1612
- value.settings = record;
1707
+ // Force set the value settings
1708
+ if (value) {
1709
+ value.settings = record;
1710
+ }
1613
1711
  }
1614
- }
1712
+ })
1615
1713
  }
1616
1714
 
1617
1715
  const isUserManager = this.isUserManager(member);
@@ -1,6 +1,8 @@
1
1
  import { SimpleError } from '@simonbackx/simple-errors';
2
- import { AuditLog, BalanceItem, CachedBalance, Document, Event, EventNotification, Group, Invoice, Member, MemberPlatformMembership, MemberResponsibilityRecord, MemberWithUsersRegistrationsAndGroups, Order, Organization, OrganizationRegistrationPeriod, Payment, Registration, RegistrationPeriod, Ticket, User, Webshop } from '@stamhoofd/models';
3
- import { AuditLogReplacement, AuditLogReplacementType, AuditLog as AuditLogStruct, DetailedReceivableBalance, Document as DocumentStruct, EventNotification as EventNotificationStruct, Event as EventStruct, GenericBalance, Group as GroupStruct, GroupType, InvoicedBalanceItem, InvoiceStruct, MemberPlatformMembership as MemberPlatformMembershipStruct, MembersBlob, MemberWithRegistrationsBlob, NamedObject, OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct, Organization as OrganizationStruct, PaymentCustomer, PaymentGeneral, PermissionLevel, Platform, PrivateOrder, PrivateWebshop, ReceivableBalanceObject, ReceivableBalanceObjectContact, ReceivableBalance as ReceivableBalanceStruct, ReceivableBalanceType, RegistrationsBlob, RegistrationWithMemberBlob, TicketPrivate, UserWithMembers, WebshopPreview, Webshop as WebshopStruct, BalanceItem as BalanceItemStruct } from '@stamhoofd/structures';
2
+ import type { AuditLog, Document, EventNotification, MemberWithUsersRegistrationsAndGroups, Order, Ticket} from '@stamhoofd/models';
3
+ import { BalanceItem, CachedBalance, Event, Group, Invoice, Member, MemberPlatformMembership, MemberResponsibilityRecord, Organization, OrganizationRegistrationPeriod, Payment, Registration, RegistrationPeriod, User, Webshop } from '@stamhoofd/models';
4
+ import type { PaymentGeneral} from '@stamhoofd/structures';
5
+ import { AuditLogReplacement, AuditLogReplacementType, AuditLog as AuditLogStruct, DetailedReceivableBalance, Document as DocumentStruct, EventNotification as EventNotificationStruct, Event as EventStruct, GenericBalance, Group as GroupStruct, GroupType, InvoicedBalanceItem, InvoiceStruct, MemberPlatformMembership as MemberPlatformMembershipStruct, MembersBlob, MemberWithRegistrationsBlob, NamedObject, OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct, Organization as OrganizationStruct, PaymentCustomer, PermissionLevel, Platform, PrivateOrder, PrivateWebshop, ReceivableBalanceObject, ReceivableBalanceObjectContact, ReceivableBalance as ReceivableBalanceStruct, ReceivableBalanceType, RegistrationsBlob, RegistrationWithMemberBlob, TicketPrivate, UserWithMembers, WebshopPreview, Webshop as WebshopStruct, BalanceItem as BalanceItemStruct } from '@stamhoofd/structures';
4
6
  import { Sorter } from '@stamhoofd/utility';
5
7
 
6
8
  import { SQL } from '@stamhoofd/sql';
@@ -36,7 +38,7 @@ export class AuthenticatedStructures {
36
38
  throw new SimpleError({
37
39
  code: 'permission_denied',
38
40
  message: 'Permission denied',
39
- human: $t(`9f5ee239-d01b-4ee1-961b-2e3224489781`),
41
+ human: $t(`%FW`),
40
42
  });
41
43
  }
42
44
  }
@@ -803,7 +805,7 @@ export class AuthenticatedStructures {
803
805
  throw new SimpleError({
804
806
  code: 'organization_not_found',
805
807
  message: 'Organization not found',
806
- human: $t(`b6f89130-e727-4f85-b3a9-18b97c4f6ab6`),
808
+ human: $t(`%we`),
807
809
  });
808
810
  }
809
811
 
@@ -843,7 +845,7 @@ export class AuthenticatedStructures {
843
845
  throw new SimpleError({
844
846
  code: 'permission_denied',
845
847
  message: 'Permission denied',
846
- human: $t(`78cd49fe-260c-4fdc-ad83-e605734c684f`),
848
+ human: $t(`%wf`),
847
849
  });
848
850
  }
849
851
  }
@@ -878,7 +880,7 @@ export class AuthenticatedStructures {
878
880
  throw new SimpleError({
879
881
  code: 'permission_denied',
880
882
  message: 'Permission denied',
881
- human: $t(`792f644d-f3eb-4772-88b9-edb88f0b6773`),
883
+ human: $t(`%wg`),
882
884
  });
883
885
  }
884
886
  }
@@ -911,7 +913,7 @@ export class AuthenticatedStructures {
911
913
  throw new SimpleError({
912
914
  code: 'permission_denied',
913
915
  message: 'Permission denied',
914
- human: $t(`b5079e56-2480-4ce6-a3a2-3f244540fa0e`),
916
+ human: $t(`%wh`),
915
917
  });
916
918
  }
917
919
  }
@@ -1029,7 +1031,7 @@ export class AuthenticatedStructures {
1029
1031
  for (const balance of balances) {
1030
1032
  let object = ReceivableBalanceObject.create({
1031
1033
  id: balance.objectId,
1032
- name: $t('6c3e777c-7cd6-4566-9540-8a829c26212f'),
1034
+ name: $t('%Gr'),
1033
1035
  });
1034
1036
 
1035
1037
  if (balance.objectType === ReceivableBalanceType.organization) {
@@ -1165,13 +1167,13 @@ export class AuthenticatedStructures {
1165
1167
  if (user.permissions?.platform !== null) {
1166
1168
  userStruct = NamedObject.create({
1167
1169
  id: '',
1168
- name: $t(`da016ffd-45c5-41cc-90e4-d4e81105ebe0`) + ' ' + Platform.shared.config.name,
1170
+ name: $t(`%wi`) + ' ' + Platform.shared.config.name,
1169
1171
  });
1170
1172
  }
1171
1173
  else {
1172
1174
  userStruct = NamedObject.create({
1173
1175
  id: '',
1174
- name: $t(`bd1e59c8-3d4c-4097-ab35-0ce7b20d0e50`),
1176
+ name: $t(`%Gr`),
1175
1177
  });
1176
1178
  }
1177
1179
  }
@@ -1190,7 +1192,7 @@ export class AuthenticatedStructures {
1190
1192
  const org = organizations.find(o => o.id === log.organizationId);
1191
1193
  replacements.set('org', AuditLogReplacement.create({
1192
1194
  id: log.organizationId,
1193
- value: org?.name ?? $t(`cc098cc0-d849-4808-b53a-0b99755b3f99`),
1195
+ value: org?.name ?? $t(`%wj`),
1194
1196
  type: AuditLogReplacementType.Organization,
1195
1197
  }));
1196
1198
  }
@@ -1,5 +1,6 @@
1
1
  import { SimpleError } from '@simonbackx/simple-errors';
2
- import { BuckarooPayment, Payment } from '@stamhoofd/models';
2
+ import type { Payment } from '@stamhoofd/models';
3
+ import { BuckarooPayment } from '@stamhoofd/models';
3
4
  import { PaymentMethod, PaymentStatus } from '@stamhoofd/structures';
4
5
  import axios from 'axios';
5
6
  import crypto from 'crypto';
@@ -210,7 +211,7 @@ export class BuckarooHelper {
210
211
  throw new SimpleError({
211
212
  code: 'buckaroo_error',
212
213
  message: 'Failed to create payment',
213
- human: $t(`08f883bb-cdc7-4d50-a35e-e2fbeaf6f284`),
214
+ human: $t(`%wk`),
214
215
  });
215
216
  }
216
217
  }
@@ -1,10 +1,12 @@
1
1
  import { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
2
2
  import { isSimpleError, SimpleError } from '@simonbackx/simple-errors';
3
3
  import { I18n } from '@stamhoofd/backend-i18n';
4
- import { Organization, Platform, RateLimiter, Token, User } from '@stamhoofd/models';
4
+ import type { User } from '@stamhoofd/models';
5
+ import { Organization, Platform, RateLimiter, Token } from '@stamhoofd/models';
5
6
  import { AsyncLocalStorage } from 'async_hooks';
6
7
 
7
- import { AutoEncoder, Decoder, field, StringDecoder } from '@simonbackx/simple-encoding';
8
+ import type { Decoder} from '@simonbackx/simple-encoding';
9
+ import { AutoEncoder, field, StringDecoder } from '@simonbackx/simple-encoding';
8
10
  import { ApiUserRateLimits } from '@stamhoofd/structures';
9
11
  import { AdminPermissionChecker } from './AdminPermissionChecker.js';
10
12
 
@@ -259,7 +261,7 @@ export class ContextInstance {
259
261
  throw new SimpleError({
260
262
  code: 'invalid_access_token',
261
263
  message: 'The access token is invalid',
262
- human: $t(`739f88f4-e87d-4872-aef3-8124a59b160c`),
264
+ human: $t(`%Fi`),
263
265
  statusCode: 401,
264
266
  });
265
267
  }
@@ -273,7 +275,7 @@ export class ContextInstance {
273
275
  throw new SimpleError({
274
276
  code: 'expired_access_token',
275
277
  message: 'The access token is expired',
276
- human: $t(`739f88f4-e87d-4872-aef3-8124a59b160c`),
278
+ human: $t(`%Fi`),
277
279
  statusCode: 401,
278
280
  });
279
281
  }
@@ -287,7 +289,7 @@ export class ContextInstance {
287
289
  throw new SimpleError({
288
290
  code: 'not_activated',
289
291
  message: 'This user is not yet activated',
290
- human: $t(`28cf3aaf-d6b3-4325-8b01-4c0e754034ed`),
292
+ human: $t(`%Fj`),
291
293
  statusCode: 401,
292
294
  });
293
295
  }
@@ -315,7 +317,7 @@ export class ContextInstance {
315
317
  throw new SimpleError({
316
318
  code: 'archived',
317
319
  message: 'Platform access is required to view inactive organizations',
318
- human: $t('3e8dba08-a505-41ec-96c1-b2b5c1c17852'),
320
+ human: $t('%1GR'),
319
321
  statusCode: 401,
320
322
  });
321
323
  }
@@ -1,6 +1,6 @@
1
- import { Response } from '@simonbackx/simple-endpoints';
1
+ import type { Response } from '@simonbackx/simple-endpoints';
2
2
  import cookie from 'cookie';
3
- import http from 'http';
3
+ import type http from 'http';
4
4
 
5
5
  export type ObjectWithHeaders = {
6
6
  headers: http.IncomingHttpHeaders;