-
Notifications
You must be signed in to change notification settings - Fork 406
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(users): delete inactive users with expired tokens on create/update
When creating or updating a user, the system checks for existing users with the same username or email. If such users exist but have never activated their accounts and their tokens are expired, they are deleted automatically. This avoids conflicts and frees up old, unused usernames and emails.
- Loading branch information
Showing
4 changed files
with
536 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1017,6 +1017,89 @@ describe('PATCH /api/v1/users/[username]', () => { | |
expect(foundUser.email).toBe(defaultUser.email); | ||
expect(foundUser.updated_at).toStrictEqual(defaultUser.updated_at); | ||
}); | ||
|
||
test('Patching itself with a duplicate "username" for an inactive user with expired activation token', async () => { | ||
const inactiveUser = await orchestrator.createUser({ username: 'existentInactiveUser' }); | ||
await orchestrator.updateActivateAccountTokenByUserId(inactiveUser.id, { | ||
expires_at: new Date(Date.now() - 1000), | ||
}); | ||
|
||
const usersRequestBuilder = new RequestBuilder('/api/v1/users/'); | ||
const defaultUser = await usersRequestBuilder.buildUser(); | ||
|
||
const { response, responseBody } = await usersRequestBuilder.patch(defaultUser.username, { | ||
username: 'existentInactiveUser', | ||
}); | ||
expect.soft(response.status).toBe(200); | ||
|
||
expect(responseBody).toStrictEqual({ | ||
id: defaultUser.id, | ||
username: 'existentInactiveUser', | ||
email: defaultUser.email, | ||
description: defaultUser.description, | ||
features: defaultUser.features, | ||
notifications: true, | ||
tabcoins: 0, | ||
tabcash: 0, | ||
created_at: defaultUser.created_at.toISOString(), | ||
updated_at: responseBody.updated_at, | ||
}); | ||
|
||
expect(responseBody.updated_at).not.toBe(defaultUser.updated_at.toISOString()); | ||
expect(Date.parse(responseBody.updated_at)).not.toBeNaN(); | ||
|
||
await expect(user.findOneById(inactiveUser.id)).rejects.toThrow( | ||
`O id "${inactiveUser.id}" não foi encontrado no sistema.`, | ||
); | ||
}); | ||
|
||
test('Patching itself with "username" and "email" duplicated from different users, both inactive with expired tokens', async () => { | ||
const firstInactiveUser = await orchestrator.createUser({ username: 'firstInactiveUser' }); | ||
const secondInactiveUser = await orchestrator.createUser({ email: '[email protected]' }); | ||
await orchestrator.updateActivateAccountTokenByUserId(firstInactiveUser.id, { | ||
expires_at: new Date(Date.now() - 1000), | ||
}); | ||
await orchestrator.updateActivateAccountTokenByUserId(secondInactiveUser.id, { | ||
expires_at: new Date(Date.now() - 1000), | ||
}); | ||
|
||
const usersRequestBuilder = new RequestBuilder('/api/v1/users/'); | ||
const defaultUser = await usersRequestBuilder.buildUser(); | ||
|
||
const { response, responseBody } = await usersRequestBuilder.patch(defaultUser.username, { | ||
username: 'firstInactiveUser', | ||
email: '[email protected]', | ||
}); | ||
expect.soft(response.status).toBe(200); | ||
|
||
expect(responseBody).toStrictEqual({ | ||
id: defaultUser.id, | ||
username: 'firstInactiveUser', | ||
email: defaultUser.email, | ||
description: defaultUser.description, | ||
features: defaultUser.features, | ||
notifications: true, | ||
tabcoins: 0, | ||
tabcash: 0, | ||
created_at: defaultUser.created_at.toISOString(), | ||
updated_at: responseBody.updated_at, | ||
}); | ||
|
||
expect(responseBody.updated_at).not.toBe(defaultUser.updated_at.toISOString()); | ||
expect(Date.parse(responseBody.updated_at)).not.toBeNaN(); | ||
|
||
const confirmationEmail = await orchestrator.getLastEmail(); | ||
|
||
expect(confirmationEmail.recipients).toStrictEqual(['<[email protected]>']); | ||
expect(confirmationEmail.subject).toBe('Confirme seu novo email'); | ||
|
||
await expect(user.findOneById(firstInactiveUser.id)).rejects.toThrow( | ||
`O id "${firstInactiveUser.id}" não foi encontrado no sistema.`, | ||
); | ||
await expect(user.findOneById(secondInactiveUser.id)).rejects.toThrow( | ||
`O id "${secondInactiveUser.id}" não foi encontrado no sistema.`, | ||
); | ||
}); | ||
}); | ||
|
||
describe('TEMPORARY BEHAVIOR', () => { | ||
|
Oops, something went wrong.