This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

implement logout usecase

+97
+58
src/modules/user/application/use-cases/LogoutUseCase.ts
··· 1 + import { UseCase } from 'src/shared/core/UseCase'; 2 + import { Result, ok } from 'src/shared/core/Result'; 3 + import { AppError } from 'src/shared/core/AppError'; 4 + import { ITokenService } from '../services/ITokenService'; 5 + 6 + export interface LogoutDTO { 7 + refreshToken?: string; 8 + } 9 + 10 + export interface LogoutResponse { 11 + success: boolean; 12 + message: string; 13 + } 14 + 15 + export type LogoutUseCaseResponse = Result< 16 + LogoutResponse, 17 + AppError.UnexpectedError 18 + >; 19 + 20 + export class LogoutUseCase 21 + implements UseCase<LogoutDTO, Promise<LogoutUseCaseResponse>> 22 + { 23 + constructor(private tokenService: ITokenService) {} 24 + 25 + async execute(request: LogoutDTO): Promise<LogoutUseCaseResponse> { 26 + const errors: string[] = []; 27 + 28 + try { 29 + // Revoke refresh token if provided 30 + if (request.refreshToken) { 31 + const revokeRefreshResult = await this.tokenService.revokeToken( 32 + request.refreshToken, 33 + ); 34 + if (revokeRefreshResult.isErr()) { 35 + console.warn( 36 + 'Failed to revoke refresh token during logout:', 37 + revokeRefreshResult.error, 38 + ); 39 + errors.push('Failed to revoke refresh token'); 40 + } 41 + } 42 + 43 + return ok({ 44 + success: true, 45 + message: 46 + errors.length > 0 47 + ? `Logged out with warnings: ${errors.join(', ')}` 48 + : 'Logged out successfully', 49 + }); 50 + } catch (error: any) { 51 + console.warn('Logout use case error:', error); 52 + return ok({ 53 + success: true, 54 + message: 'Logged out (with warnings)', 55 + }); 56 + } 57 + } 58 + }
+30
src/modules/user/infrastructure/http/controllers/LogoutController.ts
··· 1 + import { Controller } from '../../../../../shared/infrastructure/http/Controller'; 2 + import { Request, Response } from 'express'; 3 + import { LogoutUseCase } from '../../../application/use-cases/LogoutUseCase'; 4 + 5 + export class LogoutController extends Controller { 6 + constructor(private logoutUseCase: LogoutUseCase) { 7 + super(); 8 + } 9 + 10 + async executeImpl(req: Request, res: Response): Promise<any> { 11 + try { 12 + const refreshToken = req.body?.refreshToken; 13 + 14 + const result = await this.logoutUseCase.execute({ 15 + refreshToken, 16 + }); 17 + 18 + if (result.isErr()) { 19 + return this.fail(res, result.error as any); 20 + } 21 + 22 + return this.ok(res, result.value); 23 + } catch (error: any) { 24 + return this.ok(res, { 25 + success: true, 26 + message: 'Logged out (client-side cleanup completed)', 27 + }); 28 + } 29 + } 30 + }
+3
src/modules/user/infrastructure/http/routes/userRoutes.ts
··· 5 5 import { RefreshAccessTokenController } from '../controllers/RefreshAccessTokenController'; 6 6 import { AuthMiddleware } from '../../../../../shared/infrastructure/http/middleware/AuthMiddleware'; 7 7 import { GetMyProfileController } from 'src/modules/cards/infrastructure/http/controllers/GetMyProfileController'; 8 + import { LogoutController } from '../controllers/LogoutController'; 8 9 import { GenerateExtensionTokensController } from '../controllers/GenerateExtensionTokensController'; 9 10 10 11 export const createUserRoutes = ( ··· 13 14 initiateOAuthSignInController: InitiateOAuthSignInController, 14 15 completeOAuthSignInController: CompleteOAuthSignInController, 15 16 loginWithAppPasswordController: LoginWithAppPasswordController, 17 + logoutController: LogoutController, 16 18 getMyProfileController: GetMyProfileController, 17 19 refreshAccessTokenController: RefreshAccessTokenController, 18 20 generateExtensionTokensController: GenerateExtensionTokensController, ··· 27 29 router.post('/login/app-password', (req, res) => 28 30 loginWithAppPasswordController.execute(req, res), 29 31 ); 32 + router.post('/logout', (req, res) => logoutController.execute(req, res)); 30 33 router.post('/oauth/refresh', (req, res) => 31 34 refreshAccessTokenController.execute(req, res), 32 35 );
+3
src/shared/infrastructure/http/factories/ControllerFactory.ts
··· 20 20 import { UseCases } from './UseCaseFactory'; 21 21 import { GetMyProfileController } from 'src/modules/cards/infrastructure/http/controllers/GetMyProfileController'; 22 22 import { LoginWithAppPasswordController } from 'src/modules/user/infrastructure/http/controllers/LoginWithAppPasswordController'; 23 + import { LogoutController } from 'src/modules/user/infrastructure/http/controllers/LogoutController'; 23 24 import { GenerateExtensionTokensController } from 'src/modules/user/infrastructure/http/controllers/GenerateExtensionTokensController'; 24 25 25 26 export interface Controllers { 26 27 // User controllers 27 28 loginWithAppPasswordController: LoginWithAppPasswordController; 29 + logoutController: LogoutController; 28 30 initiateOAuthSignInController: InitiateOAuthSignInController; 29 31 completeOAuthSignInController: CompleteOAuthSignInController; 30 32 getMyProfileController: GetMyProfileController; ··· 57 59 loginWithAppPasswordController: new LoginWithAppPasswordController( 58 60 useCases.loginWithAppPasswordUseCase, 59 61 ), 62 + logoutController: new LogoutController(useCases.logoutUseCase), 60 63 initiateOAuthSignInController: new InitiateOAuthSignInController( 61 64 useCases.initiateOAuthSignInUseCase, 62 65 ),
+3
src/shared/infrastructure/http/factories/UseCaseFactory.ts
··· 20 20 import { Services, SharedServices } from './ServiceFactory'; 21 21 import { GetMyProfileUseCase } from 'src/modules/cards/application/useCases/queries/GetMyProfileUseCase'; 22 22 import { LoginWithAppPasswordUseCase } from 'src/modules/user/application/use-cases/LoginWithAppPasswordUseCase'; 23 + import { LogoutUseCase } from 'src/modules/user/application/use-cases/LogoutUseCase'; 23 24 import { GenerateExtensionTokensUseCase } from 'src/modules/user/application/use-cases/GenerateExtensionTokensUseCase'; 24 25 import { GetGlobalFeedUseCase } from '../../../../modules/feeds/application/useCases/queries/GetGlobalFeedUseCase'; 25 26 import { AddActivityToFeedUseCase } from '../../../../modules/feeds/application/useCases/commands/AddActivityToFeedUseCase'; ··· 27 28 export interface UseCases { 28 29 // User use cases 29 30 loginWithAppPasswordUseCase: LoginWithAppPasswordUseCase; 31 + logoutUseCase: LogoutUseCase; 30 32 initiateOAuthSignInUseCase: InitiateOAuthSignInUseCase; 31 33 completeOAuthSignInUseCase: CompleteOAuthSignInUseCase; 32 34 getMyProfileUseCase: GetMyProfileUseCase; ··· 70 72 repositories.userRepository, 71 73 services.userAuthService, 72 74 ), 75 + logoutUseCase: new LogoutUseCase(services.tokenService), 73 76 initiateOAuthSignInUseCase: new InitiateOAuthSignInUseCase( 74 77 services.oauthProcessor, 75 78 ),