From 8ee2d809c76b3d905ab72dec81605962d893b29a Mon Sep 17 00:00:00 2001 From: Philip Molares Date: Sun, 8 Jan 2023 15:15:56 +0100 Subject: [PATCH] test(backend): add regression test for issue #3135 When a PasswordTooWeakError is encountered the newly created user should be removed again. This should prevent registration error from "burning" usernames for further use. Signed-off-by: Philip Molares --- backend/test/private-api/auth.e2e-spec.ts | 292 ++++++++++++---------- 1 file changed, 163 insertions(+), 129 deletions(-) diff --git a/backend/test/private-api/auth.e2e-spec.ts b/backend/test/private-api/auth.e2e-spec.ts index 5021a2c83..4d1b52efe 100644 --- a/backend/test/private-api/auth.e2e-spec.ts +++ b/backend/test/private-api/auth.e2e-spec.ts @@ -10,6 +10,7 @@ */ import request from 'supertest'; +import { NotInDBError } from '../../src/errors/errors'; import { LoginDto } from '../../src/identity/local/login.dto'; import { RegisterDto } from '../../src/identity/local/register.dto'; import { UpdatePasswordDto } from '../../src/identity/local/update-password.dto'; @@ -65,6 +66,7 @@ describe('Auth', () => { (await newUser.identities)[0].passwordHash ?? '', ), ).resolves.toBeTruthy(); + await testSetup.userService.deleteUser(newUser); }); describe('fails', () => { it('when the user already exits', async () => { @@ -96,151 +98,183 @@ describe('Auth', () => { testSetup.configService.get('authConfig').local.enableRegister = true; }); }); - }); - - describe('PUT /auth/local', () => { - const newPassword = 'new_password'; - let cookie = ''; - beforeEach(async () => { - const loginDto: LoginDto = { - password: password, + it('correctly deletes a user if the PasswordTooWeakError is encountered', async () => { + const registrationDto: RegisterDto = { + displayName: displayName, + password: 'test1234', username: username, }; const response = await request(testSetup.app.getHttpServer()) - .post('/api/private/auth/local/login') + .post('/api/private/auth/local') .set('Content-Type', 'application/json') - .send(JSON.stringify(loginDto)) - .expect(201); - cookie = response.get('Set-Cookie')[0]; - }); - it('works', async () => { - // Change password - const changePasswordDto: UpdatePasswordDto = { - currentPassword: password, - newPassword: newPassword, - }; - await request(testSetup.app.getHttpServer()) - .put('/api/private/auth/local') - .set('Content-Type', 'application/json') - .set('Cookie', cookie) - .send(JSON.stringify(changePasswordDto)) - .expect(200); - // Successfully login with new password - const loginDto: LoginDto = { - password: newPassword, - username: username, - }; - const response = await request(testSetup.app.getHttpServer()) - .post('/api/private/auth/local/login') - .set('Content-Type', 'application/json') - .send(JSON.stringify(loginDto)) - .expect(201); - cookie = response.get('Set-Cookie')[0]; - // Reset password - const changePasswordBackDto: UpdatePasswordDto = { - currentPassword: newPassword, - newPassword: password, - }; - await request(testSetup.app.getHttpServer()) - .put('/api/private/auth/local') - .set('Content-Type', 'application/json') - .set('Cookie', cookie) - .send(JSON.stringify(changePasswordBackDto)) - .expect(200); - }); - it('fails, when registration is disabled', async () => { - testSetup.configService.get('authConfig').local.enableLogin = false; - // Try to change password - const changePasswordDto: UpdatePasswordDto = { - currentPassword: password, - newPassword: newPassword, - }; - await request(testSetup.app.getHttpServer()) - .put('/api/private/auth/local') - .set('Content-Type', 'application/json') - .set('Cookie', cookie) - .send(JSON.stringify(changePasswordDto)) + .send(JSON.stringify(registrationDto)) .expect(400); - // enable login again - testSetup.configService.get('authConfig').local.enableLogin = true; - // new password doesn't work for login - const loginNewPasswordDto: LoginDto = { - password: newPassword, - username: username, - }; - await request(testSetup.app.getHttpServer()) - .post('/api/private/auth/local/login') - .set('Content-Type', 'application/json') - .send(JSON.stringify(loginNewPasswordDto)) - .expect(401); - // old password does work for login - const loginOldPasswordDto: LoginDto = { - password: password, - username: username, - }; - await request(testSetup.app.getHttpServer()) - .post('/api/private/auth/local/login') - .set('Content-Type', 'application/json') - .send(JSON.stringify(loginOldPasswordDto)) - .expect(201); - }); - it('fails, when old password is wrong', async () => { - // Try to change password - const changePasswordDto: UpdatePasswordDto = { - currentPassword: 'wrong', - newPassword: newPassword, - }; - await request(testSetup.app.getHttpServer()) - .put('/api/private/auth/local') - .set('Content-Type', 'application/json') - .set('Cookie', cookie) - .send(JSON.stringify(changePasswordDto)) - .expect(401); - // old password still does work for login - const loginOldPasswordDto: LoginDto = { - password: password, - username: username, - }; - await request(testSetup.app.getHttpServer()) - .post('/api/private/auth/local/login') - .set('Content-Type', 'application/json') - .send(JSON.stringify(loginOldPasswordDto)) - .expect(201); + expect(response.text).toContain('PasswordTooWeakError'); + await expect(() => + testSetup.userService.getUserByUsername(username, [ + UserRelationEnum.IDENTITIES, + ]), + ).rejects.toThrow(NotInDBError); }); }); - describe('POST /auth/local/login', () => { - it('works', async () => { - testSetup.configService.get('authConfig').local.enableLogin = true; - const loginDto: LoginDto = { + describe('Already existing user', () => { + beforeAll(async () => { + const registrationDto: RegisterDto = { + displayName: displayName, password: password, username: username, }; await request(testSetup.app.getHttpServer()) - .post('/api/private/auth/local/login') + .post('/api/private/auth/local') .set('Content-Type', 'application/json') - .send(JSON.stringify(loginDto)) + .send(JSON.stringify(registrationDto)) .expect(201); }); - }); + describe('PUT /auth/local', () => { + const newPassword = 'new_password'; + let cookie = ''; + beforeEach(async () => { + const loginDto: LoginDto = { + password: password, + username: username, + }; + const response = await request(testSetup.app.getHttpServer()) + .post('/api/private/auth/local/login') + .set('Content-Type', 'application/json') + .send(JSON.stringify(loginDto)) + .expect(201); + cookie = response.get('Set-Cookie')[0]; + }); + it('works', async () => { + // Change password + const changePasswordDto: UpdatePasswordDto = { + currentPassword: password, + newPassword: newPassword, + }; + await request(testSetup.app.getHttpServer()) + .put('/api/private/auth/local') + .set('Content-Type', 'application/json') + .set('Cookie', cookie) + .send(JSON.stringify(changePasswordDto)) + .expect(200); + // Successfully login with new password + const loginDto: LoginDto = { + password: newPassword, + username: username, + }; + const response = await request(testSetup.app.getHttpServer()) + .post('/api/private/auth/local/login') + .set('Content-Type', 'application/json') + .send(JSON.stringify(loginDto)) + .expect(201); + cookie = response.get('Set-Cookie')[0]; + // Reset password + const changePasswordBackDto: UpdatePasswordDto = { + currentPassword: newPassword, + newPassword: password, + }; + await request(testSetup.app.getHttpServer()) + .put('/api/private/auth/local') + .set('Content-Type', 'application/json') + .set('Cookie', cookie) + .send(JSON.stringify(changePasswordBackDto)) + .expect(200); + }); + it('fails, when registration is disabled', async () => { + testSetup.configService.get('authConfig').local.enableLogin = false; + // Try to change password + const changePasswordDto: UpdatePasswordDto = { + currentPassword: password, + newPassword: newPassword, + }; + await request(testSetup.app.getHttpServer()) + .put('/api/private/auth/local') + .set('Content-Type', 'application/json') + .set('Cookie', cookie) + .send(JSON.stringify(changePasswordDto)) + .expect(400); + // enable login again + testSetup.configService.get('authConfig').local.enableLogin = true; + // new password doesn't work for login + const loginNewPasswordDto: LoginDto = { + password: newPassword, + username: username, + }; + await request(testSetup.app.getHttpServer()) + .post('/api/private/auth/local/login') + .set('Content-Type', 'application/json') + .send(JSON.stringify(loginNewPasswordDto)) + .expect(401); + // old password does work for login + const loginOldPasswordDto: LoginDto = { + password: password, + username: username, + }; + await request(testSetup.app.getHttpServer()) + .post('/api/private/auth/local/login') + .set('Content-Type', 'application/json') + .send(JSON.stringify(loginOldPasswordDto)) + .expect(201); + }); + it('fails, when old password is wrong', async () => { + // Try to change password + const changePasswordDto: UpdatePasswordDto = { + currentPassword: 'wrong', + newPassword: newPassword, + }; + await request(testSetup.app.getHttpServer()) + .put('/api/private/auth/local') + .set('Content-Type', 'application/json') + .set('Cookie', cookie) + .send(JSON.stringify(changePasswordDto)) + .expect(401); + // old password still does work for login + const loginOldPasswordDto: LoginDto = { + password: password, + username: username, + }; + await request(testSetup.app.getHttpServer()) + .post('/api/private/auth/local/login') + .set('Content-Type', 'application/json') + .send(JSON.stringify(loginOldPasswordDto)) + .expect(201); + }); + }); - describe('DELETE /auth/logout', () => { - it('works', async () => { - testSetup.configService.get('authConfig').local.enableLogin = true; - const loginDto: LoginDto = { - password: password, - username: username, - }; - const response = await request(testSetup.app.getHttpServer()) - .post('/api/private/auth/local/login') - .set('Content-Type', 'application/json') - .send(JSON.stringify(loginDto)) - .expect(201); - const cookie = response.get('Set-Cookie')[0]; - await request(testSetup.app.getHttpServer()) - .delete('/api/private/auth/logout') - .set('Cookie', cookie) - .expect(204); + describe('POST /auth/local/login', () => { + it('works', async () => { + testSetup.configService.get('authConfig').local.enableLogin = true; + const loginDto: LoginDto = { + password: password, + username: username, + }; + await request(testSetup.app.getHttpServer()) + .post('/api/private/auth/local/login') + .set('Content-Type', 'application/json') + .send(JSON.stringify(loginDto)) + .expect(201); + }); + }); + + describe('DELETE /auth/logout', () => { + it('works', async () => { + testSetup.configService.get('authConfig').local.enableLogin = true; + const loginDto: LoginDto = { + password: password, + username: username, + }; + const response = await request(testSetup.app.getHttpServer()) + .post('/api/private/auth/local/login') + .set('Content-Type', 'application/json') + .send(JSON.stringify(loginDto)) + .expect(201); + const cookie = response.get('Set-Cookie')[0]; + await request(testSetup.app.getHttpServer()) + .delete('/api/private/auth/logout') + .set('Cookie', cookie) + .expect(204); + }); }); }); });