@stamhoofd/backend 2.78.2 → 2.78.3

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.
@@ -1,7 +1,6 @@
1
- import { AutoEncoderPatchType, PatchableArray } from '@simonbackx/simple-encoding';
2
1
  import { Request } from '@simonbackx/simple-endpoints';
3
- import { GroupFactory, OrganizationFactory, Token, UserFactory } from '@stamhoofd/models';
4
- import { Group, GroupGenderType, GroupPatch, GroupPrivateSettings, GroupSettings, GroupSettingsPatch, Organization, PermissionLevel, PermissionRole, PermissionRoleDetailed, Permissions, PermissionsResourceType, ResourcePermissions } from '@stamhoofd/structures';
2
+ import { OrganizationFactory, Token, UserFactory } from '@stamhoofd/models';
3
+ import { Organization, PermissionLevel, Permissions } from '@stamhoofd/structures';
5
4
 
6
5
  import { testServer } from '../../../../../tests/helpers/TestServer';
7
6
  import { PatchOrganizationEndpoint } from './PatchOrganizationEndpoint';
@@ -60,218 +59,4 @@ describe('Endpoint.PatchOrganization', () => {
60
59
 
61
60
  await expect(testServer.test(endpoint, r)).rejects.toThrow(/permissions/i);
62
61
  });
63
-
64
- test('Change the name of a group with access', async () => {
65
- const organization = await new OrganizationFactory({}).create();
66
- const role = PermissionRoleDetailed.create({
67
- name: 'Role',
68
- });
69
- organization.privateMeta.roles.push(
70
- role,
71
- );
72
- const groups = await new GroupFactory({ organization }).createMultiple(2);
73
-
74
- role.resources.set(PermissionsResourceType.Groups, new Map());
75
- role.resources.get(PermissionsResourceType.Groups)!.set(groups[0].id, ResourcePermissions.create({
76
- level: PermissionLevel.Full,
77
- }));
78
-
79
- await organization.save();
80
-
81
- const validPermissions = [
82
- Permissions.create({
83
- level: PermissionLevel.None,
84
- roles: [PermissionRole.create(role)],
85
- }),
86
- Permissions.create({
87
- level: PermissionLevel.Full,
88
- }),
89
- ];
90
-
91
- for (const permission of validPermissions) {
92
- const user = await new UserFactory({ organization,
93
- permissions: permission,
94
- }).create();
95
- const token = await Token.createToken(user);
96
-
97
- const changes = new PatchableArray<string, Group, AutoEncoderPatchType<Group>>();
98
- changes.addPatch(GroupPatch.create({
99
- id: groups[0].id,
100
- settings: GroupSettingsPatch.create({
101
- name: 'My crazy group name',
102
- }),
103
- }));
104
-
105
- const r = Request.buildJson('PATCH', '/organization', organization.getApiHost(), {
106
- id: organization.id,
107
- groups: changes.encode({ version: 2 }),
108
- });
109
- r.headers.authorization = 'Bearer ' + token.accessToken;
110
-
111
- const response = await testServer.test(endpoint, r);
112
- expect(response.body).toBeDefined();
113
-
114
- if (!(response.body instanceof Organization)) {
115
- throw new Error('Expected Organization');
116
- }
117
-
118
- expect(response.body.id).toEqual(organization.id);
119
- expect(response.body.groups.find(g => g.id == groups[0].id)!.settings.name).toEqual('My crazy group name');
120
- }
121
- });
122
-
123
- test("Can't change name of group without access", async () => {
124
- const organization = await new OrganizationFactory({}).create();
125
- const role = PermissionRoleDetailed.create({
126
- name: 'Role',
127
- });
128
- const role2 = PermissionRoleDetailed.create({
129
- name: 'Role2',
130
- });
131
- organization.privateMeta.roles.push(
132
- role,
133
- role2,
134
- );
135
- await organization.save();
136
- const groups = await new GroupFactory({ organization }).createMultiple(2);
137
-
138
- groups[0].privateSettings.permissions.write.push(PermissionRole.create(role));
139
- await groups[0].save();
140
-
141
- groups[0].privateSettings.permissions.read.push(PermissionRole.create(role2));
142
- await groups[0].save();
143
-
144
- const invalidPermissions = [
145
- Permissions.create({
146
- level: PermissionLevel.Read,
147
- roles: [PermissionRole.create(role)],
148
- }),
149
- Permissions.create({
150
- level: PermissionLevel.None,
151
- roles: [PermissionRole.create(role2)],
152
- }),
153
- Permissions.create({
154
- level: PermissionLevel.Write,
155
- roles: [PermissionRole.create(role2), PermissionRole.create(role)],
156
- }),
157
- Permissions.create({
158
- level: PermissionLevel.Write,
159
- }),
160
- Permissions.create({
161
- level: PermissionLevel.Read,
162
- }),
163
- null,
164
- ];
165
-
166
- for (const permission of invalidPermissions) {
167
- const user = await new UserFactory({
168
- organization,
169
- permissions: permission,
170
- }).create();
171
- const token = await Token.createToken(user);
172
-
173
- const changes = new PatchableArray<string, Group, AutoEncoderPatchType<Group>>();
174
- changes.addPatch(GroupPatch.create({
175
- id: groups[0].id,
176
- settings: GroupSettingsPatch.create({
177
- name: 'My crazy group name',
178
- }),
179
- }));
180
- const r = Request.buildJson('PATCH', '/organization', organization.getApiHost(), {
181
- id: organization.id,
182
- groups: changes.encode({ version: 2 }),
183
- });
184
- r.headers.authorization = 'Bearer ' + token.accessToken;
185
- await expect(testServer.test(endpoint, r)).rejects.toThrow(/permissions/i);
186
- }
187
- });
188
-
189
- test('Create a group with access', async () => {
190
- const organization = await new OrganizationFactory({}).create();
191
- const groups = await new GroupFactory({ organization }).createMultiple(2);
192
-
193
- const validPermissions = [
194
- Permissions.create({
195
- level: PermissionLevel.Full,
196
- }),
197
- ];
198
-
199
- const invalidPermissions = [
200
- Permissions.create({
201
- level: PermissionLevel.Write,
202
- }),
203
- ];
204
-
205
- for (const permission of validPermissions) {
206
- const user = await new UserFactory({
207
- organization,
208
- permissions: permission,
209
- }).create();
210
- const token = await Token.createToken(user);
211
-
212
- const changes = new PatchableArray<string, Group, AutoEncoderPatchType<Group>>();
213
- const put = Group.create({
214
- cycle: 0,
215
- organizationId: organization.id,
216
- periodId: organization.periodId,
217
- settings: GroupSettings.create({
218
- name: 'My crazy group name',
219
- startDate: new Date(),
220
- endDate: new Date(),
221
- registrationStartDate: new Date(),
222
- registrationEndDate: new Date(),
223
- genderType: GroupGenderType.Mixed,
224
- }),
225
- privateSettings: GroupPrivateSettings.create({}),
226
- });
227
- changes.addPut(put);
228
-
229
- const r = Request.buildJson('PATCH', '/v140/organization', organization.getApiHost(), {
230
- id: organization.id,
231
- groups: changes.encode({ version: 140 }),
232
- });
233
- r.headers.authorization = 'Bearer ' + token.accessToken;
234
-
235
- const response = await testServer.test(endpoint, r);
236
- expect(response.body).toBeDefined();
237
-
238
- if (!(response.body instanceof Organization)) {
239
- throw new Error('Expected Organization');
240
- }
241
-
242
- expect(response.body.id).toEqual(organization.id);
243
- expect(response.body.groups.map(g => g.id)).toContainEqual(put.id);
244
- }
245
-
246
- for (const permission of invalidPermissions) {
247
- const user = await new UserFactory({
248
- organization,
249
- permissions: permission,
250
- }).create();
251
- const token = await Token.createToken(user);
252
-
253
- const changes = new PatchableArray<string, Group, AutoEncoderPatchType<Group>>();
254
- const put = Group.create({
255
- cycle: 0,
256
- organizationId: organization.id,
257
- periodId: organization.periodId,
258
- settings: GroupSettings.create({
259
- name: 'My crazy group name',
260
- startDate: new Date(),
261
- endDate: new Date(),
262
- registrationStartDate: new Date(),
263
- registrationEndDate: new Date(),
264
- genderType: GroupGenderType.Mixed,
265
- }),
266
- });
267
- changes.addPut(put);
268
-
269
- const r = Request.buildJson('PATCH', '/v2/organization', organization.getApiHost(), {
270
- id: organization.id,
271
- groups: changes.encode({ version: 2 }),
272
- });
273
- r.headers.authorization = 'Bearer ' + token.accessToken;
274
- await expect(testServer.test(endpoint, r)).rejects.toThrow(/permissions/i);
275
- }
276
- });
277
62
  });
@@ -137,7 +137,7 @@ export class PatchWebshopOrdersEndpoint extends Endpoint<Params, Query, Body, Re
137
137
  await order.updateStock(null, true);
138
138
  const totalPrice = order.data.totalPrice;
139
139
 
140
- if (totalPrice == 0) {
140
+ if (totalPrice === 0) {
141
141
  // Force unknown payment method
142
142
  order.data.paymentMethod = PaymentMethod.Unknown;
143
143
 
@@ -161,6 +161,9 @@ export class PatchWebshopOrdersEndpoint extends Endpoint<Params, Query, Body, Re
161
161
  order.paymentId = payment.id;
162
162
  order.setRelation(Order.payment, payment);
163
163
 
164
+ // Save order because we need the id
165
+ await order.save();
166
+
164
167
  // Create balance item
165
168
  const balanceItem = new BalanceItem();
166
169
  balanceItem.orderId = order.id;
@@ -189,12 +192,12 @@ export class PatchWebshopOrdersEndpoint extends Endpoint<Params, Query, Body, Re
189
192
  balanceItemPayment.price = balanceItem.price;
190
193
  await balanceItemPayment.save();
191
194
 
192
- if (payment.method == PaymentMethod.Transfer) {
195
+ if (payment.method === PaymentMethod.Transfer) {
193
196
  await order.markValid(payment, []);
194
197
  await payment.save();
195
198
  await order.save();
196
199
  }
197
- else if (payment.method == PaymentMethod.PointOfSale) {
200
+ else if (payment.method === PaymentMethod.PointOfSale) {
198
201
  // Not really paid, but needed to create the tickets if needed
199
202
  await order.markPaid(payment, organization, webshop);
200
203
  await payment.save();
@@ -1,5 +1,5 @@
1
1
  import { Request } from '@simonbackx/simple-endpoints';
2
- import { GroupFactory, OrganizationFactory, Token, UserFactory } from '@stamhoofd/models';
2
+ import { OrganizationFactory, Token, UserFactory } from '@stamhoofd/models';
3
3
  import { Organization, PermissionLevel, Permissions } from '@stamhoofd/structures';
4
4
 
5
5
  import { testServer } from '../../../../../tests/helpers/TestServer';
@@ -12,7 +12,6 @@ describe('Endpoint.GetOrganization', () => {
12
12
  test('Get organization as signed in user', async () => {
13
13
  const organization = await new OrganizationFactory({}).create();
14
14
  const user = await new UserFactory({ organization }).create();
15
- const groups = await new GroupFactory({ organization }).createMultiple(2);
16
15
  const token = await Token.createToken(user);
17
16
 
18
17
  const r = Request.buildJson('GET', '/v3/organization', organization.getApiHost());
@@ -26,7 +25,6 @@ describe('Endpoint.GetOrganization', () => {
26
25
  }
27
26
 
28
27
  expect(response.body.id).toEqual(organization.id);
29
- expect(response.body.groups.map(g => g.id).sort()).toEqual(groups.map(g => g.id).sort());
30
28
  expect(response.body.privateMeta).toEqual(null);
31
29
  });
32
30
 
@@ -39,7 +37,6 @@ describe('Endpoint.GetOrganization', () => {
39
37
  }),
40
38
  }).create();
41
39
 
42
- const groups = await new GroupFactory({ organization }).createMultiple(2);
43
40
  const token = await Token.createToken(user);
44
41
 
45
42
  const r = Request.buildJson('GET', '/v3/organization', organization.getApiHost());
@@ -53,7 +50,6 @@ describe('Endpoint.GetOrganization', () => {
53
50
  }
54
51
 
55
52
  expect(response.body.id).toEqual(organization.id);
56
- expect(response.body.groups.map(g => g.id).sort()).toEqual(groups.map(g => g.id).sort());
57
53
  expect(response.body.privateMeta).not.toEqual(null);
58
54
  });
59
55
 
@@ -72,6 +68,8 @@ describe('Endpoint.GetOrganization', () => {
72
68
  const r = Request.buildJson('GET', '/v3/organization', organization.getApiHost());
73
69
  r.headers.authorization = 'Bearer ' + token.accessToken;
74
70
 
75
- await expect(testServer.test(endpoint, r)).rejects.toThrow('The access token is invalid');
71
+ const response = await testServer.test(endpoint, r);
72
+ expect(response.body).toBeDefined();
73
+ expect(response.body.privateMeta).toEqual(null);
76
74
  });
77
75
  });
@@ -105,25 +105,7 @@ describe('Endpoint.GetWebshop', () => {
105
105
  const r = Request.buildJson('GET', '/v244/webshop/' + webshop.id, organization.getApiHost());
106
106
  r.headers.authorization = 'Bearer ' + token.accessToken;
107
107
 
108
- await expect(testServer.test(endpoint, r)).rejects.toThrow('The access token is invalid');
109
- });
110
-
111
- test('If organization scope is missing in v243, access is still checked correctly', async () => {
112
- const organization = await new OrganizationFactory({}).create();
113
- const organization2 = await new OrganizationFactory({}).create();
114
- const user = await new UserFactory({
115
- organization: organization2,
116
- permissions: Permissions.create({
117
- level: PermissionLevel.Full,
118
- }),
119
- }).create();
120
-
121
- const token = await Token.createToken(user);
122
- const webshop = await new WebshopFactory({ organizationId: organization.id }).create();
123
-
124
- const r = Request.buildJson('GET', '/v243/webshop/' + webshop.id);
125
- r.headers.authorization = 'Bearer ' + token.accessToken;
126
-
127
- await expect(testServer.test(endpoint, r)).rejects.toThrow('The access token is invalid');
108
+ const response = await testServer.test(endpoint, r);
109
+ expect((response.body as any).privateMeta).toBeUndefined();
128
110
  });
129
111
  });
@@ -1,9 +1,10 @@
1
1
  import { AutoEncoderPatchType, PatchMap } from '@simonbackx/simple-encoding';
2
2
  import { isSimpleError, isSimpleErrors, SimpleError } from '@simonbackx/simple-errors';
3
3
  import { BalanceItem, CachedBalance, Document, EmailTemplate, Event, EventNotification, Group, Member, MemberPlatformMembership, MemberWithRegistrations, Order, Organization, OrganizationRegistrationPeriod, Payment, Registration, User, Webshop } from '@stamhoofd/models';
4
- import { AccessRight, EventPermissionChecker, FinancialSupportSettings, GroupCategory, GroupStatus, MemberWithRegistrationsBlob, PermissionLevel, PermissionsResourceType, Platform as PlatformStruct, RecordCategory } from '@stamhoofd/structures';
4
+ import { AccessRight, EventPermissionChecker, FinancialSupportSettings, GroupCategory, GroupStatus, MemberWithRegistrationsBlob, PermissionLevel, PermissionsResourceType, Platform as PlatformStruct, RecordCategory, RecordSettings } from '@stamhoofd/structures';
5
5
  import { Formatter } from '@stamhoofd/utility';
6
6
  import { addTemporaryMemberAccess, hasTemporaryMemberAccess } from './TemporaryMemberAccess';
7
+ import { MemberRecordStore } from '../services/MemberRecordStore';
7
8
 
8
9
  /**
9
10
  * One class with all the responsabilities of checking permissions to each resource in the system by a given user, possibly in an organization context.
@@ -853,80 +854,6 @@ export class AdminPermissionChecker {
853
854
  return !!member.users.find(u => u.id === this.user.id);
854
855
  }
855
856
 
856
- /**
857
- * Return a list of RecordSettings the current user can view or edit
858
- */
859
- async getAccessibleRecordCategories(member: MemberWithRegistrations, level: PermissionLevel = PermissionLevel.Read): Promise<RecordCategory[]> {
860
- // First list all organizations this member is part of
861
- const organizations: Organization[] = [];
862
-
863
- if (member.organizationId) {
864
- if (this.checkScope(member.organizationId)) {
865
- organizations.push(await this.getOrganization(member.organizationId));
866
- }
867
- }
868
-
869
- for (const registration of member.registrations) {
870
- if (this.checkScope(registration.organizationId)) {
871
- if (!organizations.find(o => o.id === registration.organizationId)) {
872
- organizations.push(await this.getOrganization(registration.organizationId));
873
- }
874
- }
875
- }
876
-
877
- // Loop all organizations.
878
- // Check if we have access to their data
879
- const recordCategories: RecordCategory[] = [];
880
- for (const organization of organizations) {
881
- const permissions = await this.getOrganizationPermissions(organization);
882
-
883
- if (!permissions) {
884
- continue;
885
- }
886
-
887
- // Now add all records of this organization
888
- for (const category of organization.meta.recordsConfiguration.recordCategories) {
889
- if (recordCategories.find(c => c.id === category.id)) {
890
- // Already added
891
- continue;
892
- }
893
-
894
- if (permissions.hasResourceAccess(PermissionsResourceType.RecordCategories, category.id, level)) {
895
- recordCategories.push(category);
896
- }
897
- }
898
-
899
- // Platform ones where we have been given permissions for in this organization
900
- for (const category of this.platform.config.recordsConfiguration.recordCategories) {
901
- if (recordCategories.find(c => c.id === category.id)) {
902
- // Already added
903
- continue;
904
- }
905
-
906
- if (permissions.hasResourceAccess(PermissionsResourceType.RecordCategories, category.id, level)) {
907
- recordCategories.push(category);
908
- }
909
- }
910
- }
911
-
912
- // Platform data
913
- const platformPermissions = this.platformPermissions;
914
- if (platformPermissions) {
915
- for (const category of this.platform.config.recordsConfiguration.recordCategories) {
916
- if (recordCategories.find(c => c.id === category.id)) {
917
- // Already added
918
- continue;
919
- }
920
-
921
- if (platformPermissions?.hasResourceAccess(PermissionsResourceType.RecordCategories, category.id, level)) {
922
- recordCategories.push(category);
923
- }
924
- }
925
- }
926
-
927
- return recordCategories;
928
- }
929
-
930
857
  /**
931
858
  * Return a list of RecordSettings the current user can view or edit
932
859
  */
@@ -1053,56 +980,73 @@ export class AdminPermissionChecker {
1053
980
  return false;
1054
981
  }
1055
982
 
1056
- /**
1057
- * Return a list of RecordSettings the current user can view or edit
1058
- */
1059
- async getAccessibleRecordSet(member: MemberWithRegistrations, level: PermissionLevel = PermissionLevel.Read): Promise<Set<string>> {
1060
- const categories = await this.getAccessibleRecordCategories(member, level);
1061
- const set = new Set<string>();
983
+ async checkRecordAccess(member: MemberWithRegistrations, recordId: string, level: PermissionLevel = PermissionLevel.Read): Promise<{ canAccess: false; record: RecordSettings | null } | { canAccess: true; record: RecordSettings }> {
984
+ const record = await MemberRecordStore.getRecord(recordId);
985
+ if (!record) {
986
+ return {
987
+ canAccess: false,
988
+ record: null,
989
+ };
990
+ }
1062
991
 
1063
- for (const category of categories) {
1064
- for (const record of category.getAllRecords()) {
1065
- set.add(record.id);
1066
- }
992
+ if (!this.checkScope(record.organizationId)) {
993
+ return {
994
+ canAccess: false,
995
+ record: record.record,
996
+ };
1067
997
  }
1068
998
 
1069
999
  const isUserManager = this.isUserManager(member);
1070
-
1071
- // Also include those we can access as user manager
1072
1000
  if (isUserManager) {
1073
- const allCategories = this.platform.config.recordsConfiguration.recordCategories.slice();
1074
-
1075
- // First list all organizations this member is part of
1076
- const organizations: Organization[] = [];
1077
-
1078
- if (member.organizationId) {
1079
- if (this.checkScope(member.organizationId)) {
1080
- organizations.push(await this.getOrganization(member.organizationId));
1081
- }
1001
+ if (record.record.checkPermissionForUserManager(level)) {
1002
+ return {
1003
+ canAccess: true,
1004
+ record: record.record,
1005
+ };
1082
1006
  }
1007
+ }
1083
1008
 
1084
- for (const registration of member.registrations) {
1085
- if (this.checkScope(registration.organizationId)) {
1086
- if (!organizations.find(o => o.id === registration.organizationId)) {
1087
- organizations.push(await this.getOrganization(registration.organizationId));
1088
- }
1089
- }
1090
- }
1009
+ if (!this.user.permissions) {
1010
+ return {
1011
+ canAccess: false,
1012
+ record: record.record,
1013
+ };
1014
+ }
1091
1015
 
1092
- for (const organization of organizations) {
1093
- allCategories.push(...organization.meta.recordsConfiguration.recordCategories);
1016
+ if (record.organizationId) {
1017
+ const organizationPermissions = await this.getOrganizationPermissions(record.organizationId);
1018
+ if (organizationPermissions && organizationPermissions.hasResourceAccess(PermissionsResourceType.RecordCategories, record.rootCategoryId, level)) {
1019
+ return {
1020
+ canAccess: true,
1021
+ record: record.record,
1022
+ };
1094
1023
  }
1095
-
1096
- for (const category of allCategories) {
1097
- for (const record of category.getAllRecords()) {
1098
- if (record.checkPermissionForUserManager(level)) {
1099
- set.add(record.id);
1100
- }
1024
+ }
1025
+ else {
1026
+ // 1. Check all organizations (they can give permissions)
1027
+ for (const organizationId of this.user.permissions.organizationPermissions.keys()) {
1028
+ const organizationPermissions = await this.getOrganizationPermissions(organizationId);
1029
+ if (organizationPermissions && organizationPermissions.hasResourceAccess(PermissionsResourceType.RecordCategories, record.rootCategoryId, level)) {
1030
+ return {
1031
+ canAccess: true,
1032
+ record: record.record,
1033
+ };
1101
1034
  }
1102
1035
  }
1103
1036
  }
1104
1037
 
1105
- return set;
1038
+ // 2. Check platform permissions
1039
+ if (this.platformPermissions?.hasResourceAccess(PermissionsResourceType.RecordCategories, record.rootCategoryId, level)) {
1040
+ return {
1041
+ canAccess: true,
1042
+ record: record.record,
1043
+ };
1044
+ }
1045
+
1046
+ return {
1047
+ canAccess: false,
1048
+ record: record.record,
1049
+ };
1106
1050
  }
1107
1051
 
1108
1052
  async getAccessibleGroups(organizationId: string, level: PermissionLevel = PermissionLevel.Read): Promise<string[] | 'all'> {
@@ -1125,14 +1069,19 @@ export class AdminPermissionChecker {
1125
1069
  * Changes data inline
1126
1070
  */
1127
1071
  async filterMemberData(member: MemberWithRegistrations, data: MemberWithRegistrationsBlob): Promise<MemberWithRegistrationsBlob> {
1128
- const records = await this.getAccessibleRecordSet(member, PermissionLevel.Read);
1129
-
1130
1072
  const cloned = data.clone();
1131
1073
 
1132
1074
  for (const [key, value] of cloned.details.recordAnswers.entries()) {
1133
- if (!records.has(value.settings.id)) {
1075
+ const { canAccess, record } = await this.checkRecordAccess(member, key, PermissionLevel.Read);
1076
+ if (!canAccess) {
1134
1077
  cloned.details.recordAnswers.delete(key);
1135
1078
  }
1079
+ else {
1080
+ if (value) {
1081
+ // Force update
1082
+ value.settings = record;
1083
+ }
1084
+ }
1136
1085
  }
1137
1086
 
1138
1087
  const isUserManager = this.isUserManager(member);
@@ -1227,39 +1176,20 @@ export class AdminPermissionChecker {
1227
1176
  });
1228
1177
  }
1229
1178
 
1230
- const records = await this.getAccessibleRecordSet(member, PermissionLevel.Write);
1231
-
1232
1179
  for (const [key, value] of data.details.recordAnswers.entries()) {
1233
- let name: string | undefined = undefined;
1234
- if (value) {
1235
- if (value.isPatch()) {
1236
- throw new SimpleError({
1237
- code: 'invalid_request',
1238
- message: 'Cannot PATCH a record answer object',
1239
- statusCode: 400,
1240
- });
1241
- }
1242
-
1243
- const id = value.settings.id;
1244
-
1245
- if (id !== key) {
1246
- throw new SimpleError({
1247
- code: 'invalid_request',
1248
- message: 'Record answer key does not match record id',
1249
- statusCode: 400,
1250
- });
1251
- }
1252
-
1253
- name = value.settings.name;
1254
- }
1255
-
1256
- if (!records.has(key)) {
1180
+ const { canAccess, record } = await this.checkRecordAccess(member, key, PermissionLevel.Write);
1181
+ if (!canAccess) {
1257
1182
  throw new SimpleError({
1258
1183
  code: 'permission_denied',
1259
- message: `Je hebt geen toegangsrechten om het antwoord op ${name ?? 'deze vraag'} aan te passen voor dit lid`,
1184
+ message: `Je hebt geen toegangsrechten om het antwoord op ${record?.name ?? 'deze vraag'} aan te passen voor dit lid`,
1260
1185
  statusCode: 400,
1261
1186
  });
1262
1187
  }
1188
+
1189
+ // Force set the value settings
1190
+ if (value) {
1191
+ value.settings = record;
1192
+ }
1263
1193
  }
1264
1194
  }
1265
1195
 
@@ -1,15 +1,20 @@
1
1
  import { I18n } from '@stamhoofd/backend-i18n';
2
2
  import { FileSignService } from '../services/FileSignService';
3
- import { Context } from './Context';
3
+ import { Context, ContextInstance } from './Context';
4
+ import { Address, Country } from '@stamhoofd/structures';
5
+ import { MemberRecordStore } from '../services/MemberRecordStore';
4
6
 
5
7
  export class GlobalHelper {
6
8
  static async load() {
7
9
  await I18n.load();
8
10
  this.loadGlobalTranslateFunction();
9
11
  await FileSignService.load();
12
+ MemberRecordStore.init();
10
13
  }
11
14
 
12
15
  private static loadGlobalTranslateFunction() {
13
16
  (global as any).$t = (key: string, replace?: Record<string, string>) => Context.i18n.$t(key, replace);
17
+ (global as any).$getLanguage = () => ContextInstance.optional?.i18n.language ?? 'nl';
18
+ (global as any).$getCountry = () => ContextInstance.optional?.i18n.country ?? STAMHOOFD.fixedCountry ?? Country.Belgium;
14
19
  }
15
20
  }
@@ -70,7 +70,7 @@ export class FileSignService {
70
70
  if (e instanceof jose.errors.JWSSignatureVerificationFailed) {
71
71
  return false;
72
72
  }
73
- console.error('Failed to verify file:', e);
73
+ console.error('Failed to verify file signature:', e);
74
74
  return false;
75
75
  }
76
76
  };
@@ -115,7 +115,7 @@ export class FileSignService {
115
115
  });
116
116
  }
117
117
  catch (e) {
118
- console.error('Failed to sign file:', e);
118
+ console.error('Failed to generate signedUrl for file:', e);
119
119
  return null;
120
120
  }
121
121
  }