@stamhoofd/backend 2.39.1 → 2.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/eslint.config.mjs +5 -0
- package/index.ts +81 -74
- package/jest.config.cjs +10 -0
- package/migrations.ts +16 -14
- package/package.json +11 -11
- package/src/crons/clear-excel-cache.test.ts +48 -50
- package/src/crons/clear-excel-cache.ts +18 -18
- package/src/crons/setup-steps.ts +2 -2
- package/src/crons.ts +325 -306
- package/src/decoders/StringArrayDecoder.ts +7 -7
- package/src/decoders/StringNullableDecoder.ts +1 -2
- package/src/email-recipient-loaders/members.ts +22 -22
- package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +8 -9
- package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +39 -40
- package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +8 -8
- package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +44 -45
- package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +58 -57
- package/src/endpoints/auth/CreateAdminEndpoint.ts +48 -45
- package/src/endpoints/auth/CreateTokenEndpoint.test.ts +31 -31
- package/src/endpoints/auth/CreateTokenEndpoint.ts +146 -147
- package/src/endpoints/auth/DeleteTokenEndpoint.ts +7 -7
- package/src/endpoints/auth/DeleteUserEndpoint.ts +15 -15
- package/src/endpoints/auth/ForgotPasswordEndpoint.ts +17 -18
- package/src/endpoints/auth/GetOtherUserEndpoint.ts +9 -10
- package/src/endpoints/auth/GetUserEndpoint.test.ts +32 -35
- package/src/endpoints/auth/GetUserEndpoint.ts +5 -6
- package/src/endpoints/auth/PatchApiUserEndpoint.ts +35 -33
- package/src/endpoints/auth/PatchUserEndpoint.ts +55 -52
- package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +9 -9
- package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +8 -8
- package/src/endpoints/auth/SignupEndpoint.ts +37 -36
- package/src/endpoints/auth/VerifyEmailEndpoint.ts +29 -28
- package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +33 -33
- package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +7 -7
- package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +37 -37
- package/src/endpoints/global/email/CreateEmailEndpoint.ts +30 -30
- package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +13 -13
- package/src/endpoints/global/email/GetEmailEndpoint.ts +13 -13
- package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +16 -16
- package/src/endpoints/global/email/PatchEmailEndpoint.ts +25 -25
- package/src/endpoints/global/events/GetEventsEndpoint.ts +43 -44
- package/src/endpoints/global/events/PatchEventsEndpoint.ts +127 -172
- package/src/endpoints/global/files/ExportToExcelEndpoint.ts +49 -50
- package/src/endpoints/global/files/GetFileCache.ts +13 -13
- package/src/endpoints/global/files/UploadFile.ts +51 -54
- package/src/endpoints/global/files/UploadImage.ts +53 -53
- package/src/endpoints/global/groups/GetGroupsEndpoint.ts +25 -25
- package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +24 -23
- package/src/endpoints/global/members/GetMembersCountEndpoint.ts +8 -8
- package/src/endpoints/global/members/GetMembersEndpoint.ts +105 -102
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +240 -239
- package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +12 -14
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +32 -33
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +48 -57
- package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.test.ts +21 -22
- package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +28 -28
- package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +18 -18
- package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +20 -20
- package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +17 -17
- package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +81 -75
- package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +14 -14
- package/src/endpoints/global/platform/GetPlatformEnpoint.ts +11 -11
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +71 -68
- package/src/endpoints/global/registration/GetPaymentRegistrations.ts +27 -27
- package/src/endpoints/global/registration/GetUserBillingStatusEndpoint.ts +30 -30
- package/src/endpoints/global/registration/GetUserDetailedBillingStatusEndpoint.ts +34 -34
- package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +26 -26
- package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +12 -12
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +90 -90
- package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +118 -121
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +362 -350
- package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +8 -9
- package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +21 -21
- package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +65 -65
- package/src/endpoints/organization/dashboard/billing/GetOrganizationBillingStatusEndpoint.ts +9 -9
- package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedBillingStatusEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +17 -17
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +21 -21
- package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +15 -15
- package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +52 -52
- package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplateEndpoint.ts +37 -37
- package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/email/EmailEndpoint.ts +113 -112
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +29 -29
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +48 -47
- package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +22 -21
- package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +13 -14
- package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +12 -13
- package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +24 -24
- package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +10 -12
- package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +14 -14
- package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +13 -13
- package/src/endpoints/organization/dashboard/organization/GetOrganizationSSOEndpoint.ts +12 -12
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +120 -124
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +172 -173
- package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +88 -89
- package/src/endpoints/organization/dashboard/organization/SetOrganizationSSOEndpoint.ts +12 -12
- package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +17 -17
- package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +8 -8
- package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +66 -67
- package/src/endpoints/organization/dashboard/payments/PatchBalanceItemsEndpoint.ts +47 -47
- package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +93 -91
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +16 -17
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +170 -167
- package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +25 -24
- package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +22 -23
- package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +22 -22
- package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +17 -18
- package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +8 -9
- package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +17 -18
- package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +14 -15
- package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +19 -19
- package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +19 -19
- package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +12 -12
- package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +103 -100
- package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +11 -12
- package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +15 -15
- package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +23 -23
- package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +54 -52
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +84 -81
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +120 -111
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +24 -24
- package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +18 -18
- package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +141 -130
- package/src/endpoints/organization/shared/GetDocumentHtml.ts +25 -25
- package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +18 -18
- package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.test.ts +36 -37
- package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +9 -9
- package/src/endpoints/organization/shared/auth/OpenIDConnectCallbackEndpoint.ts +11 -11
- package/src/endpoints/organization/shared/auth/OpenIDConnectStartEndpoint.ts +28 -27
- package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +20 -20
- package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +22 -22
- package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +14 -14
- package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +57 -56
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +65 -66
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +18 -17
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +124 -128
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +154 -145
- package/src/excel-loaders/members.ts +102 -103
- package/src/excel-loaders/payments.ts +155 -156
- package/src/helpers/AddressValidator.test.ts +32 -32
- package/src/helpers/AddressValidator.ts +128 -122
- package/src/helpers/AdminPermissionChecker.ts +339 -236
- package/src/helpers/AuthenticatedStructures.ts +233 -134
- package/src/helpers/BuckarooHelper.ts +134 -134
- package/src/helpers/CheckSettlements.ts +94 -88
- package/src/helpers/Context.ts +87 -86
- package/src/helpers/CookieHelper.ts +23 -22
- package/src/helpers/EmailResumer.ts +10 -10
- package/src/helpers/FileCache.ts +62 -62
- package/src/helpers/ForwardHandler.test.ts +122 -124
- package/src/helpers/ForwardHandler.ts +76 -70
- package/src/helpers/MemberUserSyncer.ts +101 -96
- package/src/helpers/MembershipCharger.ts +69 -69
- package/src/helpers/MembershipHelper.ts +11 -12
- package/src/helpers/OpenIDConnectHelper.ts +85 -82
- package/src/helpers/PeriodHelper.ts +65 -70
- package/src/helpers/StripeHelper.ts +146 -137
- package/src/helpers/StripePayoutChecker.ts +51 -52
- package/src/helpers/ViesHelper.ts +46 -44
- package/src/helpers/fetchToAsyncIterator.ts +14 -14
- package/src/helpers/xlsxAddressTransformerColumnFactory.ts +50 -52
- package/src/middleware/ContextMiddleware.ts +5 -5
- package/src/migrations/1646578856-validate-addresses.ts +6 -9
- package/src/seeds/0000000000-example.ts +3 -5
- package/src/seeds/1715028563-user-permissions.ts +16 -18
- package/src/seeds/1722256498-group-update-occupancy.ts +12 -12
- package/src/seeds/1722344162-sync-member-users.ts +14 -15
- package/src/seeds/1722344162-update-membership.ts +6 -6
- package/src/seeds/1726055544-balance-item-paid.ts +4 -4
- package/src/seeds/1726055545-balance-item-pending.ts +4 -4
- package/src/seeds/1726494419-update-cached-outstanding-balance.ts +16 -16
- package/src/seeds/1726494420-update-cached-outstanding-balance-from-items.ts +12 -12
- package/src/seeds/1726572303-schedule-stock-updates.ts +12 -12
- package/src/seeds/1726847064-setup-steps.ts +16 -0
- package/src/sql-filters/balance-item-payments.ts +7 -7
- package/src/sql-filters/events.ts +14 -14
- package/src/sql-filters/members.ts +96 -96
- package/src/sql-filters/organizations.ts +139 -75
- package/src/sql-filters/payments.ts +28 -28
- package/src/sql-filters/registrations.ts +14 -14
- package/src/sql-sorters/events.ts +25 -25
- package/src/sql-sorters/members.ts +26 -26
- package/src/sql-sorters/organizations.ts +36 -36
- package/src/sql-sorters/payments.ts +26 -26
- package/tests/e2e/stock.test.ts +616 -621
- package/tests/e2e/tickets.test.ts +255 -260
- package/tests/helpers/StripeMocker.ts +177 -179
- package/tests/helpers/TestServer.ts +9 -9
- package/tests/jest.global.setup.ts +14 -13
- package/tests/jest.setup.ts +33 -32
- package/.eslintrc.js +0 -61
- package/jest.config.js +0 -11
- package/src/helpers/SetupStepsUpdater.ts +0 -359
- package/src/seeds/1724076679-setup-steps.ts +0 -16
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import { createMollieClient } from '@mollie/api-client';
|
|
1
|
+
import { createMollieClient, PaymentStatus as MolliePaymentStatus } from '@mollie/api-client';
|
|
2
2
|
import { AutoEncoder, BooleanDecoder, Decoder, field } from '@simonbackx/simple-encoding';
|
|
3
|
-
import { DecodedRequest, Endpoint, Request, Response } from
|
|
4
|
-
import { SimpleError } from
|
|
3
|
+
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
4
|
+
import { SimpleError } from '@simonbackx/simple-errors';
|
|
5
5
|
import { BalanceItem, BalanceItemPayment, MolliePayment, MollieToken, Organization, PayconiqPayment, Payment } from '@stamhoofd/models';
|
|
6
6
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
7
|
-
import { PaymentGeneral, PaymentMethod, PaymentProvider, PaymentStatus } from
|
|
7
|
+
import { PaymentGeneral, PaymentMethod, PaymentProvider, PaymentStatus } from '@stamhoofd/structures';
|
|
8
8
|
|
|
9
9
|
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
|
|
10
10
|
import { BuckarooHelper } from '../../../helpers/BuckarooHelper';
|
|
11
11
|
import { Context } from '../../../helpers/Context';
|
|
12
12
|
import { StripeHelper } from '../../../helpers/StripeHelper';
|
|
13
13
|
|
|
14
|
-
type Params = {id: string};
|
|
14
|
+
type Params = { id: string };
|
|
15
15
|
class Query extends AutoEncoder {
|
|
16
16
|
@field({ decoder: BooleanDecoder, optional: true })
|
|
17
|
-
exchange = false
|
|
17
|
+
exchange = false;
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* If possible, cancel the payment if it is not yet paid/pending
|
|
21
21
|
*/
|
|
22
22
|
@field({ decoder: BooleanDecoder, optional: true })
|
|
23
|
-
cancel = false
|
|
23
|
+
cancel = false;
|
|
24
24
|
}
|
|
25
|
-
type Body = undefined
|
|
26
|
-
type ResponseBody = PaymentGeneral | undefined
|
|
25
|
+
type Body = undefined;
|
|
26
|
+
type ResponseBody = PaymentGeneral | undefined;
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* One endpoint to create, patch and delete groups. Usefull because on organization setup, we need to create multiple groups at once. Also, sometimes we need to link values and update multiple groups at once
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
32
|
export class ExchangePaymentEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
33
|
-
queryDecoder = Query as Decoder<Query
|
|
33
|
+
queryDecoder = Query as Decoder<Query>;
|
|
34
34
|
|
|
35
35
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
36
|
-
if (request.method
|
|
36
|
+
if (request.method !== 'POST') {
|
|
37
37
|
return [false];
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
const params = Endpoint.parseParameters(request.url,
|
|
40
|
+
const params = Endpoint.parseParameters(request.url, '/payments/@id', { id: String });
|
|
41
41
|
|
|
42
42
|
if (params) {
|
|
43
43
|
return [true, params as Params];
|
|
@@ -46,293 +46,304 @@ export class ExchangePaymentEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
49
|
-
const organization = await Context.setOptionalOrganizationScope()
|
|
49
|
+
const organization = await Context.setOptionalOrganizationScope();
|
|
50
50
|
if (!request.query.exchange) {
|
|
51
|
-
await Context.authenticate()
|
|
51
|
+
await Context.authenticate();
|
|
52
52
|
}
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
// Not method on payment because circular references (not supprted in ts)
|
|
55
|
-
const payment = await ExchangePaymentEndpoint.pollStatus(request.params.id, organization, request.query.cancel)
|
|
55
|
+
const payment = await ExchangePaymentEndpoint.pollStatus(request.params.id, organization, request.query.cancel);
|
|
56
56
|
if (!payment) {
|
|
57
57
|
throw new SimpleError({
|
|
58
|
-
code:
|
|
59
|
-
message:
|
|
60
|
-
})
|
|
58
|
+
code: '',
|
|
59
|
+
message: 'Deze link is ongeldig',
|
|
60
|
+
});
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
if (request.query.exchange) {
|
|
64
64
|
return new Response(undefined);
|
|
65
65
|
}
|
|
66
|
-
|
|
67
|
-
return new Response(
|
|
68
|
-
await AuthenticatedStructures.paymentGeneral(payment, true)
|
|
66
|
+
|
|
67
|
+
return new Response(
|
|
68
|
+
await AuthenticatedStructures.paymentGeneral(payment, true),
|
|
69
69
|
);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
static async handlePaymentStatusUpdate(payment: Payment, organization: Organization, status: PaymentStatus) {
|
|
73
73
|
if (payment.status === status) {
|
|
74
74
|
return;
|
|
75
|
-
}
|
|
75
|
+
}
|
|
76
76
|
|
|
77
77
|
if (status === PaymentStatus.Succeeded) {
|
|
78
|
-
payment.status = PaymentStatus.Succeeded
|
|
79
|
-
payment.paidAt = new Date()
|
|
78
|
+
payment.status = PaymentStatus.Succeeded;
|
|
79
|
+
payment.paidAt = new Date();
|
|
80
80
|
await payment.save();
|
|
81
81
|
|
|
82
82
|
// Prevent concurrency issues
|
|
83
|
-
await QueueHandler.schedule(
|
|
84
|
-
const unloaded = (await BalanceItemPayment.where({paymentId: payment.id})).map(r => r.setRelation(BalanceItemPayment.payment, payment))
|
|
83
|
+
await QueueHandler.schedule('balance-item-update/' + organization.id, async () => {
|
|
84
|
+
const unloaded = (await BalanceItemPayment.where({ paymentId: payment.id })).map(r => r.setRelation(BalanceItemPayment.payment, payment));
|
|
85
85
|
const balanceItemPayments = await BalanceItemPayment.balanceItem.load(
|
|
86
|
-
unloaded
|
|
86
|
+
unloaded,
|
|
87
87
|
);
|
|
88
88
|
|
|
89
89
|
for (const balanceItemPayment of balanceItemPayments) {
|
|
90
90
|
await balanceItemPayment.markPaid(organization);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
await BalanceItem.updateOutstanding(balanceItemPayments.map(p => p.balanceItem))
|
|
94
|
-
})
|
|
93
|
+
await BalanceItem.updateOutstanding(balanceItemPayments.map(p => p.balanceItem));
|
|
94
|
+
});
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
const oldStatus = payment.status
|
|
98
|
+
const oldStatus = payment.status;
|
|
99
99
|
|
|
100
100
|
// Save before updating balance items
|
|
101
|
-
payment.status = status
|
|
102
|
-
payment.paidAt = null
|
|
101
|
+
payment.status = status;
|
|
102
|
+
payment.paidAt = null;
|
|
103
103
|
await payment.save();
|
|
104
104
|
|
|
105
105
|
// If OLD status was succeeded, we need to revert the actions
|
|
106
106
|
if (oldStatus === PaymentStatus.Succeeded) {
|
|
107
107
|
// No longer succeeded
|
|
108
|
-
await QueueHandler.schedule(
|
|
108
|
+
await QueueHandler.schedule('balance-item-update/' + organization.id, async () => {
|
|
109
109
|
const balanceItemPayments = await BalanceItemPayment.balanceItem.load(
|
|
110
|
-
(await BalanceItemPayment.where({paymentId: payment.id})).map(r => r.setRelation(BalanceItemPayment.payment, payment))
|
|
110
|
+
(await BalanceItemPayment.where({ paymentId: payment.id })).map(r => r.setRelation(BalanceItemPayment.payment, payment)),
|
|
111
111
|
);
|
|
112
112
|
|
|
113
113
|
for (const balanceItemPayment of balanceItemPayments) {
|
|
114
114
|
await balanceItemPayment.undoPaid(organization);
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
await BalanceItem.updateOutstanding(balanceItemPayments.map(p => p.balanceItem))
|
|
118
|
-
})
|
|
117
|
+
await BalanceItem.updateOutstanding(balanceItemPayments.map(p => p.balanceItem));
|
|
118
|
+
});
|
|
119
119
|
}
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
// Moved to failed
|
|
122
122
|
if (status == PaymentStatus.Failed) {
|
|
123
|
-
await QueueHandler.schedule(
|
|
123
|
+
await QueueHandler.schedule('balance-item-update/' + organization.id, async () => {
|
|
124
124
|
const balanceItemPayments = await BalanceItemPayment.balanceItem.load(
|
|
125
|
-
(await BalanceItemPayment.where({paymentId: payment.id})).map(r => r.setRelation(BalanceItemPayment.payment, payment))
|
|
125
|
+
(await BalanceItemPayment.where({ paymentId: payment.id })).map(r => r.setRelation(BalanceItemPayment.payment, payment)),
|
|
126
126
|
);
|
|
127
127
|
|
|
128
128
|
for (const balanceItemPayment of balanceItemPayments) {
|
|
129
129
|
await balanceItemPayment.markFailed(organization);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
await BalanceItem.updateOutstanding(balanceItemPayments.map(p => p.balanceItem))
|
|
133
|
-
})
|
|
132
|
+
await BalanceItem.updateOutstanding(balanceItemPayments.map(p => p.balanceItem));
|
|
133
|
+
});
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
// If OLD status was FAILED, we need to revert the actions
|
|
137
137
|
if (oldStatus === PaymentStatus.Failed) { // OLD FAILED!! -> NOW PENDING
|
|
138
|
-
await QueueHandler.schedule(
|
|
138
|
+
await QueueHandler.schedule('balance-item-update/' + organization.id, async () => {
|
|
139
139
|
const balanceItemPayments = await BalanceItemPayment.balanceItem.load(
|
|
140
|
-
(await BalanceItemPayment.where({paymentId: payment.id})).map(r => r.setRelation(BalanceItemPayment.payment, payment))
|
|
140
|
+
(await BalanceItemPayment.where({ paymentId: payment.id })).map(r => r.setRelation(BalanceItemPayment.payment, payment)),
|
|
141
141
|
);
|
|
142
142
|
|
|
143
143
|
for (const balanceItemPayment of balanceItemPayments) {
|
|
144
144
|
await balanceItemPayment.undoFailed(organization);
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
await BalanceItem.updateOutstanding(balanceItemPayments.map(p => p.balanceItem))
|
|
148
|
-
})
|
|
147
|
+
await BalanceItem.updateOutstanding(balanceItemPayments.map(p => p.balanceItem));
|
|
148
|
+
});
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
/**
|
|
153
153
|
* ID of payment is needed because of race conditions (need to fetch payment in a race condition save queue)
|
|
154
154
|
*/
|
|
155
|
-
static async pollStatus(paymentId: string, org: Organization|null, cancel = false): Promise<Payment | undefined> {
|
|
155
|
+
static async pollStatus(paymentId: string, org: Organization | null, cancel = false): Promise<Payment | undefined> {
|
|
156
156
|
// Prevent polling the same payment multiple times at the same time: create a queue to prevent races
|
|
157
|
-
QueueHandler.cancel(
|
|
158
|
-
return await QueueHandler.schedule(
|
|
157
|
+
QueueHandler.cancel('payments/' + paymentId); // Prevent creating more than one queue item for the same payment
|
|
158
|
+
return await QueueHandler.schedule('payments/' + paymentId, async () => {
|
|
159
159
|
// Get a new copy of the payment (is required to prevent concurreny bugs)
|
|
160
|
-
const payment = await Payment.getByID(paymentId)
|
|
160
|
+
const payment = await Payment.getByID(paymentId);
|
|
161
161
|
if (!payment) {
|
|
162
|
-
return
|
|
162
|
+
return;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
if (!payment.organizationId) {
|
|
166
|
-
console.error('Payment without organization not supported', payment.id)
|
|
167
|
-
return
|
|
166
|
+
console.error('Payment without organization not supported', payment.id);
|
|
167
|
+
return;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
const organization = org ?? await Organization.getByID(payment.organizationId)
|
|
170
|
+
const organization = org ?? await Organization.getByID(payment.organizationId);
|
|
171
171
|
if (!organization) {
|
|
172
|
-
console.error('Organization not found for payment', payment.id)
|
|
173
|
-
return
|
|
172
|
+
console.error('Organization not found for payment', payment.id);
|
|
173
|
+
return;
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
const testMode = organization.privateMeta.useTestPayments ?? STAMHOOFD.environment
|
|
176
|
+
const testMode = organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production';
|
|
177
177
|
|
|
178
178
|
if (payment.status == PaymentStatus.Pending || payment.status == PaymentStatus.Created || (payment.provider === PaymentProvider.Buckaroo && payment.status == PaymentStatus.Failed)) {
|
|
179
179
|
if (payment.provider === PaymentProvider.Stripe) {
|
|
180
180
|
try {
|
|
181
|
-
let status = await StripeHelper.getStatus(payment, cancel || this.shouldTryToCancel(payment.status, payment), testMode)
|
|
181
|
+
let status = await StripeHelper.getStatus(payment, cancel || this.shouldTryToCancel(payment.status, payment), testMode);
|
|
182
182
|
|
|
183
183
|
if (this.isManualExpired(status, payment)) {
|
|
184
|
-
console.error('Manually marking Stripe payment as expired', payment.id)
|
|
185
|
-
status = PaymentStatus.Failed
|
|
184
|
+
console.error('Manually marking Stripe payment as expired', payment.id);
|
|
185
|
+
status = PaymentStatus.Failed;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
await this.handlePaymentStatusUpdate(payment, organization, status)
|
|
189
|
-
}
|
|
188
|
+
await this.handlePaymentStatusUpdate(payment, organization, status);
|
|
189
|
+
}
|
|
190
|
+
catch (e) {
|
|
190
191
|
console.error('Payment check failed Stripe', payment.id, e);
|
|
191
192
|
if (this.isManualExpired(payment.status, payment)) {
|
|
192
|
-
console.error('Manually marking Stripe payment as expired', payment.id)
|
|
193
|
-
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed)
|
|
193
|
+
console.error('Manually marking Stripe payment as expired', payment.id);
|
|
194
|
+
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed);
|
|
194
195
|
}
|
|
195
196
|
}
|
|
196
|
-
}
|
|
197
|
+
}
|
|
198
|
+
else if (payment.provider === PaymentProvider.Mollie) {
|
|
197
199
|
// check status via mollie
|
|
198
|
-
const molliePayments = await MolliePayment.where({ paymentId: payment.id}, { limit: 1 })
|
|
200
|
+
const molliePayments = await MolliePayment.where({ paymentId: payment.id }, { limit: 1 });
|
|
199
201
|
if (molliePayments.length == 1) {
|
|
200
|
-
const molliePayment = molliePayments[0]
|
|
202
|
+
const molliePayment = molliePayments[0];
|
|
201
203
|
// check status
|
|
202
|
-
const token = await MollieToken.getTokenFor(organization.id)
|
|
203
|
-
|
|
204
|
+
const token = await MollieToken.getTokenFor(organization.id);
|
|
205
|
+
|
|
204
206
|
if (token) {
|
|
205
207
|
try {
|
|
206
208
|
const mollieClient = createMollieClient({ accessToken: await token.getAccessToken() });
|
|
207
209
|
const mollieData = await mollieClient.payments.get(molliePayment.mollieId, {
|
|
208
|
-
testmode: organization.privateMeta.useTestPayments ?? STAMHOOFD.environment
|
|
209
|
-
})
|
|
210
|
+
testmode: organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production',
|
|
211
|
+
});
|
|
210
212
|
|
|
211
|
-
console.log(mollieData) // log to log files to check issues
|
|
213
|
+
console.log(mollieData); // log to log files to check issues
|
|
212
214
|
|
|
213
|
-
const details =
|
|
215
|
+
const details = mollieData.details as any;
|
|
214
216
|
if (details?.consumerName) {
|
|
215
|
-
payment.ibanName = details.consumerName
|
|
217
|
+
payment.ibanName = details.consumerName;
|
|
216
218
|
}
|
|
217
219
|
if (details?.consumerAccount) {
|
|
218
|
-
payment.iban = details.consumerAccount
|
|
220
|
+
payment.iban = details.consumerAccount;
|
|
219
221
|
}
|
|
220
222
|
if (details?.cardHolder) {
|
|
221
|
-
payment.ibanName = details.cardHolder
|
|
223
|
+
payment.ibanName = details.cardHolder;
|
|
222
224
|
}
|
|
223
225
|
if (details?.cardNumber) {
|
|
224
|
-
payment.iban =
|
|
226
|
+
payment.iban = 'xxxx xxxx xxxx ' + details.cardNumber;
|
|
225
227
|
}
|
|
226
228
|
|
|
227
|
-
if (mollieData.status
|
|
228
|
-
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Succeeded)
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
|
|
229
|
+
if (mollieData.status === MolliePaymentStatus.paid) {
|
|
230
|
+
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Succeeded);
|
|
231
|
+
}
|
|
232
|
+
else if (mollieData.status === MolliePaymentStatus.failed || mollieData.status === MolliePaymentStatus.expired || mollieData.status === MolliePaymentStatus.canceled) {
|
|
233
|
+
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed);
|
|
234
|
+
}
|
|
235
|
+
else if (this.isManualExpired(payment.status, payment)) {
|
|
232
236
|
// Mollie still returning pending after 1 day: mark as failed
|
|
233
|
-
console.error('Manually marking Mollie payment as expired', payment.id)
|
|
234
|
-
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed)
|
|
237
|
+
console.error('Manually marking Mollie payment as expired', payment.id);
|
|
238
|
+
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed);
|
|
235
239
|
}
|
|
236
|
-
}
|
|
240
|
+
}
|
|
241
|
+
catch (e) {
|
|
237
242
|
console.error('Payment check failed Mollie', payment.id, e);
|
|
238
243
|
if (this.isManualExpired(payment.status, payment)) {
|
|
239
|
-
console.error('Manually marking Mollie payment as expired', payment.id)
|
|
240
|
-
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed)
|
|
244
|
+
console.error('Manually marking Mollie payment as expired', payment.id);
|
|
245
|
+
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed);
|
|
241
246
|
}
|
|
242
247
|
}
|
|
243
|
-
}
|
|
244
|
-
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
console.warn('Mollie payment is missing for organization ' + organization.id + ' while checking payment status...');
|
|
245
251
|
|
|
246
252
|
if (this.isManualExpired(payment.status, payment)) {
|
|
247
|
-
console.error('Manually marking payment without mollie token as expired', payment.id)
|
|
248
|
-
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed)
|
|
253
|
+
console.error('Manually marking payment without mollie token as expired', payment.id);
|
|
254
|
+
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed);
|
|
249
255
|
}
|
|
250
256
|
}
|
|
251
|
-
}
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
252
259
|
if (this.isManualExpired(payment.status, payment)) {
|
|
253
|
-
console.error('Manually marking payment without mollie payments as expired', payment.id)
|
|
254
|
-
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed)
|
|
260
|
+
console.error('Manually marking payment without mollie payments as expired', payment.id);
|
|
261
|
+
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed);
|
|
255
262
|
}
|
|
256
263
|
}
|
|
257
|
-
}
|
|
258
|
-
|
|
264
|
+
}
|
|
265
|
+
else if (payment.provider == PaymentProvider.Buckaroo) {
|
|
266
|
+
const helper = new BuckarooHelper(organization.privateMeta.buckarooSettings?.key ?? '', organization.privateMeta.buckarooSettings?.secret ?? '', organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production');
|
|
259
267
|
try {
|
|
260
|
-
let status = await helper.getStatus(payment)
|
|
268
|
+
let status = await helper.getStatus(payment);
|
|
261
269
|
|
|
262
270
|
if (this.isManualExpired(status, payment)) {
|
|
263
|
-
console.error('Manually marking Buckaroo payment as expired', payment.id)
|
|
264
|
-
status = PaymentStatus.Failed
|
|
271
|
+
console.error('Manually marking Buckaroo payment as expired', payment.id);
|
|
272
|
+
status = PaymentStatus.Failed;
|
|
265
273
|
}
|
|
266
274
|
|
|
267
|
-
await this.handlePaymentStatusUpdate(payment, organization, status)
|
|
268
|
-
}
|
|
275
|
+
await this.handlePaymentStatusUpdate(payment, organization, status);
|
|
276
|
+
}
|
|
277
|
+
catch (e) {
|
|
269
278
|
console.error('Payment check failed Buckaroo', payment.id, e);
|
|
270
279
|
if (this.isManualExpired(payment.status, payment)) {
|
|
271
|
-
console.error('Manually marking Buckaroo payment as expired', payment.id)
|
|
272
|
-
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed)
|
|
280
|
+
console.error('Manually marking Buckaroo payment as expired', payment.id);
|
|
281
|
+
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed);
|
|
273
282
|
}
|
|
274
283
|
}
|
|
275
|
-
|
|
276
|
-
|
|
284
|
+
}
|
|
285
|
+
else if (payment.provider == PaymentProvider.Payconiq) {
|
|
277
286
|
// Check status
|
|
278
287
|
|
|
279
|
-
const payconiqPayments = await PayconiqPayment.where({ paymentId: payment.id}, { limit: 1 })
|
|
288
|
+
const payconiqPayments = await PayconiqPayment.where({ paymentId: payment.id }, { limit: 1 });
|
|
280
289
|
if (payconiqPayments.length == 1) {
|
|
281
|
-
const payconiqPayment = payconiqPayments[0]
|
|
290
|
+
const payconiqPayment = payconiqPayments[0];
|
|
282
291
|
|
|
283
292
|
if (cancel) {
|
|
284
|
-
console.error('Cancelling Payconiq payment on request', payment.id)
|
|
285
|
-
await payconiqPayment.cancel(organization)
|
|
293
|
+
console.error('Cancelling Payconiq payment on request', payment.id);
|
|
294
|
+
await payconiqPayment.cancel(organization);
|
|
286
295
|
}
|
|
287
296
|
|
|
288
|
-
let status = await payconiqPayment.getStatus(organization)
|
|
297
|
+
let status = await payconiqPayment.getStatus(organization);
|
|
289
298
|
|
|
290
299
|
if (!cancel && this.shouldTryToCancel(status, payment)) {
|
|
291
|
-
console.error('Manually cancelling Payconiq payment', payment.id)
|
|
300
|
+
console.error('Manually cancelling Payconiq payment', payment.id);
|
|
292
301
|
if (await payconiqPayment.cancel(organization)) {
|
|
293
|
-
status = PaymentStatus.Failed
|
|
302
|
+
status = PaymentStatus.Failed;
|
|
294
303
|
}
|
|
295
304
|
}
|
|
296
305
|
|
|
297
306
|
if (this.isManualExpired(status, payment)) {
|
|
298
|
-
console.error('Manually marking Payconiq payment as expired', payment.id)
|
|
299
|
-
status = PaymentStatus.Failed
|
|
307
|
+
console.error('Manually marking Payconiq payment as expired', payment.id);
|
|
308
|
+
status = PaymentStatus.Failed;
|
|
300
309
|
}
|
|
301
310
|
|
|
302
|
-
await this.handlePaymentStatusUpdate(payment, organization, status)
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
console.warn(
|
|
311
|
+
await this.handlePaymentStatusUpdate(payment, organization, status);
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
console.warn('Payconiq payment is missing for organization ' + organization.id + ' while checking payment status...');
|
|
306
315
|
|
|
307
316
|
if (this.isManualExpired(payment.status, payment)) {
|
|
308
|
-
console.error('Manually marking Payconiq payment as expired because not found', payment.id)
|
|
309
|
-
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed)
|
|
317
|
+
console.error('Manually marking Payconiq payment as expired because not found', payment.id);
|
|
318
|
+
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed);
|
|
310
319
|
}
|
|
311
320
|
}
|
|
312
|
-
}
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
313
323
|
console.error('Invalid payment provider', payment.provider, 'for payment', payment.id);
|
|
314
324
|
if (this.isManualExpired(payment.status, payment)) {
|
|
315
|
-
console.error('Manually marking unknown payment as expired', payment.id)
|
|
316
|
-
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed)
|
|
325
|
+
console.error('Manually marking unknown payment as expired', payment.id);
|
|
326
|
+
await this.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed);
|
|
317
327
|
}
|
|
318
328
|
}
|
|
319
|
-
}
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
320
331
|
// Do a manual update if needed
|
|
321
332
|
if (payment.status === PaymentStatus.Succeeded) {
|
|
322
333
|
if (payment.provider === PaymentProvider.Stripe) {
|
|
323
334
|
// Update the status
|
|
324
|
-
await StripeHelper.getStatus(payment, false, testMode)
|
|
335
|
+
await StripeHelper.getStatus(payment, false, testMode);
|
|
325
336
|
}
|
|
326
337
|
}
|
|
327
338
|
}
|
|
328
|
-
return payment
|
|
329
|
-
})
|
|
339
|
+
return payment;
|
|
340
|
+
});
|
|
330
341
|
}
|
|
331
342
|
|
|
332
343
|
static isManualExpired(status: PaymentStatus, payment: Payment) {
|
|
333
344
|
if ((status == PaymentStatus.Pending || status === PaymentStatus.Created) && payment.method !== PaymentMethod.DirectDebit) {
|
|
334
345
|
// If payment is not succeeded after one day, mark as failed
|
|
335
|
-
if (payment.createdAt < new Date(new Date().getTime() - 60*1000*60*24)) {
|
|
346
|
+
if (payment.createdAt < new Date(new Date().getTime() - 60 * 1000 * 60 * 24)) {
|
|
336
347
|
return true;
|
|
337
348
|
}
|
|
338
349
|
}
|
|
@@ -344,11 +355,11 @@ export class ExchangePaymentEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
344
355
|
*/
|
|
345
356
|
static shouldTryToCancel(status: PaymentStatus, payment: Payment) {
|
|
346
357
|
if ((status == PaymentStatus.Pending || status === PaymentStatus.Created) && payment.method !== PaymentMethod.DirectDebit) {
|
|
347
|
-
let timeout = STAMHOOFD.environment === 'development' ? 60*1000*2 : 60*1000*30;
|
|
358
|
+
let timeout = STAMHOOFD.environment === 'development' ? 60 * 1000 * 2 : 60 * 1000 * 30;
|
|
348
359
|
|
|
349
360
|
// If payconiq and not yet 'identified' (scanned), cancel after 5 minutes
|
|
350
361
|
if (payment.provider === PaymentProvider.Payconiq && status === PaymentStatus.Created) {
|
|
351
|
-
timeout = STAMHOOFD.environment === 'development' ? 60*1000*1 : 60*1000*5;
|
|
362
|
+
timeout = STAMHOOFD.environment === 'development' ? 60 * 1000 * 1 : 60 * 1000 * 5;
|
|
352
363
|
}
|
|
353
364
|
|
|
354
365
|
if (payment.createdAt < new Date(new Date().getTime() - timeout)) {
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { DecodedRequest, Endpoint, Request, Response } from
|
|
2
|
-
import { SimpleError } from
|
|
3
|
-
import { signInternal } from
|
|
4
|
-
import { Document } from
|
|
1
|
+
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
2
|
+
import { SimpleError } from '@simonbackx/simple-errors';
|
|
3
|
+
import { signInternal } from '@stamhoofd/backend-env';
|
|
4
|
+
import { Document } from '@stamhoofd/models';
|
|
5
5
|
|
|
6
|
-
import { Context } from
|
|
6
|
+
import { Context } from '../../../helpers/Context';
|
|
7
7
|
type Params = { id: string };
|
|
8
8
|
type Query = undefined;
|
|
9
|
-
type Body = undefined
|
|
10
|
-
type ResponseBody = Buffer
|
|
9
|
+
type Body = undefined;
|
|
10
|
+
type ResponseBody = Buffer;
|
|
11
11
|
|
|
12
12
|
export class GetDocumentHtml extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
13
13
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
14
|
-
if (request.method
|
|
14
|
+
if (request.method !== 'GET') {
|
|
15
15
|
return [false];
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const params = Endpoint.parseParameters(request.url,
|
|
18
|
+
const params = Endpoint.parseParameters(request.url, '/documents/@id/html', { id: String });
|
|
19
19
|
|
|
20
20
|
if (params) {
|
|
21
21
|
return [true, params as Params];
|
|
@@ -24,31 +24,31 @@ export class GetDocumentHtml extends Endpoint<Params, Query, Body, ResponseBody>
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
27
|
-
const organization = await Context.setOrganizationScope()
|
|
28
|
-
await Context.authenticate()
|
|
27
|
+
const organization = await Context.setOrganizationScope();
|
|
28
|
+
await Context.authenticate();
|
|
29
29
|
|
|
30
|
-
const document = await Document.getByID(request.params.id)
|
|
30
|
+
const document = await Document.getByID(request.params.id);
|
|
31
31
|
if (!document || !(await Context.auth.canAccessDocument(document))) {
|
|
32
32
|
throw new SimpleError({
|
|
33
|
-
code:
|
|
34
|
-
message:
|
|
35
|
-
})
|
|
33
|
+
code: 'not_found',
|
|
34
|
+
message: 'Onbekend document',
|
|
35
|
+
});
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
const html = await document.getRenderedHtml(organization);
|
|
39
39
|
if (!html) {
|
|
40
40
|
throw new SimpleError({
|
|
41
|
-
code:
|
|
42
|
-
message:
|
|
43
|
-
})
|
|
41
|
+
code: 'failed_generating',
|
|
42
|
+
message: 'Er ging iets mis bij het aanmaken van het document. Probeer later opieuw en neem contact met ons op als het probleem blijft herhalen.',
|
|
43
|
+
});
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const response = new Response(Buffer.from(html, 'utf8'))
|
|
47
|
-
response.headers[
|
|
48
|
-
response.headers[
|
|
49
|
-
response.headers[
|
|
50
|
-
response.headers[
|
|
51
|
-
response.headers[
|
|
52
|
-
return response
|
|
46
|
+
const response = new Response(Buffer.from(html, 'utf8'));
|
|
47
|
+
response.headers['content-type'] = 'text/plain; charset=utf-8'; // avoid JS execution
|
|
48
|
+
response.headers['content-length'] = Buffer.byteLength(html, 'utf8').toString();
|
|
49
|
+
response.headers['x-cache-id'] = 'document-' + document.id;
|
|
50
|
+
response.headers['x-cache-timestamp'] = document.updatedAt.getTime().toString();
|
|
51
|
+
response.headers['x-cache-signature'] = signInternal('document-' + document.id, document.updatedAt.getTime().toString(), html);
|
|
52
|
+
return response;
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { DecodedRequest, Endpoint, Request, Response } from
|
|
2
|
-
import { SimpleError } from
|
|
3
|
-
import { Payment } from
|
|
4
|
-
import { PaymentGeneral } from
|
|
1
|
+
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
2
|
+
import { SimpleError } from '@simonbackx/simple-errors';
|
|
3
|
+
import { Payment } from '@stamhoofd/models';
|
|
4
|
+
import { PaymentGeneral } from '@stamhoofd/structures';
|
|
5
5
|
|
|
6
|
-
import { AuthenticatedStructures } from
|
|
7
|
-
import { Context } from
|
|
6
|
+
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
|
|
7
|
+
import { Context } from '../../../helpers/Context';
|
|
8
8
|
|
|
9
9
|
type Params = { id: string };
|
|
10
|
-
type Query = undefined
|
|
11
|
-
type Body = undefined
|
|
12
|
-
type ResponseBody = PaymentGeneral
|
|
10
|
+
type Query = undefined;
|
|
11
|
+
type Body = undefined;
|
|
12
|
+
type ResponseBody = PaymentGeneral;
|
|
13
13
|
|
|
14
14
|
export class GetPaymentEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
15
15
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
16
|
-
if (request.method
|
|
16
|
+
if (request.method !== 'GET') {
|
|
17
17
|
return [false];
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const params = Endpoint.parseParameters(request.url,
|
|
20
|
+
const params = Endpoint.parseParameters(request.url, '/payments/@id', { id: String });
|
|
21
21
|
|
|
22
22
|
if (params) {
|
|
23
23
|
return [true, params as Params];
|
|
@@ -26,20 +26,20 @@ export class GetPaymentEndpoint extends Endpoint<Params, Query, Body, ResponseBo
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
29
|
-
await Context.setOptionalOrganizationScope()
|
|
30
|
-
await Context.authenticate()
|
|
29
|
+
await Context.setOptionalOrganizationScope();
|
|
30
|
+
await Context.authenticate();
|
|
31
31
|
|
|
32
32
|
const payment = await Payment.getByID(request.params.id);
|
|
33
33
|
if (!payment) {
|
|
34
34
|
throw new SimpleError({
|
|
35
|
-
code:
|
|
36
|
-
message:
|
|
37
|
-
human:
|
|
38
|
-
})
|
|
35
|
+
code: 'not_found',
|
|
36
|
+
message: 'Payment not found',
|
|
37
|
+
human: 'Je hebt geen toegang tot deze betaling',
|
|
38
|
+
});
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
return new Response(
|
|
42
|
-
await AuthenticatedStructures.paymentGeneral(payment, true)
|
|
42
|
+
await AuthenticatedStructures.paymentGeneral(payment, true),
|
|
43
43
|
);
|
|
44
44
|
}
|
|
45
45
|
}
|