feat: logout sessions on password change (#23188)

* log out ohter sessions on password change

* translations

* update and add tests

* rename event to UserLogoutOtherSessions

* fix typo

* requested changes

* fix tests

* fix medium:test

* use ValidateBoolean

* fix format

* dont delete current session id

* Update server/src/dtos/auth.dto.ts

Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>

* rename event and invalidateOtherSessions

* chore: cleanup

---------

Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Co-authored-by: Jason Rasmussen <jason@rasm.me>
This commit is contained in:
Jorge Montejo
2025-10-27 14:16:10 +01:00
committed by GitHub
parent 6bb1a9e083
commit 382481735a
15 changed files with 90 additions and 19 deletions
+24
View File
@@ -124,6 +124,11 @@ describe(AuthService.name, () => {
expect(mocks.user.getForChangePassword).toHaveBeenCalledWith(user.id);
expect(mocks.crypto.compareBcrypt).toHaveBeenCalledWith('old-password', 'hash-password');
expect(mocks.event.emit).toHaveBeenCalledWith('AuthChangePassword', {
userId: user.id,
currentSessionId: auth.session?.id,
shouldLogoutSessions: undefined,
});
});
it('should throw when password does not match existing password', async () => {
@@ -147,6 +152,25 @@ describe(AuthService.name, () => {
await expect(sut.changePassword(auth, dto)).rejects.toBeInstanceOf(BadRequestException);
});
it('should change the password and logout other sessions', async () => {
const user = factory.userAdmin();
const auth = factory.auth({ user });
const dto = { password: 'old-password', newPassword: 'new-password', invalidateSessions: true };
mocks.user.getForChangePassword.mockResolvedValue({ id: user.id, password: 'hash-password' });
mocks.user.update.mockResolvedValue(user);
await sut.changePassword(auth, dto);
expect(mocks.user.getForChangePassword).toHaveBeenCalledWith(user.id);
expect(mocks.crypto.compareBcrypt).toHaveBeenCalledWith('old-password', 'hash-password');
expect(mocks.event.emit).toHaveBeenCalledWith('AuthChangePassword', {
userId: user.id,
invalidateSessions: true,
currentSessionId: auth.session?.id,
});
});
});
describe('logout', () => {