@stamhoofd/backend 2.39.1 → 2.40.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +275 -273
- 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 +58 -60
- 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,191 +1,291 @@
|
|
|
1
|
-
import { SimpleError } from
|
|
2
|
-
import { Event, Group, Member, MemberPlatformMembership, MemberResponsibilityRecord, MemberWithRegistrations, Organization, OrganizationRegistrationPeriod, Payment, RegistrationPeriod, User, Webshop } from
|
|
1
|
+
import { SimpleError } from '@simonbackx/simple-errors';
|
|
2
|
+
import { Event, Group, Member, MemberPlatformMembership, MemberResponsibilityRecord, MemberWithRegistrations, Organization, OrganizationRegistrationPeriod, Payment, RegistrationPeriod, User, Webshop } from '@stamhoofd/models';
|
|
3
3
|
import { Event as EventStruct, Group as GroupStruct, MemberPlatformMembership as MemberPlatformMembershipStruct, MemberWithRegistrationsBlob, MembersBlob, OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct, Organization as OrganizationStruct, PaymentGeneral, PermissionLevel, PrivateWebshop, UserWithMembers, WebshopPreview, Webshop as WebshopStruct } from '@stamhoofd/structures';
|
|
4
4
|
|
|
5
|
-
import { Formatter } from
|
|
6
|
-
import { Context } from
|
|
5
|
+
import { Formatter } from '@stamhoofd/utility';
|
|
6
|
+
import { Context } from './Context';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Builds authenticated structures for the current user
|
|
10
10
|
*/
|
|
11
11
|
export class AuthenticatedStructures {
|
|
12
12
|
static async paymentGeneral(payment: Payment, checkPermissions = true): Promise<PaymentGeneral> {
|
|
13
|
-
return (await this.paymentsGeneral([payment], checkPermissions))[0]
|
|
13
|
+
return (await this.paymentsGeneral([payment], checkPermissions))[0];
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
* @param payments
|
|
17
|
+
*
|
|
18
|
+
* @param payments
|
|
19
19
|
* @param checkPermissions Only set to undefined when not returned in the API + not for public use
|
|
20
|
-
* @returns
|
|
20
|
+
* @returns
|
|
21
21
|
*/
|
|
22
22
|
static async paymentsGeneral(payments: Payment[], checkPermissions = true): Promise<PaymentGeneral[]> {
|
|
23
23
|
if (payments.length === 0) {
|
|
24
|
-
return []
|
|
24
|
+
return [];
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const {balanceItemPayments, balanceItems} = await Payment.loadBalanceItems(payments)
|
|
28
|
-
const {registrations, orders} = await Payment.loadBalanceItemRelations(balanceItems);
|
|
27
|
+
const { balanceItemPayments, balanceItems } = await Payment.loadBalanceItems(payments);
|
|
28
|
+
const { registrations, orders } = await Payment.loadBalanceItemRelations(balanceItems);
|
|
29
29
|
|
|
30
30
|
if (checkPermissions) {
|
|
31
31
|
// Note: permission checking is moved here for performacne to avoid loading the data multiple times
|
|
32
|
-
if (!(await Context.auth.canAccessBalanceItems(balanceItems, PermissionLevel.Read, {registrations, orders}))) {
|
|
32
|
+
if (!(await Context.auth.canAccessBalanceItems(balanceItems, PermissionLevel.Read, { registrations, orders }))) {
|
|
33
33
|
throw new SimpleError({
|
|
34
|
-
code:
|
|
35
|
-
message:
|
|
36
|
-
human:
|
|
37
|
-
})
|
|
34
|
+
code: 'not_found',
|
|
35
|
+
message: 'Payment not found',
|
|
36
|
+
human: 'Je hebt geen toegang tot deze betaling',
|
|
37
|
+
});
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
const includeSettlements = checkPermissions && !!Context.user && !!Context.user.permissions
|
|
41
|
+
const includeSettlements = checkPermissions && !!Context.user && !!Context.user.permissions;
|
|
42
42
|
|
|
43
|
-
console.log('includeSettlements', includeSettlements)
|
|
43
|
+
console.log('includeSettlements', includeSettlements);
|
|
44
44
|
|
|
45
45
|
return Payment.getGeneralStructureFromRelations({
|
|
46
46
|
payments,
|
|
47
47
|
balanceItemPayments,
|
|
48
|
-
balanceItems
|
|
49
|
-
}, includeSettlements)
|
|
48
|
+
balanceItems,
|
|
49
|
+
}, includeSettlements);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
static async group(group: Group) {
|
|
53
|
-
return (await this.groups([group]))[0]
|
|
53
|
+
return (await this.groups([group]))[0];
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
static async groups(groups: Group[]) {
|
|
57
|
-
const waitingListIds = Formatter.uniqueArray(groups.map(g => g.waitingListId).filter(id => id !== null))
|
|
58
|
-
const waitingLists = waitingListIds.length > 0 ? await Group.getByIDs(...waitingListIds) : []
|
|
57
|
+
const waitingListIds = Formatter.uniqueArray(groups.map(g => g.waitingListId).filter(id => id !== null));
|
|
58
|
+
const waitingLists = waitingListIds.length > 0 ? await Group.getByIDs(...waitingListIds) : [];
|
|
59
59
|
|
|
60
|
-
const structs: GroupStruct[] = []
|
|
60
|
+
const structs: GroupStruct[] = [];
|
|
61
61
|
for (const group of groups) {
|
|
62
|
-
const waitingList = waitingLists.find(g => g.id == group.waitingListId) ?? null
|
|
63
|
-
const waitingListStruct = waitingList ? GroupStruct.create(waitingList) : null
|
|
62
|
+
const waitingList = waitingLists.find(g => g.id == group.waitingListId) ?? null;
|
|
63
|
+
const waitingListStruct = waitingList ? GroupStruct.create(waitingList) : null;
|
|
64
64
|
if (waitingList && waitingListStruct && !await Context.optionalAuth?.canAccessGroup(waitingList)) {
|
|
65
65
|
waitingListStruct.privateSettings = null;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
const struct = GroupStruct.create({
|
|
69
69
|
...group,
|
|
70
|
-
waitingList: waitingListStruct
|
|
71
|
-
})
|
|
70
|
+
waitingList: waitingListStruct,
|
|
71
|
+
});
|
|
72
72
|
|
|
73
73
|
if (!await Context.optionalAuth?.canAccessGroup(group)) {
|
|
74
74
|
struct.privateSettings = null;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
structs.push(struct)
|
|
77
|
+
structs.push(struct);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
return structs;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
static async organizationRegistrationPeriods(organizationRegistrationPeriods: OrganizationRegistrationPeriod[]) {
|
|
83
|
+
static async organizationRegistrationPeriods(organizationRegistrationPeriods: OrganizationRegistrationPeriod[], periods?: RegistrationPeriod[]) {
|
|
84
84
|
if (organizationRegistrationPeriods.length === 0) {
|
|
85
85
|
return [];
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
if (!periods) {
|
|
89
|
+
const periodIds = Formatter.uniqueArray(organizationRegistrationPeriods.map(p => p.periodId));
|
|
90
|
+
periods = await RegistrationPeriod.getByIDs(...periodIds);
|
|
91
|
+
}
|
|
90
92
|
|
|
91
|
-
const groupIds = Formatter.uniqueArray(organizationRegistrationPeriods.flatMap(p => p.settings.categories.flatMap(c => c.groupIds)))
|
|
92
|
-
const groups = groupIds.length ? await Group.getByIDs(...groupIds) : []
|
|
93
|
+
const groupIds = Formatter.uniqueArray(organizationRegistrationPeriods.flatMap(p => p.settings.categories.flatMap(c => c.groupIds)));
|
|
94
|
+
const groups = groupIds.length ? await Group.getByIDs(...groupIds) : [];
|
|
93
95
|
|
|
94
|
-
const groupStructs = await this.groups(groups)
|
|
96
|
+
const groupStructs = await this.groups(groups);
|
|
95
97
|
|
|
96
|
-
const structs: OrganizationRegistrationPeriodStruct[] = []
|
|
98
|
+
const structs: OrganizationRegistrationPeriodStruct[] = [];
|
|
97
99
|
for (const organizationPeriod of organizationRegistrationPeriods) {
|
|
98
|
-
const period = periods.find(p => p.id == organizationPeriod.periodId) ?? null
|
|
100
|
+
const period = periods.find(p => p.id == organizationPeriod.periodId) ?? null;
|
|
99
101
|
if (!period) {
|
|
100
|
-
continue
|
|
102
|
+
continue;
|
|
101
103
|
}
|
|
102
|
-
const groupIds = Formatter.uniqueArray(organizationPeriod.settings.categories.flatMap(c => c.groupIds))
|
|
104
|
+
const groupIds = Formatter.uniqueArray(organizationPeriod.settings.categories.flatMap(c => c.groupIds));
|
|
103
105
|
|
|
104
106
|
structs.push(
|
|
105
107
|
OrganizationRegistrationPeriodStruct.create({
|
|
106
108
|
...organizationPeriod,
|
|
107
109
|
period: period.getStructure(),
|
|
108
|
-
groups: groupStructs.filter(gg => groupIds.includes(gg.id)).sort(GroupStruct.defaultSort)
|
|
109
|
-
})
|
|
110
|
-
)
|
|
110
|
+
groups: groupStructs.filter(gg => groupIds.includes(gg.id)).sort(GroupStruct.defaultSort),
|
|
111
|
+
}),
|
|
112
|
+
);
|
|
111
113
|
}
|
|
112
114
|
|
|
113
|
-
return structs
|
|
115
|
+
return structs;
|
|
114
116
|
}
|
|
115
117
|
|
|
116
|
-
static async organizationRegistrationPeriod(organizationRegistrationPeriod: OrganizationRegistrationPeriod) {
|
|
117
|
-
return (await this.organizationRegistrationPeriods([organizationRegistrationPeriod]))[0]
|
|
118
|
+
static async organizationRegistrationPeriod(organizationRegistrationPeriod: OrganizationRegistrationPeriod, periods?: RegistrationPeriod[]) {
|
|
119
|
+
return (await this.organizationRegistrationPeriods([organizationRegistrationPeriod], periods))[0];
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
static async webshop(webshop: Webshop) {
|
|
121
123
|
if (await Context.optionalAuth?.canAccessWebshop(webshop)) {
|
|
122
|
-
return PrivateWebshop.create(webshop)
|
|
124
|
+
return PrivateWebshop.create(webshop);
|
|
123
125
|
}
|
|
124
|
-
return WebshopStruct.create(webshop)
|
|
126
|
+
return WebshopStruct.create(webshop);
|
|
125
127
|
}
|
|
126
128
|
|
|
127
129
|
static async organization(organization: Organization): Promise<OrganizationStruct> {
|
|
128
|
-
|
|
130
|
+
return (await this.organizations([organization]))[0];
|
|
131
|
+
}
|
|
129
132
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
+
static async organizations(organizations: Organization[]): Promise<OrganizationStruct[]> {
|
|
134
|
+
if (organizations.length === 0) {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
133
137
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
// #region get period ids / organizations map
|
|
139
|
+
const periodIdOrganizationsMap = new Map<string, Organization[]>();
|
|
140
|
+
|
|
141
|
+
for (const organization of organizations) {
|
|
142
|
+
const periodId = organization.periodId;
|
|
143
|
+
const array = periodIdOrganizationsMap.get(periodId);
|
|
144
|
+
if (array !== undefined) {
|
|
145
|
+
array.push(organization);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
periodIdOrganizationsMap.set(periodId, [organization]);
|
|
139
149
|
}
|
|
150
|
+
}
|
|
151
|
+
// #endregion
|
|
140
152
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
153
|
+
// #region get registration period and whether private data can be accessed for each organization
|
|
154
|
+
const organizationData: Map<string, { organizationRegistrationPeriod: OrganizationRegistrationPeriod; canAccessPrivateData: boolean }> = new Map();
|
|
155
|
+
const organizationIdsToGetWebshopsFor: string[] = [];
|
|
156
|
+
|
|
157
|
+
for (const [periodId, organizations] of periodIdOrganizationsMap.entries()) {
|
|
158
|
+
const organizationMap = new Map(organizations.map(o => [o.id, o]));
|
|
159
|
+
|
|
160
|
+
const result = await OrganizationRegistrationPeriod.where({
|
|
161
|
+
periodId,
|
|
162
|
+
organizationId: {
|
|
163
|
+
sign: 'IN',
|
|
164
|
+
value: Array.from(organizationMap.keys()),
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const organizationRegistrationPeriods = new Map(result.map(r => [r.organizationId, r]));
|
|
169
|
+
|
|
170
|
+
for (const organization of organizations) {
|
|
171
|
+
const organizationId = organization.id;
|
|
172
|
+
const organizationRegistrationPeriod = organizationRegistrationPeriods.get(organizationId) ?? await organization.getPeriod();
|
|
173
|
+
|
|
174
|
+
// check if private data can be accessed
|
|
175
|
+
const canAccessPrivateData = await Context.optionalAuth?.canAccessPrivateOrganizationData(organization) ?? false;
|
|
176
|
+
if (canAccessPrivateData) {
|
|
177
|
+
organizationIdsToGetWebshopsFor.push(organizationId);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
organizationData.set(organizationId, { organizationRegistrationPeriod, canAccessPrivateData });
|
|
181
|
+
}
|
|
147
182
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
183
|
+
// #endregion
|
|
184
|
+
|
|
185
|
+
// #region get periods
|
|
186
|
+
const allPeriodIds = periodIdOrganizationsMap.keys();
|
|
187
|
+
const allPeriods = await RegistrationPeriod.getByIDs(...allPeriodIds);
|
|
188
|
+
const periodMap = new Map<string, RegistrationPeriod>(allPeriods.map(p => [p.id, p]));
|
|
189
|
+
// #endregion
|
|
190
|
+
|
|
191
|
+
// #region get webshop previews
|
|
192
|
+
const webshops = organizationIdsToGetWebshopsFor.length > 0
|
|
193
|
+
? await Webshop.where(
|
|
194
|
+
{
|
|
195
|
+
organizationId: {
|
|
196
|
+
sign: 'IN',
|
|
197
|
+
value: organizationIdsToGetWebshopsFor,
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
{ select: Webshop.selectColumnsWithout(undefined, 'products', 'categories') },
|
|
201
|
+
)
|
|
202
|
+
: [];
|
|
154
203
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
204
|
+
const webshopPreviews = new Map<string, WebshopPreview[]>();
|
|
205
|
+
|
|
206
|
+
for (const w of webshops) {
|
|
207
|
+
if (!await Context.auth.canAccessWebshop(w)) {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const organizationId = w.organizationId;
|
|
212
|
+
const array = webshopPreviews.get(organizationId);
|
|
213
|
+
const preview = WebshopPreview.create(w);
|
|
214
|
+
|
|
215
|
+
if (array) {
|
|
216
|
+
array.push(preview);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
webshopPreviews.set(organizationId, [preview]);
|
|
220
|
+
}
|
|
159
221
|
}
|
|
222
|
+
// #endregion
|
|
223
|
+
|
|
224
|
+
// #region create organization structs
|
|
225
|
+
const results: OrganizationStruct[] = [];
|
|
160
226
|
|
|
161
|
-
const structs: OrganizationStruct[] = [];
|
|
162
227
|
for (const organization of organizations) {
|
|
163
|
-
|
|
228
|
+
const registrationPeriod = periodMap.get(organization.periodId);
|
|
229
|
+
if (!registrationPeriod) {
|
|
230
|
+
console.error('Registration period is undefined.');
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const organizationId = organization.id;
|
|
235
|
+
const data = organizationData.get(organizationId);
|
|
236
|
+
if (data === undefined) {
|
|
237
|
+
console.error('Organization data is undefined.');
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
let result: OrganizationStruct;
|
|
242
|
+
|
|
243
|
+
const period = await this.organizationRegistrationPeriod(data.organizationRegistrationPeriod, [registrationPeriod]);
|
|
244
|
+
const baseStruct = organization.getBaseStructure();
|
|
245
|
+
|
|
246
|
+
if (data.canAccessPrivateData) {
|
|
247
|
+
result = OrganizationStruct.create({
|
|
248
|
+
...baseStruct,
|
|
249
|
+
period,
|
|
250
|
+
privateMeta: organization.privateMeta,
|
|
251
|
+
webshops: webshopPreviews.get(organization.id),
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
result = OrganizationStruct.create({
|
|
256
|
+
...baseStruct,
|
|
257
|
+
period,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
results.push(result);
|
|
164
262
|
}
|
|
165
|
-
|
|
263
|
+
// #endregion
|
|
264
|
+
|
|
265
|
+
return results;
|
|
166
266
|
}
|
|
167
267
|
|
|
168
268
|
static async adminOrganizations(organizations: Organization[]): Promise<OrganizationStruct[]> {
|
|
169
269
|
const structs: OrganizationStruct[] = [];
|
|
170
270
|
|
|
171
271
|
for (const organization of organizations) {
|
|
172
|
-
const base = organization.getBaseStructure()
|
|
173
|
-
structs.push(base)
|
|
272
|
+
const base = organization.getBaseStructure();
|
|
273
|
+
structs.push(base);
|
|
174
274
|
}
|
|
175
|
-
|
|
176
|
-
return Promise.resolve(structs)
|
|
275
|
+
|
|
276
|
+
return Promise.resolve(structs);
|
|
177
277
|
}
|
|
178
278
|
|
|
179
279
|
static async userWithMembers(user: User): Promise<UserWithMembers> {
|
|
180
|
-
const members = await Member.getMembersWithRegistrationForUser(user)
|
|
280
|
+
const members = await Member.getMembersWithRegistrationForUser(user);
|
|
181
281
|
|
|
182
282
|
return UserWithMembers.create({
|
|
183
283
|
...user,
|
|
184
284
|
hasAccount: user.hasAccount(),
|
|
185
285
|
|
|
186
286
|
// Always include the current context organization - because it is possible we switch organization and we don't want to refetch every time
|
|
187
|
-
members: await this.membersBlob(members, true, user)
|
|
188
|
-
})
|
|
287
|
+
members: await this.membersBlob(members, true, user),
|
|
288
|
+
});
|
|
189
289
|
}
|
|
190
290
|
|
|
191
291
|
/**
|
|
@@ -193,134 +293,133 @@ export class AuthenticatedStructures {
|
|
|
193
293
|
*/
|
|
194
294
|
static async usersWithMembers(users: User[]): Promise<UserWithMembers[]> {
|
|
195
295
|
const structs: UserWithMembers[] = [];
|
|
196
|
-
const memberIds = Formatter.uniqueArray(users.map(u => u.memberId).filter(id => id !== null))
|
|
197
|
-
const members = memberIds.length > 0 ? await Member.getBlobByIds(...memberIds) : []
|
|
296
|
+
const memberIds = Formatter.uniqueArray(users.map(u => u.memberId).filter(id => id !== null));
|
|
297
|
+
const members = memberIds.length > 0 ? await Member.getBlobByIds(...memberIds) : [];
|
|
198
298
|
|
|
199
299
|
for (const user of users) {
|
|
200
|
-
const filteredMembers = user.memberId ? members.filter(m => m.id === user.memberId) : []
|
|
300
|
+
const filteredMembers = user.memberId ? members.filter(m => m.id === user.memberId) : [];
|
|
201
301
|
structs.push(UserWithMembers.create({
|
|
202
302
|
...user,
|
|
203
303
|
hasAccount: user.hasAccount(),
|
|
204
|
-
members: await this.membersBlob(filteredMembers, false)
|
|
205
|
-
}))
|
|
304
|
+
members: await this.membersBlob(filteredMembers, false),
|
|
305
|
+
}));
|
|
206
306
|
}
|
|
207
|
-
|
|
208
|
-
return structs
|
|
307
|
+
|
|
308
|
+
return structs;
|
|
209
309
|
}
|
|
210
310
|
|
|
211
311
|
static async membersBlob(members: MemberWithRegistrations[], includeContextOrganization = false, includeUser?: User): Promise<MembersBlob> {
|
|
212
312
|
if (members.length === 0 && !includeUser) {
|
|
213
|
-
return MembersBlob.create({members: [], organizations: []})
|
|
313
|
+
return MembersBlob.create({ members: [], organizations: [] });
|
|
214
314
|
}
|
|
215
|
-
const organizations = new Map<string, Organization>()
|
|
216
|
-
|
|
315
|
+
const organizations = new Map<string, Organization>();
|
|
316
|
+
|
|
217
317
|
if (includeUser) {
|
|
218
318
|
for (const organizationId of includeUser.permissions?.organizationPermissions.keys() ?? []) {
|
|
219
319
|
if (includeContextOrganization || organizationId !== Context.auth.organization?.id) {
|
|
220
320
|
const found = organizations.get(organizationId);
|
|
221
321
|
if (!found) {
|
|
222
|
-
const organization = await Context.auth.getOrganization(organizationId)
|
|
223
|
-
organizations.set(organization.id, organization)
|
|
322
|
+
const organization = await Context.auth.getOrganization(organizationId);
|
|
323
|
+
organizations.set(organization.id, organization);
|
|
224
324
|
}
|
|
225
325
|
}
|
|
226
326
|
}
|
|
227
327
|
}
|
|
228
328
|
|
|
229
|
-
|
|
230
|
-
const memberBlobs: MemberWithRegistrationsBlob[] = []
|
|
329
|
+
const memberBlobs: MemberWithRegistrationsBlob[] = [];
|
|
231
330
|
for (const member of members) {
|
|
232
331
|
for (const registration of member.registrations) {
|
|
233
332
|
if (includeContextOrganization || registration.organizationId !== Context.auth.organization?.id) {
|
|
234
333
|
const found = organizations.get(registration.id);
|
|
235
334
|
if (!found) {
|
|
236
|
-
const organization = await Context.auth.getOrganization(registration.organizationId)
|
|
237
|
-
organizations.set(organization.id, organization)
|
|
335
|
+
const organization = await Context.auth.getOrganization(registration.organizationId);
|
|
336
|
+
organizations.set(organization.id, organization);
|
|
238
337
|
}
|
|
239
338
|
}
|
|
240
339
|
}
|
|
241
|
-
member.registrations = member.registrations.filter(r => (Context.auth.organization && Context.auth.organization.active && r.organizationId === Context.auth.organization.id) || (organizations.get(r.organizationId)?.active ?? false))
|
|
242
|
-
const blob = member.getStructureWithRegistrations()
|
|
340
|
+
member.registrations = member.registrations.filter(r => (Context.auth.organization && Context.auth.organization.active && r.organizationId === Context.auth.organization.id) || (organizations.get(r.organizationId)?.active ?? false));
|
|
341
|
+
const blob = member.getStructureWithRegistrations();
|
|
243
342
|
memberBlobs.push(
|
|
244
|
-
await Context.auth.filterMemberData(member, blob)
|
|
245
|
-
)
|
|
246
|
-
|
|
343
|
+
await Context.auth.filterMemberData(member, blob),
|
|
344
|
+
);
|
|
247
345
|
}
|
|
248
346
|
|
|
249
347
|
// Load responsibilities
|
|
250
|
-
const responsibilities = members.length > 0 ? await MemberResponsibilityRecord.where({ memberId: { sign: 'IN', value: members.map(m => m.id) } }) : []
|
|
251
|
-
const platformMemberships = members.length > 0 ? await MemberPlatformMembership.where({ deletedAt: null, memberId: { sign: 'IN', value: members.map(m => m.id) } }) : []
|
|
348
|
+
const responsibilities = members.length > 0 ? await MemberResponsibilityRecord.where({ memberId: { sign: 'IN', value: members.map(m => m.id) } }) : [];
|
|
349
|
+
const platformMemberships = members.length > 0 ? await MemberPlatformMembership.where({ deletedAt: null, memberId: { sign: 'IN', value: members.map(m => m.id) } }) : [];
|
|
252
350
|
|
|
253
351
|
// Load missing organizations
|
|
254
|
-
const organizationIds = Formatter.uniqueArray(responsibilities.map(r => r.organizationId).filter(id => id !== null))
|
|
352
|
+
const organizationIds = Formatter.uniqueArray(responsibilities.map(r => r.organizationId).filter(id => id !== null));
|
|
255
353
|
for (const id of organizationIds) {
|
|
256
354
|
if (includeContextOrganization || id !== Context.auth.organization?.id) {
|
|
257
355
|
const found = organizations.get(id);
|
|
258
356
|
if (!found) {
|
|
259
|
-
const organization = await Context.auth.getOrganization(id)
|
|
260
|
-
organizations.set(organization.id, organization)
|
|
357
|
+
const organization = await Context.auth.getOrganization(id);
|
|
358
|
+
organizations.set(organization.id, organization);
|
|
261
359
|
}
|
|
262
360
|
}
|
|
263
361
|
}
|
|
264
362
|
|
|
265
|
-
const
|
|
363
|
+
const activeOrganizations = [...organizations.values()].filter(o => o.active);
|
|
364
|
+
const organizationStructs = await this.organizations(activeOrganizations);
|
|
266
365
|
|
|
267
366
|
// Load missing groups
|
|
268
|
-
const allGroups = new Map<string, GroupStruct>()
|
|
367
|
+
const allGroups = new Map<string, GroupStruct>();
|
|
269
368
|
for (const organization of organizationStructs) {
|
|
270
369
|
for (const group of organization.period.groups) {
|
|
271
|
-
allGroups.set(group.id, group)
|
|
370
|
+
allGroups.set(group.id, group);
|
|
272
371
|
}
|
|
273
372
|
}
|
|
274
373
|
|
|
275
374
|
for (const blob of memberBlobs) {
|
|
276
375
|
for (const registration of blob.registrations) {
|
|
277
376
|
if (registration.group) {
|
|
278
|
-
allGroups.set(registration.group.id, registration.group)
|
|
377
|
+
allGroups.set(registration.group.id, registration.group);
|
|
279
378
|
}
|
|
280
379
|
}
|
|
281
380
|
}
|
|
282
381
|
|
|
283
|
-
const groupIds = Formatter.uniqueArray(responsibilities.map(r => r.groupId).filter(id => id !== null)).filter(id => !allGroups.has(id))
|
|
284
|
-
const groups = groupIds.length > 0 ? await Group.getByIDs(...groupIds) : []
|
|
285
|
-
const groupStructs = await this.groups(groups)
|
|
286
|
-
|
|
382
|
+
const groupIds = Formatter.uniqueArray(responsibilities.map(r => r.groupId).filter(id => id !== null)).filter(id => !allGroups.has(id));
|
|
383
|
+
const groups = groupIds.length > 0 ? await Group.getByIDs(...groupIds) : [];
|
|
384
|
+
const groupStructs = await this.groups(groups);
|
|
385
|
+
|
|
287
386
|
for (const group of groupStructs) {
|
|
288
|
-
allGroups.set(group.id, group)
|
|
387
|
+
allGroups.set(group.id, group);
|
|
289
388
|
}
|
|
290
389
|
|
|
291
390
|
for (const blob of memberBlobs) {
|
|
292
|
-
blob.responsibilities = responsibilities.filter(r => r.memberId == blob.id).map(r => {
|
|
293
|
-
const group = allGroups.get(r.groupId ?? '') ?? null
|
|
294
|
-
return r.getStructure(group)
|
|
295
|
-
})
|
|
296
|
-
blob.platformMemberships = platformMemberships.filter(r => r.memberId == blob.id).map(r => MemberPlatformMembershipStruct.create(r))
|
|
391
|
+
blob.responsibilities = responsibilities.filter(r => r.memberId == blob.id).map((r) => {
|
|
392
|
+
const group = allGroups.get(r.groupId ?? '') ?? null;
|
|
393
|
+
return r.getStructure(group);
|
|
394
|
+
});
|
|
395
|
+
blob.platformMemberships = platformMemberships.filter(r => r.memberId == blob.id).map(r => MemberPlatformMembershipStruct.create(r));
|
|
297
396
|
}
|
|
298
397
|
|
|
299
398
|
return MembersBlob.create({
|
|
300
399
|
members: memberBlobs,
|
|
301
|
-
organizations: organizationStructs
|
|
302
|
-
})
|
|
400
|
+
organizations: organizationStructs,
|
|
401
|
+
});
|
|
303
402
|
}
|
|
304
403
|
|
|
305
404
|
static async events(events: Event[]): Promise<EventStruct[]> {
|
|
306
405
|
// Load groups
|
|
307
|
-
const groupIds = events.map(e => e.groupId).filter(id => id !== null)
|
|
308
|
-
const groups = groupIds.length > 0 ? await Group.getByIDs(...groupIds) : []
|
|
309
|
-
const groupStructs = await this.groups(groups)
|
|
406
|
+
const groupIds = events.map(e => e.groupId).filter(id => id !== null);
|
|
407
|
+
const groups = groupIds.length > 0 ? await Group.getByIDs(...groupIds) : [];
|
|
408
|
+
const groupStructs = await this.groups(groups);
|
|
310
409
|
|
|
311
|
-
const result: EventStruct[] = []
|
|
410
|
+
const result: EventStruct[] = [];
|
|
312
411
|
|
|
313
412
|
for (const event of events) {
|
|
314
|
-
const group = groupStructs.find(g => g.id == event.groupId) ?? null
|
|
413
|
+
const group = groupStructs.find(g => g.id == event.groupId) ?? null;
|
|
315
414
|
|
|
316
415
|
const struct = EventStruct.create({
|
|
317
416
|
...event,
|
|
318
|
-
group
|
|
319
|
-
})
|
|
417
|
+
group,
|
|
418
|
+
});
|
|
320
419
|
|
|
321
|
-
result.push(struct)
|
|
420
|
+
result.push(struct);
|
|
322
421
|
}
|
|
323
|
-
|
|
324
|
-
return result
|
|
422
|
+
|
|
423
|
+
return result;
|
|
325
424
|
}
|
|
326
425
|
}
|