eletrotupi / tcc/ commit / bc71b93

api/mail: state the code window and stop logging credentials

The welcome and activation emails now state that the code expires in
five minutes, so a code that no longer works reads as expired rather
than as mistyped. The mail path no longer writes the user row or the job
payload into the log, which also stops the reset token from accumulating
there
Pedro Lucas Porcellis porcellis@eletrotupi.com · 24 days ago bc71b93c4b3cd3b175782e5ea07ea419f9d94381 Browse files
Parents a812da8
Changed files
5
Additions
+7
Deletions
-9
api/src/lib/queue/processors/mail.ts
1 1
import { Job } from "bullmq";
2 2
import {
3 3
  MailJobName,
4 4
  MailJobData,
5 5
  WelcomeEmailPayload,
18 18
): Promise<void> {
19 19
  // job.name is the discriminant
20 20
  switch (job.name as MailJobName) {
21 21
    case MailJobName.WelcomeEmail: {
22 22
      const data = job.data as WelcomeEmailPayload;
23 -
      console.log("Dispatching an welcome email", data);
23 +
      console.log("Dispatching a welcome email for user", data.userId);
24 24

25 25
      await sendWelcomeEmail(Number(data.userId), data.code);
26 26

27 27
      break;
28 28
    }
29 29

30 30
    case MailJobName.ActivateAccountEmail: {
31 31
      const data = job.data as ActivateAccountEmailPayload;
32 -
      console.log("Dispatching an activate account email", data);
32 +
      console.log("Dispatching an activation email for user", data.userId);
33 33

34 34
      await sendActivateAccountEmail(Number(data.userId), data.code);
35 35

36 36
      break;
37 37
    }
38 38

39 39
    case MailJobName.PasswordReset: {
40 40
      const data = job.data as PasswordResetPayload;
41 -
      console.log("Dispatching an welcome email", data);
41 +
      console.log("Dispatching a password reset email for user", data.userId);
42 42

43 43
      await sendResetPasswordEmail(data.userId, data.token);
44 44

45 45
      break;
46 46
    }
47 47

48 48
    default:
49 49
      throw new Error(`Unknown mail job: ${job.name}`);
50 50
  }
51 51
}
api/src/services/mail/sendActivateAccountEmail.ts
1 1
import { findUserById } from '@app/services/user.service';
2 2
import { sendEmail }  from '@app/lib/mail';
3 3

4 4
const email = (firstName: string, code: string) => {
5 5
  return (`
6 6
Oi, ${firstName}.
7 7

8 8
Você criou sua conta no nexo. Porém, precisa ativar sua conta.
9 9

10 10
Aqui seu código de ativação: ${code}.
11 +
O código expira em cinco minutos.
11 12

12 13
Qualquer coisa prende o grito!
13 14
  `)
14 15
}
15 16

16 17
export async function sendActivateAccountEmail(userId: number, code: string): Promise<void> {
17 18
  const user = await findUserById(userId)!;
18 -

19 -
  console.log("Email/activateAccount: ", user, code);
20 19

21 20
  const { data, error } = await sendEmail({
22 21
    to: user!.email,
23 22
    subject: "Ative sua conta no nexo!",
24 23
    text: email(user!.firstName, code)
29 28
  }
30 29

31 30
  console.log("Email sent successfully!");
32 31
  console.log("Email ID:", data?.id);
33 32
}
api/src/services/mail/sendPasswordReset.ts
1 1
import { findUserById } from '@app/services/user.service';
2 2
import { sendEmail }  from '@app/lib/mail';
3 3

4 4
const email = (firstName: string, token: string) => {
5 5
  return (`
14 14
}
15 15

16 16
export async function sendResetPasswordEmail(userId: number, token: string): Promise<void> {
17 17
  const user = await findUserById(userId)!;
18 18

19 -
  console.log("Email/passwdReset: ", user);
20 -

21 19
  const { data, error } = await sendEmail({
22 20
    to: user!.email,
23 21
    subject: "Esqueceu a senha do nexo?",
24 22
    text: email(user!.firstName, token)
25 23
  });
29 27
  }
30 28

31 29
  console.log("Email sent successfully!");
32 30
  console.log("Email ID:", data?.id);
33 31
}
api/src/services/mail/welcome.ts
1 1
import { findUserById } from '@app/services/user.service';
2 2
import { sendEmail }  from '@app/lib/mail';
3 3

4 4
const email = (firstName: string, code: string) => {
5 5
  return (`
6 6
Oi! Seja bem vindo, ${firstName}.
7 7

8 8
Você criou sua conta com sucesso no nexo! Aqui seu código de ativação: ${code}.
9 +
O código expira em cinco minutos.
9 10

10 11
Qualquer coisa prende o grito!
11 12
  `)
12 13
}
13 14

14 15
export async function sendWelcomeEmail(userId: number, code: string): Promise<void> {
15 16
  const user = await findUserById(userId)!;
16 -

17 -
  console.log("Email/welcome: ", user, code);
18 17

19 18
  const { data, error } = await sendEmail({
20 19
    to: user!.email,
21 20
    subject: "Bem vindo ao nexo!",
22 21
    text: email(user!.firstName, code)
27 26
  }
28 27

29 28
  console.log("Email sent successfully!");
30 29
  console.log("Email ID:", data?.id);
31 30
}
api/tests/jobs/mail.test.ts
1 1
import { describe, it, expect, afterAll, beforeEach, vi } from 'vitest'
2 2
import { sendWelcomeEmail } from '@app/services/mail/welcome'
3 3
import { sendActivateAccountEmail } from '@app/services/mail/sendActivateAccountEmail'
4 4
import { sendResetPasswordEmail } from '@app/services/mail/sendPasswordReset'
5 5
import { mailProcessor } from '@app/lib/queue/processors/mail'
44 44
    )
45 45

46 46
    // The code itself is in the body so the user knows what to enter
47 47
    const [call] = mockedSendEmail.mock.calls
48 48
    expect(call[0].text).toContain('123456')
49 +
    expect(call[0].text).toContain('expira em cinco minutos')
49 50
  })
50 51
})
51 52

52 53
describe('sendActivateAccountEmail', () => {
53 54
  it('sends to the correct address with the activation code', async () => {
65 66
        text: expect.stringContaining('João'),
66 67
      })
67 68
    )
68 69
    const [call] = mockedSendEmail.mock.calls
69 70
    expect(call[0].text).toContain('654321')
71 +
    expect(call[0].text).toContain('expira em cinco minutos')
70 72
  })
71 73
})
72 74

73 75
describe('sendResetPasswordEmail', () => {
74 76
  it('sends to the correct address with the reset token', async () => {
112 114
    await expect(
113 115
      mailProcessor({ name: 'mail:unknown', data: {} } as any)
114 116
    ).rejects.toThrow('Unknown mail job')
115 117
  })
116 118
})