From 1e7d27fca594436a17473aecd70571f7964a5dec Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Wed, 15 May 2024 17:29:09 +0530 Subject: [PATCH 1/2] Task:PS-372 User: Delete user API- delete user from keycloak,user & related tables --- src/adapters/hasura/user.adapter.ts | 3 ++ src/adapters/postgres/user-adapter.ts | 60 +++++++++++++++++++++++++++ src/adapters/userservicelocator.ts | 2 + src/user/user.controller.ts | 24 +++++++++++ 4 files changed, 89 insertions(+) diff --git a/src/adapters/hasura/user.adapter.ts b/src/adapters/hasura/user.adapter.ts index 63f17a0e..ace77332 100644 --- a/src/adapters/hasura/user.adapter.ts +++ b/src/adapters/hasura/user.adapter.ts @@ -941,4 +941,7 @@ export class HasuraUserService implements IServicelocator { return e; } } + + public async deleteUserById(userId){} + } \ No newline at end of file diff --git a/src/adapters/postgres/user-adapter.ts b/src/adapters/postgres/user-adapter.ts index b4130911..f8a56061 100644 --- a/src/adapters/postgres/user-adapter.ts +++ b/src/adapters/postgres/user-adapter.ts @@ -775,6 +775,66 @@ export class PostgresUserService { }; } + public async deleteUserById(userId){ + const { KEYCLOAK, KEYCLOAK_ADMIN } = process.env; + // Validate userId format + if (!isUUID(userId)) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.BAD_REQUEST, + errorMessage: "Please enter a valid UUID for userId", + }); + } + + try { + // Check if user exists in usersRepository + const user = await this.usersRepository.findOne({ where :{userId:userId}}); + if (!user) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.NOT_FOUND, + errorMessage: "User not found in user table.", + }); + } + + + // Delete from User table + const userResult = await this.usersRepository.delete(userId); + + // Delete from CohortMembers table + const cohortMembersResult = await this.cohortMemberRepository.delete({ userId: userId }); + + // Delete from UserTenantMapping table + const userTenantMappingResult = await this.userTenantMappingRepository.delete({ userId: userId }); + + // Delete from UserRoleMapping table + const userRoleMappingResult = await this.userRoleMappingRepository.delete({ userId: userId }); + + // Delete from FieldValues table where ItemId matches userId + const fieldValuesResult = await this.fieldsValueRepository.delete({ itemId: userId }); + + const keycloakResponse = await getKeycloakAdminToken(); + const token = keycloakResponse.data.access_token; + + await this.axios.delete(`${KEYCLOAK}${KEYCLOAK_ADMIN}/${userId}`, { + headers: { + 'Authorization': `Bearer ${token}` + }}); + + + return new SuccessResponse({ + statusCode: HttpStatus.OK, + message: "User and related entries deleted Successfully.", + data: { + user: userResult + }, + }); + } catch (e) { + return new ErrorResponseTypeOrm({ + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + errorMessage: e, + }); + } + } + } diff --git a/src/adapters/userservicelocator.ts b/src/adapters/userservicelocator.ts index 3832723a..d25066da 100644 --- a/src/adapters/userservicelocator.ts +++ b/src/adapters/userservicelocator.ts @@ -23,4 +23,6 @@ export interface IServicelocator { userSearchDto: UserSearchDto ); resetUserPassword(request: any, username: string, newPassword: string); + deleteUserById(userId); + } diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 3d1acf11..714c6612 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -14,6 +14,7 @@ import { UsePipes, ValidationPipe, HttpStatus, + Delete, } from "@nestjs/common"; import { Request } from "@nestjs/common"; @@ -161,4 +162,27 @@ export class UserController { .buildUserAdapter() .resetUserPassword(request, reqBody.username, reqBody.newPassword); } + + //delete + @Delete("/:userId") + + @ApiBasicAuth("access-token") + @ApiCreatedResponse({ description: "User deleted successfully" }) + @ApiNotFoundResponse({ description: "Data not found" }) + @SerializeOptions({ + strategy: "excludeAll", + }) + + public async deleteUserById( + @Headers() headers, + @Param("userId") userId: string, + @Req() request: Request, + @Res() response: Response + ) { + + const result = await this.userAdapter + .buildUserAdapter() + .deleteUserById(userId); + return response.status(result.statusCode).json(result); + } } From 08a2b5c08217b54f61c3be60899edbf0413bf3e2 Mon Sep 17 00:00:00 2001 From: apurvaubade Date: Wed, 15 May 2024 17:52:22 +0530 Subject: [PATCH 2/2] Resolve all comments --- src/adapters/userservicelocator.ts | 2 +- src/user/user.controller.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adapters/userservicelocator.ts b/src/adapters/userservicelocator.ts index d25066da..b91584ed 100644 --- a/src/adapters/userservicelocator.ts +++ b/src/adapters/userservicelocator.ts @@ -23,6 +23,6 @@ export interface IServicelocator { userSearchDto: UserSearchDto ); resetUserPassword(request: any, username: string, newPassword: string); - deleteUserById(userId); + deleteUserById(userId: string): Promise; } diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 714c6612..d2806b4f 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -167,7 +167,7 @@ export class UserController { @Delete("/:userId") @ApiBasicAuth("access-token") - @ApiCreatedResponse({ description: "User deleted successfully" }) + @ApiOkResponse({ description: "User deleted successfully" }) @ApiNotFoundResponse({ description: "Data not found" }) @SerializeOptions({ strategy: "excludeAll",