diff --git a/src/commands/logout.ts b/src/commands/logout.ts index 3d3ec770..56b56174 100644 --- a/src/commands/logout.ts +++ b/src/commands/logout.ts @@ -1,6 +1,7 @@ import { Command } from '@oclif/core'; import { ConfigService } from '../services/config.service'; import { CLIUtils } from '../utils/cli.utils'; +import { AuthService } from '../services/auth.service'; export default class Logout extends Command { static readonly args = {}; @@ -13,6 +14,7 @@ export default class Logout extends Command { public run = async () => { const user = await ConfigService.instance.readUser(); if (user) { + await AuthService.instance.logout(); await ConfigService.instance.clearUser(); const message = 'User logged out successfully.'; CLIUtils.success(this.log.bind(this), message); diff --git a/src/services/auth.service.ts b/src/services/auth.service.ts index a99e0393..4dda62c2 100644 --- a/src/services/auth.service.ts +++ b/src/services/auth.service.ts @@ -137,4 +137,24 @@ export class AuthService { }); return loginCreds; }; + + /** + * Logs the user out of the application by invoking the logout method + * from the authentication client. This will terminate the user's session + * and clear any associated authentication data. + * + * @returns A promise that resolves when the logout process is complete. + */ + public logout = async (): Promise => { + try { + const user = await ConfigService.instance.readUser(); + if (!user || !user.newToken) { + return; + } + const authClient = SdkManager.instance.getAuth(); + return authClient.logout(user.newToken); + } catch { + //no op + } + }; } diff --git a/test/commands/logout.test.ts b/test/commands/logout.test.ts index 0de0be04..af0b42bd 100644 --- a/test/commands/logout.test.ts +++ b/test/commands/logout.test.ts @@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { ConfigService } from '../../src/services/config.service'; import { UserCredentialsFixture } from '../fixtures/login.fixture'; import Logout from '../../src/commands/logout'; +import { AuthService } from '../../src/services/auth.service'; describe('Logout Command', () => { beforeEach(() => { @@ -10,6 +11,7 @@ describe('Logout Command', () => { it('When user is logged out, then it returns false', async () => { const readUserSpy = vi.spyOn(ConfigService.instance, 'readUser').mockResolvedValue(undefined); + const networkLogout = vi.spyOn(AuthService.instance, 'logout').mockRejectedValue(new Error()); const clearUserSpy = vi.spyOn(ConfigService.instance, 'clearUser').mockRejectedValue(new Error()); const message = 'No user is currently logged in.'; @@ -19,11 +21,13 @@ describe('Logout Command', () => { expect(result).to.be.deep.equal(expected); expect(readUserSpy).toHaveBeenCalledOnce(); + expect(networkLogout).not.toHaveBeenCalled(); expect(clearUserSpy).not.toHaveBeenCalled(); }); it('When user is logged in, then the current user logged out', async () => { const readUserSpy = vi.spyOn(ConfigService.instance, 'readUser').mockResolvedValue(UserCredentialsFixture); + const networkLogout = vi.spyOn(AuthService.instance, 'logout').mockResolvedValue(); const clearUserSpy = vi.spyOn(ConfigService.instance, 'clearUser').mockResolvedValue(); const message = 'User logged out successfully.'; @@ -33,6 +37,7 @@ describe('Logout Command', () => { expect(result).to.be.deep.equal(expected); expect(readUserSpy).toHaveBeenCalledOnce(); + expect(networkLogout).toHaveBeenCalledOnce(); expect(clearUserSpy).toHaveBeenCalledOnce(); }); });