fix(server): replace email-in-use messages to prevent user-existence oracle

Error messages on registration and profile-update that named whether an
email address was already taken allowed callers to enumerate registered
accounts. All three sites now return the same generic message regardless
of whether the address is in use.
This commit is contained in:
timonrieger
2026-04-29 22:53:44 +02:00
parent fa6ce8cc00
commit 32cc8ca0aa
5 changed files with 5 additions and 5 deletions
+1 -1
View File
@@ -120,7 +120,7 @@ describe('/users', () => {
.set('Authorization', `Bearer ${nonAdmin.accessToken}`);
expect(status).toBe(400);
expect(body).toMatchObject(errorDto.badRequest('Email already in use by another account'));
expect(body).toMatchObject(errorDto.badRequest('Email is not available'));
});
it('should update my email', async () => {
+1 -1
View File
@@ -218,7 +218,7 @@ export class BaseService {
async createUser(dto: Insertable<UserTable> & { email: string }): Promise<UserAdmin> {
const exists = await this.userRepository.getByEmail(dto.email);
if (exists) {
throw new BadRequestException('User exists');
throw new BadRequestException('Email is not available');
}
if (!dto.isAdmin) {
+1 -1
View File
@@ -64,7 +64,7 @@ export class UserAdminService extends BaseService {
if (dto.email) {
const duplicate = await this.userRepository.getByEmail(dto.email);
if (duplicate && duplicate.id !== id) {
throw new BadRequestException('Email already in use by another account');
throw new BadRequestException('Email is not available');
}
}
+1 -1
View File
@@ -49,7 +49,7 @@ export class UserService extends BaseService {
if (dto.email) {
const duplicate = await this.userRepository.getByEmail(dto.email);
if (duplicate && duplicate.id !== user.id) {
throw new BadRequestException('Email already in use by another account');
throw new BadRequestException('Email is not available');
}
}
@@ -48,7 +48,7 @@ describe(UserService.name, () => {
ctx.getMock(EventRepository).emit.mockResolvedValue();
const user = mediumFactory.userInsert();
await expect(sut.createUser({ name: 'Test', email: user.email })).resolves.toMatchObject({ email: user.email });
await expect(sut.createUser({ name: 'Test', email: user.email })).rejects.toThrow('User exists');
await expect(sut.createUser({ name: 'Test', email: user.email })).rejects.toThrow('Email is not available');
});
it('should not return password', async () => {