Skip to content

Commit 11a297d

Browse files
committedDec 5, 2024
feat(api): send notification email for route DELETE /api/users/me
1 parent 4215430 commit 11a297d

File tree

3 files changed

+49
-10
lines changed

3 files changed

+49
-10
lines changed
 

Diff for: ‎api/src/identity-access-management/application/user/user.controller.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,11 @@ const rememberUserHasSeenLastDataProtectionPolicyInformation = async function (
203203
return dependencies.userSerializer.serialize(updatedUser);
204204
};
205205

206-
const selfDeleteUserAccount = async function (request, h) {
206+
const selfDeleteUserAccount = async function (request, h, dependencies = { requestResponseUtils }) {
207207
const authenticatedUserId = request.auth.credentials.userId;
208+
const localeFromHeader = dependencies.requestResponseUtils.extractLocaleFromRequest(request);
208209

209-
await usecases.selfDeleteUserAccount({ userId: authenticatedUserId });
210+
await usecases.selfDeleteUserAccount({ userId: authenticatedUserId, localeFromHeader });
210211

211212
return h.response().code(204);
212213
};

Diff for: ‎api/src/identity-access-management/domain/usecases/self-delete-user-account.usecase.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ForbiddenAccess } from '../../../shared/domain/errors.js';
2+
import { createSelfDeleteUserAccountEmail } from '../emails/create-self-delete-user-account.email.js';
23

34
/**
45
* @typedef {import('../../infrastructure/repositories/privacy-users-api.repository.js')} PrivacyUsersApiRepository
@@ -10,15 +11,33 @@ import { ForbiddenAccess } from '../../../shared/domain/errors.js';
1011
* @param{PrivacyUsersApiRepository} privacyUsersApiRepository
1112
* @returns {Promise<boolean>}
1213
*/
13-
export const selfDeleteUserAccount = async function ({ userId, privacyUsersApiRepository }) {
14+
export const selfDeleteUserAccount = async function ({
15+
userId,
16+
localeFromHeader,
17+
userRepository,
18+
privacyUsersApiRepository,
19+
emailRepository,
20+
}) {
1421
const canSelfDeleteAccount = await privacyUsersApiRepository.canSelfDeleteAccount({ userId });
1522

1623
if (!canSelfDeleteAccount) {
1724
throw new ForbiddenAccess();
1825
}
1926

27+
const user = await userRepository.get(userId);
28+
2029
const anonymizedByUserId = userId;
2130
const anonymizedByUserRole = 'USER';
2231
const client = 'PIX_APP';
2332
await privacyUsersApiRepository.anonymizeUser({ userId, anonymizedByUserId, anonymizedByUserRole, client });
33+
34+
if (user.email) {
35+
await emailRepository.sendEmailAsync(
36+
createSelfDeleteUserAccountEmail({
37+
locale: localeFromHeader,
38+
email: user.email,
39+
firstName: user.firstName,
40+
}),
41+
);
42+
}
2443
};

Diff for: ‎api/tests/identity-access-management/integration/domain/usecases/self-delete-user-account.usecase.test.js

+26-7
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,34 @@ import { databaseBuilder, expect, sinon } from '../../../../test-helper.js';
55

66
describe('Integration | Identity Access Management | Domain | UseCase | self-delete-user-account', function () {
77
context('when user can self delete their account', function () {
8-
it('doesn’t throw ForbiddenError', async function () {
9-
// given
10-
const userId = databaseBuilder.factory.buildUser().id;
11-
await databaseBuilder.commit();
8+
context('when user has an email', function () {
9+
it('doesn’t throw ForbiddenError and creates a SendEmailJob', async function () {
10+
// given
11+
const userId = databaseBuilder.factory.buildUser().id;
12+
await databaseBuilder.commit();
1213

13-
sinon.stub(config.featureToggles, 'isSelfAccountDeletionEnabled').value(true);
14+
sinon.stub(config.featureToggles, 'isSelfAccountDeletionEnabled').value(true);
1415

15-
// when & then
16-
await expect(usecases.selfDeleteUserAccount({ userId })).to.not.be.rejectedWith(ForbiddenAccess);
16+
// when & then
17+
await expect(usecases.selfDeleteUserAccount({ userId })).to.not.be.rejectedWith(ForbiddenAccess);
18+
19+
await expect('SendEmailJob').to.have.been.performed.withJobsCount(1);
20+
});
21+
});
22+
23+
context('when user doesn’t have an email', function () {
24+
it('doesn’t throw ForbiddenError and doesn’t create a SendEmailJob', async function () {
25+
// given
26+
const userId = databaseBuilder.factory.buildUser.withoutPixAuthenticationMethod().id;
27+
await databaseBuilder.commit();
28+
29+
sinon.stub(config.featureToggles, 'isSelfAccountDeletionEnabled').value(true);
30+
31+
// when & then
32+
await expect(usecases.selfDeleteUserAccount({ userId })).to.not.be.rejectedWith(ForbiddenAccess);
33+
34+
await expect('SendEmailJob').to.have.been.performed.withJobsCount(0);
35+
});
1736
});
1837
});
1938

0 commit comments

Comments
 (0)