diff --git a/packages/hoppscotch-backend/src/errors.ts b/packages/hoppscotch-backend/src/errors.ts index 2b48e1cea..208a80464 100644 --- a/packages/hoppscotch-backend/src/errors.ts +++ b/packages/hoppscotch-backend/src/errors.ts @@ -84,6 +84,12 @@ export const USER_ALREADY_INVITED = 'admin/user_already_invited' as const; */ export const USER_UPDATE_FAILED = 'user/update_failed' as const; +/** + * User display name validation failure + * (UserService) + */ +export const USER_SHORT_DISPLAY_NAME = 'user/short_display_name' as const; + /** * User deletion failure * (UserService) diff --git a/packages/hoppscotch-backend/src/user/user.resolver.ts b/packages/hoppscotch-backend/src/user/user.resolver.ts index 080592c81..da83e8625 100644 --- a/packages/hoppscotch-backend/src/user/user.resolver.ts +++ b/packages/hoppscotch-backend/src/user/user.resolver.ts @@ -58,6 +58,29 @@ export class UserResolver { if (E.isLeft(updatedUser)) throwErr(updatedUser.left); return updatedUser.right; } + + @Mutation(() => User, { + description: 'Update a users display name', + }) + @UseGuards(GqlAuthGuard) + async updateDisplayName( + @GqlUser() user: AuthUser, + @Args({ + name: 'updatedDisplayName', + description: 'New name of user', + type: () => String, + }) + updatedDisplayName: string, + ) { + const updatedUser = await this.userService.updateUserDisplayName( + user.uid, + updatedDisplayName, + ); + + if (E.isLeft(updatedUser)) throwErr(updatedUser.left); + return updatedUser.right; + } + @Mutation(() => Boolean, { description: 'Delete an user account', }) diff --git a/packages/hoppscotch-backend/src/user/user.service.spec.ts b/packages/hoppscotch-backend/src/user/user.service.spec.ts index 21e2736bc..b5093831c 100644 --- a/packages/hoppscotch-backend/src/user/user.service.spec.ts +++ b/packages/hoppscotch-backend/src/user/user.service.spec.ts @@ -1,4 +1,9 @@ -import { JSON_INVALID, USERS_NOT_FOUND, USER_NOT_FOUND } from 'src/errors'; +import { + JSON_INVALID, + USERS_NOT_FOUND, + USER_NOT_FOUND, + USER_SHORT_DISPLAY_NAME, +} from 'src/errors'; import { mockDeep, mockReset } from 'jest-mock-extended'; import { PrismaService } from 'src/prisma/prisma.service'; import { AuthUser } from 'src/types/AuthUser'; @@ -480,6 +485,14 @@ describe('UserService', () => { ); expect(result).toEqualLeft(USER_NOT_FOUND); }); + test('should resolve left and error when short display name is passed', async () => { + const newDisplayName = ''; + const result = await userService.updateUserDisplayName( + user.uid, + newDisplayName, + ); + expect(result).toEqualLeft(USER_SHORT_DISPLAY_NAME); + }); }); describe('fetchAllUsers', () => { diff --git a/packages/hoppscotch-backend/src/user/user.service.ts b/packages/hoppscotch-backend/src/user/user.service.ts index 59d17a089..26018894b 100644 --- a/packages/hoppscotch-backend/src/user/user.service.ts +++ b/packages/hoppscotch-backend/src/user/user.service.ts @@ -8,7 +8,11 @@ import * as T from 'fp-ts/Task'; import * as A from 'fp-ts/Array'; import { pipe, constVoid } from 'fp-ts/function'; import { AuthUser } from 'src/types/AuthUser'; -import { USERS_NOT_FOUND, USER_NOT_FOUND } from 'src/errors'; +import { + USERS_NOT_FOUND, + USER_NOT_FOUND, + USER_SHORT_DISPLAY_NAME, +} from 'src/errors'; import { SessionType, User } from './user.model'; import { USER_UPDATE_FAILED } from 'src/errors'; import { PubSubService } from 'src/pubsub/pubsub.service'; @@ -291,6 +295,10 @@ export class UserService { * @returns a Either of User or error */ async updateUserDisplayName(userUID: string, displayName: string) { + if (!displayName || displayName.length === 0) { + return E.left(USER_SHORT_DISPLAY_NAME); + } + try { const dbUpdatedUser = await this.prisma.user.update({ where: { uid: userUID },