@stamhoofd/models 2.81.0 → 2.83.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.
Files changed (91) hide show
  1. package/dist/src/factories/EventNotificationTypeFactory.js +1 -1
  2. package/dist/src/factories/EventNotificationTypeFactory.js.map +1 -1
  3. package/dist/src/factories/GroupFactory.d.ts.map +1 -1
  4. package/dist/src/factories/GroupFactory.js +1 -1
  5. package/dist/src/factories/GroupFactory.js.map +1 -1
  6. package/dist/src/factories/RecordCategoryFactory.d.ts.map +1 -1
  7. package/dist/src/factories/RecordCategoryFactory.js +1 -1
  8. package/dist/src/factories/RecordCategoryFactory.js.map +1 -1
  9. package/dist/src/factories/RecordFactory.d.ts.map +1 -1
  10. package/dist/src/factories/RecordFactory.js +1 -1
  11. package/dist/src/factories/RecordFactory.js.map +1 -1
  12. package/dist/src/helpers/DNSValidator.js +8 -8
  13. package/dist/src/helpers/DNSValidator.js.map +1 -1
  14. package/dist/src/helpers/EmailBuilder.d.ts.map +1 -1
  15. package/dist/src/helpers/EmailBuilder.js +10 -7
  16. package/dist/src/helpers/EmailBuilder.js.map +1 -1
  17. package/dist/src/helpers/GroupBuilder.js +23 -23
  18. package/dist/src/helpers/GroupBuilder.js.map +1 -1
  19. package/dist/src/helpers/MemberMerger.test.js +4 -4
  20. package/dist/src/helpers/MemberMerger.test.js.map +1 -1
  21. package/dist/src/helpers/RateLimiter.d.ts +6 -5
  22. package/dist/src/helpers/RateLimiter.d.ts.map +1 -1
  23. package/dist/src/helpers/RateLimiter.js +13 -6
  24. package/dist/src/helpers/RateLimiter.js.map +1 -1
  25. package/dist/src/migrations/1743070458-default-email-template-orders.sql +2 -0
  26. package/dist/src/models/DocumentTemplate.js +3 -3
  27. package/dist/src/models/DocumentTemplate.js.map +1 -1
  28. package/dist/src/models/Email.js +10 -10
  29. package/dist/src/models/Email.js.map +1 -1
  30. package/dist/src/models/EmailVerificationCode.js +2 -2
  31. package/dist/src/models/EmailVerificationCode.js.map +1 -1
  32. package/dist/src/models/Event.d.ts.map +1 -1
  33. package/dist/src/models/Event.js +1 -1
  34. package/dist/src/models/Event.js.map +1 -1
  35. package/dist/src/models/Image.d.ts +3 -1
  36. package/dist/src/models/Image.d.ts.map +1 -1
  37. package/dist/src/models/Image.js +12 -2
  38. package/dist/src/models/Image.js.map +1 -1
  39. package/dist/src/models/MemberPlatformMembership.js +5 -5
  40. package/dist/src/models/MemberPlatformMembership.js.map +1 -1
  41. package/dist/src/models/MollieToken.js +1 -1
  42. package/dist/src/models/MollieToken.js.map +1 -1
  43. package/dist/src/models/Order.js +3 -3
  44. package/dist/src/models/Order.js.map +1 -1
  45. package/dist/src/models/Organization.d.ts.map +1 -1
  46. package/dist/src/models/Organization.js +4 -4
  47. package/dist/src/models/Organization.js.map +1 -1
  48. package/dist/src/models/PayconiqPayment.js +1 -1
  49. package/dist/src/models/PayconiqPayment.js.map +1 -1
  50. package/dist/src/models/Registration.js +2 -2
  51. package/dist/src/models/Registration.js.map +1 -1
  52. package/dist/src/models/STPackage.js +3 -3
  53. package/dist/src/models/STPackage.js.map +1 -1
  54. package/dist/src/models/Token.d.ts +0 -2
  55. package/dist/src/models/Token.d.ts.map +1 -1
  56. package/dist/src/models/Token.js +2 -26
  57. package/dist/src/models/Token.js.map +1 -1
  58. package/dist/src/models/User.js +2 -2
  59. package/dist/src/models/User.js.map +1 -1
  60. package/dist/src/models/Webshop.d.ts.map +1 -1
  61. package/dist/src/models/Webshop.js +3 -0
  62. package/dist/src/models/Webshop.js.map +1 -1
  63. package/dist/src/models/addresses/PostalCode.js +1 -1
  64. package/dist/src/models/addresses/PostalCode.js.map +1 -1
  65. package/package.json +2 -2
  66. package/src/factories/EventNotificationTypeFactory.ts +1 -1
  67. package/src/factories/GroupFactory.ts +2 -2
  68. package/src/factories/RecordCategoryFactory.ts +2 -2
  69. package/src/factories/RecordFactory.ts +2 -2
  70. package/src/helpers/DNSValidator.ts +8 -8
  71. package/src/helpers/EmailBuilder.ts +11 -7
  72. package/src/helpers/GroupBuilder.ts +24 -24
  73. package/src/helpers/MemberMerger.test.ts +5 -4
  74. package/src/helpers/RateLimiter.ts +18 -9
  75. package/src/migrations/1743070458-default-email-template-orders.sql +2 -0
  76. package/src/models/DocumentTemplate.ts +3 -3
  77. package/src/models/Email.ts +10 -10
  78. package/src/models/EmailVerificationCode.ts +2 -2
  79. package/src/models/Event.ts +2 -2
  80. package/src/models/Image.ts +14 -2
  81. package/src/models/MemberPlatformMembership.ts +5 -5
  82. package/src/models/MollieToken.ts +1 -1
  83. package/src/models/Order.ts +3 -3
  84. package/src/models/Organization.ts +5 -5
  85. package/src/models/PayconiqPayment.ts +1 -1
  86. package/src/models/Registration.ts +2 -2
  87. package/src/models/STPackage.ts +3 -3
  88. package/src/models/Token.ts +2 -26
  89. package/src/models/User.ts +2 -2
  90. package/src/models/Webshop.ts +4 -0
  91. package/src/models/addresses/PostalCode.ts +1 -1
@@ -111,7 +111,7 @@ export class Email extends QueryableModel {
111
111
  throw new SimpleError({
112
112
  code: 'invalid_field',
113
113
  message: 'Missing subject',
114
- human: 'Vul een onderwerp in voor je een e-mail verstuurt',
114
+ human: $t(`e78c8218-4d25-413b-ae6b-fd916e663e5a`),
115
115
  });
116
116
  }
117
117
 
@@ -119,7 +119,7 @@ export class Email extends QueryableModel {
119
119
  throw new SimpleError({
120
120
  code: 'invalid_field',
121
121
  message: 'Missing text',
122
- human: 'Vul een tekst in voor je een e-mail verstuurt',
122
+ human: $t(`65b701a3-c74c-4eb6-b98e-7b9dcad0a358`),
123
123
  });
124
124
  }
125
125
 
@@ -127,7 +127,7 @@ export class Email extends QueryableModel {
127
127
  throw new SimpleError({
128
128
  code: 'invalid_field',
129
129
  message: 'Missing html',
130
- human: 'Vul een tekst in voor je een e-mail verstuurt',
130
+ human: $t(`65b701a3-c74c-4eb6-b98e-7b9dcad0a358`),
131
131
  });
132
132
  }
133
133
 
@@ -135,7 +135,7 @@ export class Email extends QueryableModel {
135
135
  throw new SimpleError({
136
136
  code: 'invalid_field',
137
137
  message: 'Missing from',
138
- human: 'Vul een afzender in voor je een e-mail verstuurt',
138
+ human: $t(`e92cd077-b0f1-4b0a-82a0-8a8baa82e73a`),
139
139
  });
140
140
  }
141
141
 
@@ -152,7 +152,7 @@ export class Email extends QueryableModel {
152
152
  throw new SimpleError({
153
153
  code: 'too_big_attachments',
154
154
  message: 'Too big attachments',
155
- human: 'Jouw bericht is te groot. Grote bijlages verstuur je beter niet via e-mail, je plaatst dan best een link naar de locatie in bv. Google Drive. De maximale grootte van een e-mail is 10MB, inclusief het bericht. Als je grote bestanden verstuurt kan je ze ook proberen te verkleinen.',
155
+ human: $t(`e8b9a1db-97d0-410e-99b2-6a87c1087593`),
156
156
  field: 'attachments',
157
157
  });
158
158
  }
@@ -173,7 +173,7 @@ export class Email extends QueryableModel {
173
173
  throw new SimpleError({
174
174
  code: 'content_type_not_supported',
175
175
  message: 'Content-Type not supported',
176
- human: 'Het bestandstype van jouw bijlage wordt niet ondersteund of is onveilig om in een e-mail te plaatsen. Overweeg om je bestand op bv. Google Drive te zetten en de link in jouw e-mail te zetten.',
176
+ human: $t(`54da84d6-5f6a-4db2-be34-9ddb7f47bbe8`),
177
177
  field: 'attachments',
178
178
  });
179
179
  }
@@ -246,7 +246,7 @@ export class Email extends QueryableModel {
246
246
  throw new SimpleError({
247
247
  code: 'not_found',
248
248
  message: 'Email not found',
249
- human: 'De e-mail die je probeert te versturen bestaat niet meer',
249
+ human: $t(`55899a7c-f3d4-43fe-a431-70a3a9e78e34`),
250
250
  });
251
251
  }
252
252
  if (upToDate.status === EmailStatus.Sent || upToDate.status === EmailStatus.Failed) {
@@ -281,7 +281,7 @@ export class Email extends QueryableModel {
281
281
  throw new SimpleError({
282
282
  code: 'invalid_field',
283
283
  message: 'Missing from',
284
- human: 'Vul een afzender in voor je een e-mail verstuurt',
284
+ human: $t(`e92cd077-b0f1-4b0a-82a0-8a8baa82e73a`),
285
285
  });
286
286
  }
287
287
 
@@ -304,7 +304,7 @@ export class Email extends QueryableModel {
304
304
  throw new SimpleError({
305
305
  code: 'not_found',
306
306
  message: 'Email not found',
307
- human: 'De e-mail die je probeert te versturen bestaat niet meer',
307
+ human: $t(`55899a7c-f3d4-43fe-a431-70a3a9e78e34`),
308
308
  });
309
309
  }
310
310
 
@@ -312,7 +312,7 @@ export class Email extends QueryableModel {
312
312
  throw new SimpleError({
313
313
  code: 'recipients_not_created',
314
314
  message: 'Failed to create recipients',
315
- human: 'Er ging iets mis bij het aanmaken van de afzenders.',
315
+ human: $t(`f660b2eb-e382-4d21-86e4-673ca7bc2d4a`),
316
316
  });
317
317
  }
318
318
 
@@ -217,7 +217,7 @@ export class EmailVerificationCode extends QueryableModel {
217
217
  throw new SimpleError({
218
218
  code: 'too_many_attempts',
219
219
  message: 'Too many attempts',
220
- human: 'Je hebt de code te veel foutief ingegeven. Verstuur eerst een nieuwe code voor je opnieuw probeert.',
220
+ human: $t(`9ea99caf-e245-45b2-97d5-004393e78b49`),
221
221
  statusCode: 429,
222
222
  });
223
223
  }
@@ -238,7 +238,7 @@ export class EmailVerificationCode extends QueryableModel {
238
238
  throw new SimpleError({
239
239
  code: 'too_many_attempts',
240
240
  message: 'Too many attempts',
241
- human: 'Je hebt de code te veel foutief ingegeven. Verstuur eerst een nieuwe code voor je opnieuw probeert.',
241
+ human: $t(`9ea99caf-e245-45b2-97d5-004393e78b49`),
242
242
  statusCode: 429,
243
243
  });
244
244
  }
@@ -1,6 +1,6 @@
1
1
  import { column } from '@simonbackx/simple-database';
2
2
  import { QueryableModel } from '@stamhoofd/sql';
3
- import { EventMeta, Event as EventStruct, GroupType } from '@stamhoofd/structures';
3
+ import { EventMeta, Event as EventStruct, GroupType, TranslatedString } from '@stamhoofd/structures';
4
4
  import { v4 as uuidv4 } from 'uuid';
5
5
  import { Group } from './Group';
6
6
 
@@ -87,7 +87,7 @@ export class Event extends QueryableModel {
87
87
 
88
88
  if (group.type === GroupType.EventRegistration) {
89
89
  // Don't change the name of the waiting list
90
- group.settings.name = this.name;
90
+ group.settings.name = new TranslatedString(this.name);
91
91
  group.settings.eventId = this.id;
92
92
  }
93
93
 
@@ -24,7 +24,7 @@ export class Image extends QueryableModel {
24
24
  @column({ type: 'datetime' })
25
25
  createdAt: Date = new Date();
26
26
 
27
- static async create(fileContent: string | Buffer, type: string | undefined, resolutions: ResolutionRequest[], isPrivateFile: boolean = false): Promise<Image> {
27
+ static async create(fileContent: string | Buffer, type: string | undefined, resolutions: ResolutionRequest[], isPrivateFile: boolean = false, user: { id: string } | null = null): Promise<Image> {
28
28
  if (!STAMHOOFD.SPACES_BUCKET || !STAMHOOFD.SPACES_ENDPOINT || !STAMHOOFD.SPACES_KEY || !STAMHOOFD.SPACES_SECRET) {
29
29
  throw new SimpleError({
30
30
  code: 'not_available',
@@ -92,6 +92,18 @@ export class Image extends QueryableModel {
92
92
  prefix += '/';
93
93
  }
94
94
 
95
+ prefix += (STAMHOOFD.environment ?? 'development') === 'development' ? ('development/') : ('');
96
+
97
+ // Prepend user id to the file path
98
+ if (isPrivateFile && user) {
99
+ // Private files
100
+ prefix += 'users/' + user.id + '/';
101
+ }
102
+ else {
103
+ // Public files
104
+ prefix += 'p/';
105
+ }
106
+
95
107
  const uploadPromises: Promise<any>[] = [];
96
108
  const image = new Image();
97
109
  image.id = uuidv4();
@@ -99,7 +111,7 @@ export class Image extends QueryableModel {
99
111
  for (const f of files) {
100
112
  const fileId = uuidv4();
101
113
 
102
- const key = prefix + (STAMHOOFD.environment ?? 'development') + '/' + image.id + '/' + fileId + (!supportsTransparency ? '.jpg' : '.png');
114
+ const key = prefix + image.id + '/' + fileId + (!supportsTransparency ? '.jpg' : '.png');
103
115
  const params = {
104
116
  Bucket: STAMHOOFD.SPACES_BUCKET,
105
117
  Key: key,
@@ -166,7 +166,7 @@ export class MemberPlatformMembership extends QueryableModel {
166
166
  throw new SimpleError({
167
167
  code: 'invalid_membership_type',
168
168
  message: 'Unknown membership type',
169
- human: 'Deze aansluiting is niet (meer) beschikbaar',
169
+ human: $t(`14e020be-1dd8-4caf-9dce-369cbe0db902`),
170
170
  });
171
171
  }
172
172
 
@@ -176,7 +176,7 @@ export class MemberPlatformMembership extends QueryableModel {
176
176
  throw new SimpleError({
177
177
  code: 'period_unavailable',
178
178
  message: 'Membership not available for this period',
179
- human: 'Deze aansluiting is nog niet beschikbaar voor dit werkjaar',
179
+ human: $t(`d5795b94-23d5-4fe7-97e1-6f0fe916caca`),
180
180
  });
181
181
  }
182
182
 
@@ -267,7 +267,7 @@ export class MemberPlatformMembership extends QueryableModel {
267
267
  throw new SimpleError({
268
268
  code: 'invalid_membership_type',
269
269
  message: 'Unknown membership type',
270
- human: 'Deze aansluiting is niet (meer) beschikbaar',
270
+ human: $t(`14e020be-1dd8-4caf-9dce-369cbe0db902`),
271
271
  });
272
272
  }
273
273
 
@@ -277,7 +277,7 @@ export class MemberPlatformMembership extends QueryableModel {
277
277
  throw new SimpleError({
278
278
  code: 'period_unavailable',
279
279
  message: 'Membership not available for this period',
280
- human: 'Deze aansluiting is nog niet beschikbaar voor dit werkjaar',
280
+ human: $t(`d5795b94-23d5-4fe7-97e1-6f0fe916caca`),
281
281
  });
282
282
  }
283
283
 
@@ -287,7 +287,7 @@ export class MemberPlatformMembership extends QueryableModel {
287
287
  // todo
288
288
  code: 'not_found',
289
289
  message: 'Organization not found',
290
- human: 'De organisatie is niet gevonden',
290
+ human: $t(`1524a6e6-aad7-4072-81c1-ce6fc196224f`),
291
291
  });
292
292
  }
293
293
 
@@ -366,7 +366,7 @@ export class MollieToken extends QueryableModel {
366
366
  profile: {
367
367
  name: organization.name + ' - Stamhoofd',
368
368
  // url: "https://"+organization.getHost(),
369
- description: 'Betalen van inschrijvingsgelden of webshops voor een vereniging via Stamhoofd (partner).',
369
+ description: $t(`62246c37-15c7-4f7d-94e2-7476f971c8da`),
370
370
  categoryCode: 8398,
371
371
  },
372
372
  });
@@ -116,9 +116,9 @@ export class Order extends QueryableModel {
116
116
 
117
117
  generateBalanceDescription(webshop: Webshop) {
118
118
  if (!this.number) {
119
- return 'Bestelling - ' + webshop.meta.name;
119
+ return $t(`df5c326c-e9a3-4f76-ba80-8a22f95f0e70`) + ' ' + webshop.meta.name;
120
120
  }
121
- return 'Bestelling #' + this.number.toString() + ' - ' + webshop.meta.name;
121
+ return $t(`12be5ac0-8353-43a2-badb-ab3b27d156b3`) + this.number.toString() + ' - ' + webshop.meta.name;
122
122
  }
123
123
 
124
124
  /**
@@ -925,7 +925,7 @@ export class Order extends QueryableModel {
925
925
  throw new SimpleError({
926
926
  code: 'missing_iban',
927
927
  message: 'Missing IBAN',
928
- human: 'Er is geen rekeningnummer ingesteld voor overschrijvingen. Contacteer de beheerder.',
928
+ human: $t(`cc8b5066-a7e4-4eae-b556-f56de5d3502c`),
929
929
  });
930
930
  }
931
931
  payment.generateDescription(organization, this.number.toString(), this.getTransferReplacements());
@@ -3,7 +3,7 @@ import { SimpleError } from '@simonbackx/simple-errors';
3
3
  import { I18n } from '@stamhoofd/backend-i18n';
4
4
  import { EmailInterfaceRecipient } from '@stamhoofd/email';
5
5
  import { QueryableModel } from '@stamhoofd/sql';
6
- import { Address, Country, DNSRecordStatus, EmailTemplateType, OrganizationEmail, OrganizationMetaData, OrganizationPrivateMetaData, Organization as OrganizationStruct, PaymentMethod, PaymentProvider, PrivatePaymentConfiguration, Recipient, Replacement, STPackageType, TransferSettings } from '@stamhoofd/structures';
6
+ import { Address, Country, DNSRecordStatus, EmailTemplateType, Language, OrganizationEmail, OrganizationMetaData, OrganizationPrivateMetaData, Organization as OrganizationStruct, PaymentMethod, PaymentProvider, PrivatePaymentConfiguration, Recipient, Replacement, STPackageType, TransferSettings } from '@stamhoofd/structures';
7
7
  import { AWSError } from 'aws-sdk';
8
8
  import SES from 'aws-sdk/clients/sesv2';
9
9
  import { PromiseResult } from 'aws-sdk/lib/request';
@@ -103,7 +103,7 @@ export class Organization extends QueryableModel {
103
103
  * Return default locale confiruation
104
104
  */
105
105
  get i18n() {
106
- return new I18n('nl', this.address.country);
106
+ return new I18n(Language.Dutch, this.address.country);
107
107
  }
108
108
 
109
109
  /**
@@ -201,7 +201,7 @@ export class Organization extends QueryableModel {
201
201
  throw new SimpleError({
202
202
  code: 'archived',
203
203
  message: 'This organization is archived',
204
- human: 'Deze groep is gearchiveerd',
204
+ human: $t(`8bd60208-9101-40cf-9f1d-1fd90cdafd62`),
205
205
  });
206
206
  }
207
207
  return organization;
@@ -423,7 +423,7 @@ export class Organization extends QueryableModel {
423
423
  bcc?: boolean;
424
424
  }) {
425
425
  const recipients = await this.getAdminRecipients();
426
- const defaultI18n = new I18n('nl', Country.Belgium);
426
+ const defaultI18n = new I18n(Language.Dutch, Country.Belgium);
427
427
  const i18n = this.i18n;
428
428
 
429
429
  const replaceAll = [
@@ -883,7 +883,7 @@ export class Organization extends QueryableModel {
883
883
  throw new SimpleError({
884
884
  code: 'payment_provider_not_configured',
885
885
  message: 'Payment provider not configured for ' + method,
886
- human: 'Deze betaalmethode werd helaas niet volledig geconfigureerd. Probeer later even opnieuw, neem contact met ons op of kies een andere betaalmethode.',
886
+ human: $t(`9e44e007-3b35-4edf-979f-41b458d2eb39`),
887
887
  });
888
888
  }
889
889
 
@@ -124,7 +124,7 @@ export class PayconiqPayment extends QueryableModel {
124
124
  if (!apiKey) {
125
125
  throw new SimpleError({
126
126
  code: '',
127
- message: 'Betaling via Payconiq is tijdelijk onbeschikbaar',
127
+ message: $t('4a3b54dc-e945-4a15-8b31-b9b4bb483b2a'),
128
128
  });
129
129
  }
130
130
 
@@ -194,7 +194,7 @@ export class Registration extends QueryableModel {
194
194
  }),
195
195
  Replacement.create({
196
196
  token: 'groupName',
197
- value: group.settings.name,
197
+ value: group.settings.name.toString(),
198
198
  }),
199
199
  ],
200
200
  }));
@@ -261,7 +261,7 @@ export class Registration extends QueryableModel {
261
261
  }),
262
262
  Replacement.create({
263
263
  token: 'overviewContext',
264
- value: 'Inschrijving van ' + paymentGeneral.memberNames,
264
+ value: $t(`01d5fd7e-2960-4eb4-ab3a-2ac6dcb2e39c`) + ' ' + paymentGeneral.memberNames,
265
265
  }),
266
266
  Replacement.create({
267
267
  token: 'memberNames',
@@ -152,7 +152,7 @@ export class STPackage extends QueryableModel {
152
152
  throw new SimpleError({
153
153
  code: 'not_allowed',
154
154
  message: 'Not allowed',
155
- human: 'Je kan dit pakket niet verlengen',
155
+ human: $t(`fcb50c02-7510-4e48-bfac-10bb584e3454`),
156
156
  });
157
157
  }
158
158
 
@@ -288,11 +288,11 @@ export class STPackage extends QueryableModel {
288
288
  }),
289
289
  Replacement.create({
290
290
  token: 'validUntil',
291
- value: this.validUntil ? Formatter.dateTime(this.validUntil) : 'nooit',
291
+ value: this.validUntil ? Formatter.dateTime(this.validUntil) : $t(`a402f8d1-b470-4b1e-948b-1524576708ea`),
292
292
  }),
293
293
  Replacement.create({
294
294
  token: 'validUntilDate',
295
- value: this.validUntil ? Formatter.date(this.validUntil) : 'nooit',
295
+ value: this.validUntil ? Formatter.date(this.validUntil) : $t(`a402f8d1-b470-4b1e-948b-1524576708ea`),
296
296
  }),
297
297
  Replacement.create({
298
298
  token: 'renewUrl',
@@ -1,6 +1,6 @@
1
1
  import { column, Database, ManyToOneRelation } from '@simonbackx/simple-database';
2
2
  import { QueryableModel } from '@stamhoofd/sql';
3
- import { ApiUser } from '@stamhoofd/structures';
3
+ import { ApiUser, ApiUserRateLimits } from '@stamhoofd/structures';
4
4
  import crypto from 'crypto';
5
5
 
6
6
  import { RateLimiter } from '../helpers/RateLimiter';
@@ -20,31 +20,6 @@ async function randomBytes(size: number): Promise<Buffer> {
20
20
  });
21
21
  }
22
22
 
23
- export const apiUserRateLimiter = new RateLimiter({
24
- limits: [
25
- {
26
- // Block heavy bursts (5req/s for 5s)
27
- limit: 25,
28
- duration: 5 * 1000,
29
- },
30
- {
31
- // max 1req/s during 150s
32
- limit: 150,
33
- duration: 150 * 1000,
34
- },
35
- {
36
- // 1000 requests per hour
37
- limit: 1000,
38
- duration: 60 * 1000 * 60,
39
- },
40
- {
41
- // 2000 requests per day
42
- limit: 2000,
43
- duration: 24 * 60 * 1000 * 60,
44
- },
45
- ],
46
- });
47
-
48
23
  export class Token extends QueryableModel {
49
24
  static table = 'tokens';
50
25
  static MAX_DEVICES = 15;
@@ -109,6 +84,7 @@ export class Token extends QueryableModel {
109
84
  permissions: user.permissions,
110
85
  expiresAt: lastToken?.accessTokenValidUntil ?? null,
111
86
  createdAt: user.createdAt,
87
+ meta: user.meta,
112
88
  });
113
89
  }
114
90
 
@@ -456,7 +456,7 @@ export class User extends QueryableModel {
456
456
  throw new SimpleError({
457
457
  code: 'duplicate_login_provider',
458
458
  message: 'This account is already linked to another account',
459
- human: 'Er is een ander extern account gekoppeld aan deze gebruiker. Het is niet mogelijk om in te loggen op dit account. Ontkoppel eerst je andere account.',
459
+ human: $t(`d4f1cb82-1e15-421a-8218-37cd3066436c`),
460
460
  statusCode: 400,
461
461
  });
462
462
  }
@@ -467,7 +467,7 @@ export class User extends QueryableModel {
467
467
  throw new SimpleError({
468
468
  code: 'password_based_account',
469
469
  message: 'This user uses a password to login. Log in with the password and link the external account through the settings.',
470
- human: 'Log eerst in met je bestaande wachtwoord en koppel daarna de nieuwe login methode via je account instellingen.',
470
+ human: $t(`0154f68a-7458-4b87-91f2-5d04be0737fd`),
471
471
  statusCode: 400,
472
472
  });
473
473
  }
@@ -173,6 +173,10 @@ export class Webshop extends QueryableModel {
173
173
  return this.domain;
174
174
  }
175
175
 
176
+ if (!STAMHOOFD.domains.webshop) {
177
+ throw new Error('No webshop domains configured');
178
+ }
179
+
176
180
  const domain = STAMHOOFD.domains.webshop[this.organization.address.country] ?? STAMHOOFD.domains.webshop[''];
177
181
  return domain + '/' + this.uri;
178
182
  }
@@ -92,7 +92,7 @@ export class PostalCode extends QueryableModel {
92
92
  throw new SimpleError({
93
93
  code: 'invalid_field',
94
94
  message: 'Invalid city. Suggestions: ' + Formatter.joinLast(cities.map(c => c.name), ', ', ' of ') + '?',
95
- human: 'Welke gemeente bedoel je precies? ' + Formatter.joinLast(cities.map(c => c.name), ', ', ' of ') + '?',
95
+ human: $t(`8c2fe8b6-416a-47e5-b77b-20c8192ad0c7`) + ' ' + Formatter.joinLast(cities.map(c => c.name), ', ', ' ' + $t(`411cf334-eebb-4f27-beb6-d81bd544c3f5`) + ' ') + '?',
96
96
  field: 'city',
97
97
  });
98
98
  }