@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,26 +1,26 @@
|
|
|
1
|
-
import { DecodedRequest, Endpoint, Request, Response } from
|
|
2
|
-
import { SimpleError } from
|
|
1
|
+
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
2
|
+
import { SimpleError } from '@simonbackx/simple-errors';
|
|
3
3
|
import { User } from '@stamhoofd/models';
|
|
4
4
|
|
|
5
|
-
import { Context } from
|
|
5
|
+
import { Context } from '../../../../helpers/Context';
|
|
6
6
|
type Params = { id: string };
|
|
7
7
|
type Query = undefined;
|
|
8
|
-
type Body = undefined
|
|
9
|
-
type ResponseBody = undefined
|
|
8
|
+
type Body = undefined;
|
|
9
|
+
type ResponseBody = undefined;
|
|
10
10
|
|
|
11
11
|
export class DeleteUserEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
12
12
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
13
|
-
if (request.method
|
|
13
|
+
if (request.method !== 'DELETE') {
|
|
14
14
|
return [false];
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const params = Endpoint.parseParameters(request.url,
|
|
17
|
+
const params = Endpoint.parseParameters(request.url, '/user/@id', { id: String });
|
|
18
18
|
|
|
19
19
|
if (params) {
|
|
20
20
|
return [true, params as Params];
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const params2 = Endpoint.parseParameters(request.url,
|
|
23
|
+
const params2 = Endpoint.parseParameters(request.url, '/api-keys/@id', { id: String });
|
|
24
24
|
|
|
25
25
|
if (params2) {
|
|
26
26
|
return [true, params2 as Params];
|
|
@@ -31,30 +31,30 @@ export class DeleteUserEndpoint extends Endpoint<Params, Query, Body, ResponseBo
|
|
|
31
31
|
|
|
32
32
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
33
33
|
const organization = await Context.setOrganizationScope();
|
|
34
|
-
const {user} = await Context.authenticate()
|
|
34
|
+
const { user } = await Context.authenticate();
|
|
35
35
|
|
|
36
36
|
// Fast throw first (more in depth checking for patches later)
|
|
37
37
|
if (!await Context.auth.canManageAdmins(organization.id)) {
|
|
38
|
-
throw Context.auth.error()
|
|
38
|
+
throw Context.auth.error();
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
if (user.id == request.params.id) {
|
|
42
42
|
throw new SimpleError({
|
|
43
|
-
code:
|
|
44
|
-
message:
|
|
45
|
-
})
|
|
43
|
+
code: 'permission_denied',
|
|
44
|
+
message: 'Je kan jezelf niet verwijderen',
|
|
45
|
+
});
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
const editUser = await User.getByID(request.params.id)
|
|
48
|
+
const editUser = await User.getByID(request.params.id);
|
|
49
49
|
if (!editUser || !Context.auth.checkScope(editUser.organizationId)) {
|
|
50
50
|
throw new SimpleError({
|
|
51
|
-
code:
|
|
52
|
-
message:
|
|
53
|
-
})
|
|
51
|
+
code: 'permission_denied',
|
|
52
|
+
message: 'Je hebt geen toegang om deze gebruiker te verwijderen',
|
|
53
|
+
});
|
|
54
54
|
}
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
await editUser.delete();
|
|
57
57
|
|
|
58
|
-
return new Response(undefined);
|
|
58
|
+
return new Response(undefined);
|
|
59
59
|
}
|
|
60
60
|
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { DecodedRequest, Endpoint, Request, Response } from
|
|
2
|
-
import { SimpleError } from
|
|
1
|
+
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
2
|
+
import { SimpleError } from '@simonbackx/simple-errors';
|
|
3
3
|
import { Token, User } from '@stamhoofd/models';
|
|
4
|
-
import { ApiUser } from
|
|
4
|
+
import { ApiUser } from '@stamhoofd/structures';
|
|
5
5
|
|
|
6
|
-
import { Context } from
|
|
6
|
+
import { Context } from '../../../../helpers/Context';
|
|
7
7
|
type Params = Record<string, never>;
|
|
8
8
|
type Query = undefined;
|
|
9
|
-
type Body = undefined
|
|
10
|
-
type ResponseBody = ApiUser[]
|
|
9
|
+
type Body = undefined;
|
|
10
|
+
type ResponseBody = ApiUser[];
|
|
11
11
|
|
|
12
12
|
export class GetOrganizationAdminsEndpoint 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, '/api-keys', {});
|
|
19
19
|
|
|
20
20
|
if (params) {
|
|
21
21
|
return [true, params as Params];
|
|
@@ -25,23 +25,23 @@ export class GetOrganizationAdminsEndpoint extends Endpoint<Params, Query, Body,
|
|
|
25
25
|
|
|
26
26
|
async handle(_: DecodedRequest<Params, Query, Body>) {
|
|
27
27
|
const organization = await Context.setOrganizationScope();
|
|
28
|
-
await Context.authenticate()
|
|
28
|
+
await Context.authenticate();
|
|
29
29
|
|
|
30
30
|
// Fast throw first (more in depth checking for patches later)
|
|
31
31
|
if (!await Context.auth.canManageAdmins(organization.id)) {
|
|
32
|
-
throw Context.auth.error()
|
|
32
|
+
throw Context.auth.error();
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// Get all admins
|
|
36
|
-
const admins = await User.getApiUsers([organization.id])
|
|
36
|
+
const admins = await User.getApiUsers([organization.id]);
|
|
37
37
|
|
|
38
|
-
const mapped: ApiUser[] = []
|
|
38
|
+
const mapped: ApiUser[] = [];
|
|
39
39
|
for (const admin of admins) {
|
|
40
|
-
mapped.push(await Token.getAPIUserWithToken(admin))
|
|
40
|
+
mapped.push(await Token.getAPIUserWithToken(admin));
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
return new Response(
|
|
44
|
-
mapped
|
|
44
|
+
mapped,
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { DecodedRequest, Endpoint, Request, Response } from
|
|
1
|
+
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
2
2
|
import { User } from '@stamhoofd/models';
|
|
3
|
-
import { OrganizationAdmins, User as UserStruct } from
|
|
3
|
+
import { OrganizationAdmins, User as UserStruct } from '@stamhoofd/structures';
|
|
4
4
|
|
|
5
|
-
import { Context } from
|
|
6
|
-
import { AuthenticatedStructures } from
|
|
5
|
+
import { Context } from '../../../../helpers/Context';
|
|
6
|
+
import { AuthenticatedStructures } from '../../../../helpers/AuthenticatedStructures';
|
|
7
7
|
type Params = Record<string, never>;
|
|
8
8
|
type Query = undefined;
|
|
9
|
-
type Body = undefined
|
|
10
|
-
type ResponseBody = OrganizationAdmins
|
|
9
|
+
type Body = undefined;
|
|
10
|
+
type ResponseBody = OrganizationAdmins;
|
|
11
11
|
|
|
12
12
|
export class GetOrganizationAdminsEndpoint 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, '/organization/admins', {});
|
|
19
19
|
|
|
20
20
|
if (params) {
|
|
21
21
|
return [true, params as Params];
|
|
@@ -25,18 +25,18 @@ export class GetOrganizationAdminsEndpoint extends Endpoint<Params, Query, Body,
|
|
|
25
25
|
|
|
26
26
|
async handle(_: DecodedRequest<Params, Query, Body>) {
|
|
27
27
|
const organization = await Context.setOrganizationScope();
|
|
28
|
-
await Context.authenticate()
|
|
28
|
+
await Context.authenticate();
|
|
29
29
|
|
|
30
30
|
// Fast throw first (more in depth checking for patches later)
|
|
31
31
|
if (!await Context.auth.canManageAdmins(organization.id)) {
|
|
32
|
-
throw Context.auth.error()
|
|
32
|
+
throw Context.auth.error();
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// Get all admins
|
|
36
|
-
const admins = await User.getAdmins([organization.id])
|
|
36
|
+
const admins = await User.getAdmins([organization.id]);
|
|
37
37
|
|
|
38
38
|
return new Response(OrganizationAdmins.create({
|
|
39
|
-
users: await AuthenticatedStructures.usersWithMembers(admins)
|
|
39
|
+
users: await AuthenticatedStructures.usersWithMembers(admins),
|
|
40
40
|
}));
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Decoder } from '@simonbackx/simple-encoding';
|
|
2
|
-
import { DecodedRequest, Endpoint, Request, Response } from
|
|
2
|
+
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
3
3
|
import { SimpleError, SimpleErrors } from '@simonbackx/simple-errors';
|
|
4
4
|
import { Webshop } from '@stamhoofd/models';
|
|
5
|
-
import { PermissionLevel, PermissionsResourceType, PrivateWebshop, ResourcePermissions, Version, WebshopPrivateMetaData } from
|
|
5
|
+
import { PermissionLevel, PermissionsResourceType, PrivateWebshop, ResourcePermissions, Version, WebshopPrivateMetaData } from '@stamhoofd/structures';
|
|
6
6
|
import { Formatter } from '@stamhoofd/utility';
|
|
7
7
|
|
|
8
8
|
import { Context } from '../../../../helpers/Context';
|
|
@@ -17,14 +17,14 @@ type ResponseBody = PrivateWebshop;
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
export class CreateWebshopEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
20
|
-
bodyDecoder = PrivateWebshop as Decoder<PrivateWebshop
|
|
20
|
+
bodyDecoder = PrivateWebshop as Decoder<PrivateWebshop>;
|
|
21
21
|
|
|
22
22
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
23
|
-
if (request.method
|
|
23
|
+
if (request.method !== 'POST') {
|
|
24
24
|
return [false];
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const params = Endpoint.parseParameters(request.url,
|
|
27
|
+
const params = Endpoint.parseParameters(request.url, '/webshop', {});
|
|
28
28
|
|
|
29
29
|
if (params) {
|
|
30
30
|
return [true, params as Params];
|
|
@@ -34,183 +34,186 @@ export class CreateWebshopEndpoint extends Endpoint<Params, Query, Body, Respons
|
|
|
34
34
|
|
|
35
35
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
36
36
|
const organization = await Context.setOrganizationScope();
|
|
37
|
-
const {user} = await Context.authenticate()
|
|
37
|
+
const { user } = await Context.authenticate();
|
|
38
38
|
|
|
39
39
|
// Fast throw first (more in depth checking for patches later)
|
|
40
40
|
if (!await Context.auth.canCreateWebshops(organization.id)) {
|
|
41
|
-
throw Context.auth.error(
|
|
41
|
+
throw Context.auth.error('Je kan geen webshops maken, vraag aan de hoofdbeheerders om jou toegang te geven.');
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const errors = new SimpleErrors()
|
|
44
|
+
const errors = new SimpleErrors();
|
|
45
45
|
|
|
46
|
-
const webshop = new Webshop()
|
|
46
|
+
const webshop = new Webshop();
|
|
47
47
|
|
|
48
|
-
webshop.id = request.body.id
|
|
49
|
-
webshop.meta = request.body.meta
|
|
48
|
+
webshop.id = request.body.id;
|
|
49
|
+
webshop.meta = request.body.meta;
|
|
50
50
|
webshop.meta.domainActive = false;
|
|
51
|
-
webshop.privateMeta = request.body.privateMeta
|
|
52
|
-
webshop.products = request.body.products
|
|
53
|
-
webshop.categories = request.body.categories
|
|
54
|
-
webshop.organizationId = organization.id
|
|
51
|
+
webshop.privateMeta = request.body.privateMeta;
|
|
52
|
+
webshop.products = request.body.products;
|
|
53
|
+
webshop.categories = request.body.categories;
|
|
54
|
+
webshop.organizationId = organization.id;
|
|
55
55
|
webshop.privateMeta.authorId = user.id;
|
|
56
56
|
webshop.privateMeta.dnsRecords = [];
|
|
57
|
-
let updateDNS = false
|
|
57
|
+
let updateDNS = false;
|
|
58
58
|
|
|
59
59
|
// Check if we can decide the domain
|
|
60
60
|
if (!request.body.domain && !request.body.domainUri) {
|
|
61
|
-
const webshops = await Webshop.where({
|
|
62
|
-
organizationId: organization.id,
|
|
63
|
-
domain: {
|
|
61
|
+
const webshops = await Webshop.where({
|
|
62
|
+
organizationId: organization.id,
|
|
63
|
+
domain: {
|
|
64
64
|
value: null,
|
|
65
|
-
sign:
|
|
65
|
+
sign: '!=',
|
|
66
66
|
},
|
|
67
67
|
domainUri: {
|
|
68
|
-
value:
|
|
69
|
-
sign:
|
|
70
|
-
}
|
|
71
|
-
})
|
|
68
|
+
value: '',
|
|
69
|
+
sign: '!=',
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
72
|
|
|
73
|
-
const counters = new Map<string, number>()
|
|
73
|
+
const counters = new Map<string, number>();
|
|
74
74
|
for (const webshop of webshops) {
|
|
75
75
|
if (!webshop.domain || !webshop.meta.domainActive) {
|
|
76
|
-
continue
|
|
76
|
+
continue;
|
|
77
77
|
}
|
|
78
|
-
const count
|
|
79
|
-
counters.set(webshop.domain, count)
|
|
78
|
+
const count = (counters.get(webshop.domain) ?? 0) + 1;
|
|
79
|
+
counters.set(webshop.domain, count);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
if (counters.size > 0) {
|
|
83
|
-
const maxDomain = [...counters.entries()].reduce((a, e
|
|
84
|
-
console.log(
|
|
85
|
-
|
|
86
|
-
webshop.domain = maxDomain
|
|
87
|
-
webshop.domainUri = Formatter.slug(webshop.meta.name)
|
|
88
|
-
webshop.privateMeta.dnsRecords = WebshopPrivateMetaData.buildDNSRecords(maxDomain)
|
|
89
|
-
await this.checkDomainUri(webshop)
|
|
90
|
-
updateDNS = true
|
|
83
|
+
const maxDomain = [...counters.entries()].reduce((a, e) => e[1] > a[1] ? e : a)[0];
|
|
84
|
+
console.log('Choosing default domain for new webshop: ', maxDomain);
|
|
85
|
+
|
|
86
|
+
webshop.domain = maxDomain;
|
|
87
|
+
webshop.domainUri = Formatter.slug(webshop.meta.name);
|
|
88
|
+
webshop.privateMeta.dnsRecords = WebshopPrivateMetaData.buildDNSRecords(maxDomain);
|
|
89
|
+
await this.checkDomainUri(webshop);
|
|
90
|
+
updateDNS = true;
|
|
91
91
|
}
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
94
|
if (request.body.domain) {
|
|
95
|
-
webshop.domain = request.body.domain
|
|
95
|
+
webshop.domain = request.body.domain;
|
|
96
96
|
|
|
97
97
|
if (request.body.domainUri) {
|
|
98
|
-
webshop.domainUri = Formatter.slug(request.body.domainUri)
|
|
98
|
+
webshop.domainUri = Formatter.slug(request.body.domainUri);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
webshop.privateMeta.dnsRecords = WebshopPrivateMetaData.buildDNSRecords(request.body.domain)
|
|
102
|
-
await this.checkDomainUri(webshop)
|
|
103
|
-
updateDNS = true
|
|
101
|
+
webshop.privateMeta.dnsRecords = WebshopPrivateMetaData.buildDNSRecords(request.body.domain);
|
|
102
|
+
await this.checkDomainUri(webshop);
|
|
103
|
+
updateDNS = true;
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
webshop.uri = request.body.uri.length > 0 ? Formatter.slug(request.body.uri) : Formatter.slug(webshop.meta.name)
|
|
107
|
+
webshop.uri = request.body.uri.length > 0 ? Formatter.slug(request.body.uri) : Formatter.slug(webshop.meta.name);
|
|
108
108
|
|
|
109
109
|
// Check if this uri is inique
|
|
110
|
-
let original = webshop.uri
|
|
111
|
-
const possibleSuffixes = [new Date().getFullYear().toString(), Formatter.slug(organization.uri)]
|
|
110
|
+
let original = webshop.uri;
|
|
111
|
+
const possibleSuffixes = [new Date().getFullYear().toString(), Formatter.slug(organization.uri)];
|
|
112
112
|
|
|
113
113
|
// Remove possible suffices from original
|
|
114
114
|
for (const suffix of possibleSuffixes) {
|
|
115
|
-
if (original.endsWith(
|
|
116
|
-
original = original.slice(0, -suffix.length - 1)
|
|
115
|
+
if (original.endsWith('-' + suffix)) {
|
|
116
|
+
original = original.slice(0, -suffix.length - 1);
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
let tried = 0
|
|
120
|
+
let tried = 0;
|
|
121
121
|
while (webshop.uri.length > 100 || await Webshop.getByURI(webshop.uri) !== undefined) {
|
|
122
|
+
console.log('Webshop already exists', webshop.uri);
|
|
122
123
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
let suffix = ""
|
|
124
|
+
let suffix = '';
|
|
126
125
|
if (tried < possibleSuffixes.length) {
|
|
127
|
-
suffix =
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
126
|
+
suffix = '-' + possibleSuffixes[tried];
|
|
127
|
+
}
|
|
128
|
+
else if (tried > 9) {
|
|
129
|
+
suffix = '-' + Math.floor(Math.random() * 100000);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
suffix = '-' + (tried - possibleSuffixes.length + 2);
|
|
132
133
|
}
|
|
133
|
-
|
|
134
|
+
|
|
134
135
|
webshop.uri = original.slice(0, 100 - suffix.length) + suffix;
|
|
135
|
-
|
|
136
|
-
tried
|
|
136
|
+
|
|
137
|
+
tried++;
|
|
137
138
|
if (tried > 15) {
|
|
138
|
-
console.log(
|
|
139
|
+
console.log('Failed to generate unique webshop uri');
|
|
139
140
|
|
|
140
141
|
throw new SimpleError({
|
|
141
|
-
code:
|
|
142
|
-
message:
|
|
143
|
-
human:
|
|
144
|
-
statusCode: 500
|
|
145
|
-
})
|
|
142
|
+
code: 'failed_to_generate_unique_uri',
|
|
143
|
+
message: 'Failed to generate unique uri',
|
|
144
|
+
human: 'Er is een fout opgetreden bij het maken van de webshop, kies een andere naam voor jouw webshop',
|
|
145
|
+
statusCode: 500,
|
|
146
|
+
});
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
if (!await Context.auth.canAccessWebshop(webshop, PermissionLevel.Full)) {
|
|
150
151
|
// Create a temporary permission role for this user
|
|
151
|
-
const organizationPermissions = user.permissions?.organizationPermissions?.get(organization.id)
|
|
152
|
+
const organizationPermissions = user.permissions?.organizationPermissions?.get(organization.id);
|
|
152
153
|
if (!organizationPermissions) {
|
|
153
|
-
throw new Error('Unexpected missing permissions')
|
|
154
|
+
throw new Error('Unexpected missing permissions');
|
|
154
155
|
}
|
|
155
156
|
const resourcePermissions = ResourcePermissions.create({
|
|
156
157
|
resourceName: webshop.meta.name,
|
|
157
|
-
level: PermissionLevel.Full
|
|
158
|
-
})
|
|
159
|
-
const patch = resourcePermissions.createInsertPatch(PermissionsResourceType.Webshops, webshop.id, organizationPermissions)
|
|
160
|
-
user.permissions!.organizationPermissions.set(organization.id, organizationPermissions.patch(patch))
|
|
161
|
-
console.log('Automatically granted author full permissions to resource', 'webshop', webshop.id, 'user', user.id, 'patch', patch.encode({version: Version}))
|
|
162
|
-
await user.save()
|
|
158
|
+
level: PermissionLevel.Full,
|
|
159
|
+
});
|
|
160
|
+
const patch = resourcePermissions.createInsertPatch(PermissionsResourceType.Webshops, webshop.id, organizationPermissions);
|
|
161
|
+
user.permissions!.organizationPermissions.set(organization.id, organizationPermissions.patch(patch));
|
|
162
|
+
console.log('Automatically granted author full permissions to resource', 'webshop', webshop.id, 'user', user.id, 'patch', patch.encode({ version: Version }));
|
|
163
|
+
await user.save();
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
// Verify if we have full access
|
|
166
167
|
if (!await Context.auth.canAccessWebshop(webshop, PermissionLevel.Full)) {
|
|
167
168
|
throw new SimpleError({
|
|
168
|
-
code:
|
|
169
|
-
message:
|
|
170
|
-
human:
|
|
171
|
-
})
|
|
169
|
+
code: 'missing_permissions',
|
|
170
|
+
message: 'You cannot create a webshop without having full permissions on the created webshop',
|
|
171
|
+
human: 'Als je een webshop aanmaakt moet je ervoor zorgen dat jezelf ook volledige toegang hebt.',
|
|
172
|
+
});
|
|
172
173
|
}
|
|
173
174
|
|
|
174
|
-
await webshop.save()
|
|
175
|
+
await webshop.save();
|
|
175
176
|
|
|
176
177
|
if (updateDNS) {
|
|
177
|
-
await webshop.updateDNSRecords()
|
|
178
|
+
await webshop.updateDNSRecords();
|
|
178
179
|
}
|
|
179
|
-
|
|
180
|
-
errors.throwIfNotEmpty()
|
|
180
|
+
|
|
181
|
+
errors.throwIfNotEmpty();
|
|
181
182
|
return new Response(PrivateWebshop.create(webshop));
|
|
182
183
|
}
|
|
183
184
|
|
|
184
185
|
async checkDomainUri(webshop: Webshop) {
|
|
185
186
|
if (!webshop.domain) {
|
|
186
|
-
return
|
|
187
|
+
return;
|
|
187
188
|
}
|
|
188
189
|
// Check if this uri is inique
|
|
189
|
-
const original = webshop.domainUri ? webshop.domainUri + '-' : ''
|
|
190
|
-
const possibleSuffixes = [new Date().getFullYear().toString()]
|
|
191
|
-
let tried = 0
|
|
190
|
+
const original = webshop.domainUri ? webshop.domainUri + '-' : '';
|
|
191
|
+
const possibleSuffixes = [new Date().getFullYear().toString()];
|
|
192
|
+
let tried = 0;
|
|
192
193
|
while (await Webshop.getByDomain(webshop.domain, webshop.domainUri) !== undefined) {
|
|
193
|
-
console.log(
|
|
194
|
+
console.log('Webshop already exists', webshop.domainUri);
|
|
194
195
|
|
|
195
196
|
if (tried < possibleSuffixes.length) {
|
|
196
|
-
webshop.domainUri = original + possibleSuffixes[tried]
|
|
197
|
-
} else if (tried > 9) {
|
|
198
|
-
webshop.domainUri = original + Math.floor(Math.random() * 100000)
|
|
199
|
-
} else {
|
|
200
|
-
webshop.domainUri = original + (tried - possibleSuffixes.length + 2)
|
|
197
|
+
webshop.domainUri = original + possibleSuffixes[tried];
|
|
201
198
|
}
|
|
202
|
-
|
|
203
|
-
|
|
199
|
+
else if (tried > 9) {
|
|
200
|
+
webshop.domainUri = original + Math.floor(Math.random() * 100000);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
webshop.domainUri = original + (tried - possibleSuffixes.length + 2);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
tried++;
|
|
204
207
|
|
|
205
208
|
if (tried > 15) {
|
|
206
|
-
console.log(
|
|
209
|
+
console.log('Failed to generate unique webshop domainUri');
|
|
207
210
|
|
|
208
211
|
throw new SimpleError({
|
|
209
|
-
code:
|
|
210
|
-
message:
|
|
211
|
-
human:
|
|
212
|
-
statusCode: 500
|
|
213
|
-
})
|
|
212
|
+
code: 'failed_to_generate_unique_domainUri',
|
|
213
|
+
message: 'Failed to generate unique domainUri',
|
|
214
|
+
human: 'Er is een fout opgetreden bij het maken van de webshop, kies een andere naam voor jouw webshop',
|
|
215
|
+
statusCode: 500,
|
|
216
|
+
});
|
|
214
217
|
}
|
|
215
218
|
}
|
|
216
219
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { DecodedRequest, Endpoint, Request, Response } from
|
|
1
|
+
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
2
2
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
3
3
|
import { BalanceItem, Order, Webshop } from '@stamhoofd/models';
|
|
4
|
-
import { PermissionLevel } from
|
|
4
|
+
import { PermissionLevel } from '@stamhoofd/structures';
|
|
5
5
|
|
|
6
|
-
import { Context } from
|
|
6
|
+
import { Context } from '../../../../helpers/Context';
|
|
7
7
|
|
|
8
8
|
type Params = { id: string };
|
|
9
9
|
type Query = undefined;
|
|
@@ -15,13 +15,12 @@ type ResponseBody = undefined;
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
export class DeleteWebshopEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
18
|
-
|
|
19
18
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
20
|
-
if (request.method
|
|
19
|
+
if (request.method !== 'DELETE') {
|
|
21
20
|
return [false];
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
const params = Endpoint.parseParameters(request.url,
|
|
23
|
+
const params = Endpoint.parseParameters(request.url, '/webshop/@id', { id: String });
|
|
25
24
|
|
|
26
25
|
if (params) {
|
|
27
26
|
return [true, params as Params];
|
|
@@ -31,21 +30,21 @@ export class DeleteWebshopEndpoint extends Endpoint<Params, Query, Body, Respons
|
|
|
31
30
|
|
|
32
31
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
33
32
|
const organization = await Context.setOrganizationScope();
|
|
34
|
-
await Context.authenticate()
|
|
33
|
+
await Context.authenticate();
|
|
35
34
|
|
|
36
35
|
// Fast throw first (more in depth checking for patches later)
|
|
37
36
|
if (!await Context.auth.hasSomeAccess(organization.id)) {
|
|
38
|
-
throw Context.auth.error()
|
|
37
|
+
throw Context.auth.error();
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
const webshop = await Webshop.getByID(request.params.id)
|
|
40
|
+
const webshop = await Webshop.getByID(request.params.id);
|
|
42
41
|
if (!webshop || !await Context.auth.canAccessWebshop(webshop, PermissionLevel.Full)) {
|
|
43
|
-
throw Context.auth.notFoundOrNoAccess()
|
|
42
|
+
throw Context.auth.notFoundOrNoAccess();
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
const orders = await Order.where({ webshopId: webshop.id });
|
|
47
|
-
await BalanceItem.deleteForDeletedOrders(orders.map(o => o.id))
|
|
48
|
-
await webshop.delete()
|
|
46
|
+
await BalanceItem.deleteForDeletedOrders(orders.map(o => o.id));
|
|
47
|
+
await webshop.delete();
|
|
49
48
|
return new Response(undefined);
|
|
50
49
|
}
|
|
51
50
|
}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import { DecodedRequest, Endpoint, Request, Response } from
|
|
1
|
+
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
2
2
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
3
3
|
import { Webshop, WebshopDiscountCode } from '@stamhoofd/models';
|
|
4
|
-
import { DiscountCode, PermissionLevel } from
|
|
4
|
+
import { DiscountCode, PermissionLevel } from '@stamhoofd/structures';
|
|
5
5
|
|
|
6
|
-
import { Context } from
|
|
6
|
+
import { Context } from '../../../../helpers/Context';
|
|
7
7
|
|
|
8
8
|
type Params = { id: string };
|
|
9
|
-
type Query = undefined
|
|
10
|
-
type Body = undefined
|
|
11
|
-
type ResponseBody = DiscountCode[]
|
|
9
|
+
type Query = undefined;
|
|
10
|
+
type Body = undefined;
|
|
11
|
+
type ResponseBody = DiscountCode[];
|
|
12
12
|
|
|
13
13
|
export class GetWebshopDiscountCodesEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
14
14
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
15
|
-
if (request.method
|
|
15
|
+
if (request.method !== 'GET') {
|
|
16
16
|
return [false];
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const params = Endpoint.parseParameters(request.url,
|
|
19
|
+
const params = Endpoint.parseParameters(request.url, '/webshop/@id/discount-codes', { id: String });
|
|
20
20
|
|
|
21
21
|
if (params) {
|
|
22
22
|
return [true, params as Params];
|
|
@@ -26,22 +26,22 @@ export class GetWebshopDiscountCodesEndpoint extends Endpoint<Params, Query, Bod
|
|
|
26
26
|
|
|
27
27
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
28
28
|
const organization = await Context.setOrganizationScope();
|
|
29
|
-
await Context.authenticate()
|
|
29
|
+
await Context.authenticate();
|
|
30
30
|
|
|
31
31
|
// Fast throw first (more in depth checking for patches later)
|
|
32
32
|
if (!await Context.auth.hasSomeAccess(organization.id)) {
|
|
33
|
-
throw Context.auth.error()
|
|
33
|
+
throw Context.auth.error();
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const webshop = await Webshop.getByID(request.params.id)
|
|
36
|
+
const webshop = await Webshop.getByID(request.params.id);
|
|
37
37
|
if (!webshop || !await Context.auth.canAccessWebshop(webshop, PermissionLevel.Full)) {
|
|
38
|
-
throw Context.auth.notFoundOrNoAccess()
|
|
38
|
+
throw Context.auth.notFoundOrNoAccess();
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
const discountCodes = await WebshopDiscountCode.where({webshopId: request.params.id})
|
|
40
|
+
|
|
41
|
+
const discountCodes = await WebshopDiscountCode.where({ webshopId: request.params.id });
|
|
42
42
|
|
|
43
43
|
return new Response(
|
|
44
|
-
discountCodes.map(d => d.getStructure())
|
|
44
|
+
discountCodes.map(d => d.getStructure()),
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
47
|
}
|