@stamhoofd/backend 2.56.0 → 2.57.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stamhoofd/backend",
3
- "version": "2.56.0",
3
+ "version": "2.57.1",
4
4
  "main": "./dist/index.js",
5
5
  "exports": {
6
6
  ".": {
@@ -34,17 +34,17 @@
34
34
  "@bwip-js/node": "^4.5.1",
35
35
  "@mollie/api-client": "3.7.0",
36
36
  "@simonbackx/simple-database": "1.25.0",
37
- "@simonbackx/simple-encoding": "2.16.6",
37
+ "@simonbackx/simple-encoding": "2.17.0",
38
38
  "@simonbackx/simple-endpoints": "1.14.0",
39
39
  "@simonbackx/simple-logging": "^1.0.1",
40
- "@stamhoofd/backend-i18n": "2.56.0",
41
- "@stamhoofd/backend-middleware": "2.56.0",
42
- "@stamhoofd/email": "2.56.0",
43
- "@stamhoofd/models": "2.56.0",
44
- "@stamhoofd/queues": "2.56.0",
45
- "@stamhoofd/sql": "2.56.0",
46
- "@stamhoofd/structures": "2.56.0",
47
- "@stamhoofd/utility": "2.56.0",
40
+ "@stamhoofd/backend-i18n": "2.57.1",
41
+ "@stamhoofd/backend-middleware": "2.57.1",
42
+ "@stamhoofd/email": "2.57.1",
43
+ "@stamhoofd/models": "2.57.1",
44
+ "@stamhoofd/queues": "2.57.1",
45
+ "@stamhoofd/sql": "2.57.1",
46
+ "@stamhoofd/structures": "2.57.1",
47
+ "@stamhoofd/utility": "2.57.1",
48
48
  "archiver": "^7.0.1",
49
49
  "aws-sdk": "^2.885.0",
50
50
  "axios": "1.6.8",
@@ -64,5 +64,5 @@
64
64
  "publishConfig": {
65
65
  "access": "public"
66
66
  },
67
- "gitHead": "39e791f29d992c918b83871d9dc6cf72c418b2c4"
67
+ "gitHead": "f109d195d0bbb0e49c7b7bcef403b710c68c025b"
68
68
  }
@@ -1,7 +1,7 @@
1
1
  import { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder, PatchableArrayDecoder, patchObject, StringDecoder } from '@simonbackx/simple-encoding';
2
2
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
3
  import { Event, Group, Platform, RegistrationPeriod } from '@stamhoofd/models';
4
- import { Event as EventStruct, GroupType, NamedObject, Group as GroupStruct } from '@stamhoofd/structures';
4
+ import { Event as EventStruct, GroupType, NamedObject, Group as GroupStruct, AuditLogType } from '@stamhoofd/structures';
5
5
 
6
6
  import { SimpleError } from '@simonbackx/simple-errors';
7
7
  import { SQL, SQLWhereSign } from '@stamhoofd/sql';
@@ -9,6 +9,7 @@ import { Formatter } from '@stamhoofd/utility';
9
9
  import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
10
10
  import { Context } from '../../../helpers/Context';
11
11
  import { PatchOrganizationRegistrationPeriodsEndpoint } from '../../organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint';
12
+ import { AuditLogService } from '../../../services/AuditLogService';
12
13
 
13
14
  type Params = { id: string };
14
15
  type Query = undefined;
@@ -106,10 +107,18 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
106
107
  await event.save();
107
108
 
108
109
  events.push(event);
110
+
111
+ await AuditLogService.log({
112
+ type: AuditLogType.EventAdded,
113
+ event,
114
+ });
109
115
  }
110
116
 
117
+ const patchingEvents = await Event.getByIDs(...request.body.getPatches().map(p => p.id));
118
+ const initialStructs = (await AuthenticatedStructures.events(patchingEvents)).map(e => e.clone()); // Clone is required for audit log (otherwise references might change)
119
+
111
120
  for (const patch of request.body.getPatches()) {
112
- const event = await Event.getByID(patch.id);
121
+ const event = patchingEvents.find(e => e.id === patch.id);
113
122
 
114
123
  if (!event) {
115
124
  throw new SimpleError({
@@ -242,6 +251,15 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
242
251
  }
243
252
 
244
253
  events.push(event);
254
+
255
+ const struct = initialStructs.find(e => e.id === patch.id);
256
+
257
+ await AuditLogService.log({
258
+ type: AuditLogType.EventEdited,
259
+ event,
260
+ oldData: struct,
261
+ patch,
262
+ });
245
263
  }
246
264
 
247
265
  for (const id of request.body.getDeletes()) {
@@ -258,10 +276,16 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
258
276
  }
259
277
 
260
278
  await event.delete();
279
+
280
+ await AuditLogService.log({
281
+ type: AuditLogType.EventDeleted,
282
+ event,
283
+ });
261
284
  }
262
285
 
286
+ const structures = await AuthenticatedStructures.events(events);
263
287
  return new Response(
264
- await AuthenticatedStructures.events(events),
288
+ structures,
265
289
  );
266
290
  }
267
291
 
@@ -51,6 +51,8 @@ export class PatchPlatformEndpoint extends Endpoint<
51
51
  const platform = await Platform.getShared();
52
52
 
53
53
  if (request.body.privateConfig) {
54
+ const oldConfig = platform.privateConfig.clone();
55
+
54
56
  // Did we patch roles?
55
57
  if (request.body.privateConfig.roles) {
56
58
  if (!Context.auth.canManagePlatformAdmins()) {
@@ -75,6 +77,12 @@ export class PatchPlatformEndpoint extends Endpoint<
75
77
  request.body.privateConfig.emails,
76
78
  );
77
79
  }
80
+
81
+ await AuditLogService.log({
82
+ type: AuditLogType.PlatformSettingsChanged,
83
+ oldConfig,
84
+ patch: request.body.privateConfig,
85
+ });
78
86
  }
79
87
 
80
88
  let shouldUpdateSetupSteps = false;
@@ -110,7 +118,7 @@ export class PatchPlatformEndpoint extends Endpoint<
110
118
  }
111
119
 
112
120
  await AuditLogService.log({
113
- type: AuditLogType.PlatformSettingChanged,
121
+ type: AuditLogType.PlatformSettingsChanged,
114
122
  oldConfig,
115
123
  patch: newConfig,
116
124
  });
@@ -2,7 +2,7 @@ import { AutoEncoderPatchType, Decoder, isPatchableArray, ObjectData, PatchableA
2
2
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
3
  import { SimpleError, SimpleErrors } from '@simonbackx/simple-errors';
4
4
  import { Organization, OrganizationRegistrationPeriod, PayconiqPayment, Platform, RegistrationPeriod, SetupStepUpdater, StripeAccount, Webshop } from '@stamhoofd/models';
5
- import { BuckarooSettings, Company, OrganizationMetaData, OrganizationPatch, Organization as OrganizationStruct, PayconiqAccount, PaymentMethod, PaymentMethodHelper, PermissionLevel, PlatformConfig } from '@stamhoofd/structures';
5
+ import { AuditLogType, BuckarooSettings, Company, OrganizationMetaData, OrganizationPatch, Organization as OrganizationStruct, PayconiqAccount, PaymentMethod, PaymentMethodHelper, PermissionLevel, PlatformConfig } from '@stamhoofd/structures';
6
6
  import { Formatter } from '@stamhoofd/utility';
7
7
 
8
8
  import { AuthenticatedStructures } from '../../../../helpers/AuthenticatedStructures';
@@ -10,6 +10,7 @@ import { BuckarooHelper } from '../../../../helpers/BuckarooHelper';
10
10
  import { Context } from '../../../../helpers/Context';
11
11
  import { TagHelper } from '../../../../helpers/TagHelper';
12
12
  import { ViesHelper } from '../../../../helpers/ViesHelper';
13
+ import { AuditLogService } from '../../../../services/AuditLogService';
13
14
 
14
15
  type Params = Record<string, never>;
15
16
  type Query = undefined;
@@ -213,6 +214,7 @@ export class PatchOrganizationEndpoint extends Endpoint<Params, Query, Body, Res
213
214
  await this.validateCompanies(organization, request.body.meta.companies);
214
215
  shouldUpdateSetupSteps = true;
215
216
  }
217
+ const oldMeta = organization.meta.clone();
216
218
 
217
219
  const savedPackages = organization.meta.packages;
218
220
  organization.meta.patchOrPut(request.body.meta);
@@ -281,6 +283,13 @@ export class PatchOrganizationEndpoint extends Endpoint<Params, Query, Body, Res
281
283
 
282
284
  updateTags = true;
283
285
  }
286
+
287
+ await AuditLogService.log({
288
+ type: AuditLogType.OrganizationSettingsChanged,
289
+ organization,
290
+ oldMeta,
291
+ patch: request.body.meta,
292
+ });
284
293
  }
285
294
 
286
295
  if (request.body.active !== undefined) {
@@ -1,11 +1,12 @@
1
1
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
2
- import { GroupPrivateSettings, Group as GroupStruct, GroupType, OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct, PermissionLevel, PermissionsResourceType, ResourcePermissions, Version } from '@stamhoofd/structures';
2
+ import { AuditLogType, GroupPrivateSettings, Group as GroupStruct, GroupType, OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct, PermissionLevel, PermissionsResourceType, ResourcePermissions, Version } from '@stamhoofd/structures';
3
3
 
4
4
  import { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder, PatchableArrayDecoder, StringDecoder } from '@simonbackx/simple-encoding';
5
5
  import { SimpleError } from '@simonbackx/simple-errors';
6
6
  import { Group, Member, Organization, OrganizationRegistrationPeriod, Platform, RegistrationPeriod, SetupStepUpdater } from '@stamhoofd/models';
7
7
  import { AuthenticatedStructures } from '../../../../helpers/AuthenticatedStructures';
8
8
  import { Context } from '../../../../helpers/Context';
9
+ import { AuditLogService } from '../../../../services/AuditLogService';
9
10
 
10
11
  type Params = Record<string, never>;
11
12
  type Query = undefined;
@@ -281,6 +282,11 @@ export class PatchOrganizationRegistrationPeriodsEndpoint extends Endpoint<Param
281
282
  model.deletedAt = new Date();
282
283
  await model.save();
283
284
  Member.updateMembershipsForGroupId(id);
285
+
286
+ await AuditLogService.log({
287
+ type: AuditLogType.GroupDeleted,
288
+ group: model,
289
+ });
284
290
  }
285
291
 
286
292
  static async patchGroup(struct: AutoEncoderPatchType<GroupStruct>, period?: RegistrationPeriod | null) {
@@ -289,6 +295,7 @@ export class PatchOrganizationRegistrationPeriodsEndpoint extends Endpoint<Param
289
295
  if (!model || !await Context.auth.canAccessGroup(model, PermissionLevel.Full)) {
290
296
  throw Context.auth.error('Je hebt geen toegangsrechten om deze groep te wijzigen');
291
297
  }
298
+ const originalStruct = (await AuthenticatedStructures.group(model)).clone(); // Clone is required for deep changes
292
299
 
293
300
  const previousProperties = {
294
301
  deletedAt: model.deletedAt,
@@ -417,6 +424,13 @@ export class PatchOrganizationRegistrationPeriodsEndpoint extends Endpoint<Param
417
424
  if (struct.deletedAt !== undefined || struct.defaultAgeGroupId !== undefined) {
418
425
  Member.updateMembershipsForGroupId(model.id);
419
426
  }
427
+
428
+ await AuditLogService.log({
429
+ type: AuditLogType.GroupEdited,
430
+ group: model,
431
+ oldData: originalStruct,
432
+ patch,
433
+ });
420
434
  }
421
435
 
422
436
  static async createGroup(struct: GroupStruct, organizationId: string, period: RegistrationPeriod, options?: { allowedIds?: string[] }): Promise<Group> {
@@ -497,6 +511,12 @@ export class PatchOrganizationRegistrationPeriodsEndpoint extends Endpoint<Param
497
511
 
498
512
  await model.save();
499
513
  await model.updateOccupancy({ isNew: true }); // Force update steps
514
+
515
+ await AuditLogService.log({
516
+ type: AuditLogType.GroupAdded,
517
+ group: model,
518
+ });
519
+
500
520
  return model;
501
521
  }
502
522
  }