Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sempre validar se username é único antes de validar o mesmo para o email #1772

Merged
merged 1 commit into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 20 additions & 17 deletions models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,24 +405,27 @@ async function validateUniqueUser(userData, options) {

const results = await database.query(query, options);

if (results.rowCount > 0) {
const isSameUsername = results.rows[0].username.toLowerCase() === userData.username?.toLowerCase();
if (isSameUsername) {
throw new ValidationError({
message: `O "username" informado já está sendo usado.`,
stack: new Error().stack,
errorLocationCode: `MODEL:USER:VALIDATE_UNIQUE_USERNAME:ALREADY_EXISTS`,
key: 'username',
});
} else {
throw new ValidationError({
message: `O email informado já está sendo usado.`,
stack: new Error().stack,
errorLocationCode: `MODEL:USER:VALIDATE_UNIQUE_EMAIL:ALREADY_EXISTS`,
key: 'email',
});
}
if (!results.rowCount) return;

const isSameUsername = results.rows.some(
({ username }) => username.toLowerCase() === userData.username?.toLowerCase(),
);

if (isSameUsername) {
throw new ValidationError({
message: `O "username" informado já está sendo usado.`,
stack: new Error().stack,
errorLocationCode: `MODEL:USER:VALIDATE_UNIQUE_USERNAME:ALREADY_EXISTS`,
key: 'username',
});
}

throw new ValidationError({
message: `O email informado já está sendo usado.`,
stack: new Error().stack,
errorLocationCode: `MODEL:USER:VALIDATE_UNIQUE_EMAIL:ALREADY_EXISTS`,
key: 'email',
});
}

async function hashPasswordInObject(userObject) {
Expand Down
58 changes: 58 additions & 0 deletions tests/integration/api/v1/users/[username]/patch.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,64 @@ describe('PATCH /api/v1/users/[username]', () => {
expect(foundUser.updated_at.toISOString()).toBe(responseBody.updated_at);
});

test('Patching itself with duplicate "email" and "username" should only return "username" error', async () => {
await orchestrator.createUser({ username: 'usernameStoredPreviously' });
await orchestrator.createUser({ email: '[email protected]' });
await orchestrator.createUser({ username: 'usernameStoredLater' });

const usersRequestBuilder = new RequestBuilder('/api/v1/users/');
const defaultUser = await usersRequestBuilder.buildUser();
await orchestrator.deleteAllEmails();

const { response, responseBody } = await usersRequestBuilder.patch(defaultUser.username, {
email: '[email protected]',
username: 'usernameStoredPreviously',
});
expect.soft(response.status).toBe(400);

expect(responseBody).toStrictEqual({
status_code: 400,
name: 'ValidationError',
message: 'O "username" informado já está sendo usado.',
action: 'Ajuste os dados enviados e tente novamente.',
error_location_code: 'MODEL:USER:VALIDATE_UNIQUE_USERNAME:ALREADY_EXISTS',
error_id: responseBody.error_id,
request_id: responseBody.request_id,
key: 'username',
});
expect(uuidVersion(responseBody.error_id)).toBe(4);
expect(uuidVersion(responseBody.request_id)).toBe(4);

const { response: response2, responseBody: responseBody2 } = await usersRequestBuilder.patch(
defaultUser.username,
{
email: '[email protected]',
username: 'usernameStoredLater',
},
);
expect.soft(response2.status).toBe(400);

expect(responseBody2).toStrictEqual({
status_code: 400,
name: 'ValidationError',
message: 'O "username" informado já está sendo usado.',
action: 'Ajuste os dados enviados e tente novamente.',
error_location_code: 'MODEL:USER:VALIDATE_UNIQUE_USERNAME:ALREADY_EXISTS',
error_id: responseBody2.error_id,
request_id: responseBody2.request_id,
key: 'username',
});
expect(uuidVersion(responseBody2.error_id)).toBe(4);
expect(uuidVersion(responseBody2.request_id)).toBe(4);

const confirmationEmail = await orchestrator.getLastEmail();
expect(confirmationEmail).toBeNull();

const foundUser = await user.findOneById(defaultUser.id);
expect(foundUser.email).toBe(defaultUser.email);
expect(foundUser.updated_at).toStrictEqual(defaultUser.updated_at);
});

test('Patching itself with another "email"', async () => {
let defaultUser = await orchestrator.createUser({
email: '[email protected]',
Expand Down