@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
|
@@ -10,13 +10,12 @@ type Body = undefined;
|
|
|
10
10
|
type ResponseBody = UserWithMembers;
|
|
11
11
|
|
|
12
12
|
export class GetUserEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
13
|
-
|
|
14
13
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
15
|
-
if (request.method
|
|
14
|
+
if (request.method !== 'GET') {
|
|
16
15
|
return [false];
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
const params = Endpoint.parseParameters(request.url,
|
|
18
|
+
const params = Endpoint.parseParameters(request.url, '/user', {});
|
|
20
19
|
|
|
21
20
|
if (params) {
|
|
22
21
|
return [true, params as Params];
|
|
@@ -25,11 +24,11 @@ export class GetUserEndpoint extends Endpoint<Params, Query, Body, ResponseBody>
|
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
28
|
-
await Context.setOptionalOrganizationScope()
|
|
29
|
-
const {user} = await Context.authenticate({allowWithoutAccount: true})
|
|
27
|
+
await Context.setOptionalOrganizationScope();
|
|
28
|
+
const { user } = await Context.authenticate({ allowWithoutAccount: true });
|
|
30
29
|
|
|
31
30
|
return new Response(
|
|
32
|
-
await AuthenticatedStructures.userWithMembers(user)
|
|
31
|
+
await AuthenticatedStructures.userWithMembers(user),
|
|
33
32
|
);
|
|
34
33
|
}
|
|
35
34
|
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import { AutoEncoderPatchType, Decoder } from '@simonbackx/simple-encoding';
|
|
2
|
-
import { DecodedRequest, Endpoint, Request, Response } from
|
|
3
|
-
import { SimpleError } from
|
|
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, PermissionLevel, UserPermissions } from
|
|
5
|
+
import { ApiUser, PermissionLevel, UserPermissions } from '@stamhoofd/structures';
|
|
6
6
|
|
|
7
7
|
import { Context } from '../../helpers/Context';
|
|
8
8
|
|
|
9
9
|
type Params = { id: string };
|
|
10
10
|
type Query = undefined;
|
|
11
|
-
type Body = AutoEncoderPatchType<ApiUser
|
|
12
|
-
type ResponseBody = ApiUser
|
|
11
|
+
type Body = AutoEncoderPatchType<ApiUser>;
|
|
12
|
+
type ResponseBody = ApiUser;
|
|
13
13
|
|
|
14
14
|
export class PatchUserEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
15
|
-
bodyDecoder = ApiUser.patchType() as Decoder<AutoEncoderPatchType<ApiUser
|
|
15
|
+
bodyDecoder = ApiUser.patchType() as Decoder<AutoEncoderPatchType<ApiUser>>;
|
|
16
16
|
|
|
17
17
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
18
|
-
if (request.method
|
|
18
|
+
if (request.method !== 'PATCH') {
|
|
19
19
|
return [false];
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const params = Endpoint.parseParameters(request.url,
|
|
22
|
+
const params = Endpoint.parseParameters(request.url, '/api-keys/@id', { id: String });
|
|
23
23
|
|
|
24
24
|
if (params) {
|
|
25
25
|
return [true, params as Params];
|
|
@@ -29,55 +29,57 @@ export class PatchUserEndpoint extends Endpoint<Params, Query, Body, ResponseBod
|
|
|
29
29
|
|
|
30
30
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
31
31
|
const organization = await Context.setOrganizationScope();
|
|
32
|
-
const {user} = await Context.authenticate()
|
|
32
|
+
const { user } = await Context.authenticate();
|
|
33
33
|
|
|
34
34
|
if (request.body.id !== request.params.id) {
|
|
35
35
|
throw new SimpleError({
|
|
36
|
-
code:
|
|
37
|
-
message:
|
|
38
|
-
statusCode: 400
|
|
39
|
-
})
|
|
36
|
+
code: 'invalid_request',
|
|
37
|
+
message: 'Invalid request: id mismatch',
|
|
38
|
+
statusCode: 400,
|
|
39
|
+
});
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
const editUser = request.body.id === user.id ? user : await User.getByID(request.body.id)
|
|
43
|
-
|
|
42
|
+
const editUser = request.body.id === user.id ? user : await User.getByID(request.body.id);
|
|
43
|
+
|
|
44
44
|
if (!editUser || !await Context.auth.canAccessUser(editUser, PermissionLevel.Write) || !editUser.isApiUser) {
|
|
45
|
-
throw Context.auth.notFoundOrNoAccess(
|
|
45
|
+
throw Context.auth.notFoundOrNoAccess('Je hebt geen toegang om deze API-user te wijzigen');
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
editUser.firstName = request.body.name ?? editUser.name
|
|
49
|
-
editUser.lastName = null
|
|
48
|
+
editUser.firstName = request.body.name ?? editUser.name;
|
|
49
|
+
editUser.lastName = null;
|
|
50
50
|
|
|
51
51
|
if (request.body.permissions !== undefined && editUser.permissions) {
|
|
52
52
|
if (!await Context.auth.canAccessUser(editUser, PermissionLevel.Full)) {
|
|
53
53
|
throw new SimpleError({
|
|
54
|
-
code:
|
|
55
|
-
message:
|
|
56
|
-
})
|
|
54
|
+
code: 'permission_denied',
|
|
55
|
+
message: 'Je hebt geen rechten om de rechten van deze API-user te wijzigen',
|
|
56
|
+
});
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
if (request.body.permissions) {
|
|
60
60
|
if (organization) {
|
|
61
|
-
editUser.permissions = UserPermissions.limitedPatch(editUser.permissions, request.body.permissions, organization.id)
|
|
61
|
+
editUser.permissions = UserPermissions.limitedPatch(editUser.permissions, request.body.permissions, organization.id);
|
|
62
62
|
|
|
63
63
|
if (editUser.id === user.id && (!editUser.permissions || !editUser.permissions.forOrganization(organization)?.hasFullAccess())) {
|
|
64
64
|
throw new SimpleError({
|
|
65
|
-
code:
|
|
66
|
-
message:
|
|
67
|
-
})
|
|
65
|
+
code: 'permission_denied',
|
|
66
|
+
message: 'Je kan jezelf niet verwijderen als hoofdbeheerder',
|
|
67
|
+
});
|
|
68
68
|
}
|
|
69
|
-
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
70
71
|
if (editUser.permissions) {
|
|
71
|
-
editUser.permissions.patchOrPut(request.body.permissions)
|
|
72
|
-
}
|
|
73
|
-
|
|
72
|
+
editUser.permissions.patchOrPut(request.body.permissions);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
editUser.permissions = request.body.permissions.isPut() ? request.body.permissions : null;
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
if (editUser.id === user.id && !editUser.permissions?.platform?.hasFullAccess()) {
|
|
77
79
|
throw new SimpleError({
|
|
78
|
-
code:
|
|
79
|
-
message:
|
|
80
|
-
})
|
|
80
|
+
code: 'permission_denied',
|
|
81
|
+
message: 'Je kan jezelf niet verwijderen als hoofdbeheerder',
|
|
82
|
+
});
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
85
|
}
|
|
@@ -85,6 +87,6 @@ export class PatchUserEndpoint extends Endpoint<Params, Query, Body, ResponseBod
|
|
|
85
87
|
|
|
86
88
|
await editUser.save();
|
|
87
89
|
|
|
88
|
-
return new Response(await Token.getAPIUserWithToken(editUser));
|
|
90
|
+
return new Response(await Token.getAPIUserWithToken(editUser));
|
|
89
91
|
}
|
|
90
92
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { AutoEncoderPatchType, Decoder } from '@simonbackx/simple-encoding';
|
|
2
|
-
import { DecodedRequest, Endpoint, Request, Response } from
|
|
3
|
-
import { SimpleError } from
|
|
2
|
+
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
3
|
+
import { SimpleError } from '@simonbackx/simple-errors';
|
|
4
4
|
import { EmailVerificationCode, Member, PasswordToken, Token, User } from '@stamhoofd/models';
|
|
5
|
-
import { NewUser, PermissionLevel, SignupResponse, UserPermissions, UserWithMembers } from
|
|
5
|
+
import { NewUser, PermissionLevel, SignupResponse, UserPermissions, UserWithMembers } from '@stamhoofd/structures';
|
|
6
6
|
|
|
7
7
|
import { Context } from '../../helpers/Context';
|
|
8
8
|
import { MemberUserSyncer } from '../../helpers/MemberUserSyncer';
|
|
@@ -10,18 +10,18 @@ import { AuthenticatedStructures } from '../../helpers/AuthenticatedStructures';
|
|
|
10
10
|
|
|
11
11
|
type Params = { id: string };
|
|
12
12
|
type Query = undefined;
|
|
13
|
-
type Body = AutoEncoderPatchType<NewUser
|
|
14
|
-
type ResponseBody = UserWithMembers
|
|
13
|
+
type Body = AutoEncoderPatchType<NewUser>;
|
|
14
|
+
type ResponseBody = UserWithMembers;
|
|
15
15
|
|
|
16
16
|
export class PatchUserEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
17
|
-
bodyDecoder = NewUser.patchType() as Decoder<AutoEncoderPatchType<NewUser
|
|
17
|
+
bodyDecoder = NewUser.patchType() as Decoder<AutoEncoderPatchType<NewUser>>;
|
|
18
18
|
|
|
19
19
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
20
|
-
if (request.method
|
|
20
|
+
if (request.method !== 'PATCH') {
|
|
21
21
|
return [false];
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
const params = Endpoint.parseParameters(request.url,
|
|
24
|
+
const params = Endpoint.parseParameters(request.url, '/user/@id', { id: String });
|
|
25
25
|
|
|
26
26
|
if (params) {
|
|
27
27
|
return [true, params as Params];
|
|
@@ -31,76 +31,79 @@ export class PatchUserEndpoint extends Endpoint<Params, Query, Body, ResponseBod
|
|
|
31
31
|
|
|
32
32
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
33
33
|
const organization = await Context.setOptionalOrganizationScope();
|
|
34
|
-
const {user, token} = await Context.authenticate({allowWithoutAccount: true})
|
|
34
|
+
const { user, token } = await Context.authenticate({ allowWithoutAccount: true });
|
|
35
35
|
|
|
36
36
|
if (request.body.id !== request.params.id) {
|
|
37
37
|
throw new SimpleError({
|
|
38
|
-
code:
|
|
39
|
-
message:
|
|
40
|
-
statusCode: 400
|
|
41
|
-
})
|
|
38
|
+
code: 'invalid_request',
|
|
39
|
+
message: 'Invalid request: id mismatch',
|
|
40
|
+
statusCode: 400,
|
|
41
|
+
});
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const editUser = request.body.id === user.id ? user : await User.getByID(request.body.id)
|
|
45
|
-
|
|
44
|
+
const editUser = request.body.id === user.id ? user : await User.getByID(request.body.id);
|
|
45
|
+
|
|
46
46
|
if (!editUser || !await Context.auth.canAccessUser(editUser, PermissionLevel.Write) || editUser.isApiUser) {
|
|
47
|
-
throw Context.auth.notFoundOrNoAccess(
|
|
47
|
+
throw Context.auth.notFoundOrNoAccess('Je hebt geen toegang om deze gebruiker te wijzigen');
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
if (await Context.auth.canEditUserName(editUser)) {
|
|
51
51
|
if (editUser.memberId) {
|
|
52
|
-
const member = await Member.getWithRegistrations(editUser.memberId)
|
|
52
|
+
const member = await Member.getWithRegistrations(editUser.memberId);
|
|
53
53
|
if (member) {
|
|
54
|
-
member.details.firstName = request.body.firstName ?? member.details.firstName
|
|
55
|
-
member.details.lastName = request.body.lastName ?? member.details.lastName
|
|
54
|
+
member.details.firstName = request.body.firstName ?? member.details.firstName;
|
|
55
|
+
member.details.lastName = request.body.lastName ?? member.details.lastName;
|
|
56
56
|
|
|
57
|
-
editUser.firstName = member.details.firstName
|
|
58
|
-
editUser.lastName = member.details.lastName
|
|
59
|
-
await member.save()
|
|
57
|
+
editUser.firstName = member.details.firstName;
|
|
58
|
+
editUser.lastName = member.details.lastName;
|
|
59
|
+
await member.save();
|
|
60
60
|
|
|
61
61
|
// Also propage the name change to other users of the same member if needed
|
|
62
|
-
await MemberUserSyncer.onChangeMember(member)
|
|
62
|
+
await MemberUserSyncer.onChangeMember(member);
|
|
63
63
|
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
editUser.
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
editUser.firstName = request.body.firstName ?? editUser.firstName;
|
|
67
|
+
editUser.lastName = request.body.lastName ?? editUser.lastName;
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
if (request.body.permissions !== undefined) {
|
|
71
72
|
if (!await Context.auth.canAccessUser(editUser, PermissionLevel.Full)) {
|
|
72
73
|
throw new SimpleError({
|
|
73
|
-
code:
|
|
74
|
-
message:
|
|
75
|
-
})
|
|
74
|
+
code: 'permission_denied',
|
|
75
|
+
message: 'Je hebt geen rechten om de rechten van deze gebruiker te wijzigen',
|
|
76
|
+
});
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
if (request.body.permissions) {
|
|
79
80
|
if (organization) {
|
|
80
|
-
editUser.permissions = UserPermissions.limitedPatch(editUser.permissions, request.body.permissions, organization.id)
|
|
81
|
+
editUser.permissions = UserPermissions.limitedPatch(editUser.permissions, request.body.permissions, organization.id);
|
|
81
82
|
|
|
82
83
|
if (editUser.id === user.id && (!editUser.permissions || !editUser.permissions.forOrganization(organization)?.hasFullAccess()) && STAMHOOFD.environment !== 'development') {
|
|
83
84
|
throw new SimpleError({
|
|
84
|
-
code:
|
|
85
|
-
message:
|
|
86
|
-
})
|
|
85
|
+
code: 'permission_denied',
|
|
86
|
+
message: 'Je kan jezelf niet verwijderen als hoofdbeheerder',
|
|
87
|
+
});
|
|
87
88
|
}
|
|
88
|
-
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
89
91
|
if (editUser.permissions) {
|
|
90
|
-
editUser.permissions.patchOrPut(request.body.permissions)
|
|
91
|
-
}
|
|
92
|
-
|
|
92
|
+
editUser.permissions.patchOrPut(request.body.permissions);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
editUser.permissions = request.body.permissions.isPut() ? request.body.permissions : null;
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
if (editUser.permissions && editUser.permissions.isEmpty) {
|
|
96
|
-
editUser.permissions = null
|
|
99
|
+
editUser.permissions = null;
|
|
97
100
|
}
|
|
98
101
|
|
|
99
102
|
if (editUser.id === user.id && !editUser.permissions?.platform?.hasFullAccess() && STAMHOOFD.environment !== 'development') {
|
|
100
103
|
throw new SimpleError({
|
|
101
|
-
code:
|
|
102
|
-
message:
|
|
103
|
-
})
|
|
104
|
+
code: 'permission_denied',
|
|
105
|
+
message: 'Je kan jezelf niet verwijderen als hoofdbeheerder',
|
|
106
|
+
});
|
|
104
107
|
}
|
|
105
108
|
}
|
|
106
109
|
}
|
|
@@ -108,9 +111,9 @@ export class PatchUserEndpoint extends Endpoint<Params, Query, Body, ResponseBod
|
|
|
108
111
|
|
|
109
112
|
if (editUser.id == user.id && request.body.password) {
|
|
110
113
|
// password changes
|
|
111
|
-
await editUser.changePassword(request.body.password)
|
|
112
|
-
await PasswordToken.clearFor(editUser.id)
|
|
113
|
-
await Token.clearFor(editUser.id, token.accessToken)
|
|
114
|
+
await editUser.changePassword(request.body.password);
|
|
115
|
+
await PasswordToken.clearFor(editUser.id);
|
|
116
|
+
await Token.clearFor(editUser.id, token.accessToken);
|
|
114
117
|
}
|
|
115
118
|
|
|
116
119
|
await editUser.save();
|
|
@@ -119,23 +122,23 @@ export class PatchUserEndpoint extends Endpoint<Params, Query, Body, ResponseBod
|
|
|
119
122
|
if (request.body.email && request.body.email !== editUser.email) {
|
|
120
123
|
// Create an validation code
|
|
121
124
|
// We always need the code, to return it. Also on password recovery -> may not be visible to the client whether the user exists or not
|
|
122
|
-
const code = await EmailVerificationCode.createFor(editUser, request.body.email)
|
|
123
|
-
code.send(editUser, organization, request.i18n, editUser.id === user.id)
|
|
125
|
+
const code = await EmailVerificationCode.createFor(editUser, request.body.email);
|
|
126
|
+
code.send(editUser, organization, request.i18n, editUser.id === user.id).catch(console.error);
|
|
124
127
|
|
|
125
128
|
throw new SimpleError({
|
|
126
|
-
code:
|
|
127
|
-
message:
|
|
128
|
-
human: editUser.id === user.id ?
|
|
129
|
+
code: 'verify_email',
|
|
130
|
+
message: 'Your email address needs verification',
|
|
131
|
+
human: editUser.id === user.id ? 'Verifieer jouw nieuwe e-mailadres via de link in de e-mail, daarna passen we het automatisch aan.' : 'Er is een verificatie e-mail verstuurd naar ' + request.body.email + ' om het e-mailadres te verifiëren. Zodra dat is gebeurd, wordt het e-mailadres gewijzigd.',
|
|
129
132
|
meta: SignupResponse.create({
|
|
130
133
|
token: code.token,
|
|
131
134
|
}).encode({ version: request.request.getVersion() }),
|
|
132
|
-
statusCode: 403
|
|
135
|
+
statusCode: 403,
|
|
133
136
|
});
|
|
134
137
|
}
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
return new Response(
|
|
138
|
-
await AuthenticatedStructures.userWithMembers(editUser)
|
|
139
|
-
);
|
|
141
|
+
await AuthenticatedStructures.userWithMembers(editUser),
|
|
142
|
+
);
|
|
140
143
|
}
|
|
141
144
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
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 { EmailVerificationCode } from '@stamhoofd/models';
|
|
4
|
-
import { PollEmailVerificationRequest, PollEmailVerificationResponse } from
|
|
4
|
+
import { PollEmailVerificationRequest, PollEmailVerificationResponse } from '@stamhoofd/structures';
|
|
5
5
|
|
|
6
6
|
import { Context } from '../../helpers/Context';
|
|
7
7
|
|
|
@@ -14,11 +14,11 @@ export class PollEmailVerificationEndpoint extends Endpoint<Params, Query, Body,
|
|
|
14
14
|
bodyDecoder = PollEmailVerificationRequest as Decoder<PollEmailVerificationRequest>;
|
|
15
15
|
|
|
16
16
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
17
|
-
if (request.method
|
|
17
|
+
if (request.method !== 'POST') {
|
|
18
18
|
return [false];
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const params = Endpoint.parseParameters(request.url,
|
|
21
|
+
const params = Endpoint.parseParameters(request.url, '/verify-email/poll', {});
|
|
22
22
|
|
|
23
23
|
if (params) {
|
|
24
24
|
return [true, params as Params];
|
|
@@ -27,11 +27,11 @@ export class PollEmailVerificationEndpoint extends Endpoint<Params, Query, Body,
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
30
|
-
const organization = await Context.setOptionalOrganizationScope()
|
|
31
|
-
const valid = await EmailVerificationCode.poll(organization?.id ?? null, request.body.token)
|
|
32
|
-
|
|
30
|
+
const organization = await Context.setOptionalOrganizationScope();
|
|
31
|
+
const valid = await EmailVerificationCode.poll(organization?.id ?? null, request.body.token);
|
|
32
|
+
|
|
33
33
|
return new Response(PollEmailVerificationResponse.create({
|
|
34
|
-
valid
|
|
34
|
+
valid,
|
|
35
35
|
}));
|
|
36
36
|
}
|
|
37
|
-
}
|
|
37
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
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 { EmailVerificationCode } from '@stamhoofd/models';
|
|
4
|
-
import { PollEmailVerificationRequest, PollEmailVerificationResponse } from
|
|
4
|
+
import { PollEmailVerificationRequest, PollEmailVerificationResponse } from '@stamhoofd/structures';
|
|
5
5
|
|
|
6
6
|
import { Context } from '../../helpers/Context';
|
|
7
7
|
|
|
@@ -14,11 +14,11 @@ export class PollEmailVerificationEndpoint extends Endpoint<Params, Query, Body,
|
|
|
14
14
|
bodyDecoder = PollEmailVerificationRequest as Decoder<PollEmailVerificationRequest>;
|
|
15
15
|
|
|
16
16
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
17
|
-
if (request.method
|
|
17
|
+
if (request.method !== 'POST') {
|
|
18
18
|
return [false];
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const params = Endpoint.parseParameters(request.url,
|
|
21
|
+
const params = Endpoint.parseParameters(request.url, '/verify-email/retry', {});
|
|
22
22
|
|
|
23
23
|
if (params) {
|
|
24
24
|
return [true, params as Params];
|
|
@@ -27,15 +27,15 @@ export class PollEmailVerificationEndpoint extends Endpoint<Params, Query, Body,
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
30
|
-
const organization = await Context.setOptionalOrganizationScope()
|
|
30
|
+
const organization = await Context.setOptionalOrganizationScope();
|
|
31
31
|
const valid = await EmailVerificationCode.poll(organization?.id ?? null, request.body.token);
|
|
32
32
|
|
|
33
33
|
if (valid) {
|
|
34
|
-
EmailVerificationCode.resend(organization, request.body.token, request.i18n).catch(console.error)
|
|
34
|
+
EmailVerificationCode.resend(organization, request.body.token, request.i18n).catch(console.error);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
return new Response(PollEmailVerificationResponse.create({
|
|
38
|
-
valid
|
|
38
|
+
valid,
|
|
39
39
|
}));
|
|
40
40
|
}
|
|
41
|
-
}
|
|
41
|
+
}
|
|
@@ -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 } from '@simonbackx/simple-errors';
|
|
4
4
|
import { EmailVerificationCode, PasswordToken, sendEmailTemplate, User } from '@stamhoofd/models';
|
|
5
|
-
import { EmailTemplateType, NewUser, Recipient, Replacement, SignupResponse } from
|
|
5
|
+
import { EmailTemplateType, NewUser, Recipient, Replacement, SignupResponse } from '@stamhoofd/structures';
|
|
6
6
|
|
|
7
7
|
import { Context } from '../../helpers/Context';
|
|
8
8
|
|
|
@@ -15,11 +15,11 @@ export class SignupEndpoint extends Endpoint<Params, Query, Body, ResponseBody>
|
|
|
15
15
|
bodyDecoder = NewUser as Decoder<NewUser>;
|
|
16
16
|
|
|
17
17
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
18
|
-
if (request.method
|
|
18
|
+
if (request.method !== 'POST') {
|
|
19
19
|
return [false];
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const params = Endpoint.parseParameters(request.url,
|
|
22
|
+
const params = Endpoint.parseParameters(request.url, '/sign-up', {});
|
|
23
23
|
|
|
24
24
|
if (params) {
|
|
25
25
|
return [true, params as Params];
|
|
@@ -28,32 +28,34 @@ export class SignupEndpoint extends Endpoint<Params, Query, Body, ResponseBody>
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
31
|
-
const organization = await Context.setUserOrganizationScope()
|
|
31
|
+
const organization = await Context.setUserOrganizationScope();
|
|
32
32
|
|
|
33
|
-
const u = await User.getForRegister(organization?.id ?? null, request.body.email)
|
|
33
|
+
const u = await User.getForRegister(organization?.id ?? null, request.body.email);
|
|
34
34
|
|
|
35
35
|
// Don't optimize. Always run two queries atm.
|
|
36
|
-
let user = u
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
let user = u
|
|
37
|
+
? undefined
|
|
38
|
+
: (await User.register(
|
|
39
|
+
organization,
|
|
40
|
+
request.body,
|
|
41
|
+
));
|
|
40
42
|
|
|
41
|
-
let sendCode = true
|
|
43
|
+
let sendCode = true;
|
|
42
44
|
|
|
43
45
|
if (!user) {
|
|
44
46
|
if (!u) {
|
|
45
47
|
// Fail silently because user did exist, and we don't want to expose that the user doesn't exists
|
|
46
|
-
console.error("Could not register, but user doesn't exist: "+request.body.email)
|
|
48
|
+
console.error("Could not register, but user doesn't exist: " + request.body.email);
|
|
47
49
|
|
|
48
50
|
throw new SimpleError({
|
|
49
|
-
code:
|
|
50
|
-
message:
|
|
51
|
-
human:
|
|
52
|
-
statusCode: 500
|
|
53
|
-
})
|
|
51
|
+
code: 'unexpected_error',
|
|
52
|
+
message: 'Something went wrong',
|
|
53
|
+
human: 'Er ging iets mis',
|
|
54
|
+
statusCode: 500,
|
|
55
|
+
});
|
|
54
56
|
}
|
|
55
57
|
|
|
56
|
-
user = u
|
|
58
|
+
user = u;
|
|
57
59
|
|
|
58
60
|
if (u.hasAccount()) {
|
|
59
61
|
// Don't send the code
|
|
@@ -62,7 +64,7 @@ export class SignupEndpoint extends Endpoint<Params, Query, Body, ResponseBody>
|
|
|
62
64
|
// We don't await this block to avoid user enumeration attack using request response time
|
|
63
65
|
(async () => {
|
|
64
66
|
// Send an e-mail to say you already have an account + follow password forgot flow
|
|
65
|
-
const recoveryUrl = await PasswordToken.getPasswordRecoveryUrl(user, organization, request.i18n)
|
|
67
|
+
const recoveryUrl = await PasswordToken.getPasswordRecoveryUrl(user, organization, request.i18n);
|
|
66
68
|
|
|
67
69
|
// Create e-mail builder
|
|
68
70
|
await sendEmailTemplate(organization, {
|
|
@@ -74,42 +76,41 @@ export class SignupEndpoint extends Endpoint<Params, Query, Body, ResponseBody>
|
|
|
74
76
|
replacements: [
|
|
75
77
|
Replacement.create({
|
|
76
78
|
token: 'resetUrl',
|
|
77
|
-
value: recoveryUrl
|
|
78
|
-
})
|
|
79
|
-
]
|
|
80
|
-
})
|
|
79
|
+
value: recoveryUrl,
|
|
80
|
+
}),
|
|
81
|
+
],
|
|
82
|
+
}),
|
|
81
83
|
],
|
|
82
84
|
template: {
|
|
83
85
|
type: EmailTemplateType.SignupAlreadyHasAccount,
|
|
84
86
|
},
|
|
85
|
-
type: 'transactional'
|
|
86
|
-
})
|
|
87
|
-
|
|
87
|
+
type: 'transactional',
|
|
88
|
+
});
|
|
88
89
|
})().catch(console.error);
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
91
92
|
// This is safe, because we are the first one. There is no password yet.
|
|
92
93
|
// If a hacker tries this, he won't be able to sign in, because he needs to
|
|
93
94
|
// verify the e-mail first (same as if the user didn't exist)
|
|
94
95
|
// If we didn't set the password, we would allow a different kind of attack:
|
|
95
96
|
// a hacker could send an e-mail to the user (try to register again, seindgin a new email which would trigger a different password change), right after the user registered (without verifying yet), when he had set a different password
|
|
96
|
-
// user clicks on second e-mail -> this sets the hackers password instead
|
|
97
|
-
user.verified = false
|
|
98
|
-
await user.changePassword(request.body.password)
|
|
99
|
-
await PasswordToken.clearFor(user.id)
|
|
100
|
-
await user.save()
|
|
97
|
+
// user clicks on second e-mail -> this sets the hackers password instead
|
|
98
|
+
user.verified = false;
|
|
99
|
+
await user.changePassword(request.body.password);
|
|
100
|
+
await PasswordToken.clearFor(user.id);
|
|
101
|
+
await user.save();
|
|
101
102
|
}
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
// We always need the code, to return it. Also on password recovery -> may not be visible to the client whether the user exists or not
|
|
105
|
-
const code = await EmailVerificationCode.createFor(user, user.email)
|
|
106
|
+
const code = await EmailVerificationCode.createFor(user, user.email);
|
|
106
107
|
|
|
107
108
|
if (sendCode) {
|
|
108
|
-
code.send(user, organization, request.i18n).catch(console.error)
|
|
109
|
+
code.send(user, organization, request.i18n).catch(console.error);
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
return new Response(SignupResponse.create({
|
|
112
|
-
token: code.token
|
|
113
|
+
token: code.token,
|
|
113
114
|
}));
|
|
114
115
|
}
|
|
115
116
|
}
|