@stamhoofd/backend 2.20.0 → 2.21.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.20.0",
3
+ "version": "2.21.1",
4
4
  "main": "./dist/index.js",
5
5
  "exports": {
6
6
  ".": {
@@ -36,14 +36,14 @@
36
36
  "@simonbackx/simple-encoding": "2.15.0",
37
37
  "@simonbackx/simple-endpoints": "1.14.0",
38
38
  "@simonbackx/simple-logging": "^1.0.1",
39
- "@stamhoofd/backend-i18n": "^2.17.0",
40
- "@stamhoofd/backend-middleware": "^2.17.0",
41
- "@stamhoofd/email": "^2.17.0",
42
- "@stamhoofd/models": "^2.20.0",
43
- "@stamhoofd/queues": "^2.17.3",
44
- "@stamhoofd/sql": "^2.20.0",
45
- "@stamhoofd/structures": "^2.20.0",
46
- "@stamhoofd/utility": "^2.17.0",
39
+ "@stamhoofd/backend-i18n": "2.21.1",
40
+ "@stamhoofd/backend-middleware": "2.21.1",
41
+ "@stamhoofd/email": "2.21.1",
42
+ "@stamhoofd/models": "2.21.1",
43
+ "@stamhoofd/queues": "2.21.1",
44
+ "@stamhoofd/sql": "2.21.1",
45
+ "@stamhoofd/structures": "2.21.1",
46
+ "@stamhoofd/utility": "2.21.1",
47
47
  "archiver": "^7.0.1",
48
48
  "aws-sdk": "^2.885.0",
49
49
  "axios": "1.6.8",
@@ -60,5 +60,5 @@
60
60
  "postmark": "4.0.2",
61
61
  "stripe": "^16.6.0"
62
62
  },
63
- "gitHead": "946c0ddcaa7cdc9b769d4dc9083a517fe7ad19f8"
63
+ "gitHead": "5762f9e0dc07731e32a5d58fb83e4aa0e3da4fa9"
64
64
  }
@@ -1,8 +1,7 @@
1
1
  import { Decoder } from '@simonbackx/simple-encoding';
2
2
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
- import { Email } from '@stamhoofd/email';
4
- import { PasswordToken, User } from '@stamhoofd/models';
5
- import { ForgotPasswordRequest } from '@stamhoofd/structures';
3
+ import { PasswordToken, sendEmailTemplate, User } from '@stamhoofd/models';
4
+ import { EmailTemplateType, ForgotPasswordRequest, Recipient, Replacement } from '@stamhoofd/structures';
6
5
 
7
6
  import { Context } from '../../helpers/Context';
8
7
 
@@ -29,41 +28,46 @@ export class ForgotPasswordEndpoint extends Endpoint<Params, Query, Body, Respon
29
28
  }
30
29
 
31
30
  async handle(request: DecodedRequest<Params, Query, Body>) {
32
- // for now we care more about UX, so we show a mesage if the user doesn't exist
33
31
  const organization = await Context.setOptionalOrganizationScope()
34
32
  const user = await User.getForAuthentication(organization?.id ?? null, request.body.email, {allowWithoutAccount: true});
35
33
 
36
- const { from, replyTo } = {
37
- from: organization ? organization.getStrongEmail(request.i18n) : Email.getInternalEmailFor(request.i18n),
38
- replyTo: undefined
39
- }
40
- const name = organization ? organization.name : request.i18n.t("shared.platformName");
41
-
42
34
  if (!user) {
43
- // Send email
44
- Email.send({
45
- from,
46
- replyTo,
47
- to: request.body.email,
48
- subject: "["+name+"] Wachtwoord vergeten",
49
- type: "transactional",
50
- text: "Hallo, \n\nJe gaf aan dat je jouw wachtwoord bent vergeten, maar er bestaat geen account op het e-mailadres dat je hebt ingegeven ("+request.body.email+"). Niet zeker meer welk e-mailadres je kan gebruiken? Wij sturen altijd e-mails naar een e-mailadres waarop je een account hebt. Lukt dat niet? Dan moet je je eerst registreren.\n\nMet vriendelijke groeten,\n"+(name),
51
- });
35
+ // Create e-mail builder
36
+ await sendEmailTemplate(organization, {
37
+ recipients: [
38
+ Recipient.create({
39
+ email: request.body.email
40
+ })
41
+ ],
42
+ template: {
43
+ type: EmailTemplateType.ForgotPasswordButNoAccount,
44
+ },
45
+ type: 'transactional'
46
+ })
52
47
 
53
48
  return new Response(undefined)
54
49
  }
55
50
 
56
51
  const recoveryUrl = await PasswordToken.getPasswordRecoveryUrl(user, organization, request.i18n)
57
-
58
- // Send email
59
- Email.send({
60
- from,
61
- replyTo,
62
- to: user.email,
63
- subject: "Wachtwoord vergeten",
64
- type: "transactional",
65
- text: (user.firstName ? "Hey "+user.firstName : "Hey") + ", \n\nJe gaf aan dat je jouw wachtwoord bent vergeten. Je kan een nieuw wachtwoord instellen door op de volgende link te klikken of door deze te kopiëren in de URL-balk van je browser:\n"+recoveryUrl+"\n\nWachtwoord al teruggevonden of heb je helemaal niet aangeduid dat je je wachtwoord vergeten bent? Dan mag je deze e-mail gewoon negeren.\n\nMet vriendelijke groeten,\n"+(user.permissions ? request.i18n.t("shared.platformName") : name)
66
- });
52
+
53
+ // Create e-mail builder
54
+ await sendEmailTemplate(organization, {
55
+ recipients: [
56
+ Recipient.create({
57
+ email: request.body.email,
58
+ replacements: [
59
+ Replacement.create({
60
+ token: 'resetUrl',
61
+ value: recoveryUrl
62
+ })
63
+ ]
64
+ })
65
+ ],
66
+ template: {
67
+ type: EmailTemplateType.ForgotPassword,
68
+ },
69
+ type: 'transactional'
70
+ })
67
71
 
68
72
  return new Response(undefined);
69
73
  }
@@ -4,7 +4,7 @@ import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-
4
4
  import { SimpleError } from '@simonbackx/simple-errors';
5
5
  import { Email } from '@stamhoofd/email';
6
6
  import { ArchiverWriterAdapter, exportToExcel, XlsxTransformerSheet, XlsxWriter } from '@stamhoofd/excel-writer';
7
- import { getEmailBuilderForTemplate, Platform, RateLimiter } from '@stamhoofd/models';
7
+ import { getEmailBuilderForTemplate, Platform, RateLimiter, sendEmailTemplate } from '@stamhoofd/models';
8
8
  import { EmailTemplateType, ExcelExportRequest, ExcelExportResponse, ExcelExportType, LimitedFilteredRequest, PaginatedResponse, Recipient, Replacement, Version } from '@stamhoofd/structures';
9
9
  import { sleep } from "@stamhoofd/utility";
10
10
  import { Context } from '../../../helpers/Context';
@@ -90,7 +90,7 @@ export class ExportToExcelEndpoint extends Endpoint<Params, Query, Body, Respons
90
90
  const result = await Promise.race([
91
91
  this.job(loader, request.body, request.params.type).then(async (url: string) => {
92
92
  if (sendEmail) {
93
- const builder = await getEmailBuilderForTemplate(organization, {
93
+ await sendEmailTemplate(null, {
94
94
  template: {
95
95
  type: EmailTemplateType.ExcelExportSucceeded
96
96
  },
@@ -99,13 +99,8 @@ export class ExportToExcelEndpoint extends Endpoint<Params, Query, Body, Respons
99
99
  token: 'downloadUrl',
100
100
  value: url
101
101
  }))
102
- ],
103
- from: Email.getInternalEmailFor(Context.i18n)
102
+ ]
104
103
  })
105
-
106
- if (builder) {
107
- Email.schedule(builder)
108
- }
109
104
 
110
105
  }
111
106
 
@@ -45,6 +45,14 @@ export class GetOrganizationFromUriEndpoint extends Endpoint<Params, Query, Body
45
45
  statusCode: 404
46
46
  })
47
47
  }
48
+
49
+ if (!organization.active) {
50
+ throw new SimpleError({
51
+ code: "archived_organization",
52
+ message: "This organization has been archived",
53
+ statusCode: 404
54
+ })
55
+ }
48
56
  return new Response(await AuthenticatedStructures.organization(organization));
49
57
  }
50
58
  }
@@ -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
  }
@@ -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
  }