@stamhoofd/backend 2.19.0 → 2.21.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/.env.template.json +1 -1
- package/package.json +6 -6
- package/src/crons.ts +3 -67
- package/src/endpoints/auth/ForgotPasswordEndpoint.ts +33 -29
- package/src/endpoints/global/files/ExportToExcelEndpoint.ts +3 -8
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +10 -1
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +0 -47
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +14 -16
- package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +8 -0
- package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +1 -1
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +171 -36
- package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +5 -2
- package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +28 -32
- package/src/helpers/AdminPermissionChecker.ts +22 -5
- package/src/helpers/AuthenticatedStructures.ts +3 -2
- package/src/helpers/SetupStepsUpdater.ts +115 -13
- package/src/endpoints/global/payments/ExchangeSTPaymentEndpoint.ts +0 -153
- package/src/endpoints/organization/dashboard/organization/ApplyRegisterCodeEndpoint.test.ts +0 -64
- package/src/endpoints/organization/dashboard/organization/ApplyRegisterCodeEndpoint.ts +0 -84
- package/src/endpoints/organization/dashboard/organization/GetRegisterCodeEndpoint.ts +0 -65
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AutoEncoderPatchType, Decoder, patchObject } from "@simonbackx/simple-encoding";
|
|
2
2
|
import { DecodedRequest, Endpoint, Request, Response } from "@simonbackx/simple-endpoints";
|
|
3
3
|
import { Organization, Platform, RegistrationPeriod } from "@stamhoofd/models";
|
|
4
|
-
import { PlatformPremiseType, Platform as PlatformStruct } from "@stamhoofd/structures";
|
|
4
|
+
import { MemberResponsibility, PlatformConfig, PlatformPremiseType, Platform as PlatformStruct } from "@stamhoofd/structures";
|
|
5
5
|
|
|
6
6
|
import { SimpleError } from "@simonbackx/simple-errors";
|
|
7
7
|
import { Context } from "../../../helpers/Context";
|
|
@@ -12,8 +12,15 @@ type Query = undefined;
|
|
|
12
12
|
type Body = AutoEncoderPatchType<PlatformStruct>;
|
|
13
13
|
type ResponseBody = PlatformStruct;
|
|
14
14
|
|
|
15
|
-
export class PatchPlatformEndpoint extends Endpoint<
|
|
16
|
-
|
|
15
|
+
export class PatchPlatformEndpoint extends Endpoint<
|
|
16
|
+
Params,
|
|
17
|
+
Query,
|
|
18
|
+
Body,
|
|
19
|
+
ResponseBody
|
|
20
|
+
> {
|
|
21
|
+
bodyDecoder = PlatformStruct.patchType() as Decoder<
|
|
22
|
+
AutoEncoderPatchType<PlatformStruct>
|
|
23
|
+
>;
|
|
17
24
|
|
|
18
25
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
19
26
|
if (request.method != "PATCH") {
|
|
@@ -29,65 +36,102 @@ export class PatchPlatformEndpoint extends Endpoint<Params, Query, Body, Respons
|
|
|
29
36
|
}
|
|
30
37
|
|
|
31
38
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
32
|
-
await Context.authenticate()
|
|
39
|
+
await Context.authenticate();
|
|
33
40
|
|
|
34
41
|
// Fast throw first (more in depth checking for patches later)
|
|
35
42
|
if (!Context.auth.hasPlatformFullAccess()) {
|
|
36
|
-
throw Context.auth.error()
|
|
43
|
+
throw Context.auth.error();
|
|
37
44
|
}
|
|
38
45
|
|
|
39
|
-
const platform = await Platform.getShared()
|
|
46
|
+
const platform = await Platform.getShared();
|
|
40
47
|
|
|
41
48
|
if (request.body.privateConfig) {
|
|
42
49
|
// Did we patch roles?
|
|
43
50
|
if (request.body.privateConfig.roles) {
|
|
44
51
|
if (!Context.auth.canManagePlatformAdmins()) {
|
|
45
|
-
throw Context.auth.error()
|
|
52
|
+
throw Context.auth.error();
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
// Update roles
|
|
49
|
-
platform.privateConfig.roles = patchObject(
|
|
56
|
+
platform.privateConfig.roles = patchObject(
|
|
57
|
+
platform.privateConfig.roles,
|
|
58
|
+
request.body.privateConfig.roles
|
|
59
|
+
);
|
|
50
60
|
}
|
|
51
61
|
|
|
52
62
|
if (request.body.privateConfig.emails) {
|
|
53
63
|
if (!Context.auth.hasPlatformFullAccess()) {
|
|
54
|
-
throw Context.auth.error()
|
|
64
|
+
throw Context.auth.error();
|
|
55
65
|
}
|
|
56
66
|
|
|
57
67
|
// Update roles
|
|
58
|
-
platform.privateConfig.emails = patchObject(
|
|
68
|
+
platform.privateConfig.emails = patchObject(
|
|
69
|
+
platform.privateConfig.emails,
|
|
70
|
+
request.body.privateConfig.emails
|
|
71
|
+
);
|
|
59
72
|
}
|
|
60
73
|
}
|
|
61
74
|
|
|
75
|
+
let shouldUpdateSetupSteps = false;
|
|
76
|
+
|
|
62
77
|
if (request.body.config) {
|
|
63
78
|
if (!Context.auth.hasPlatformFullAccess()) {
|
|
64
|
-
throw Context.auth.error()
|
|
79
|
+
throw Context.auth.error();
|
|
65
80
|
}
|
|
66
81
|
|
|
82
|
+
const newConfig = request.body.config;
|
|
83
|
+
|
|
67
84
|
// Update config
|
|
68
|
-
if(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
85
|
+
if (newConfig) {
|
|
86
|
+
if (newConfig.premiseTypes || newConfig.responsibilities) {
|
|
87
|
+
const oldConfig = platform.config.clone();
|
|
88
|
+
platform.config = patchObject(platform.config, newConfig);
|
|
89
|
+
const currentConfig = platform.config;
|
|
90
|
+
|
|
91
|
+
shouldUpdateSetupSteps = this.shouldUpdateSetupSteps(
|
|
92
|
+
currentConfig,
|
|
93
|
+
newConfig,
|
|
94
|
+
oldConfig
|
|
95
|
+
);
|
|
96
|
+
} else {
|
|
97
|
+
platform.config = patchObject(platform.config, newConfig);
|
|
76
98
|
}
|
|
77
|
-
} else {
|
|
78
|
-
platform.config = patchObject(platform.config, request.body.config)
|
|
79
99
|
}
|
|
80
100
|
}
|
|
81
101
|
|
|
82
|
-
if (
|
|
83
|
-
|
|
102
|
+
if (
|
|
103
|
+
request.body.period &&
|
|
104
|
+
request.body.period.id !== platform.periodId
|
|
105
|
+
) {
|
|
106
|
+
const period = await RegistrationPeriod.getByID(
|
|
107
|
+
request.body.period.id
|
|
108
|
+
);
|
|
84
109
|
if (!period || period.organizationId) {
|
|
85
110
|
throw new SimpleError({
|
|
86
111
|
code: "invalid_period",
|
|
87
|
-
message: "Invalid period"
|
|
88
|
-
})
|
|
112
|
+
message: "Invalid period",
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
platform.periodId = period.id;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (request.body.membershipOrganizationId !== undefined) {
|
|
119
|
+
if (!Context.auth.hasPlatformFullAccess()) {
|
|
120
|
+
throw Context.auth.error()
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (request.body.membershipOrganizationId) {
|
|
124
|
+
const organization = await Organization.getByID(request.body.membershipOrganizationId)
|
|
125
|
+
if (!organization) {
|
|
126
|
+
throw new SimpleError({
|
|
127
|
+
code: "invalid_organization",
|
|
128
|
+
message: "Invalid organization"
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
platform.membershipOrganizationId = organization.id
|
|
132
|
+
} else {
|
|
133
|
+
platform.membershipOrganizationId = null
|
|
89
134
|
}
|
|
90
|
-
platform.periodId = period.id
|
|
91
135
|
}
|
|
92
136
|
|
|
93
137
|
if (request.body.membershipOrganizationId !== undefined) {
|
|
@@ -109,35 +153,126 @@ export class PatchPlatformEndpoint extends Endpoint<Params, Query, Body, Respons
|
|
|
109
153
|
}
|
|
110
154
|
}
|
|
111
155
|
|
|
112
|
-
await platform.save()
|
|
156
|
+
await platform.save();
|
|
157
|
+
|
|
158
|
+
if(shouldUpdateSetupSteps) {
|
|
159
|
+
SetupStepUpdater.updateSetupStepsForAllOrganizationsInCurrentPeriod().catch(console.error);
|
|
160
|
+
}
|
|
161
|
+
|
|
113
162
|
return new Response(await Platform.getSharedPrivateStruct());
|
|
114
163
|
}
|
|
115
164
|
|
|
116
|
-
private
|
|
117
|
-
|
|
165
|
+
private shouldUpdateSetupSteps(
|
|
166
|
+
currentConfig: PlatformConfig,
|
|
167
|
+
newConfig: PlatformConfig | AutoEncoderPatchType<PlatformConfig>,
|
|
168
|
+
oldConfig: PlatformConfig
|
|
169
|
+
): boolean {
|
|
170
|
+
let shouldUpdate = false;
|
|
171
|
+
const premiseTypes: PlatformPremiseType[] = currentConfig.premiseTypes;
|
|
172
|
+
const responsibilities: MemberResponsibility[] =
|
|
173
|
+
currentConfig.responsibilities;
|
|
174
|
+
|
|
175
|
+
if (
|
|
176
|
+
newConfig.premiseTypes &&
|
|
177
|
+
this.shouldUpdateSetupStepPremise(
|
|
178
|
+
premiseTypes,
|
|
179
|
+
oldConfig.premiseTypes
|
|
180
|
+
)
|
|
181
|
+
) {
|
|
182
|
+
shouldUpdate = true;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (
|
|
186
|
+
!shouldUpdate &&
|
|
187
|
+
newConfig.responsibilities &&
|
|
188
|
+
this.shouldUpdateSetupStepFunctions(
|
|
189
|
+
responsibilities,
|
|
190
|
+
oldConfig.responsibilities
|
|
191
|
+
)
|
|
192
|
+
) {
|
|
193
|
+
shouldUpdate = true;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return shouldUpdate;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private shouldUpdateSetupStepPremise(
|
|
200
|
+
newPremiseTypes: PlatformPremiseType[],
|
|
201
|
+
oldPremiseTypes: PlatformPremiseType[]
|
|
202
|
+
) {
|
|
203
|
+
for (const premiseType of newPremiseTypes) {
|
|
118
204
|
const id = premiseType.id;
|
|
119
|
-
const oldVersion = oldPremiseTypes.find(x => x.id === id);
|
|
205
|
+
const oldVersion = oldPremiseTypes.find((x) => x.id === id);
|
|
120
206
|
|
|
121
207
|
// if premise type is not new
|
|
122
|
-
if(oldVersion) {
|
|
123
|
-
if(
|
|
208
|
+
if (oldVersion) {
|
|
209
|
+
if (
|
|
210
|
+
oldVersion.min !== premiseType.min ||
|
|
211
|
+
oldVersion.max !== premiseType.max
|
|
212
|
+
) {
|
|
124
213
|
return true;
|
|
125
214
|
}
|
|
126
215
|
continue;
|
|
127
216
|
}
|
|
128
217
|
|
|
129
218
|
// if premise type is new
|
|
130
|
-
if(premiseType.min || premiseType.max) {
|
|
219
|
+
if (premiseType.min || premiseType.max) {
|
|
131
220
|
return true;
|
|
132
221
|
}
|
|
133
222
|
}
|
|
134
223
|
|
|
135
|
-
for(const oldPremiseType of oldPremiseTypes) {
|
|
224
|
+
for (const oldPremiseType of oldPremiseTypes) {
|
|
136
225
|
const id = oldPremiseType.id;
|
|
137
226
|
|
|
138
227
|
// if premise type is removed
|
|
139
|
-
if(!newPremiseTypes.some(x => x.id === id)) {
|
|
140
|
-
if(oldPremiseType.min || oldPremiseType.max) {
|
|
228
|
+
if (!newPremiseTypes.some((x) => x.id === id)) {
|
|
229
|
+
if (oldPremiseType.min || oldPremiseType.max) {
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
private shouldUpdateSetupStepFunctions(
|
|
237
|
+
newResponsibilities: MemberResponsibility[],
|
|
238
|
+
oldResponsibilities: MemberResponsibility[]
|
|
239
|
+
) {
|
|
240
|
+
for (const responsibility of newResponsibilities) {
|
|
241
|
+
const id = responsibility.id;
|
|
242
|
+
const oldVersion = oldResponsibilities.find((x) => x.id === id);
|
|
243
|
+
|
|
244
|
+
// if responsibility is not new
|
|
245
|
+
if (oldVersion) {
|
|
246
|
+
// if restrictions changed
|
|
247
|
+
if (
|
|
248
|
+
oldVersion.minimumMembers !==
|
|
249
|
+
responsibility.minimumMembers ||
|
|
250
|
+
oldVersion.maximumMembers !== responsibility.maximumMembers
|
|
251
|
+
) {
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// if responsibility is new
|
|
258
|
+
if (
|
|
259
|
+
responsibility.minimumMembers ||
|
|
260
|
+
responsibility.maximumMembers
|
|
261
|
+
) {
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
for (const oldResponsibility of oldResponsibilities) {
|
|
267
|
+
const id = oldResponsibility.id;
|
|
268
|
+
|
|
269
|
+
// if responsibility is removed
|
|
270
|
+
if (!newResponsibilities.some((x) => x.id === id)) {
|
|
271
|
+
// if responsibility had restrictions
|
|
272
|
+
if (
|
|
273
|
+
oldResponsibility.minimumMembers ||
|
|
274
|
+
oldResponsibility.maximumMembers
|
|
275
|
+
) {
|
|
141
276
|
return true;
|
|
142
277
|
}
|
|
143
278
|
}
|
|
@@ -3,6 +3,7 @@ import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-
|
|
|
3
3
|
import jwt from 'jsonwebtoken';
|
|
4
4
|
|
|
5
5
|
import { Context } from '../../../../helpers/Context';
|
|
6
|
+
import { SimpleError } from '@simonbackx/simple-errors';
|
|
6
7
|
|
|
7
8
|
type Params = Record<string, never>;
|
|
8
9
|
type Query = undefined;
|
|
@@ -39,7 +40,7 @@ export class CreateNoltTokenEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
39
40
|
if (!await Context.auth.hasSomeAccess(organization.id)) {
|
|
40
41
|
throw Context.auth.error()
|
|
41
42
|
}
|
|
42
|
-
|
|
43
|
+
|
|
43
44
|
// Create token
|
|
44
45
|
const payload = {
|
|
45
46
|
// The ID that you use in your app for this user
|
|
@@ -262,7 +262,7 @@ export class PatchOrganizationEndpoint extends Endpoint<Params, Query, Body, Res
|
|
|
262
262
|
}
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
-
if (request.body.meta?.tags) {
|
|
265
|
+
if (request.body.meta?.tags && (Array.isArray(request.body.meta?.tags) || request.body.meta?.tags.changes.length > 0)) {
|
|
266
266
|
if (!Context.auth.hasPlatformFullAccess()) {
|
|
267
267
|
throw Context.auth.error()
|
|
268
268
|
}
|
package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts
CHANGED
|
@@ -42,7 +42,7 @@ export class SetupStepReviewEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
42
42
|
|
|
43
43
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
44
44
|
const organization = await Context.setOrganizationScope();
|
|
45
|
-
await Context.authenticate()
|
|
45
|
+
const { user } = await Context.authenticate()
|
|
46
46
|
|
|
47
47
|
if (!await Context.auth.hasFullAccess(organization.id)) {
|
|
48
48
|
throw Context.auth.error()
|
|
@@ -64,7 +64,10 @@ export class SetupStepReviewEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
64
64
|
const setupSteps = organizationPeriod.setupSteps;
|
|
65
65
|
|
|
66
66
|
if(isReviewed) {
|
|
67
|
-
setupSteps.markReviewed(stepType
|
|
67
|
+
setupSteps.markReviewed(stepType, {
|
|
68
|
+
userId: user.id,
|
|
69
|
+
userName: user.name ?? '?'
|
|
70
|
+
});
|
|
68
71
|
} else {
|
|
69
72
|
setupSteps.resetReviewed(stepType);
|
|
70
73
|
}
|
|
@@ -2,19 +2,15 @@ import { createMollieClient } from '@mollie/api-client';
|
|
|
2
2
|
import { AutoEncoder, BooleanDecoder, Decoder, field } from '@simonbackx/simple-encoding';
|
|
3
3
|
import { DecodedRequest, Endpoint, Request, Response } from "@simonbackx/simple-endpoints";
|
|
4
4
|
import { SimpleError } from "@simonbackx/simple-errors";
|
|
5
|
-
import { BalanceItem, BalanceItemPayment, MolliePayment, MollieToken, Organization, PayconiqPayment, Payment
|
|
5
|
+
import { BalanceItem, BalanceItemPayment, MolliePayment, MollieToken, Organization, PayconiqPayment, Payment } from '@stamhoofd/models';
|
|
6
6
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
7
|
-
import { PaymentGeneral, PaymentMethod,
|
|
7
|
+
import { PaymentGeneral, PaymentMethod, PaymentProvider, PaymentStatus } from "@stamhoofd/structures";
|
|
8
8
|
|
|
9
9
|
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
|
|
10
10
|
import { BuckarooHelper } from '../../../helpers/BuckarooHelper';
|
|
11
11
|
import { Context } from '../../../helpers/Context';
|
|
12
12
|
import { StripeHelper } from '../../../helpers/StripeHelper';
|
|
13
13
|
|
|
14
|
-
function calculateFee(totalPrice: number, fixed: number, percentageTimes100: number) {
|
|
15
|
-
return Math.round(fixed + Math.max(1, totalPrice * percentageTimes100 / 100 / 100)); // € 0,21 + 0,2%
|
|
16
|
-
}
|
|
17
|
-
|
|
18
14
|
type Params = {id: string};
|
|
19
15
|
class Query extends AutoEncoder {
|
|
20
16
|
@field({ decoder: BooleanDecoder, optional: true })
|
|
@@ -77,7 +73,7 @@ export class ExchangePaymentEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
77
73
|
if (payment.status === status) {
|
|
78
74
|
return;
|
|
79
75
|
}
|
|
80
|
-
const wasPaid = payment.paidAt !== null
|
|
76
|
+
// const wasPaid = payment.paidAt !== null
|
|
81
77
|
if (status === PaymentStatus.Succeeded) {
|
|
82
78
|
payment.status = PaymentStatus.Succeeded
|
|
83
79
|
payment.paidAt = new Date()
|
|
@@ -97,31 +93,31 @@ export class ExchangePaymentEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
97
93
|
await BalanceItem.updateOutstanding(balanceItemPayments.map(p => p.balanceItem), organization.id)
|
|
98
94
|
})
|
|
99
95
|
|
|
100
|
-
if (!wasPaid && payment.provider === PaymentProvider.Buckaroo && payment.method) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
96
|
+
//if (!wasPaid && payment.provider === PaymentProvider.Buckaroo && payment.method) {
|
|
97
|
+
// // Charge transaction fees
|
|
98
|
+
// let fee = 0
|
|
99
|
+
//
|
|
100
|
+
// if (payment.method === PaymentMethod.iDEAL) {
|
|
101
|
+
// fee = calculateFee(payment.price, 21, 20); // € 0,21 + 0,2%
|
|
102
|
+
// } else if (payment.method === PaymentMethod.Bancontact || payment.method === PaymentMethod.Payconiq) {
|
|
103
|
+
// fee = calculateFee(payment.price, 24, 20); // € 0,24 + 0,2%
|
|
104
|
+
// } else {
|
|
105
|
+
// fee = calculateFee(payment.price, 25, 150); // € 0,25 + 1,5%
|
|
106
|
+
// }
|
|
107
|
+
//
|
|
108
|
+
// const name = "Transactiekosten voor "+PaymentMethodHelper.getName(payment.method)
|
|
109
|
+
// const item = STInvoiceItem.create({
|
|
110
|
+
// name,
|
|
111
|
+
// description: "Via Buckaroo",
|
|
112
|
+
// amount: 1,
|
|
113
|
+
// unitPrice: fee,
|
|
114
|
+
// canUseCredits: false
|
|
115
|
+
// })
|
|
116
|
+
// console.log("Scheduling transaction fee charge for ", payment.id, item)
|
|
117
|
+
// await QueueHandler.schedule("billing/invoices-"+organization.id, async () => {
|
|
118
|
+
// await STPendingInvoice.addItems(organization, [item])
|
|
119
|
+
// });
|
|
120
|
+
//}
|
|
125
121
|
return;
|
|
126
122
|
}
|
|
127
123
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AutoEncoderPatchType, PatchMap } from "@simonbackx/simple-encoding"
|
|
2
2
|
import { SimpleError } from "@simonbackx/simple-errors"
|
|
3
|
-
import { BalanceItem, Document, DocumentTemplate, EmailTemplate, Event, Group, Member, MemberWithRegistrations, Order, Organization, Payment, Registration, User, Webshop } from "@stamhoofd/models"
|
|
3
|
+
import { BalanceItem, Document, DocumentTemplate, EmailTemplate, Event, Group, Member, MemberWithRegistrations, Order, Organization, OrganizationRegistrationPeriod, Payment, Registration, User, Webshop } from "@stamhoofd/models"
|
|
4
4
|
import { AccessRight, FinancialSupportSettings, GroupCategory, GroupStatus, MemberWithRegistrationsBlob, PermissionLevel, PermissionsResourceType, Platform as PlatformStruct, RecordCategory } from "@stamhoofd/structures"
|
|
5
5
|
import { Formatter } from "@stamhoofd/utility"
|
|
6
6
|
|
|
@@ -75,6 +75,11 @@ export class AdminPermissionChecker {
|
|
|
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()
|
|
81
|
+
}
|
|
82
|
+
|
|
78
83
|
error(message?: string): SimpleError {
|
|
79
84
|
return new SimpleError({
|
|
80
85
|
code: "permission_denied",
|
|
@@ -171,7 +176,8 @@ export class AdminPermissionChecker {
|
|
|
171
176
|
}
|
|
172
177
|
|
|
173
178
|
// Check parent categories
|
|
174
|
-
const
|
|
179
|
+
const organizationPeriod = await this.getOrganizationCurrentPeriod(organization)
|
|
180
|
+
const parentCategories = group.getParentCategories(organizationPeriod.settings.categories)
|
|
175
181
|
for (const category of parentCategories) {
|
|
176
182
|
if (organizationPermissions.hasResourceAccess(PermissionsResourceType.GroupCategories, category.id, permissionLevel)) {
|
|
177
183
|
return true
|
|
@@ -677,11 +683,22 @@ export class AdminPermissionChecker {
|
|
|
677
683
|
return false;
|
|
678
684
|
}
|
|
679
685
|
|
|
680
|
-
if (
|
|
681
|
-
return
|
|
686
|
+
if (organizationPermissions.hasResourceAccessRight(PermissionsResourceType.GroupCategories, category.id, AccessRight.OrganizationCreateGroups)) {
|
|
687
|
+
return true;
|
|
682
688
|
}
|
|
683
689
|
|
|
684
|
-
|
|
690
|
+
// Check parents
|
|
691
|
+
const organization = await this.getOrganization(organizationId)
|
|
692
|
+
const organizationPeriod = await this.getOrganizationCurrentPeriod(organization)
|
|
693
|
+
const parentCategories = category.getParentCategories(organizationPeriod.settings.categories)
|
|
694
|
+
|
|
695
|
+
for (const parentCategory of parentCategories) {
|
|
696
|
+
if (organizationPermissions.hasResourceAccessRight(PermissionsResourceType.GroupCategories, parentCategory.id, AccessRight.OrganizationCreateGroups)) {
|
|
697
|
+
return true;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
return false;
|
|
685
702
|
}
|
|
686
703
|
|
|
687
704
|
canUpload() {
|
|
@@ -238,11 +238,12 @@ export class AuthenticatedStructures {
|
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
|
-
|
|
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
242
|
const blob = member.getStructureWithRegistrations()
|
|
243
243
|
memberBlobs.push(
|
|
244
244
|
await Context.auth.filterMemberData(member, blob)
|
|
245
245
|
)
|
|
246
|
+
|
|
246
247
|
}
|
|
247
248
|
|
|
248
249
|
// Load responsibilities
|
|
@@ -268,7 +269,7 @@ export class AuthenticatedStructures {
|
|
|
268
269
|
|
|
269
270
|
return MembersBlob.create({
|
|
270
271
|
members: memberBlobs,
|
|
271
|
-
organizations: await Promise.all([...organizations.values()].map(o => this.organization(o)))
|
|
272
|
+
organizations: await Promise.all([...organizations.values()].filter(o => o.active).map(o => this.organization(o)))
|
|
272
273
|
})
|
|
273
274
|
}
|
|
274
275
|
|