From 9354738abc7adf467842e708c7294c939fcf3692 Mon Sep 17 00:00:00 2001 From: iruy-fr Date: Thu, 3 Sep 2026 16:44:42 -0300 Subject: [PATCH] FIX: surface failed MFA resets --- .../auth/auth.service.reset-users.spec.ts | 57 +++++++++++++++++++ src/modules/auth/auth.service.ts | 16 ++++++ 2 files changed, 73 insertions(+) create mode 100644 src/modules/auth/auth.service.reset-users.spec.ts diff --git a/src/modules/auth/auth.service.reset-users.spec.ts b/src/modules/auth/auth.service.reset-users.spec.ts new file mode 100644 index 0000000..f981ce0 --- /dev/null +++ b/src/modules/auth/auth.service.reset-users.spec.ts @@ -0,0 +1,57 @@ +import { HttpException, HttpStatus } from '@nestjs/common'; +import { Metadata } from '@grpc/grpc-js'; +import { of } from 'rxjs'; + +import { AuthClientService } from './auth.service'; + +describe('AuthClientService.resetUsers', () => { + const logger = { + info: jest.fn(), + debug: jest.fn(), + error: jest.fn(), + }; + const resetUser = jest.fn(); + let service: AuthClientService; + + beforeEach(() => { + jest.clearAllMocks(); + service = new AuthClientService({ logger } as any, {} as any); + (service as any).authService = { ResetUser: resetUser }; + }); + + it('returns the DUC response when every requested user was reset', async () => { + const response = { + message: 'Users reset successfully', + successfulUsers: ['user-1'], + failedUsers: [], + }; + resetUser.mockReturnValue(of(response)); + + await expect( + service.resetUsers(['user-1'], new Metadata()), + ).resolves.toEqual(response); + }); + + it('returns a non-2xx error instead of masking failed resets', async () => { + const response = { + message: 'Some users failed', + successfulUsers: ['user-1'], + failedUsers: ['user-2'], + }; + resetUser.mockReturnValue(of(response)); + + try { + await service.resetUsers(['user-1', 'user-2'], new Metadata()); + fail('Expected resetUsers to reject'); + } catch (error) { + expect(error).toBeInstanceOf(HttpException); + expect((error as HttpException).getStatus()).toBe(HttpStatus.BAD_GATEWAY); + expect((error as HttpException).getResponse()).toEqual({ + statusCode: HttpStatus.BAD_GATEWAY, + message: 'Failed to reset MFA for one or more users.', + successfulUsers: ['user-1'], + failedUsers: ['user-2'], + }); + } + }); +}); diff --git a/src/modules/auth/auth.service.ts b/src/modules/auth/auth.service.ts index c82aeef..79c35c6 100644 --- a/src/modules/auth/auth.service.ts +++ b/src/modules/auth/auth.service.ts @@ -295,6 +295,22 @@ export class AuthClientService implements OnModuleInit { this.authService.ResetUser({ users }, metadata), ); + if (response.failedUsers?.length > 0) { + this.logger.error('resetUsers - Partial or total failure', { + successfulUsers: response.successfulUsers, + failedUsers: response.failedUsers, + }); + throw new HttpException( + { + statusCode: HttpStatus.BAD_GATEWAY, + message: 'Failed to reset MFA for one or more users.', + successfulUsers: response.successfulUsers, + failedUsers: response.failedUsers, + }, + HttpStatus.BAD_GATEWAY, + ); + } + this.logger.info('resetUsers - Success', { response }); return response; } catch (error) {