@stamhoofd/backend 2.39.1 → 2.40.1

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 (198) hide show
  1. package/eslint.config.mjs +5 -0
  2. package/index.ts +81 -74
  3. package/jest.config.cjs +10 -0
  4. package/migrations.ts +16 -14
  5. package/package.json +11 -11
  6. package/src/crons/clear-excel-cache.test.ts +48 -50
  7. package/src/crons/clear-excel-cache.ts +18 -18
  8. package/src/crons/setup-steps.ts +2 -2
  9. package/src/crons.ts +325 -306
  10. package/src/decoders/StringArrayDecoder.ts +7 -7
  11. package/src/decoders/StringNullableDecoder.ts +1 -2
  12. package/src/email-recipient-loaders/members.ts +22 -22
  13. package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +8 -9
  14. package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +39 -40
  15. package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +8 -8
  16. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +44 -45
  17. package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +58 -57
  18. package/src/endpoints/auth/CreateAdminEndpoint.ts +48 -45
  19. package/src/endpoints/auth/CreateTokenEndpoint.test.ts +31 -31
  20. package/src/endpoints/auth/CreateTokenEndpoint.ts +146 -147
  21. package/src/endpoints/auth/DeleteTokenEndpoint.ts +7 -7
  22. package/src/endpoints/auth/DeleteUserEndpoint.ts +15 -15
  23. package/src/endpoints/auth/ForgotPasswordEndpoint.ts +17 -18
  24. package/src/endpoints/auth/GetOtherUserEndpoint.ts +9 -10
  25. package/src/endpoints/auth/GetUserEndpoint.test.ts +32 -35
  26. package/src/endpoints/auth/GetUserEndpoint.ts +5 -6
  27. package/src/endpoints/auth/PatchApiUserEndpoint.ts +35 -33
  28. package/src/endpoints/auth/PatchUserEndpoint.ts +55 -52
  29. package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +9 -9
  30. package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +8 -8
  31. package/src/endpoints/auth/SignupEndpoint.ts +37 -36
  32. package/src/endpoints/auth/VerifyEmailEndpoint.ts +29 -28
  33. package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +33 -33
  34. package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +7 -7
  35. package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +37 -37
  36. package/src/endpoints/global/email/CreateEmailEndpoint.ts +30 -30
  37. package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +13 -13
  38. package/src/endpoints/global/email/GetEmailEndpoint.ts +13 -13
  39. package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +16 -16
  40. package/src/endpoints/global/email/PatchEmailEndpoint.ts +25 -25
  41. package/src/endpoints/global/events/GetEventsEndpoint.ts +43 -44
  42. package/src/endpoints/global/events/PatchEventsEndpoint.ts +127 -172
  43. package/src/endpoints/global/files/ExportToExcelEndpoint.ts +49 -50
  44. package/src/endpoints/global/files/GetFileCache.ts +13 -13
  45. package/src/endpoints/global/files/UploadFile.ts +51 -54
  46. package/src/endpoints/global/files/UploadImage.ts +53 -53
  47. package/src/endpoints/global/groups/GetGroupsEndpoint.ts +25 -25
  48. package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +24 -23
  49. package/src/endpoints/global/members/GetMembersCountEndpoint.ts +8 -8
  50. package/src/endpoints/global/members/GetMembersEndpoint.ts +105 -102
  51. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +240 -239
  52. package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +12 -14
  53. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +32 -33
  54. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +48 -57
  55. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.test.ts +21 -22
  56. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +28 -28
  57. package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +18 -18
  58. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +20 -20
  59. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +17 -17
  60. package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +81 -75
  61. package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +14 -14
  62. package/src/endpoints/global/platform/GetPlatformEnpoint.ts +11 -11
  63. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +71 -68
  64. package/src/endpoints/global/registration/GetPaymentRegistrations.ts +27 -27
  65. package/src/endpoints/global/registration/GetUserBillingStatusEndpoint.ts +30 -30
  66. package/src/endpoints/global/registration/GetUserDetailedBillingStatusEndpoint.ts +34 -34
  67. package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +26 -26
  68. package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +12 -12
  69. package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +90 -90
  70. package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +118 -121
  71. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +362 -350
  72. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +8 -9
  73. package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +21 -21
  74. package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +65 -65
  75. package/src/endpoints/organization/dashboard/billing/GetOrganizationBillingStatusEndpoint.ts +9 -9
  76. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedBillingStatusEndpoint.ts +14 -14
  77. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +17 -17
  78. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +21 -21
  79. package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +15 -15
  80. package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +52 -52
  81. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplateEndpoint.ts +37 -37
  82. package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +14 -14
  83. package/src/endpoints/organization/dashboard/email/EmailEndpoint.ts +113 -112
  84. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +29 -29
  85. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +48 -47
  86. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +22 -21
  87. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +13 -14
  88. package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +12 -13
  89. package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +24 -24
  90. package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +10 -12
  91. package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +14 -14
  92. package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +13 -13
  93. package/src/endpoints/organization/dashboard/organization/GetOrganizationSSOEndpoint.ts +12 -12
  94. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +120 -124
  95. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +172 -173
  96. package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +88 -89
  97. package/src/endpoints/organization/dashboard/organization/SetOrganizationSSOEndpoint.ts +12 -12
  98. package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +17 -17
  99. package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +8 -8
  100. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +66 -67
  101. package/src/endpoints/organization/dashboard/payments/PatchBalanceItemsEndpoint.ts +47 -47
  102. package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +93 -91
  103. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +16 -17
  104. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +170 -167
  105. package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +25 -24
  106. package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +22 -23
  107. package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +22 -22
  108. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +17 -18
  109. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +8 -9
  110. package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +17 -18
  111. package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +14 -15
  112. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +19 -19
  113. package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +19 -19
  114. package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +14 -14
  115. package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +12 -12
  116. package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +103 -100
  117. package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +11 -12
  118. package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +15 -15
  119. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +14 -14
  120. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +14 -14
  121. package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +23 -23
  122. package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +54 -52
  123. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +84 -81
  124. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +120 -111
  125. package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +24 -24
  126. package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +18 -18
  127. package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +141 -130
  128. package/src/endpoints/organization/shared/GetDocumentHtml.ts +25 -25
  129. package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +18 -18
  130. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.test.ts +36 -37
  131. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +9 -9
  132. package/src/endpoints/organization/shared/auth/OpenIDConnectCallbackEndpoint.ts +11 -11
  133. package/src/endpoints/organization/shared/auth/OpenIDConnectStartEndpoint.ts +28 -27
  134. package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +20 -20
  135. package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +22 -22
  136. package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +14 -14
  137. package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +57 -56
  138. package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +65 -66
  139. package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +18 -17
  140. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +124 -128
  141. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +154 -145
  142. package/src/excel-loaders/members.ts +275 -273
  143. package/src/excel-loaders/payments.ts +155 -156
  144. package/src/helpers/AddressValidator.test.ts +32 -32
  145. package/src/helpers/AddressValidator.ts +128 -122
  146. package/src/helpers/AdminPermissionChecker.ts +339 -236
  147. package/src/helpers/AuthenticatedStructures.ts +233 -134
  148. package/src/helpers/BuckarooHelper.ts +134 -134
  149. package/src/helpers/CheckSettlements.ts +94 -88
  150. package/src/helpers/Context.ts +87 -86
  151. package/src/helpers/CookieHelper.ts +23 -22
  152. package/src/helpers/EmailResumer.ts +10 -10
  153. package/src/helpers/FileCache.ts +62 -62
  154. package/src/helpers/ForwardHandler.test.ts +122 -124
  155. package/src/helpers/ForwardHandler.ts +76 -70
  156. package/src/helpers/MemberUserSyncer.ts +101 -96
  157. package/src/helpers/MembershipCharger.ts +69 -69
  158. package/src/helpers/MembershipHelper.ts +11 -12
  159. package/src/helpers/OpenIDConnectHelper.ts +85 -82
  160. package/src/helpers/PeriodHelper.ts +65 -70
  161. package/src/helpers/StripeHelper.ts +146 -137
  162. package/src/helpers/StripePayoutChecker.ts +51 -52
  163. package/src/helpers/ViesHelper.ts +46 -44
  164. package/src/helpers/fetchToAsyncIterator.ts +14 -14
  165. package/src/helpers/xlsxAddressTransformerColumnFactory.ts +58 -60
  166. package/src/middleware/ContextMiddleware.ts +5 -5
  167. package/src/migrations/1646578856-validate-addresses.ts +6 -9
  168. package/src/seeds/0000000000-example.ts +3 -5
  169. package/src/seeds/1715028563-user-permissions.ts +16 -18
  170. package/src/seeds/1722256498-group-update-occupancy.ts +12 -12
  171. package/src/seeds/1722344162-sync-member-users.ts +14 -15
  172. package/src/seeds/1722344162-update-membership.ts +6 -6
  173. package/src/seeds/1726055544-balance-item-paid.ts +4 -4
  174. package/src/seeds/1726055545-balance-item-pending.ts +4 -4
  175. package/src/seeds/1726494419-update-cached-outstanding-balance.ts +16 -16
  176. package/src/seeds/1726494420-update-cached-outstanding-balance-from-items.ts +12 -12
  177. package/src/seeds/1726572303-schedule-stock-updates.ts +12 -12
  178. package/src/seeds/1726847064-setup-steps.ts +16 -0
  179. package/src/sql-filters/balance-item-payments.ts +7 -7
  180. package/src/sql-filters/events.ts +14 -14
  181. package/src/sql-filters/members.ts +96 -96
  182. package/src/sql-filters/organizations.ts +139 -75
  183. package/src/sql-filters/payments.ts +28 -28
  184. package/src/sql-filters/registrations.ts +14 -14
  185. package/src/sql-sorters/events.ts +25 -25
  186. package/src/sql-sorters/members.ts +26 -26
  187. package/src/sql-sorters/organizations.ts +36 -36
  188. package/src/sql-sorters/payments.ts +26 -26
  189. package/tests/e2e/stock.test.ts +616 -621
  190. package/tests/e2e/tickets.test.ts +255 -260
  191. package/tests/helpers/StripeMocker.ts +177 -179
  192. package/tests/helpers/TestServer.ts +9 -9
  193. package/tests/jest.global.setup.ts +14 -13
  194. package/tests/jest.setup.ts +33 -32
  195. package/.eslintrc.js +0 -61
  196. package/jest.config.js +0 -11
  197. package/src/helpers/SetupStepsUpdater.ts +0 -359
  198. package/src/seeds/1724076679-setup-steps.ts +0 -16
@@ -1,24 +1,24 @@
1
- import { DecodedRequest, Endpoint, Request, Response } from "@simonbackx/simple-endpoints";
2
- import { OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct, SetupStepType } from "@stamhoofd/structures";
1
+ import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
2
+ import { OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct, SetupStepType } from '@stamhoofd/structures';
3
3
 
4
- import { AutoEncoder, BooleanDecoder, Decoder, EnumDecoder, field } from "@simonbackx/simple-encoding";
5
- import { SimpleError } from "@simonbackx/simple-errors";
6
- import { OrganizationRegistrationPeriod } from "@stamhoofd/models";
7
- import { AuthenticatedStructures } from "../../../../helpers/AuthenticatedStructures";
8
- import { Context } from "../../../../helpers/Context";
4
+ import { AutoEncoder, BooleanDecoder, Decoder, EnumDecoder, field } from '@simonbackx/simple-encoding';
5
+ import { SimpleError } from '@simonbackx/simple-errors';
6
+ import { OrganizationRegistrationPeriod } from '@stamhoofd/models';
7
+ import { AuthenticatedStructures } from '../../../../helpers/AuthenticatedStructures';
8
+ import { Context } from '../../../../helpers/Context';
9
9
 
10
10
  type Params = { readonly id: string };
11
11
  type Query = undefined;
12
12
 
13
13
  class Body extends AutoEncoder {
14
- @field({decoder: new EnumDecoder(SetupStepType)})
15
- type: SetupStepType
14
+ @field({ decoder: new EnumDecoder(SetupStepType) })
15
+ type: SetupStepType;
16
16
 
17
- @field({decoder: BooleanDecoder})
18
- isReviewed: boolean
17
+ @field({ decoder: BooleanDecoder })
18
+ isReviewed: boolean;
19
19
  }
20
20
 
21
- type ResponseBody = OrganizationRegistrationPeriodStruct
21
+ type ResponseBody = OrganizationRegistrationPeriodStruct;
22
22
 
23
23
  /**
24
24
  * Endpoint to mark a setup step as reviewed
@@ -28,11 +28,11 @@ export class SetupStepReviewEndpoint extends Endpoint<Params, Query, Body, Respo
28
28
  bodyDecoder = Body as Decoder<Body>;
29
29
 
30
30
  protected doesMatch(request: Request): [true, Params] | [false] {
31
- if (request.method != "POST") {
31
+ if (request.method !== 'POST') {
32
32
  return [false];
33
33
  }
34
34
 
35
- const params = Endpoint.parseParameters(request.url, "/organization/registration-period/@id/setup-steps/review", {id: String});
35
+ const params = Endpoint.parseParameters(request.url, '/organization/registration-period/@id/setup-steps/review', { id: String });
36
36
 
37
37
  if (params) {
38
38
  return [true, params as Params];
@@ -42,10 +42,10 @@ export class SetupStepReviewEndpoint extends Endpoint<Params, Query, Body, Respo
42
42
 
43
43
  async handle(request: DecodedRequest<Params, Query, Body>) {
44
44
  const organization = await Context.setOrganizationScope();
45
- const { user } = await Context.authenticate()
45
+ const { user } = await Context.authenticate();
46
46
 
47
47
  if (!await Context.auth.hasFullAccess(organization.id)) {
48
- throw Context.auth.error()
48
+ throw Context.auth.error();
49
49
  }
50
50
 
51
51
  const periodId = request.params.id;
@@ -55,22 +55,23 @@ export class SetupStepReviewEndpoint extends Endpoint<Params, Query, Body, Respo
55
55
  const organizationPeriod = await OrganizationRegistrationPeriod.getByID(periodId);
56
56
  if (!organizationPeriod || organizationPeriod.organizationId !== organization.id) {
57
57
  throw new SimpleError({
58
- code: "not_found",
59
- message: "Period not found",
60
- statusCode: 404
61
- })
58
+ code: 'not_found',
59
+ message: 'Period not found',
60
+ statusCode: 404,
61
+ });
62
62
  }
63
63
 
64
64
  const setupSteps = organizationPeriod.setupSteps;
65
65
 
66
- if(isReviewed) {
66
+ if (isReviewed) {
67
67
  setupSteps.markReviewed(stepType, {
68
68
  userId: user.id,
69
- userName: user.name ?? '?'
69
+ userName: user.name ?? '?',
70
70
  });
71
- } else {
71
+ }
72
+ else {
72
73
  setupSteps.resetReviewed(stepType);
73
- }
74
+ }
74
75
 
75
76
  await organizationPeriod.save();
76
77
 
@@ -1,24 +1,23 @@
1
-
2
1
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
2
  import { SimpleError } from '@simonbackx/simple-errors';
4
3
  import { StripeAccount } from '@stamhoofd/models';
5
- import { PermissionLevel, StripeAccount as StripeAccountStruct } from "@stamhoofd/structures";
4
+ import { PermissionLevel, StripeAccount as StripeAccountStruct } from '@stamhoofd/structures';
6
5
  import Stripe from 'stripe';
7
6
 
8
7
  import { Context } from '../../../../helpers/Context';
9
8
  import { StripeHelper } from '../../../../helpers/StripeHelper';
10
9
  type Params = Record<string, never>;
11
10
  type Body = undefined;
12
- type Query = undefined
13
- type ResponseBody = StripeAccountStruct
11
+ type Query = undefined;
12
+ type ResponseBody = StripeAccountStruct;
14
13
 
15
- export class ConnectMollieEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
14
+ export class ConnectMollieEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
16
15
  protected doesMatch(request: Request): [true, Params] | [false] {
17
- if (request.method != "POST") {
16
+ if (request.method !== 'POST') {
18
17
  return [false];
19
18
  }
20
19
 
21
- const params = Endpoint.parseParameters(request.url, "/stripe/connect", {});
20
+ const params = Endpoint.parseParameters(request.url, '/stripe/connect', {});
22
21
 
23
22
  if (params) {
24
23
  return [true, params as Params];
@@ -29,24 +28,24 @@ export class ConnectMollieEndpoint extends Endpoint<Params, Query, Body, Respons
29
28
 
30
29
  async handle(_: DecodedRequest<Params, Query, Body>) {
31
30
  const organization = await Context.setOrganizationScope();
32
- await Context.authenticate()
31
+ await Context.authenticate();
33
32
 
34
33
  // Fast throw first (more in depth checking for patches later)
35
34
  if (!await Context.auth.canManagePaymentAccounts(organization.id, PermissionLevel.Full)) {
36
- throw Context.auth.error()
35
+ throw Context.auth.error();
37
36
  }
38
37
 
39
- const models = await StripeAccount.where({ organizationId: organization.id, status: "active" })
38
+ const models = await StripeAccount.where({ organizationId: organization.id, status: 'active' });
40
39
 
41
- const canCreateMultipleStripeAccounts = models.every(a => (a.meta.charges_enabled && a.meta.payouts_enabled) || (a.meta.details_submitted))
40
+ const canCreateMultipleStripeAccounts = models.every(a => (a.meta.charges_enabled && a.meta.payouts_enabled) || (a.meta.details_submitted));
42
41
  if (models.length > 0 && !canCreateMultipleStripeAccounts) {
43
42
  throw new SimpleError({
44
- code: "already_connected",
45
- message: "Je hebt al een Stripe account gekoppeld"
46
- })
43
+ code: 'already_connected',
44
+ message: 'Je hebt al een Stripe account gekoppeld',
45
+ });
47
46
  }
48
47
 
49
- const type = STAMHOOFD.STRIPE_CONNECT_METHOD
48
+ const type = STAMHOOFD.STRIPE_CONNECT_METHOD;
50
49
 
51
50
  const sharedData: Stripe.AccountCreateParams = {
52
51
  capabilities: {
@@ -55,7 +54,7 @@ export class ConnectMollieEndpoint extends Endpoint<Params, Query, Body, Respons
55
54
  bancontact_payments: { requested: true },
56
55
  ideal_payments: { requested: true },
57
56
  },
58
- }
57
+ };
59
58
 
60
59
  let expressData: Stripe.AccountCreateParams = {
61
60
  country: organization.address.country,
@@ -68,9 +67,9 @@ export class ConnectMollieEndpoint extends Endpoint<Params, Query, Body, Respons
68
67
  delay_days: 'minimum',
69
68
  interval: 'weekly',
70
69
  weekly_anchor: 'monday',
71
- }
72
- }
73
- }
70
+ },
71
+ },
72
+ },
74
73
  };
75
74
 
76
75
  if (type !== 'express') {
@@ -78,22 +77,22 @@ export class ConnectMollieEndpoint extends Endpoint<Params, Query, Body, Respons
78
77
  }
79
78
 
80
79
  // Create a new Stripe account
81
- const stripe = StripeHelper.getInstance()
80
+ const stripe = StripeHelper.getInstance();
82
81
  const account = await stripe.accounts.create({
83
82
  type,
84
83
  ...sharedData,
85
- ...expressData
84
+ ...expressData,
86
85
  });
87
86
 
88
87
  // Save the Stripe account in the database
89
88
  const model = new StripeAccount();
90
89
  model.organizationId = organization.id;
91
90
  model.accountId = account.id;
92
- model.setMetaFromStripeAccount(account)
91
+ model.setMetaFromStripeAccount(account);
93
92
  await model.save();
94
93
 
95
94
  // Return information about the Stripe Account
96
-
95
+
97
96
  return new Response(StripeAccountStruct.create(model));
98
97
  }
99
98
  }
@@ -1,4 +1,3 @@
1
-
2
1
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
2
  import { StripeAccount } from '@stamhoofd/models';
4
3
  import { PermissionLevel } from '@stamhoofd/structures';
@@ -9,16 +8,16 @@ import { SimpleError } from '@simonbackx/simple-errors';
9
8
 
10
9
  type Params = { id: string };
11
10
  type Body = undefined;
12
- type Query = undefined
13
- type ResponseBody = undefined
11
+ type Query = undefined;
12
+ type ResponseBody = undefined;
14
13
 
15
- export class DeleteStripeAccountEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
14
+ export class DeleteStripeAccountEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
16
15
  protected doesMatch(request: Request): [true, Params] | [false] {
17
- if (request.method != "DELETE") {
16
+ if (request.method !== 'DELETE') {
18
17
  return [false];
19
18
  }
20
19
 
21
- const params = Endpoint.parseParameters(request.url, "/stripe/accounts/@id", {id: String});
20
+ const params = Endpoint.parseParameters(request.url, '/stripe/accounts/@id', { id: String });
22
21
 
23
22
  if (params) {
24
23
  return [true, params as Params];
@@ -29,39 +28,40 @@ export class DeleteStripeAccountEndpoint extends Endpoint<Params, Query, Body, R
29
28
 
30
29
  async handle(request: DecodedRequest<Params, Query, Body>) {
31
30
  const organization = await Context.setOrganizationScope();
32
- await Context.authenticate()
31
+ await Context.authenticate();
33
32
 
34
33
  // Fast throw first (more in depth checking for patches later)
35
34
  if (!await Context.auth.canManagePaymentAccounts(organization.id, PermissionLevel.Full)) {
36
- throw Context.auth.error()
35
+ throw Context.auth.error();
37
36
  }
38
37
 
39
- // Search account in database
40
- const model = await StripeAccount.getByID(request.params.id)
41
- if (!model || model.organizationId != organization.id || model.status !== "active") {
42
- throw Context.auth.notFoundOrNoAccess("Account niet gevonden")
38
+ // Search account in database
39
+ const model = await StripeAccount.getByID(request.params.id);
40
+ if (!model || model.organizationId !== organization.id || model.status !== 'active') {
41
+ throw Context.auth.notFoundOrNoAccess('Account niet gevonden');
43
42
  }
44
43
 
45
44
  if (model.accountId === STAMHOOFD.STRIPE_ACCOUNT_ID) {
46
45
  throw new SimpleError({
47
- code: "invalid_request",
48
- message: "Je kan het hoofdaccount van het platform niet verwijderen.",
49
- statusCode: 400
50
- })
46
+ code: 'invalid_request',
47
+ message: 'Je kan het hoofdaccount van het platform niet verwijderen.',
48
+ statusCode: 400,
49
+ });
51
50
  }
52
51
 
53
52
  // For now we don't delete them in Stripe because this causes issues with data access
54
- const stripe = StripeHelper.getInstance()
55
-
53
+ const stripe = StripeHelper.getInstance();
54
+
56
55
  try {
57
56
  await stripe.accounts.del(model.accountId);
58
- } catch (e) {
59
- console.error('Tried deleting account but failed', e)
57
+ }
58
+ catch (e) {
59
+ console.error('Tried deleting account but failed', e);
60
60
  }
61
61
 
62
62
  // If that succeeded
63
- model.status = "deleted"
64
- await model.save()
63
+ model.status = 'deleted';
64
+ await model.save();
65
65
 
66
66
  return new Response(undefined);
67
67
  }
@@ -1,4 +1,3 @@
1
-
2
1
  import { AutoEncoder, Decoder, field, StringDecoder } from '@simonbackx/simple-encoding';
3
2
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
4
3
  import { SimpleError } from '@simonbackx/simple-errors';
@@ -14,30 +13,30 @@ class Body extends AutoEncoder {
14
13
  * The account id (internal id, not the stripe id)
15
14
  */
16
15
  @field({ decoder: StringDecoder })
17
- accountId: string
16
+ accountId: string;
18
17
 
19
18
  @field({ decoder: StringDecoder })
20
- returnUrl: string
19
+ returnUrl: string;
21
20
 
22
21
  @field({ decoder: StringDecoder })
23
- refreshUrl: string
22
+ refreshUrl: string;
24
23
  }
25
24
 
26
- type Query = undefined
25
+ type Query = undefined;
27
26
  class ResponseBody extends AutoEncoder {
28
27
  @field({ decoder: StringDecoder })
29
- url: string
28
+ url: string;
30
29
  }
31
30
 
32
31
  export class GetStripeAccountLinkEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
33
- bodyDecoder = Body as Decoder<Body>
32
+ bodyDecoder = Body as Decoder<Body>;
34
33
 
35
34
  protected doesMatch(request: Request): [true, Params] | [false] {
36
- if (request.method != "POST") {
35
+ if (request.method !== 'POST') {
37
36
  return [false];
38
37
  }
39
38
 
40
- const params = Endpoint.parseParameters(request.url, "/stripe/account-link", {});
39
+ const params = Endpoint.parseParameters(request.url, '/stripe/account-link', {});
41
40
 
42
41
  if (params) {
43
42
  return [true, params as Params];
@@ -48,21 +47,21 @@ export class GetStripeAccountLinkEndpoint extends Endpoint<Params, Query, Body,
48
47
 
49
48
  async handle(request: DecodedRequest<Params, Query, Body>) {
50
49
  const organization = await Context.setOrganizationScope();
51
- await Context.authenticate()
50
+ await Context.authenticate();
52
51
 
53
52
  // Fast throw first (more in depth checking for patches later)
54
53
  if (!await Context.auth.canManagePaymentAccounts(organization.id, PermissionLevel.Full)) {
55
- throw Context.auth.error()
54
+ throw Context.auth.error();
56
55
  }
57
56
 
58
57
  // Search account in database
59
- const model = await StripeAccount.getByID(request.body.accountId)
60
- if (!model || model.organizationId != organization.id || model.status !== 'active') {
61
- throw Context.auth.notFoundOrNoAccess("Account niet gevonden")
58
+ const model = await StripeAccount.getByID(request.body.accountId);
59
+ if (!model || model.organizationId !== organization.id || model.status !== 'active') {
60
+ throw Context.auth.notFoundOrNoAccess('Account niet gevonden');
62
61
  }
63
62
 
64
63
  // Get account
65
- const stripe = StripeHelper.getInstance()
64
+ const stripe = StripeHelper.getInstance();
66
65
  const accountLink = await stripe.accountLinks.create({
67
66
  account: model.accountId,
68
67
  refresh_url: request.body.refreshUrl,
@@ -70,12 +69,12 @@ export class GetStripeAccountLinkEndpoint extends Endpoint<Params, Query, Body,
70
69
  type: 'account_onboarding',
71
70
  collection_options: {
72
71
  fields: 'eventually_due',
73
- future_requirements: 'include'
74
- }
72
+ future_requirements: 'include',
73
+ },
75
74
  });
76
75
 
77
76
  return new Response(ResponseBody.create({
78
- url: accountLink.url
77
+ url: accountLink.url,
79
78
  }));
80
79
  }
81
80
  }
@@ -1,4 +1,3 @@
1
-
2
1
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
2
  import { StripeAccount } from '@stamhoofd/models';
4
3
  import { PermissionLevel, StripeAccount as StripeAccountStruct } from '@stamhoofd/structures';
@@ -7,16 +6,16 @@ import { Context } from '../../../../helpers/Context';
7
6
 
8
7
  type Params = Record<string, never>;
9
8
  type Body = undefined;
10
- type Query = undefined
11
- type ResponseBody = StripeAccountStruct[]
9
+ type Query = undefined;
10
+ type ResponseBody = StripeAccountStruct[];
12
11
 
13
- export class GetStripeAccountLinkEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
12
+ export class GetStripeAccountLinkEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
14
13
  protected doesMatch(request: Request): [true, Params] | [false] {
15
- if (request.method != "GET") {
14
+ if (request.method !== 'GET') {
16
15
  return [false];
17
16
  }
18
17
 
19
- const params = Endpoint.parseParameters(request.url, "/stripe/accounts", {});
18
+ const params = Endpoint.parseParameters(request.url, '/stripe/accounts', {});
20
19
 
21
20
  if (params) {
22
21
  return [true, params as Params];
@@ -27,14 +26,14 @@ export class GetStripeAccountLinkEndpoint extends Endpoint<Params, Query, Body,
27
26
 
28
27
  async handle(_: DecodedRequest<Params, Query, Body>) {
29
28
  const organization = await Context.setOrganizationScope();
30
- await Context.authenticate()
29
+ await Context.authenticate();
31
30
 
32
31
  // Fast throw first (more in depth checking for patches later)
33
32
  if (!await Context.auth.canManagePaymentAccounts(organization.id, PermissionLevel.Read)) {
34
- throw Context.auth.error()
33
+ throw Context.auth.error();
35
34
  }
36
35
 
37
- const models = await StripeAccount.where({ organizationId: organization.id, status: 'active' })
36
+ const models = await StripeAccount.where({ organizationId: organization.id, status: 'active' });
38
37
  return new Response(models.map(m => StripeAccountStruct.create(m)));
39
38
  }
40
39
  }
@@ -1,4 +1,3 @@
1
-
2
1
  import { AutoEncoder, Decoder, field, StringDecoder } from '@simonbackx/simple-encoding';
3
2
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
4
3
  import { SimpleError } from '@simonbackx/simple-errors';
@@ -14,24 +13,24 @@ class Body extends AutoEncoder {
14
13
  * The account id (internal id, not the stripe id)
15
14
  */
16
15
  @field({ decoder: StringDecoder })
17
- accountId: string
16
+ accountId: string;
18
17
  }
19
18
 
20
- type Query = undefined
19
+ type Query = undefined;
21
20
  class ResponseBody extends AutoEncoder {
22
21
  @field({ decoder: StringDecoder })
23
- url: string
22
+ url: string;
24
23
  }
25
24
 
26
25
  export class GetStripeLoginLinkEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
27
- bodyDecoder = Body as Decoder<Body>
26
+ bodyDecoder = Body as Decoder<Body>;
28
27
 
29
28
  protected doesMatch(request: Request): [true, Params] | [false] {
30
- if (request.method != "POST") {
29
+ if (request.method !== 'POST') {
31
30
  return [false];
32
31
  }
33
32
 
34
- const params = Endpoint.parseParameters(request.url, "/stripe/login-link", {});
33
+ const params = Endpoint.parseParameters(request.url, '/stripe/login-link', {});
35
34
 
36
35
  if (params) {
37
36
  return [true, params as Params];
@@ -42,34 +41,34 @@ export class GetStripeLoginLinkEndpoint extends Endpoint<Params, Query, Body, Re
42
41
 
43
42
  async handle(request: DecodedRequest<Params, Query, Body>) {
44
43
  const organization = await Context.setOrganizationScope();
45
- await Context.authenticate()
44
+ await Context.authenticate();
46
45
 
47
46
  // Fast throw first (more in depth checking for patches later)
48
47
  if (!await Context.auth.canManagePaymentAccounts(organization.id, PermissionLevel.Full)) {
49
- throw Context.auth.error()
48
+ throw Context.auth.error();
50
49
  }
51
50
 
52
51
  // Search account in database
53
- const model = await StripeAccount.getByID(request.body.accountId)
54
- if (!model || model.organizationId != organization.id || model.status !== 'active') {
52
+ const model = await StripeAccount.getByID(request.body.accountId);
53
+ if (!model || model.organizationId !== organization.id || model.status !== 'active') {
55
54
  throw new SimpleError({
56
- code: "not_found",
57
- message: "Account niet gevonden",
58
- statusCode: 400
59
- })
55
+ code: 'not_found',
56
+ message: 'Account niet gevonden',
57
+ statusCode: 400,
58
+ });
60
59
  }
61
60
 
62
61
  if (model.meta.type === 'standard') {
63
62
  return new Response(ResponseBody.create({
64
- url: 'https://dashboard.stripe.com/'
63
+ url: 'https://dashboard.stripe.com/',
65
64
  }));
66
65
  }
67
66
 
68
- const stripe = StripeHelper.getInstance()
67
+ const stripe = StripeHelper.getInstance();
69
68
  const accountLink = await stripe.accounts.createLoginLink(model.accountId);
70
69
 
71
70
  return new Response(ResponseBody.create({
72
- url: accountLink.url
71
+ url: accountLink.url,
73
72
  }));
74
73
  }
75
74
  }
@@ -1,4 +1,3 @@
1
-
2
1
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
2
  import { StripeAccount } from '@stamhoofd/models';
4
3
  import { PermissionLevel, StripeAccount as StripeAccountStruct } from '@stamhoofd/structures';
@@ -8,16 +7,16 @@ import { StripeHelper } from '../../../../helpers/StripeHelper';
8
7
 
9
8
  type Params = { id: string };
10
9
  type Body = undefined;
11
- type Query = undefined
12
- type ResponseBody = StripeAccountStruct
10
+ type Query = undefined;
11
+ type ResponseBody = StripeAccountStruct;
13
12
 
14
- export class UpdateStripeAccountEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
13
+ export class UpdateStripeAccountEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
15
14
  protected doesMatch(request: Request): [true, Params] | [false] {
16
- if (request.method != "POST") {
15
+ if (request.method !== 'POST') {
17
16
  return [false];
18
17
  }
19
18
 
20
- const params = Endpoint.parseParameters(request.url, "/stripe/accounts/@id", {id: String});
19
+ const params = Endpoint.parseParameters(request.url, '/stripe/accounts/@id', { id: String });
21
20
 
22
21
  if (params) {
23
22
  return [true, params as Params];
@@ -28,24 +27,24 @@ export class UpdateStripeAccountEndpoint extends Endpoint<Params, Query, Body, R
28
27
 
29
28
  async handle(request: DecodedRequest<Params, Query, Body>) {
30
29
  const organization = await Context.setOrganizationScope();
31
- await Context.authenticate()
30
+ await Context.authenticate();
32
31
 
33
32
  // Fast throw first (more in depth checking for patches later)
34
33
  if (!await Context.auth.canManagePaymentAccounts(organization.id, PermissionLevel.Read)) {
35
- throw Context.auth.error()
34
+ throw Context.auth.error();
36
35
  }
37
36
 
38
- // Search account in database
39
- const model = await StripeAccount.getByID(request.params.id)
40
- if (!model || model.organizationId != organization.id) {
41
- throw Context.auth.notFoundOrNoAccess("Account niet gevonden")
37
+ // Search account in database
38
+ const model = await StripeAccount.getByID(request.params.id);
39
+ if (!model || model.organizationId !== organization.id) {
40
+ throw Context.auth.notFoundOrNoAccess('Account niet gevonden');
42
41
  }
43
42
 
44
43
  // Get account
45
- const stripe = StripeHelper.getInstance()
44
+ const stripe = StripeHelper.getInstance();
46
45
  const account = await stripe.accounts.retrieve(model.accountId);
47
- model.setMetaFromStripeAccount(account)
48
- await model.save()
46
+ model.setMetaFromStripeAccount(account);
47
+ await model.save();
49
48
 
50
49
  return new Response(StripeAccountStruct.create(model));
51
50
  }
@@ -1,24 +1,24 @@
1
1
  import { Decoder } from '@simonbackx/simple-encoding';
2
- import { DecodedRequest, Endpoint, Request, Response } from "@simonbackx/simple-endpoints";
3
- import { SimpleError } from "@simonbackx/simple-errors";
2
+ import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
+ import { SimpleError } from '@simonbackx/simple-errors';
4
4
  import { Token, User } from '@stamhoofd/models';
5
- import { ApiUser, ApiUserWithToken, UserPermissions } from "@stamhoofd/structures";
5
+ import { ApiUser, ApiUserWithToken, UserPermissions } from '@stamhoofd/structures';
6
6
 
7
7
  import { Context } from '../../../../helpers/Context';
8
8
  type Params = Record<string, never>;
9
9
  type Query = undefined;
10
- type Body = ApiUser
11
- type ResponseBody = ApiUser
10
+ type Body = ApiUser;
11
+ type ResponseBody = ApiUser;
12
12
 
13
13
  export class CreateAdminEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
14
- bodyDecoder = ApiUser as Decoder<ApiUser>
14
+ bodyDecoder = ApiUser as Decoder<ApiUser>;
15
15
 
16
16
  protected doesMatch(request: Request): [true, Params] | [false] {
17
- if (request.method != "POST") {
17
+ if (request.method !== 'POST') {
18
18
  return [false];
19
19
  }
20
20
 
21
- const params = Endpoint.parseParameters(request.url, "/api-keys", {});
21
+ const params = Endpoint.parseParameters(request.url, '/api-keys', {});
22
22
 
23
23
  if (params) {
24
24
  return [true, params as Params];
@@ -28,22 +28,22 @@ export class CreateAdminEndpoint extends Endpoint<Params, Query, Body, ResponseB
28
28
 
29
29
  async handle(request: DecodedRequest<Params, Query, Body>) {
30
30
  const organization = await Context.setOrganizationScope();
31
- await Context.authenticate()
31
+ await Context.authenticate();
32
32
 
33
33
  // Fast throw first (more in depth checking for patches later)
34
34
  if (!await Context.auth.canManageAdmins(organization.id)) {
35
- throw Context.auth.error()
35
+ throw Context.auth.error();
36
36
  }
37
37
 
38
38
  const admin = new User();
39
39
  admin.organizationId = organization.id;
40
40
  admin.firstName = request.body.name;
41
- admin.lastName = null
42
- admin.email = 'creating.api'
43
- admin.verified = true
41
+ admin.lastName = null;
42
+ admin.email = 'creating.api';
43
+ admin.verified = true;
44
44
 
45
45
  if (!admin.isApiUser) {
46
- throw new Error('Unexpectedly created normal user while trying to create API-user')
46
+ throw new Error('Unexpectedly created normal user while trying to create API-user');
47
47
  }
48
48
 
49
49
  // Merge permissions
@@ -51,15 +51,15 @@ export class CreateAdminEndpoint extends Endpoint<Params, Query, Body, ResponseB
51
51
  throw new SimpleError({
52
52
  code: 'missing_field',
53
53
  message: 'When creating API-users, you are required to specify permissions in the request',
54
- field: 'permissions'
55
- })
54
+ field: 'permissions',
55
+ });
56
56
  }
57
57
 
58
- admin.permissions = UserPermissions.limitedAdd(null, request.body.permissions, organization.id)
58
+ admin.permissions = UserPermissions.limitedAdd(null, request.body.permissions, organization.id);
59
59
  await admin.save();
60
60
 
61
61
  // Set id
62
- admin.email = admin.id + '.api'
62
+ admin.email = admin.id + '.api';
63
63
  await admin.save();
64
64
 
65
65
  const createdToken = await Token.createApiToken(admin);
@@ -67,7 +67,7 @@ export class CreateAdminEndpoint extends Endpoint<Params, Query, Body, ResponseB
67
67
  return new Response(ApiUserWithToken.create({
68
68
  ...(await Token.getAPIUserWithToken(admin)),
69
69
  token: createdToken.accessToken,
70
- expiresAt: createdToken.accessTokenValidUntil
70
+ expiresAt: createdToken.accessTokenValidUntil,
71
71
  }));
72
72
  }
73
73
  }