@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,62 +1,62 @@
|
|
|
1
|
-
import { AutoEncoderPatchType, PatchMap } from
|
|
2
|
-
import { SimpleError } from
|
|
3
|
-
import { BalanceItem, CachedOutstandingBalance, Document, DocumentTemplate, EmailTemplate, Event, Group, Member, MemberPlatformMembership, MemberWithRegistrations, Order, Organization, OrganizationRegistrationPeriod, Payment, Registration, User, Webshop } from
|
|
4
|
-
import { AccessRight, FinancialSupportSettings, GroupCategory, GroupStatus, MemberWithRegistrationsBlob, PermissionLevel, PermissionsResourceType, Platform as PlatformStruct, RecordCategory } from
|
|
5
|
-
import { Formatter } from
|
|
1
|
+
import { AutoEncoderPatchType, PatchMap } from '@simonbackx/simple-encoding';
|
|
2
|
+
import { SimpleError } from '@simonbackx/simple-errors';
|
|
3
|
+
import { BalanceItem, CachedOutstandingBalance, Document, DocumentTemplate, EmailTemplate, Event, Group, Member, MemberPlatformMembership, MemberWithRegistrations, Order, Organization, OrganizationRegistrationPeriod, Payment, Registration, User, Webshop } from '@stamhoofd/models';
|
|
4
|
+
import { AccessRight, FinancialSupportSettings, GroupCategory, GroupStatus, LoadedPermissions, MemberWithRegistrationsBlob, PermissionLevel, PermissionsResourceType, Platform as PlatformStruct, RecordCategory } from '@stamhoofd/structures';
|
|
5
|
+
import { Formatter } from '@stamhoofd/utility';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* One class with all the responsabilities of checking permissions to each resource in the system by a given user, possibly in an organization context.
|
|
9
9
|
* This helps when dependencies of permissions change, such as parent categories for groups
|
|
10
10
|
*/
|
|
11
11
|
export class AdminPermissionChecker {
|
|
12
|
-
organization: Organization|null
|
|
13
|
-
user: User
|
|
12
|
+
organization: Organization | null;
|
|
13
|
+
user: User;
|
|
14
14
|
/**
|
|
15
15
|
* The member that is linked to this user = is this user
|
|
16
16
|
*/
|
|
17
|
-
member: MemberWithRegistrations|null = null
|
|
18
|
-
platform: PlatformStruct
|
|
17
|
+
member: MemberWithRegistrations | null = null;
|
|
18
|
+
platform: PlatformStruct;
|
|
19
19
|
|
|
20
|
-
organizationCache: Map<string, Organization|Promise<Organization|undefined>> = new Map()
|
|
21
|
-
organizationGroupsCache: Map<string, Group[]|Promise<Group[]>> = new Map()
|
|
20
|
+
organizationCache: Map<string, Organization | Promise<Organization | undefined>> = new Map();
|
|
21
|
+
organizationGroupsCache: Map<string, Group[] | Promise<Group[]>> = new Map();
|
|
22
22
|
|
|
23
|
-
constructor(user: User, platform: PlatformStruct, organization?: Organization
|
|
24
|
-
this.user = user
|
|
25
|
-
this.platform = platform
|
|
23
|
+
constructor(user: User, platform: PlatformStruct, organization?: Organization) {
|
|
24
|
+
this.user = user;
|
|
25
|
+
this.platform = platform;
|
|
26
26
|
|
|
27
27
|
if (user.organizationId && (!organization || organization.id !== user.organizationId)) {
|
|
28
28
|
throw new SimpleError({
|
|
29
29
|
code: 'invalid_scope',
|
|
30
30
|
message: 'Tried accessing a resource without an organization context, but this user is limited to the organization context',
|
|
31
|
-
statusCode: 403
|
|
32
|
-
})
|
|
31
|
+
statusCode: 403,
|
|
32
|
+
});
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
this.organization = organization ?? null
|
|
35
|
+
this.organization = organization ?? null;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
async getOrganization(id: string|Organization): Promise<Organization> {
|
|
38
|
+
async getOrganization(id: string | Organization): Promise<Organization> {
|
|
39
39
|
if (this.organization && id === this.organization.id) {
|
|
40
|
-
return this.organization
|
|
40
|
+
return this.organization;
|
|
41
41
|
}
|
|
42
42
|
if (typeof id === 'string') {
|
|
43
43
|
const c = this.organizationCache.get(id);
|
|
44
44
|
if (c) {
|
|
45
45
|
const result = await c;
|
|
46
46
|
if (!result) {
|
|
47
|
-
throw new Error('Unexpected missing organization in AdminPermissionChecker.getOrganization')
|
|
47
|
+
throw new Error('Unexpected missing organization in AdminPermissionChecker.getOrganization');
|
|
48
48
|
}
|
|
49
49
|
return result;
|
|
50
50
|
}
|
|
51
|
-
const promise = Organization.getByID(id)
|
|
52
|
-
this.organizationCache.set(id, promise)
|
|
51
|
+
const promise = Organization.getByID(id);
|
|
52
|
+
this.organizationCache.set(id, promise);
|
|
53
53
|
const result = await promise;
|
|
54
54
|
if (!result) {
|
|
55
|
-
console.error('Unexpected missing organization in AdminPermissionChecker.getOrganization', id)
|
|
56
|
-
this.organizationCache.delete(id)
|
|
57
|
-
throw new Error('Unexpected missing organization in AdminPermissionChecker.getOrganization')
|
|
55
|
+
console.error('Unexpected missing organization in AdminPermissionChecker.getOrganization', id);
|
|
56
|
+
this.organizationCache.delete(id);
|
|
57
|
+
throw new Error('Unexpected missing organization in AdminPermissionChecker.getOrganization');
|
|
58
58
|
}
|
|
59
|
-
this.organizationCache.set(id, result)
|
|
59
|
+
this.organizationCache.set(id, result);
|
|
60
60
|
return result;
|
|
61
61
|
}
|
|
62
62
|
return id;
|
|
@@ -67,52 +67,52 @@ export class AdminPermissionChecker {
|
|
|
67
67
|
if (c) {
|
|
68
68
|
return await c;
|
|
69
69
|
}
|
|
70
|
-
const organization = await this.getOrganization(id)
|
|
71
|
-
const promise = Group.getAll(id, organization.periodId, true)
|
|
72
|
-
this.organizationGroupsCache.set(id, promise)
|
|
70
|
+
const organization = await this.getOrganization(id);
|
|
71
|
+
const promise = Group.getAll(id, organization.periodId, true);
|
|
72
|
+
this.organizationGroupsCache.set(id, promise);
|
|
73
73
|
const result = await promise;
|
|
74
|
-
this.organizationGroupsCache.set(id, result)
|
|
74
|
+
this.organizationGroupsCache.set(id, result);
|
|
75
75
|
return result;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
async getOrganizationCurrentPeriod(id: string|Organization): Promise<OrganizationRegistrationPeriod> {
|
|
79
|
-
const organization = await this.getOrganization(id);
|
|
80
|
-
return await organization.getPeriod()
|
|
78
|
+
async getOrganizationCurrentPeriod(id: string | Organization): Promise<OrganizationRegistrationPeriod> {
|
|
79
|
+
const organization = await this.getOrganization(id);
|
|
80
|
+
return await organization.getPeriod();
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
error(message?: string): SimpleError {
|
|
84
84
|
return new SimpleError({
|
|
85
|
-
code:
|
|
86
|
-
message:
|
|
85
|
+
code: 'permission_denied',
|
|
86
|
+
message: 'You do not have permissions for this action',
|
|
87
87
|
human: message ?? 'Je hebt geen toegangsrechten voor deze actie',
|
|
88
|
-
statusCode: 403
|
|
89
|
-
})
|
|
88
|
+
statusCode: 403,
|
|
89
|
+
});
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
notFoundOrNoAccess(message?: string): SimpleError {
|
|
93
93
|
return new SimpleError({
|
|
94
|
-
code:
|
|
95
|
-
message:
|
|
94
|
+
code: 'not_found',
|
|
95
|
+
message: 'Resource not found or no access',
|
|
96
96
|
human: message ?? 'Niet gevonden of geen toegang tot dit object',
|
|
97
|
-
statusCode: 404
|
|
98
|
-
})
|
|
97
|
+
statusCode: 404,
|
|
98
|
+
});
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
get platformPermissions() {
|
|
102
|
-
return this.user.permissions?.forPlatform(this.platform)
|
|
102
|
+
return this.user.permissions?.forPlatform(this.platform);
|
|
103
103
|
}
|
|
104
|
-
|
|
105
|
-
async getOrganizationPermissions(organizationOrId: string|Organization) {
|
|
104
|
+
|
|
105
|
+
async getOrganizationPermissions(organizationOrId: string | Organization) {
|
|
106
106
|
if (!this.user.permissions) {
|
|
107
107
|
return null;
|
|
108
108
|
}
|
|
109
|
-
const organization = await this.getOrganization(organizationOrId)
|
|
109
|
+
const organization = await this.getOrganization(organizationOrId);
|
|
110
110
|
|
|
111
111
|
const p = this.user.permissions.forOrganization(
|
|
112
112
|
organization,
|
|
113
|
-
this.platform
|
|
114
|
-
)
|
|
115
|
-
return p
|
|
113
|
+
this.platform,
|
|
114
|
+
);
|
|
115
|
+
return p;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
async canAccessPrivateOrganizationData(organization: Organization) {
|
|
@@ -120,27 +120,28 @@ export class AdminPermissionChecker {
|
|
|
120
120
|
return false;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
if (!await this.hasSomeAccess(organization
|
|
123
|
+
if (!await this.hasSomeAccess(organization)) {
|
|
124
124
|
return false;
|
|
125
125
|
}
|
|
126
126
|
return true;
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
checkScope(organizationId: string|null) {
|
|
129
|
+
checkScope(organizationId: string | null) {
|
|
130
130
|
if (organizationId) {
|
|
131
131
|
// If request is scoped to a different organization
|
|
132
132
|
if (this.organization && organizationId !== this.organization.id) {
|
|
133
|
-
return false
|
|
133
|
+
return false;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
// If user is limited to scope
|
|
137
137
|
if (this.user.organizationId && organizationId !== this.user.organizationId) {
|
|
138
|
-
return false
|
|
138
|
+
return false;
|
|
139
139
|
}
|
|
140
|
-
}
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
141
142
|
// User is limited to a scope
|
|
142
143
|
if (this.user.organizationId) {
|
|
143
|
-
return false
|
|
144
|
+
return false;
|
|
144
145
|
}
|
|
145
146
|
}
|
|
146
147
|
|
|
@@ -150,13 +151,13 @@ export class AdminPermissionChecker {
|
|
|
150
151
|
async canAccessGroup(group: Group, permissionLevel: PermissionLevel = PermissionLevel.Read): Promise<boolean> {
|
|
151
152
|
// Check permissions aren't scoped to a specific organization, and they mismatch
|
|
152
153
|
if (!this.checkScope(group.organizationId)) {
|
|
153
|
-
return false
|
|
154
|
+
return false;
|
|
154
155
|
}
|
|
155
|
-
const organization = await this.getOrganization(group.organizationId)
|
|
156
|
+
const organization = await this.getOrganization(group.organizationId);
|
|
156
157
|
|
|
157
158
|
if (group.periodId !== organization.periodId) {
|
|
158
159
|
if (!await this.hasFullAccess(group.organizationId)) {
|
|
159
|
-
return false
|
|
160
|
+
return false;
|
|
160
161
|
}
|
|
161
162
|
}
|
|
162
163
|
|
|
@@ -164,7 +165,7 @@ export class AdminPermissionChecker {
|
|
|
164
165
|
return await this.canAccessArchivedGroups(group.organizationId);
|
|
165
166
|
}
|
|
166
167
|
|
|
167
|
-
const organizationPermissions = await this.getOrganizationPermissions(group.organizationId)
|
|
168
|
+
const organizationPermissions = await this.getOrganizationPermissions(group.organizationId);
|
|
168
169
|
|
|
169
170
|
if (!organizationPermissions) {
|
|
170
171
|
return false;
|
|
@@ -176,41 +177,142 @@ export class AdminPermissionChecker {
|
|
|
176
177
|
}
|
|
177
178
|
|
|
178
179
|
// Check parent categories
|
|
179
|
-
const organizationPeriod = await this.getOrganizationCurrentPeriod(organization)
|
|
180
|
-
const parentCategories = group.getParentCategories(organizationPeriod.settings.categories)
|
|
180
|
+
const organizationPeriod = await this.getOrganizationCurrentPeriod(organization);
|
|
181
|
+
const parentCategories = group.getParentCategories(organizationPeriod.settings.categories);
|
|
181
182
|
for (const category of parentCategories) {
|
|
182
183
|
if (organizationPermissions.hasResourceAccess(PermissionsResourceType.GroupCategories, category.id, permissionLevel)) {
|
|
183
|
-
return true
|
|
184
|
+
return true;
|
|
184
185
|
}
|
|
185
186
|
}
|
|
186
187
|
|
|
187
188
|
return false;
|
|
188
189
|
}
|
|
189
190
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
191
|
+
/**
|
|
192
|
+
* Will throw error if not allowed to edit/add/delete this event
|
|
193
|
+
* @param event
|
|
194
|
+
* @returns Organization if event for specific organization, else null
|
|
195
|
+
* @throws error if not allowed to write this event
|
|
196
|
+
*/
|
|
197
|
+
async checkEventAccess(event: Event): Promise<Organization | null> {
|
|
198
|
+
const accessRight: AccessRight = AccessRight.EventWrite;
|
|
199
|
+
|
|
200
|
+
// #region organization and groups
|
|
201
|
+
if (event.organizationId !== null) {
|
|
202
|
+
let organization: Organization | null = null;
|
|
203
|
+
let organizationPermissions: LoadedPermissions | null = null;
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
organization = await this.getOrganization(event.organizationId);
|
|
207
|
+
organizationPermissions = await this.getOrganizationPermissions(organization);
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
console.error(error);
|
|
211
|
+
throw new SimpleError({
|
|
212
|
+
code: 'not_found',
|
|
213
|
+
message: 'Event not found',
|
|
214
|
+
human: 'De activiteit werd niet gevonden',
|
|
215
|
+
});
|
|
216
|
+
}
|
|
195
217
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
218
|
+
if (organizationPermissions === null) {
|
|
219
|
+
throw new SimpleError({
|
|
220
|
+
code: 'permission_denied',
|
|
221
|
+
message: 'Je hebt geen toegangsrechten om een activiteit te beheren voor deze organisatie.',
|
|
222
|
+
statusCode: 403,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (event.meta.groups === null) {
|
|
227
|
+
if (!organizationPermissions.hasResourceAccessRight(PermissionsResourceType.Groups, '', accessRight)) {
|
|
228
|
+
throw new SimpleError({
|
|
229
|
+
code: 'permission_denied',
|
|
230
|
+
message: 'Je hebt geen toegangsrechten om een activiteit te beheren voor deze organisatie.',
|
|
231
|
+
statusCode: 403,
|
|
232
|
+
});
|
|
201
233
|
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
for (const group of event.meta.groups) {
|
|
237
|
+
if (!organizationPermissions.hasResourceAccessRight(PermissionsResourceType.Groups, group.id, accessRight)) {
|
|
238
|
+
throw new SimpleError({
|
|
239
|
+
code: 'permission_denied',
|
|
240
|
+
message: 'Je hebt geen toegangsrechten om een activiteit te beheren voor deze groep(en).',
|
|
241
|
+
statusCode: 403,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
205
244
|
}
|
|
206
245
|
}
|
|
246
|
+
|
|
247
|
+
if (event.meta.organizationTagIds !== null) {
|
|
248
|
+
// not supported currently
|
|
249
|
+
throw new SimpleError({
|
|
250
|
+
code: 'invalid_field',
|
|
251
|
+
message: 'Een activiteit voor een organisatie kan geen tags bevatten.',
|
|
252
|
+
statusCode: 403,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (event.meta.defaultAgeGroupIds !== null) {
|
|
257
|
+
// not supported currently
|
|
258
|
+
throw new SimpleError({
|
|
259
|
+
code: 'invalid_field',
|
|
260
|
+
message: 'Een activiteit voor een organisatie kan niet beperkt worden tot specifieke standaard leeftijdsgroepen.',
|
|
261
|
+
statusCode: 403,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return organization;
|
|
207
266
|
}
|
|
267
|
+
// #endregion
|
|
208
268
|
|
|
209
|
-
|
|
269
|
+
// #region platform
|
|
270
|
+
if (event.meta.groups !== null) {
|
|
271
|
+
// not supported currently
|
|
272
|
+
throw new SimpleError({
|
|
273
|
+
code: 'permission_denied',
|
|
274
|
+
message: 'Een nationale of regionale activiteit kan (momenteel) niet beperkt worden tot specifieke groepen.',
|
|
275
|
+
statusCode: 403,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const platformPermissions = this.platformPermissions;
|
|
280
|
+
if (!platformPermissions) {
|
|
281
|
+
throw new SimpleError({
|
|
282
|
+
code: 'permission_denied',
|
|
283
|
+
message: 'Je hebt geen toegangsrechten om een nationale of regionale activiteit te beheren.',
|
|
284
|
+
statusCode: 403,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// organization tags
|
|
289
|
+
if (event.meta.organizationTagIds === null) {
|
|
290
|
+
if (!(platformPermissions.hasAccessRight(accessRight) || platformPermissions.hasResourceAccessRight(PermissionsResourceType.OrganizationTags, '', accessRight))) {
|
|
291
|
+
throw new SimpleError({
|
|
292
|
+
code: 'permission_denied',
|
|
293
|
+
message: 'Je kan geen nationale activiteiten beheren',
|
|
294
|
+
statusCode: 403,
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
for (const tagId of event.meta.organizationTagIds) {
|
|
300
|
+
if (!platformPermissions.hasResourceAccessRight(PermissionsResourceType.OrganizationTags, tagId, accessRight)) {
|
|
301
|
+
throw new SimpleError({
|
|
302
|
+
code: 'permission_denied',
|
|
303
|
+
message: "Je hebt geen toegangsrechten om een nationale of regionale activiteit te beheren voor deze regio('s).",
|
|
304
|
+
statusCode: 403,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// #endregion
|
|
310
|
+
|
|
311
|
+
return null;
|
|
210
312
|
}
|
|
211
313
|
|
|
212
314
|
async canAccessArchivedGroups(organizationId: string) {
|
|
213
|
-
return await this.hasFullAccess(organizationId)
|
|
315
|
+
return await this.hasFullAccess(organizationId);
|
|
214
316
|
}
|
|
215
317
|
|
|
216
318
|
async canAccessMember(member: MemberWithRegistrations, permissionLevel: PermissionLevel = PermissionLevel.Read) {
|
|
@@ -220,15 +322,15 @@ export class AdminPermissionChecker {
|
|
|
220
322
|
|
|
221
323
|
// Check user has permissions
|
|
222
324
|
if (!this.user.permissions) {
|
|
223
|
-
return false
|
|
325
|
+
return false;
|
|
224
326
|
}
|
|
225
327
|
|
|
226
328
|
if (this.hasPlatformFullAccess()) {
|
|
227
|
-
return true
|
|
329
|
+
return true;
|
|
228
330
|
}
|
|
229
331
|
|
|
230
332
|
if (member.organizationId && await this.hasFullAccess(member.organizationId, permissionLevel)) {
|
|
231
|
-
return true
|
|
333
|
+
return true;
|
|
232
334
|
}
|
|
233
335
|
|
|
234
336
|
if (member.registrations.length === 0 && permissionLevel !== PermissionLevel.Full && (this.organization && await this.hasFullAccess(this.organization.id, PermissionLevel.Full))) {
|
|
@@ -251,12 +353,12 @@ export class AdminPermissionChecker {
|
|
|
251
353
|
*/
|
|
252
354
|
async canDeleteMember(member: MemberWithRegistrations) {
|
|
253
355
|
if (member.registrations.length === 0 && this.isUserManager(member)) {
|
|
254
|
-
const platformMemberships = await MemberPlatformMembership.where({ memberId: member.id })
|
|
356
|
+
const platformMemberships = await MemberPlatformMembership.where({ memberId: member.id });
|
|
255
357
|
if (platformMemberships.length === 0) {
|
|
256
358
|
return true;
|
|
257
359
|
}
|
|
258
360
|
|
|
259
|
-
const cachedBalance = await CachedOutstandingBalance.getForObjects([member.id])
|
|
361
|
+
const cachedBalance = await CachedOutstandingBalance.getForObjects([member.id]);
|
|
260
362
|
if (cachedBalance.length === 0 || (cachedBalance[0].amount === 0 && cachedBalance[0].amountPending === 0)) {
|
|
261
363
|
return true;
|
|
262
364
|
}
|
|
@@ -264,16 +366,16 @@ export class AdminPermissionChecker {
|
|
|
264
366
|
|
|
265
367
|
if (member.organizationId) {
|
|
266
368
|
// Not a platform
|
|
267
|
-
return await this.hasFullAccess(member.organizationId)
|
|
369
|
+
return await this.hasFullAccess(member.organizationId);
|
|
268
370
|
}
|
|
269
|
-
return this.hasPlatformFullAccess()
|
|
371
|
+
return this.hasPlatformFullAccess();
|
|
270
372
|
}
|
|
271
373
|
|
|
272
374
|
/**
|
|
273
375
|
* Note: only checks admin permissions. Users that 'own' this member can also access it but that does not use the AdminPermissionChecker
|
|
274
376
|
*/
|
|
275
377
|
async canAccessRegistration(registration: Registration, permissionLevel: PermissionLevel = PermissionLevel.Read) {
|
|
276
|
-
const organizationPermissions = await this.getOrganizationPermissions(registration.organizationId)
|
|
378
|
+
const organizationPermissions = await this.getOrganizationPermissions(registration.organizationId);
|
|
277
379
|
|
|
278
380
|
if (!organizationPermissions) {
|
|
279
381
|
return false;
|
|
@@ -289,8 +391,8 @@ export class AdminPermissionChecker {
|
|
|
289
391
|
return false;
|
|
290
392
|
}
|
|
291
393
|
|
|
292
|
-
const allGroups = await this.getOrganizationGroups(registration.organizationId)
|
|
293
|
-
const group = allGroups.find(g => g.id === registration.groupId)
|
|
394
|
+
const allGroups = await this.getOrganizationGroups(registration.organizationId);
|
|
395
|
+
const group = allGroups.find(g => g.id === registration.groupId);
|
|
294
396
|
if (!group || group.deletedAt) {
|
|
295
397
|
return false;
|
|
296
398
|
}
|
|
@@ -303,7 +405,7 @@ export class AdminPermissionChecker {
|
|
|
303
405
|
}
|
|
304
406
|
|
|
305
407
|
async canAccessWebshop(webshop: Webshop, permissionLevel: PermissionLevel = PermissionLevel.Read) {
|
|
306
|
-
const organizationPermissions = await this.getOrganizationPermissions(webshop.organizationId)
|
|
408
|
+
const organizationPermissions = await this.getOrganizationPermissions(webshop.organizationId);
|
|
307
409
|
|
|
308
410
|
if (!organizationPermissions) {
|
|
309
411
|
return false;
|
|
@@ -322,10 +424,10 @@ export class AdminPermissionChecker {
|
|
|
322
424
|
|
|
323
425
|
async canAccessWebshopTickets(webshop: Webshop, permissionLevel: PermissionLevel = PermissionLevel.Read) {
|
|
324
426
|
if (!this.checkScope(webshop.organizationId)) {
|
|
325
|
-
return false
|
|
427
|
+
return false;
|
|
326
428
|
}
|
|
327
429
|
|
|
328
|
-
const organizationPermissions = await this.getOrganizationPermissions(webshop.organizationId)
|
|
430
|
+
const organizationPermissions = await this.getOrganizationPermissions(webshop.organizationId);
|
|
329
431
|
|
|
330
432
|
if (!organizationPermissions) {
|
|
331
433
|
return false;
|
|
@@ -347,7 +449,7 @@ export class AdminPermissionChecker {
|
|
|
347
449
|
}
|
|
348
450
|
|
|
349
451
|
async canAccessPayment(payment: Payment, permissionLevel: PermissionLevel = PermissionLevel.Read) {
|
|
350
|
-
return await this.canAccessPayments([payment], permissionLevel)
|
|
452
|
+
return await this.canAccessPayments([payment], permissionLevel);
|
|
351
453
|
}
|
|
352
454
|
|
|
353
455
|
async canAccessPayments(payments: Payment[], permissionLevel: PermissionLevel = PermissionLevel.Read) {
|
|
@@ -362,7 +464,7 @@ export class AdminPermissionChecker {
|
|
|
362
464
|
return false;
|
|
363
465
|
}
|
|
364
466
|
|
|
365
|
-
const organizationId = payments[0].organizationId
|
|
467
|
+
const organizationId = payments[0].organizationId;
|
|
366
468
|
for (const item of payments) {
|
|
367
469
|
if (item.organizationId !== organizationId) {
|
|
368
470
|
// Cannot merge multiple organizations for now
|
|
@@ -372,24 +474,24 @@ export class AdminPermissionChecker {
|
|
|
372
474
|
|
|
373
475
|
// First try without queries
|
|
374
476
|
if (!organizationId) {
|
|
375
|
-
return this.hasPlatformFullAccess()
|
|
477
|
+
return this.hasPlatformFullAccess();
|
|
376
478
|
}
|
|
377
479
|
|
|
378
480
|
if (await this.canManagePayments(organizationId)) {
|
|
379
481
|
return true;
|
|
380
482
|
}
|
|
381
483
|
|
|
382
|
-
const {balanceItems} = await Payment.loadBalanceItems(payments)
|
|
383
|
-
return await this.canAccessBalanceItems(balanceItems, permissionLevel)
|
|
484
|
+
const { balanceItems } = await Payment.loadBalanceItems(payments);
|
|
485
|
+
return await this.canAccessBalanceItems(balanceItems, permissionLevel);
|
|
384
486
|
}
|
|
385
487
|
|
|
386
488
|
async canAccessBalanceItems(
|
|
387
489
|
balanceItems: BalanceItem[],
|
|
388
490
|
permissionLevel: PermissionLevel = PermissionLevel.Read,
|
|
389
491
|
data?: {
|
|
390
|
-
registrations: Registration[]
|
|
391
|
-
orders: Order[]
|
|
392
|
-
}
|
|
492
|
+
registrations: Registration[];
|
|
493
|
+
orders: Order[];
|
|
494
|
+
},
|
|
393
495
|
): Promise<boolean> {
|
|
394
496
|
for (const balanceItem of balanceItems) {
|
|
395
497
|
if (!this.checkScope(balanceItem.organizationId)) {
|
|
@@ -402,7 +504,7 @@ export class AdminPermissionChecker {
|
|
|
402
504
|
return false;
|
|
403
505
|
}
|
|
404
506
|
|
|
405
|
-
const organizationId = balanceItems[0].organizationId
|
|
507
|
+
const organizationId = balanceItems[0].organizationId;
|
|
406
508
|
for (const item of balanceItems) {
|
|
407
509
|
if (item.organizationId !== organizationId) {
|
|
408
510
|
// Cannot merge multiple organizations for now
|
|
@@ -424,7 +526,7 @@ export class AdminPermissionChecker {
|
|
|
424
526
|
}
|
|
425
527
|
|
|
426
528
|
// Slight optimization possible here
|
|
427
|
-
const {registrations, orders} = data ?? (this.user.permissions || permissionLevel === PermissionLevel.Read) ? (await Payment.loadBalanceItemRelations(balanceItems)) : {registrations: [], orders: []}
|
|
529
|
+
const { registrations, orders } = data ?? (this.user.permissions || permissionLevel === PermissionLevel.Read) ? (await Payment.loadBalanceItemRelations(balanceItems)) : { registrations: [], orders: [] };
|
|
428
530
|
|
|
429
531
|
if (this.user.permissions) {
|
|
430
532
|
// We grant permission for a whole payment when the user has at least permission for a part of that payment.
|
|
@@ -434,12 +536,12 @@ export class AdminPermissionChecker {
|
|
|
434
536
|
}
|
|
435
537
|
}
|
|
436
538
|
|
|
437
|
-
const webshopCache: Map<string, Webshop> = new Map()
|
|
539
|
+
const webshopCache: Map<string, Webshop> = new Map();
|
|
438
540
|
|
|
439
541
|
for (const order of orders) {
|
|
440
|
-
const webshop = webshopCache.get(order.webshopId) ?? await Webshop.getByID(order.webshopId)
|
|
542
|
+
const webshop = webshopCache.get(order.webshopId) ?? await Webshop.getByID(order.webshopId);
|
|
441
543
|
if (webshop) {
|
|
442
|
-
webshopCache.set(order.webshopId, webshop)
|
|
544
|
+
webshopCache.set(order.webshopId, webshop);
|
|
443
545
|
|
|
444
546
|
if (await this.canAccessWebshop(webshop, permissionLevel)) {
|
|
445
547
|
return true;
|
|
@@ -450,7 +552,7 @@ export class AdminPermissionChecker {
|
|
|
450
552
|
|
|
451
553
|
if (permissionLevel === PermissionLevel.Read) {
|
|
452
554
|
// Check members
|
|
453
|
-
const userMembers = await Member.getMembersWithRegistrationForUser(this.user)
|
|
555
|
+
const userMembers = await Member.getMembersWithRegistrationForUser(this.user);
|
|
454
556
|
for (const member of userMembers) {
|
|
455
557
|
if (balanceItems.find(m => m.memberId === member.id)) {
|
|
456
558
|
return true;
|
|
@@ -463,23 +565,23 @@ export class AdminPermissionChecker {
|
|
|
463
565
|
|
|
464
566
|
async canAccessDocumentTemplate(documentTemplate: DocumentTemplate, _: PermissionLevel = PermissionLevel.Read) {
|
|
465
567
|
if (!this.checkScope(documentTemplate.organizationId)) {
|
|
466
|
-
return false
|
|
568
|
+
return false;
|
|
467
569
|
}
|
|
468
570
|
|
|
469
|
-
return await this.hasFullAccess(documentTemplate.organizationId)
|
|
571
|
+
return await this.hasFullAccess(documentTemplate.organizationId);
|
|
470
572
|
}
|
|
471
573
|
|
|
472
574
|
async canAccessDocument(document: Document, level: PermissionLevel = PermissionLevel.Read) {
|
|
473
575
|
if (!this.checkScope(document.organizationId)) {
|
|
474
|
-
return false
|
|
576
|
+
return false;
|
|
475
577
|
}
|
|
476
578
|
|
|
477
579
|
if (await this.hasFullAccess(document.organizationId)) {
|
|
478
|
-
return true
|
|
580
|
+
return true;
|
|
479
581
|
}
|
|
480
582
|
|
|
481
583
|
if (level === PermissionLevel.Read && document.memberId) {
|
|
482
|
-
const members = await Member.getMembersWithRegistrationForUser(this.user)
|
|
584
|
+
const members = await Member.getMembersWithRegistrationForUser(this.user);
|
|
483
585
|
|
|
484
586
|
if (members.find(m => m.id == document.memberId)) {
|
|
485
587
|
return true;
|
|
@@ -501,7 +603,7 @@ export class AdminPermissionChecker {
|
|
|
501
603
|
}
|
|
502
604
|
|
|
503
605
|
if (!user.organizationId) {
|
|
504
|
-
return this.hasPlatformFullAccess()
|
|
606
|
+
return this.hasPlatformFullAccess();
|
|
505
607
|
}
|
|
506
608
|
|
|
507
609
|
return await this.canManageAdmins(user.organizationId);
|
|
@@ -514,19 +616,19 @@ export class AdminPermissionChecker {
|
|
|
514
616
|
|
|
515
617
|
if (user.organizationId) {
|
|
516
618
|
// normal behaviour
|
|
517
|
-
return this.canAccessUser(user, PermissionLevel.Write)
|
|
619
|
+
return this.canAccessUser(user, PermissionLevel.Write);
|
|
518
620
|
}
|
|
519
621
|
|
|
520
622
|
// platform user: only allowed to change names if not platform admins
|
|
521
623
|
if (user.permissions?.globalPermissions) {
|
|
522
|
-
return this.hasPlatformFullAccess()
|
|
624
|
+
return this.hasPlatformFullAccess();
|
|
523
625
|
}
|
|
524
626
|
|
|
525
|
-
return this.canAccessUser(user, PermissionLevel.Write)
|
|
627
|
+
return this.canAccessUser(user, PermissionLevel.Write);
|
|
526
628
|
}
|
|
527
629
|
|
|
528
630
|
async canEditUserEmail(user: User) {
|
|
529
|
-
return this.canEditUserName(user)
|
|
631
|
+
return this.canEditUserName(user);
|
|
530
632
|
}
|
|
531
633
|
|
|
532
634
|
async canAccessEmailTemplate(template: EmailTemplate, level: PermissionLevel = PermissionLevel.Read) {
|
|
@@ -537,7 +639,7 @@ export class AdminPermissionChecker {
|
|
|
537
639
|
}
|
|
538
640
|
return this.canReadEmailTemplates(template.organizationId);
|
|
539
641
|
}
|
|
540
|
-
|
|
642
|
+
|
|
541
643
|
// Note: if the template has an organizationId of null, everyone can access it, but only for reading
|
|
542
644
|
// that is why we only check the scope afterwards
|
|
543
645
|
if (!this.checkScope(template.organizationId)) {
|
|
@@ -545,7 +647,7 @@ export class AdminPermissionChecker {
|
|
|
545
647
|
}
|
|
546
648
|
|
|
547
649
|
if (!template.organizationId) {
|
|
548
|
-
return this.hasPlatformFullAccess()
|
|
650
|
+
return this.hasPlatformFullAccess();
|
|
549
651
|
}
|
|
550
652
|
|
|
551
653
|
if (await this.hasFullAccess(template.organizationId)) {
|
|
@@ -553,7 +655,7 @@ export class AdminPermissionChecker {
|
|
|
553
655
|
}
|
|
554
656
|
|
|
555
657
|
if (template.webshopId) {
|
|
556
|
-
const webshop = await Webshop.getByID(template.webshopId)
|
|
658
|
+
const webshop = await Webshop.getByID(template.webshopId);
|
|
557
659
|
if (!webshop || !(await this.canAccessWebshop(webshop, PermissionLevel.Full))) {
|
|
558
660
|
return false;
|
|
559
661
|
}
|
|
@@ -562,7 +664,7 @@ export class AdminPermissionChecker {
|
|
|
562
664
|
}
|
|
563
665
|
|
|
564
666
|
if (template.groupId) {
|
|
565
|
-
const group = await Group.getByID(template.groupId)
|
|
667
|
+
const group = await Group.getByID(template.groupId);
|
|
566
668
|
if (!group || !(await this.canAccessGroup(group, PermissionLevel.Full))) {
|
|
567
669
|
return false;
|
|
568
670
|
}
|
|
@@ -572,7 +674,7 @@ export class AdminPermissionChecker {
|
|
|
572
674
|
|
|
573
675
|
return false;
|
|
574
676
|
}
|
|
575
|
-
|
|
677
|
+
|
|
576
678
|
async canLinkBalanceItemToUser(balanceItem: BalanceItem, linkingUser: User) {
|
|
577
679
|
if (!this.checkScope(linkingUser.organizationId)) {
|
|
578
680
|
return false;
|
|
@@ -598,8 +700,9 @@ export class AdminPermissionChecker {
|
|
|
598
700
|
if (await this.canManagePayments(member.organizationId)) {
|
|
599
701
|
return true;
|
|
600
702
|
}
|
|
601
|
-
}
|
|
602
|
-
|
|
703
|
+
}
|
|
704
|
+
else {
|
|
705
|
+
const organizationIds = Formatter.uniqueArray(member.registrations.map(r => r.organizationId));
|
|
603
706
|
for (const organizationId of organizationIds) {
|
|
604
707
|
if (await this.canManagePayments(organizationId)) {
|
|
605
708
|
return true;
|
|
@@ -615,39 +718,39 @@ export class AdminPermissionChecker {
|
|
|
615
718
|
}
|
|
616
719
|
|
|
617
720
|
async canManageFinances(organizationId: string) {
|
|
618
|
-
const organizationPermissions = await this.getOrganizationPermissions(organizationId)
|
|
721
|
+
const organizationPermissions = await this.getOrganizationPermissions(organizationId);
|
|
619
722
|
|
|
620
723
|
if (!organizationPermissions) {
|
|
621
724
|
return false;
|
|
622
725
|
}
|
|
623
|
-
|
|
624
|
-
return organizationPermissions.hasAccessRight(AccessRight.OrganizationFinanceDirector)
|
|
726
|
+
|
|
727
|
+
return organizationPermissions.hasAccessRight(AccessRight.OrganizationFinanceDirector);
|
|
625
728
|
}
|
|
626
729
|
|
|
627
730
|
/**
|
|
628
731
|
* Mainly for transfer payment management
|
|
629
732
|
*/
|
|
630
733
|
async canManagePayments(organizationId: string) {
|
|
631
|
-
const organizationPermissions = await this.getOrganizationPermissions(organizationId)
|
|
734
|
+
const organizationPermissions = await this.getOrganizationPermissions(organizationId);
|
|
632
735
|
|
|
633
736
|
if (!organizationPermissions) {
|
|
634
737
|
return false;
|
|
635
738
|
}
|
|
636
|
-
|
|
739
|
+
|
|
637
740
|
return !!organizationPermissions && (
|
|
638
741
|
organizationPermissions.hasAccessRight(AccessRight.OrganizationManagePayments)
|
|
639
742
|
|| organizationPermissions.hasAccessRight(AccessRight.OrganizationFinanceDirector)
|
|
640
|
-
)
|
|
743
|
+
);
|
|
641
744
|
}
|
|
642
745
|
|
|
643
746
|
async canCreateWebshops(organizationId: string) {
|
|
644
|
-
const organizationPermissions = await this.getOrganizationPermissions(organizationId)
|
|
747
|
+
const organizationPermissions = await this.getOrganizationPermissions(organizationId);
|
|
645
748
|
|
|
646
749
|
if (!organizationPermissions) {
|
|
647
750
|
return false;
|
|
648
751
|
}
|
|
649
752
|
|
|
650
|
-
return !!organizationPermissions && organizationPermissions.hasAccessRight(AccessRight.OrganizationCreateWebshops)
|
|
753
|
+
return !!organizationPermissions && organizationPermissions.hasAccessRight(AccessRight.OrganizationCreateWebshops);
|
|
651
754
|
}
|
|
652
755
|
|
|
653
756
|
async canManagePaymentAccounts(organizationId: string, level: PermissionLevel = PermissionLevel.Read) {
|
|
@@ -655,47 +758,47 @@ export class AdminPermissionChecker {
|
|
|
655
758
|
return await this.hasSomeAccess(organizationId);
|
|
656
759
|
}
|
|
657
760
|
|
|
658
|
-
return await this.canManageFinances(organizationId)
|
|
761
|
+
return await this.canManageFinances(organizationId);
|
|
659
762
|
}
|
|
660
763
|
|
|
661
764
|
async canActivatePackages(organizationId: string) {
|
|
662
|
-
return this.canManageFinances(organizationId)
|
|
765
|
+
return this.canManageFinances(organizationId);
|
|
663
766
|
}
|
|
664
767
|
|
|
665
768
|
async canDeactivatePackages(organizationId: string) {
|
|
666
|
-
return this.canManageFinances(organizationId)
|
|
769
|
+
return this.canManageFinances(organizationId);
|
|
667
770
|
}
|
|
668
771
|
|
|
669
772
|
async canManageDocuments(organizationId: string, _: PermissionLevel = PermissionLevel.Read) {
|
|
670
|
-
const organizationPermissions = await this.getOrganizationPermissions(organizationId)
|
|
773
|
+
const organizationPermissions = await this.getOrganizationPermissions(organizationId);
|
|
671
774
|
|
|
672
775
|
if (!organizationPermissions) {
|
|
673
776
|
return false;
|
|
674
777
|
}
|
|
675
778
|
|
|
676
|
-
return this.hasFullAccess(organizationId)
|
|
779
|
+
return this.hasFullAccess(organizationId);
|
|
677
780
|
}
|
|
678
781
|
|
|
679
782
|
async canAccessEmailBounces(organizationId: string) {
|
|
680
|
-
return this.hasSomeAccess(organizationId)
|
|
783
|
+
return this.hasSomeAccess(organizationId);
|
|
681
784
|
}
|
|
682
785
|
|
|
683
786
|
canSendEmails() {
|
|
684
|
-
return !!this.user.permissions
|
|
787
|
+
return !!this.user.permissions;
|
|
685
788
|
}
|
|
686
789
|
|
|
687
790
|
async canReadEmailTemplates(organizationId: string) {
|
|
688
|
-
const organizationPermissions = await this.getOrganizationPermissions(organizationId)
|
|
791
|
+
const organizationPermissions = await this.getOrganizationPermissions(organizationId);
|
|
689
792
|
|
|
690
793
|
if (!organizationPermissions) {
|
|
691
794
|
return false;
|
|
692
795
|
}
|
|
693
796
|
|
|
694
|
-
return !!this.user.permissions
|
|
797
|
+
return !!this.user.permissions;
|
|
695
798
|
}
|
|
696
799
|
|
|
697
800
|
async canCreateGroupInCategory(organizationId: string, category: GroupCategory) {
|
|
698
|
-
const organizationPermissions = await this.getOrganizationPermissions(organizationId)
|
|
801
|
+
const organizationPermissions = await this.getOrganizationPermissions(organizationId);
|
|
699
802
|
|
|
700
803
|
if (!organizationPermissions) {
|
|
701
804
|
return false;
|
|
@@ -706,9 +809,9 @@ export class AdminPermissionChecker {
|
|
|
706
809
|
}
|
|
707
810
|
|
|
708
811
|
// Check parents
|
|
709
|
-
const organization = await this.getOrganization(organizationId)
|
|
710
|
-
const organizationPeriod = await this.getOrganizationCurrentPeriod(organization)
|
|
711
|
-
const parentCategories = category.getParentCategories(organizationPeriod.settings.categories)
|
|
812
|
+
const organization = await this.getOrganization(organizationId);
|
|
813
|
+
const organizationPeriod = await this.getOrganizationCurrentPeriod(organization);
|
|
814
|
+
const parentCategories = category.getParentCategories(organizationPeriod.settings.categories);
|
|
712
815
|
|
|
713
816
|
for (const parentCategory of parentCategories) {
|
|
714
817
|
if (organizationPermissions.hasResourceAccessRight(PermissionsResourceType.GroupCategories, parentCategory.id, AccessRight.OrganizationCreateGroups)) {
|
|
@@ -720,15 +823,15 @@ export class AdminPermissionChecker {
|
|
|
720
823
|
}
|
|
721
824
|
|
|
722
825
|
canUpload() {
|
|
723
|
-
return !!this.user.permissions
|
|
826
|
+
return !!this.user.permissions;
|
|
724
827
|
}
|
|
725
828
|
|
|
726
829
|
canManageOrganizationDomain(organizationId: string) {
|
|
727
|
-
return this.hasFullAccess(organizationId)
|
|
830
|
+
return this.hasFullAccess(organizationId);
|
|
728
831
|
}
|
|
729
832
|
|
|
730
833
|
canManageSSOSettings(organizationId: string) {
|
|
731
|
-
return this.hasFullAccess(organizationId)
|
|
834
|
+
return this.hasFullAccess(organizationId);
|
|
732
835
|
}
|
|
733
836
|
|
|
734
837
|
async canManageOrganizationSettings(organizationId: string) {
|
|
@@ -738,66 +841,66 @@ export class AdminPermissionChecker {
|
|
|
738
841
|
/**
|
|
739
842
|
* Use this as a circuit breaker to avoid queries for non-admin users
|
|
740
843
|
*/
|
|
741
|
-
async hasSomeAccess(
|
|
742
|
-
const organizationPermissions = await this.getOrganizationPermissions(
|
|
844
|
+
async hasSomeAccess(organizationOrId: string | Organization): Promise<boolean> {
|
|
845
|
+
const organizationPermissions = await this.getOrganizationPermissions(organizationOrId);
|
|
743
846
|
return !!organizationPermissions;
|
|
744
847
|
}
|
|
745
848
|
|
|
746
849
|
async canManageAdmins(organizationId: string) {
|
|
747
|
-
return !this.user.isApiUser && (await this.hasFullAccess(organizationId))
|
|
850
|
+
return !this.user.isApiUser && (await this.hasFullAccess(organizationId));
|
|
748
851
|
}
|
|
749
852
|
|
|
750
853
|
async hasFullAccess(organizationId: string, level = PermissionLevel.Full): Promise<boolean> {
|
|
751
|
-
const organizationPermissions = await this.getOrganizationPermissions(organizationId)
|
|
854
|
+
const organizationPermissions = await this.getOrganizationPermissions(organizationId);
|
|
752
855
|
|
|
753
856
|
if (!organizationPermissions) {
|
|
754
857
|
return false;
|
|
755
858
|
}
|
|
756
859
|
|
|
757
|
-
return !!organizationPermissions && organizationPermissions.hasAccess(level)
|
|
860
|
+
return !!organizationPermissions && organizationPermissions.hasAccess(level);
|
|
758
861
|
}
|
|
759
862
|
|
|
760
863
|
isUserManager(member: MemberWithRegistrations) {
|
|
761
|
-
return !!member.users.find(u => u.id === this.user.id)
|
|
864
|
+
return !!member.users.find(u => u.id === this.user.id);
|
|
762
865
|
}
|
|
763
866
|
|
|
764
867
|
/**
|
|
765
868
|
* Return a list of RecordSettings the current user can view or edit
|
|
766
869
|
*/
|
|
767
870
|
async getAccessibleRecordCategories(member: MemberWithRegistrations, level: PermissionLevel = PermissionLevel.Read): Promise<RecordCategory[]> {
|
|
768
|
-
const isUserManager = this.isUserManager(member)
|
|
871
|
+
const isUserManager = this.isUserManager(member);
|
|
769
872
|
|
|
770
873
|
// First list all organizations this member is part of
|
|
771
874
|
const organizations: Organization[] = [];
|
|
772
875
|
|
|
773
876
|
if (member.organizationId) {
|
|
774
877
|
if (this.checkScope(member.organizationId)) {
|
|
775
|
-
organizations.push(await this.getOrganization(member.organizationId))
|
|
878
|
+
organizations.push(await this.getOrganization(member.organizationId));
|
|
776
879
|
}
|
|
777
880
|
}
|
|
778
881
|
|
|
779
882
|
for (const registration of member.registrations) {
|
|
780
883
|
if (this.checkScope(registration.organizationId)) {
|
|
781
884
|
if (!organizations.find(o => o.id === registration.organizationId)) {
|
|
782
|
-
organizations.push(await this.getOrganization(registration.organizationId))
|
|
885
|
+
organizations.push(await this.getOrganization(registration.organizationId));
|
|
783
886
|
}
|
|
784
887
|
}
|
|
785
888
|
}
|
|
786
889
|
|
|
787
890
|
// Loop all organizations.
|
|
788
891
|
// Check if we have access to their data
|
|
789
|
-
const recordCategories: RecordCategory[] = []
|
|
892
|
+
const recordCategories: RecordCategory[] = [];
|
|
790
893
|
for (const organization of organizations) {
|
|
791
894
|
if (isUserManager) {
|
|
792
895
|
// If the user is a manager, we can always access all records
|
|
793
896
|
// if we ever add private records, we can exclude them here
|
|
794
897
|
for (const category of organization.meta.recordsConfiguration.recordCategories) {
|
|
795
|
-
recordCategories.push(category)
|
|
898
|
+
recordCategories.push(category);
|
|
796
899
|
}
|
|
797
900
|
continue;
|
|
798
901
|
}
|
|
799
902
|
|
|
800
|
-
const permissions = await this.getOrganizationPermissions(organization)
|
|
903
|
+
const permissions = await this.getOrganizationPermissions(organization);
|
|
801
904
|
if (!permissions) {
|
|
802
905
|
continue;
|
|
803
906
|
}
|
|
@@ -805,7 +908,7 @@ export class AdminPermissionChecker {
|
|
|
805
908
|
// Now add all records of this organization
|
|
806
909
|
for (const category of organization.meta.recordsConfiguration.recordCategories) {
|
|
807
910
|
if (permissions.hasResourceAccess(PermissionsResourceType.RecordCategories, category.id, level)) {
|
|
808
|
-
recordCategories.push(category)
|
|
911
|
+
recordCategories.push(category);
|
|
809
912
|
}
|
|
810
913
|
}
|
|
811
914
|
|
|
@@ -817,13 +920,13 @@ export class AdminPermissionChecker {
|
|
|
817
920
|
}
|
|
818
921
|
|
|
819
922
|
if (permissions.hasResourceAccess(PermissionsResourceType.RecordCategories, category.id, level)) {
|
|
820
|
-
recordCategories.push(category)
|
|
923
|
+
recordCategories.push(category);
|
|
821
924
|
}
|
|
822
925
|
}
|
|
823
926
|
}
|
|
824
927
|
|
|
825
928
|
// Platform data
|
|
826
|
-
const platformPermissions = this.platformPermissions
|
|
929
|
+
const platformPermissions = this.platformPermissions;
|
|
827
930
|
if (platformPermissions || isUserManager) {
|
|
828
931
|
for (const category of this.platform.config.recordsConfiguration.recordCategories) {
|
|
829
932
|
if (recordCategories.find(c => c.id === category.id)) {
|
|
@@ -832,19 +935,19 @@ export class AdminPermissionChecker {
|
|
|
832
935
|
}
|
|
833
936
|
|
|
834
937
|
if (isUserManager || platformPermissions?.hasResourceAccess(PermissionsResourceType.RecordCategories, category.id, level)) {
|
|
835
|
-
recordCategories.push(category)
|
|
938
|
+
recordCategories.push(category);
|
|
836
939
|
}
|
|
837
940
|
}
|
|
838
941
|
}
|
|
839
942
|
|
|
840
|
-
return recordCategories
|
|
943
|
+
return recordCategories;
|
|
841
944
|
}
|
|
842
945
|
|
|
843
946
|
/**
|
|
844
947
|
* Return a list of RecordSettings the current user can view or edit
|
|
845
948
|
*/
|
|
846
949
|
async hasFinancialMemberAccess(member: MemberWithRegistrations, level: PermissionLevel = PermissionLevel.Read): Promise<boolean> {
|
|
847
|
-
const isUserManager = this.isUserManager(member)
|
|
950
|
+
const isUserManager = this.isUserManager(member);
|
|
848
951
|
|
|
849
952
|
if (isUserManager && level === PermissionLevel.Read) {
|
|
850
953
|
return true;
|
|
@@ -859,21 +962,21 @@ export class AdminPermissionChecker {
|
|
|
859
962
|
|
|
860
963
|
if (member.organizationId) {
|
|
861
964
|
if (this.checkScope(member.organizationId)) {
|
|
862
|
-
organizations.push(await this.getOrganization(member.organizationId))
|
|
965
|
+
organizations.push(await this.getOrganization(member.organizationId));
|
|
863
966
|
}
|
|
864
967
|
}
|
|
865
968
|
|
|
866
969
|
for (const registration of member.registrations) {
|
|
867
970
|
if (this.checkScope(registration.organizationId)) {
|
|
868
971
|
if (!organizations.find(o => o.id === registration.organizationId)) {
|
|
869
|
-
organizations.push(await this.getOrganization(registration.organizationId))
|
|
972
|
+
organizations.push(await this.getOrganization(registration.organizationId));
|
|
870
973
|
}
|
|
871
974
|
}
|
|
872
975
|
}
|
|
873
976
|
|
|
874
977
|
// Loop all organizations.
|
|
875
978
|
for (const organization of organizations) {
|
|
876
|
-
const permissions = await this.getOrganizationPermissions(organization)
|
|
979
|
+
const permissions = await this.getOrganizationPermissions(organization);
|
|
877
980
|
if (!permissions) {
|
|
878
981
|
continue;
|
|
879
982
|
}
|
|
@@ -893,7 +996,7 @@ export class AdminPermissionChecker {
|
|
|
893
996
|
}
|
|
894
997
|
|
|
895
998
|
// Platform data
|
|
896
|
-
const platformPermissions = this.platformPermissions
|
|
999
|
+
const platformPermissions = this.platformPermissions;
|
|
897
1000
|
if (platformPermissions) {
|
|
898
1001
|
if (isUserManager) {
|
|
899
1002
|
// Requirements are higher: you need financial access to write your own financial
|
|
@@ -901,55 +1004,54 @@ export class AdminPermissionChecker {
|
|
|
901
1004
|
if (platformPermissions.hasAccessRight(AccessRight.OrganizationManagePayments)) {
|
|
902
1005
|
return true;
|
|
903
1006
|
}
|
|
904
|
-
}
|
|
1007
|
+
}
|
|
1008
|
+
else {
|
|
905
1009
|
if (platformPermissions.hasAccessRight(level === PermissionLevel.Read ? AccessRight.MemberReadFinancialData : AccessRight.MemberWriteFinancialData)) {
|
|
906
1010
|
return true;
|
|
907
1011
|
}
|
|
908
1012
|
}
|
|
909
1013
|
}
|
|
910
1014
|
|
|
911
|
-
return false
|
|
1015
|
+
return false;
|
|
912
1016
|
}
|
|
913
1017
|
|
|
914
1018
|
/**
|
|
915
1019
|
* Return a list of RecordSettings the current user can view or edit
|
|
916
1020
|
*/
|
|
917
1021
|
async getAccessibleRecordSet(member: MemberWithRegistrations, level: PermissionLevel = PermissionLevel.Read): Promise<Set<string>> {
|
|
918
|
-
const categories = await this.getAccessibleRecordCategories(member, level)
|
|
919
|
-
const set = new Set<string>()
|
|
1022
|
+
const categories = await this.getAccessibleRecordCategories(member, level);
|
|
1023
|
+
const set = new Set<string>();
|
|
920
1024
|
|
|
921
1025
|
for (const category of categories) {
|
|
922
1026
|
for (const record of category.getAllRecords()) {
|
|
923
|
-
set.add(record.id)
|
|
1027
|
+
set.add(record.id);
|
|
924
1028
|
}
|
|
925
1029
|
}
|
|
926
1030
|
|
|
927
|
-
return set
|
|
1031
|
+
return set;
|
|
928
1032
|
}
|
|
929
1033
|
|
|
930
|
-
|
|
931
1034
|
async getAccessibleGroups(organizationId: string, level: PermissionLevel = PermissionLevel.Read): Promise<string[] | 'all'> {
|
|
932
1035
|
if (await this.hasFullAccess(organizationId)) {
|
|
933
|
-
return 'all'
|
|
1036
|
+
return 'all';
|
|
934
1037
|
}
|
|
935
1038
|
|
|
936
|
-
const groups = await this.getOrganizationGroups(organizationId)
|
|
937
|
-
const accessibleGroups: string[] = []
|
|
1039
|
+
const groups = await this.getOrganizationGroups(organizationId);
|
|
1040
|
+
const accessibleGroups: string[] = [];
|
|
938
1041
|
|
|
939
1042
|
for (const group of groups) {
|
|
940
1043
|
if (await this.canAccessGroup(group, level)) {
|
|
941
|
-
accessibleGroups.push(group.id)
|
|
1044
|
+
accessibleGroups.push(group.id);
|
|
942
1045
|
}
|
|
943
1046
|
}
|
|
944
|
-
return accessibleGroups
|
|
1047
|
+
return accessibleGroups;
|
|
945
1048
|
}
|
|
946
1049
|
|
|
947
|
-
|
|
948
1050
|
/**
|
|
949
1051
|
* Changes data inline
|
|
950
1052
|
*/
|
|
951
1053
|
async filterMemberData(member: MemberWithRegistrations, data: MemberWithRegistrationsBlob): Promise<MemberWithRegistrationsBlob> {
|
|
952
|
-
const isUserManager = this.isUserManager(member)
|
|
1054
|
+
const isUserManager = this.isUserManager(member);
|
|
953
1055
|
if (isUserManager) {
|
|
954
1056
|
// For the user manager, we don't delete data, because when registering a new member, it doesn't have any organizations yet...
|
|
955
1057
|
if (!(await this.canAccessMember(member, PermissionLevel.Full))) {
|
|
@@ -960,31 +1062,31 @@ export class AdminPermissionChecker {
|
|
|
960
1062
|
return data;
|
|
961
1063
|
}
|
|
962
1064
|
|
|
963
|
-
const records = await this.getAccessibleRecordSet(member, PermissionLevel.Read)
|
|
1065
|
+
const records = await this.getAccessibleRecordSet(member, PermissionLevel.Read);
|
|
964
1066
|
|
|
965
|
-
const cloned = data.clone()
|
|
1067
|
+
const cloned = data.clone();
|
|
966
1068
|
|
|
967
1069
|
for (const [key, value] of cloned.details.recordAnswers.entries()) {
|
|
968
1070
|
if (!records.has(value.settings.id)) {
|
|
969
|
-
cloned.details.recordAnswers.delete(key)
|
|
1071
|
+
cloned.details.recordAnswers.delete(key);
|
|
970
1072
|
}
|
|
971
1073
|
}
|
|
972
1074
|
|
|
973
1075
|
// Has financial read access?
|
|
974
1076
|
if (!await this.hasFinancialMemberAccess(member, PermissionLevel.Read)) {
|
|
975
|
-
cloned.details.requiresFinancialSupport = null
|
|
976
|
-
cloned.details.uitpasNumber = null
|
|
977
|
-
cloned.outstandingBalance = 0
|
|
1077
|
+
cloned.details.requiresFinancialSupport = null;
|
|
1078
|
+
cloned.details.uitpasNumber = null;
|
|
1079
|
+
cloned.outstandingBalance = 0;
|
|
978
1080
|
|
|
979
1081
|
for (const registration of cloned.registrations) {
|
|
980
|
-
registration.price = 0
|
|
981
|
-
registration.pricePaid = 0
|
|
1082
|
+
registration.price = 0;
|
|
1083
|
+
registration.pricePaid = 0;
|
|
982
1084
|
}
|
|
983
1085
|
}
|
|
984
1086
|
|
|
985
1087
|
// At least write permissions is required for now to obtain the security code
|
|
986
1088
|
if (!(await this.canAccessMember(member, PermissionLevel.Write))) {
|
|
987
|
-
cloned.details.securityCode = null
|
|
1089
|
+
cloned.details.securityCode = null;
|
|
988
1090
|
}
|
|
989
1091
|
|
|
990
1092
|
return cloned;
|
|
@@ -998,8 +1100,8 @@ export class AdminPermissionChecker {
|
|
|
998
1100
|
throw new SimpleError({
|
|
999
1101
|
code: 'invalid_request',
|
|
1000
1102
|
message: 'Cannot PUT a full member details object',
|
|
1001
|
-
statusCode: 400
|
|
1002
|
-
})
|
|
1103
|
+
statusCode: 400,
|
|
1104
|
+
});
|
|
1003
1105
|
}
|
|
1004
1106
|
|
|
1005
1107
|
const hasRecordAnswers = !!data.details.recordAnswers;
|
|
@@ -1011,9 +1113,9 @@ export class AdminPermissionChecker {
|
|
|
1011
1113
|
const hasFullAccess = await this.canAccessMember(member, PermissionLevel.Full);
|
|
1012
1114
|
|
|
1013
1115
|
// can only be set to null, and only if can access member with full access
|
|
1014
|
-
if(!hasFullAccess || data.details.securityCode !== null) {
|
|
1116
|
+
if (!hasFullAccess || data.details.securityCode !== null) {
|
|
1015
1117
|
// Unset silently
|
|
1016
|
-
data.details.securityCode = undefined
|
|
1118
|
+
data.details.securityCode = undefined;
|
|
1017
1119
|
}
|
|
1018
1120
|
}
|
|
1019
1121
|
|
|
@@ -1022,42 +1124,42 @@ export class AdminPermissionChecker {
|
|
|
1022
1124
|
throw new SimpleError({
|
|
1023
1125
|
code: 'invalid_request',
|
|
1024
1126
|
message: 'Cannot PUT recordAnswers',
|
|
1025
|
-
statusCode: 400
|
|
1026
|
-
})
|
|
1127
|
+
statusCode: 400,
|
|
1128
|
+
});
|
|
1027
1129
|
}
|
|
1028
|
-
|
|
1029
|
-
const records = isUserManager ? new Set() : await this.getAccessibleRecordSet(member, PermissionLevel.Write)
|
|
1130
|
+
|
|
1131
|
+
const records = isUserManager ? new Set() : await this.getAccessibleRecordSet(member, PermissionLevel.Write);
|
|
1030
1132
|
|
|
1031
1133
|
for (const [key, value] of data.details.recordAnswers.entries()) {
|
|
1032
|
-
let name: string | undefined = undefined
|
|
1134
|
+
let name: string | undefined = undefined;
|
|
1033
1135
|
if (value) {
|
|
1034
1136
|
if (value.isPatch()) {
|
|
1035
1137
|
throw new SimpleError({
|
|
1036
1138
|
code: 'invalid_request',
|
|
1037
1139
|
message: 'Cannot PATCH a record answer object',
|
|
1038
|
-
statusCode: 400
|
|
1039
|
-
})
|
|
1140
|
+
statusCode: 400,
|
|
1141
|
+
});
|
|
1040
1142
|
}
|
|
1041
1143
|
|
|
1042
|
-
const id = value.settings.id
|
|
1144
|
+
const id = value.settings.id;
|
|
1043
1145
|
|
|
1044
1146
|
if (id !== key) {
|
|
1045
1147
|
throw new SimpleError({
|
|
1046
1148
|
code: 'invalid_request',
|
|
1047
1149
|
message: 'Record answer key does not match record id',
|
|
1048
|
-
statusCode: 400
|
|
1049
|
-
})
|
|
1150
|
+
statusCode: 400,
|
|
1151
|
+
});
|
|
1050
1152
|
}
|
|
1051
1153
|
|
|
1052
|
-
name = value.settings.name
|
|
1154
|
+
name = value.settings.name;
|
|
1053
1155
|
}
|
|
1054
1156
|
|
|
1055
1157
|
if (!isUserManager && !records.has(key)) {
|
|
1056
1158
|
throw new SimpleError({
|
|
1057
1159
|
code: 'permission_denied',
|
|
1058
1160
|
message: `Je hebt geen toegangsrechten om het antwoord op ${name ?? 'deze vraag'} aan te passen voor dit lid`,
|
|
1059
|
-
statusCode: 400
|
|
1060
|
-
})
|
|
1161
|
+
statusCode: 400,
|
|
1162
|
+
});
|
|
1061
1163
|
}
|
|
1062
1164
|
}
|
|
1063
1165
|
}
|
|
@@ -1066,8 +1168,8 @@ export class AdminPermissionChecker {
|
|
|
1066
1168
|
throw new SimpleError({
|
|
1067
1169
|
code: 'permission_denied',
|
|
1068
1170
|
message: 'Cannot edit notes',
|
|
1069
|
-
statusCode: 400
|
|
1070
|
-
})
|
|
1171
|
+
statusCode: 400,
|
|
1172
|
+
});
|
|
1071
1173
|
}
|
|
1072
1174
|
|
|
1073
1175
|
// Has financial write access?
|
|
@@ -1075,26 +1177,27 @@ export class AdminPermissionChecker {
|
|
|
1075
1177
|
if (isUserManager && isSetFinancialSupportTrue) {
|
|
1076
1178
|
const financialSupportSettings = this.platform.config.financialSupport;
|
|
1077
1179
|
const preventSelfAssignment = financialSupportSettings?.preventSelfAssignment === true;
|
|
1078
|
-
|
|
1079
|
-
if(preventSelfAssignment) {
|
|
1180
|
+
|
|
1181
|
+
if (preventSelfAssignment) {
|
|
1080
1182
|
throw new SimpleError({
|
|
1081
1183
|
code: 'permission_denied',
|
|
1082
1184
|
message: 'No permissions to enable financial support for your own members',
|
|
1083
1185
|
human: financialSupportSettings.preventSelfAssignmentText ?? FinancialSupportSettings.defaultPreventSelfAssignmentText,
|
|
1084
|
-
statusCode: 400
|
|
1186
|
+
statusCode: 400,
|
|
1085
1187
|
});
|
|
1086
1188
|
}
|
|
1087
1189
|
}
|
|
1088
|
-
|
|
1190
|
+
|
|
1089
1191
|
if (data.details.requiresFinancialSupport) {
|
|
1090
1192
|
if (isUserManager) {
|
|
1091
1193
|
// Already handled
|
|
1092
|
-
}
|
|
1194
|
+
}
|
|
1195
|
+
else {
|
|
1093
1196
|
throw new SimpleError({
|
|
1094
1197
|
code: 'permission_denied',
|
|
1095
1198
|
message: 'Je hebt geen toegangsrechten om de financiële status van dit lid aan te passen',
|
|
1096
|
-
statusCode: 400
|
|
1097
|
-
})
|
|
1199
|
+
statusCode: 400,
|
|
1200
|
+
});
|
|
1098
1201
|
}
|
|
1099
1202
|
}
|
|
1100
1203
|
|
|
@@ -1103,8 +1206,8 @@ export class AdminPermissionChecker {
|
|
|
1103
1206
|
throw new SimpleError({
|
|
1104
1207
|
code: 'permission_denied',
|
|
1105
1208
|
message: 'Je hebt geen toegangsrechten om het UiTPAS-nummer van dit lid aan te passen',
|
|
1106
|
-
statusCode: 400
|
|
1107
|
-
})
|
|
1209
|
+
statusCode: 400,
|
|
1210
|
+
});
|
|
1108
1211
|
}
|
|
1109
1212
|
}
|
|
1110
1213
|
|
|
@@ -1112,38 +1215,38 @@ export class AdminPermissionChecker {
|
|
|
1112
1215
|
throw new SimpleError({
|
|
1113
1216
|
code: 'permission_denied',
|
|
1114
1217
|
message: 'Je hebt geen toegangsrechten om het openstaande saldo van dit lid aan te passen',
|
|
1115
|
-
statusCode: 400
|
|
1116
|
-
})
|
|
1218
|
+
statusCode: 400,
|
|
1219
|
+
});
|
|
1117
1220
|
}
|
|
1118
1221
|
|
|
1119
|
-
for (const {put: registration} of data.registrations.getPuts()) {
|
|
1222
|
+
for (const { put: registration } of data.registrations.getPuts()) {
|
|
1120
1223
|
if (registration.price) {
|
|
1121
1224
|
throw new SimpleError({
|
|
1122
1225
|
code: 'permission_denied',
|
|
1123
1226
|
message: 'Je hebt geen toegangsrechten om de prijs van een inschrijving te bepalen',
|
|
1124
|
-
statusCode: 400
|
|
1125
|
-
})
|
|
1227
|
+
statusCode: 400,
|
|
1228
|
+
});
|
|
1126
1229
|
}
|
|
1127
1230
|
|
|
1128
1231
|
if (registration.pricePaid) {
|
|
1129
1232
|
throw new SimpleError({
|
|
1130
1233
|
code: 'permission_denied',
|
|
1131
1234
|
message: 'Je hebt geen toegangsrechten om het betaalde bedrag van een inschrijving te bepalen',
|
|
1132
|
-
statusCode: 400
|
|
1133
|
-
})
|
|
1235
|
+
statusCode: 400,
|
|
1236
|
+
});
|
|
1134
1237
|
}
|
|
1135
1238
|
}
|
|
1136
1239
|
}
|
|
1137
1240
|
|
|
1138
|
-
return data
|
|
1241
|
+
return data;
|
|
1139
1242
|
}
|
|
1140
1243
|
|
|
1141
1244
|
canAccessAllPlatformMembers(): boolean {
|
|
1142
|
-
return !!this.platformPermissions && !!this.platformPermissions.hasAccessRight(AccessRight.PlatformLoginAs)
|
|
1245
|
+
return !!this.platformPermissions && !!this.platformPermissions.hasAccessRight(AccessRight.PlatformLoginAs);
|
|
1143
1246
|
}
|
|
1144
1247
|
|
|
1145
1248
|
hasPlatformFullAccess(): boolean {
|
|
1146
|
-
return !!this.platformPermissions && !!this.platformPermissions.hasFullAccess()
|
|
1249
|
+
return !!this.platformPermissions && !!this.platformPermissions.hasFullAccess();
|
|
1147
1250
|
}
|
|
1148
1251
|
|
|
1149
1252
|
getPlatformAccessibleOrganizationTags(level: PermissionLevel): string[] | 'all' {
|
|
@@ -1152,34 +1255,34 @@ export class AdminPermissionChecker {
|
|
|
1152
1255
|
}
|
|
1153
1256
|
|
|
1154
1257
|
if (this.hasPlatformFullAccess()) {
|
|
1155
|
-
return 'all'
|
|
1258
|
+
return 'all';
|
|
1156
1259
|
}
|
|
1157
1260
|
|
|
1158
1261
|
if (this.platformPermissions?.hasResourceAccess(PermissionsResourceType.OrganizationTags, '', level)) {
|
|
1159
|
-
return 'all'
|
|
1262
|
+
return 'all';
|
|
1160
1263
|
}
|
|
1161
1264
|
|
|
1162
|
-
const allTags = this.platform.config.tags
|
|
1163
|
-
const tags: string[] = []
|
|
1265
|
+
const allTags = this.platform.config.tags;
|
|
1266
|
+
const tags: string[] = [];
|
|
1164
1267
|
|
|
1165
1268
|
for (const tag of allTags) {
|
|
1166
1269
|
if (this.platformPermissions?.hasResourceAccess(PermissionsResourceType.OrganizationTags, tag.id, level)) {
|
|
1167
|
-
tags.push(tag.id)
|
|
1270
|
+
tags.push(tag.id);
|
|
1168
1271
|
}
|
|
1169
1272
|
}
|
|
1170
1273
|
|
|
1171
1274
|
if (tags.length === allTags.length) {
|
|
1172
|
-
return 'all'
|
|
1275
|
+
return 'all';
|
|
1173
1276
|
}
|
|
1174
1277
|
|
|
1175
|
-
return tags
|
|
1278
|
+
return tags;
|
|
1176
1279
|
}
|
|
1177
1280
|
|
|
1178
1281
|
hasSomePlatformAccess(): boolean {
|
|
1179
|
-
return !!this.platformPermissions
|
|
1282
|
+
return !!this.platformPermissions;
|
|
1180
1283
|
}
|
|
1181
1284
|
|
|
1182
1285
|
canManagePlatformAdmins() {
|
|
1183
|
-
return this.hasPlatformFullAccess()
|
|
1286
|
+
return this.hasPlatformFullAccess();
|
|
1184
1287
|
}
|
|
1185
1288
|
}
|