diff --git a/nestjs-BE/server/src/auth/auth.controller.ts b/nestjs-BE/server/src/auth/auth.controller.ts index d16f6de4..aad67c36 100644 --- a/nestjs-BE/server/src/auth/auth.controller.ts +++ b/nestjs-BE/server/src/auth/auth.controller.ts @@ -1,14 +1,5 @@ -import { - Controller, - Post, - Request, - UseGuards, - Get, - Body, - NotFoundException, -} from '@nestjs/common'; +import { Controller, Post, Body, NotFoundException } from '@nestjs/common'; import { AuthService } from './auth.service'; -import { JwtAuthGuard } from './jwt-auth.guard'; import { Public } from './public.decorator'; import { KakaoUserDto } from './dto/kakao-user.dto'; import { UsersService } from 'src/users/users.service'; @@ -80,10 +71,4 @@ export class AuthController { const refreshToken = refreshTokenDto.refresh_token; return this.authService.remove(refreshToken); } - - @UseGuards(JwtAuthGuard) - @Get('profile') - getProfile(@Request() req) { - return req.user; - } } diff --git a/nestjs-BE/server/src/auth/auth.service.ts b/nestjs-BE/server/src/auth/auth.service.ts index e63a518c..87e931fc 100644 --- a/nestjs-BE/server/src/auth/auth.service.ts +++ b/nestjs-BE/server/src/auth/auth.service.ts @@ -14,6 +14,7 @@ import { UsersService } from 'src/users/users.service'; import { ProfilesService } from 'src/profiles/profiles.service'; import { CreateUserDto } from 'src/users/dto/create-user.dto'; import customEnv from 'src/config/env'; +import { ResponseUtils } from 'src/utils/response'; const { BASE_IMAGE_URL } = customEnv; export interface TokenData { @@ -97,14 +98,11 @@ export class AuthService extends BaseService { userUuid, ); super.create(refreshTokenData); - return { - statusCode: HttpStatus.OK, - message: 'Success', - data: { - access_token: accessToken, - refresh_token: refreshToken, - }, + const tokenData = { + access_token: accessToken, + refresh_token: refreshToken, }; + return ResponseUtils.createResponse(HttpStatus.OK, tokenData); } async renewAccessToken(refreshToken: string) { @@ -112,14 +110,11 @@ export class AuthService extends BaseService { this.jwtService.verify(refreshToken, { secret: jwtConstants.refreshSecret, }); - const tokenData = await this.getDataFromCacheOrDB(refreshToken); - if (!tokenData) throw new Error('No token data found'); + const { data: tokenData } = await this.findOne(refreshToken); const accessToken = await this.createAccessToken(tokenData.user_id); - return { - statusCode: HttpStatus.OK, - message: 'Success', - data: { access_token: accessToken }, - }; + return ResponseUtils.createResponse(HttpStatus.OK, { + access_token: accessToken, + }); } catch (error) { super.remove(refreshToken); throw new UnauthorizedException( diff --git a/nestjs-BE/server/src/base/base.service.ts b/nestjs-BE/server/src/base/base.service.ts index 56aecfaf..b0aa14fa 100644 --- a/nestjs-BE/server/src/base/base.service.ts +++ b/nestjs-BE/server/src/base/base.service.ts @@ -6,6 +6,7 @@ import { import { TemporaryDatabaseService } from '../temporary-database/temporary-database.service'; import LRUCache from '../utils/lru-cache'; import generateUuid from '../utils/uuid'; +import { ResponseUtils } from 'src/utils/response'; interface BaseServiceOptions { prisma: PrismaServiceMySQL | PrismaServiceMongoDB; @@ -47,11 +48,7 @@ export abstract class BaseService { this.temporaryDatabaseService.create(this.className, key, data); this.cache.put(key, data); - return { - statusCode: HttpStatus.CREATED, - message: 'Created', - data, - }; + return ResponseUtils.createResponse(HttpStatus.CREATED, data); } async findOne(key: string) { @@ -67,11 +64,7 @@ export abstract class BaseService { if (data) { const mergedData = this.mergeWithUpdateCommand(data, key); this.cache.put(key, mergedData); - return { - statusCode: HttpStatus.OK, - message: 'Success', - data: mergedData, - }; + return ResponseUtils.createResponse(HttpStatus.OK, mergedData); } else { throw new HttpException('Not Found', HttpStatus.NOT_FOUND); } @@ -94,16 +87,9 @@ export abstract class BaseService { this.temporaryDatabaseService.update(this.className, key, updatedData); } this.cache.put(key, updatedData.value); - return { - statusCode: HttpStatus.OK, - message: 'Success', - data: updatedData.value, - }; + return ResponseUtils.createResponse(HttpStatus.OK, updatedData.value); } else { - return { - statusCode: HttpStatus.NOT_FOUND, - message: 'Not Found', - }; + return ResponseUtils.createResponse(HttpStatus.NOT_FOUND); } } @@ -132,13 +118,11 @@ export abstract class BaseService { value: key, }); } - return { - statusCode: HttpStatus.NO_CONTENT, - message: 'No Content', - }; + return ResponseUtils.createResponse(HttpStatus.NO_CONTENT); } async getDataFromCacheOrDB(key: string): Promise { + if (!key) throw new HttpException('Bad Request', HttpStatus.BAD_REQUEST); const cacheData = this.cache.get(key); if (cacheData) return cacheData; const temporaryDatabaseData = this.temporaryDatabaseService.get( diff --git a/nestjs-BE/server/src/invite-codes/invite-codes.service.ts b/nestjs-BE/server/src/invite-codes/invite-codes.service.ts index b2580229..8c8f54e7 100644 --- a/nestjs-BE/server/src/invite-codes/invite-codes.service.ts +++ b/nestjs-BE/server/src/invite-codes/invite-codes.service.ts @@ -9,6 +9,7 @@ import { INVITE_CODE_LENGTH, } from 'src/config/magic-number'; import { SpacesService } from 'src/spaces/spaces.service'; +import { ResponseUtils } from 'src/utils/response'; export interface InviteCodeData extends CreateInviteCodeDto { uuid?: string; @@ -37,47 +38,58 @@ export class InviteCodesService extends BaseService { } async createCode(createInviteCodeDto: CreateInviteCodeDto) { - const inviteCode = await this.generateUniqueInviteCode(INVITE_CODE_LENGTH); - const currentDate = new Date(); - const expiryDate = new Date(currentDate); - expiryDate.setHours(currentDate.getHours() + INVITE_CODE_EXPIRY_HOURS); - const data: InviteCodeData = { - ...createInviteCodeDto, - invite_code: inviteCode, - expiry_date: expiryDate, - }; const { space_uuid: spaceUuid } = createInviteCodeDto; - const space = await this.spacesService.getDataFromCacheOrDB(spaceUuid); - if (!space) throw new HttpException('Not Found', HttpStatus.NOT_FOUND); - super.create(data); + await this.spacesService.findOne(spaceUuid); + const inviteCodeData = await this.generateInviteCode(createInviteCodeDto); + super.create(inviteCodeData); + const { invite_code } = inviteCodeData; + return ResponseUtils.createResponse(HttpStatus.CREATED, { invite_code }); + } + + async findSpace(inviteCode: string) { + const inviteCodeData = await this.getInviteCodeData(inviteCode); + this.checkExpiry(inviteCode, inviteCodeData.expiry_date); + const spaceResponse = await this.spacesService.findOne( + inviteCodeData.space_uuid, + ); + return spaceResponse; + } + + private async generateInviteCode(createInviteCodeDto: CreateInviteCodeDto) { + const uniqueInviteCode = + await this.generateUniqueInviteCode(INVITE_CODE_LENGTH); + const expiryDate = this.calculateExpiryDate(); + return { - statusCode: HttpStatus.CREATED, - message: 'Created', - data: { invite_code: inviteCode }, + ...createInviteCodeDto, + invite_code: uniqueInviteCode, + expiry_date: expiryDate, }; } - async findSpace(inviteCode: string) { - const inviteCodeData = await super.getDataFromCacheOrDB(inviteCode); - if (!inviteCodeData) { - throw new HttpException('Invalid invite code.', HttpStatus.NOT_FOUND); - } + private calculateExpiryDate(): Date { + const currentDate = new Date(); + const expiryDate = new Date(currentDate); + expiryDate.setHours(currentDate.getHours() + INVITE_CODE_EXPIRY_HOURS); + return expiryDate; + } + + private async getInviteCodeData(inviteCode: string) { + const inviteCodeResponse = await super.findOne(inviteCode); + const { data: inviteCodeData } = inviteCodeResponse; + return inviteCodeData; + } + + private checkExpiry(inviteCode: string, expiryDate: Date) { const currentTimestamp = new Date().getTime(); - const expiryTimestamp = new Date(inviteCodeData.expiry_date).getTime(); + const expiryTimestamp = new Date(expiryDate).getTime(); if (expiryTimestamp < currentTimestamp) { super.remove(inviteCode); throw new HttpException('Invite code has expired.', HttpStatus.GONE); } - const spaceUuid = inviteCodeData.space_uuid; - const spaceData = await this.spacesService.getDataFromCacheOrDB(spaceUuid); - return { - statusCode: HttpStatus.OK, - message: 'Success', - data: spaceData, - }; } - generateShortInviteCode(length: number) { + private generateShortInviteCode(length: number) { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let inviteCode = ''; @@ -89,7 +101,7 @@ export class InviteCodesService extends BaseService { return inviteCode; } - async generateUniqueInviteCode(length: number): Promise { + private async generateUniqueInviteCode(length: number): Promise { let inviteCode: string; let inviteCodeData: InviteCodeData; diff --git a/nestjs-BE/server/src/profile-space/profile-space.controller.ts b/nestjs-BE/server/src/profile-space/profile-space.controller.ts index 54263551..e10e3642 100644 --- a/nestjs-BE/server/src/profile-space/profile-space.controller.ts +++ b/nestjs-BE/server/src/profile-space/profile-space.controller.ts @@ -80,7 +80,7 @@ export class ProfileSpaceController { }) getSpaces(@Req() req: RequestWithUser) { const userUuid = req.user.uuid; - return this.profileSpaceService.getSpaces(userUuid); + return this.profileSpaceService.retrieveUserSpaces(userUuid); } @Get('users/:space_uuid') @@ -94,6 +94,6 @@ export class ProfileSpaceController { description: 'Space not found.', }) getUsers(@Param('space_uuid') spaceUuid: string) { - return this.profileSpaceService.getUsers(spaceUuid); + return this.profileSpaceService.retrieveSpaceUsers(spaceUuid); } } diff --git a/nestjs-BE/server/src/profile-space/profile-space.service.ts b/nestjs-BE/server/src/profile-space/profile-space.service.ts index 93534f68..a451a220 100644 --- a/nestjs-BE/server/src/profile-space/profile-space.service.ts +++ b/nestjs-BE/server/src/profile-space/profile-space.service.ts @@ -13,6 +13,7 @@ import { ProfilesService } from 'src/profiles/profiles.service'; import { UpdateProfileDto } from 'src/profiles/dto/update-profile.dto'; import { UpdateSpaceDto } from 'src/spaces/dto/update-space.dto'; import LRUCache from 'src/utils/lru-cache'; +import { ResponseUtils } from 'src/utils/response'; interface UpdateProfileAndSpaceDto { profileData: UpdateProfileDto; @@ -64,10 +65,13 @@ export class ProfileSpaceService extends BaseService { data: UpdateProfileAndSpaceDto, ) { const { spaceData, profileData } = data; - const userSpaces = await this.getUserSpaces(userUuid, profileData.uuid); + const userSpaces = await this.fetchUserSpacesFromCacheOrDB( + userUuid, + profileData.uuid, + ); userSpaces.push(spaceData); this.userCache.put(userUuid, userSpaces); - const spaceProfiles = await this.getSpaceUsers(spaceUuid); + const spaceProfiles = await this.fetchSpaceUsersFromCacheOrDB(spaceUuid); spaceProfiles.push(profileData); this.spaceCache.put(spaceUuid, spaceProfiles); } @@ -77,20 +81,23 @@ export class ProfileSpaceService extends BaseService { spaceUuid: string, profileData: UpdateProfileDto, ) { - const userSpaces = await this.getUserSpaces(userUuid, profileData.uuid); + const userSpaces = await this.fetchUserSpacesFromCacheOrDB( + userUuid, + profileData.uuid, + ); const filterUserSpaces = userSpaces.filter( (space) => space.uuid !== spaceUuid, ); this.userCache.put(userUuid, filterUserSpaces); - const spaceUsers = await this.getSpaceUsers(spaceUuid); + const spaceUsers = await this.fetchSpaceUsersFromCacheOrDB(spaceUuid); const filterSpaceUsers = spaceUsers.filter( (profile) => profile.uuid !== profileData.uuid, ); - this.userCache.put(spaceUuid, filterSpaceUsers); + this.spaceCache.put(spaceUuid, filterSpaceUsers); return filterSpaceUsers.length === 0; } - async getUserSpaces( + async fetchUserSpacesFromCacheOrDB( userUuid: string, profileUuid: string, ): Promise { @@ -111,7 +118,9 @@ export class ProfileSpaceService extends BaseService { return storeUserSpaces; } - async getSpaceUsers(spaceUuid: string): Promise { + async fetchSpaceUsersFromCacheOrDB( + spaceUuid: string, + ): Promise { const cacheSpaceProfiles = this.spaceCache.get(spaceUuid); if (cacheSpaceProfiles) return cacheSpaceProfiles; @@ -131,30 +140,25 @@ export class ProfileSpaceService extends BaseService { return storeSpaceProfiles; } - async getSpaces(userUuid: string) { + async retrieveUserSpaces(userUuid: string) { const profileResponse = await this.profilesService.findOne(userUuid); const profileUuid = profileResponse.data?.uuid; - const spaces = await this.getUserSpaces(userUuid, profileUuid); + const spaces = await this.fetchUserSpacesFromCacheOrDB( + userUuid, + profileUuid, + ); this.userCache.put(userUuid, spaces); - return { - statusCode: HttpStatus.OK, - message: 'Success', - data: spaces, - }; + return ResponseUtils.createResponse(HttpStatus.OK, spaces); } - async getUsers(spaceUuid: string) { - const users = await this.getSpaceUsers(spaceUuid); + async retrieveSpaceUsers(spaceUuid: string) { + const users = await this.fetchSpaceUsersFromCacheOrDB(spaceUuid); const usersData = await Promise.all( users.map(async (user) => { return await this.profilesService.findOne(user.user_id); }), ); this.spaceCache.put(spaceUuid, usersData); - return { - statusCode: HttpStatus.OK, - message: 'Success', - data: usersData, - }; + return ResponseUtils.createResponse(HttpStatus.OK, usersData); } } diff --git a/nestjs-BE/server/src/temporary-database/temporary-database.service.ts b/nestjs-BE/server/src/temporary-database/temporary-database.service.ts index de993400..4330e949 100644 --- a/nestjs-BE/server/src/temporary-database/temporary-database.service.ts +++ b/nestjs-BE/server/src/temporary-database/temporary-database.service.ts @@ -20,7 +20,7 @@ type DeleteDataType = { value: string; }; -type InsertDataType = +export type InsertDataType = | TokenData | InviteCodeData | CreateProfileSpaceDto @@ -136,6 +136,7 @@ export class TemporaryDatabaseService { operation({ service, uniqueKey, command, data }: OperationData) { const filePath = join(this.FOLDER_NAME, `${service}-${command}.csv`); fs.appendFile(filePath, `${uniqueKey},${JSON.stringify(data)}\n`, 'utf8'); + this.database.get(service).get(command).set(uniqueKey, data); } @Cron('0 */10 * * * *') diff --git a/nestjs-BE/server/src/utils/response.ts b/nestjs-BE/server/src/utils/response.ts new file mode 100644 index 00000000..a3c01ef4 --- /dev/null +++ b/nestjs-BE/server/src/utils/response.ts @@ -0,0 +1,34 @@ +import { HttpStatus } from '@nestjs/common'; +import { InsertDataType } from 'src/temporary-database/temporary-database.service'; +type TokenDataType = { + access_token: string; + refresh_token?: string; +}; +type InviteDataType = { + invite_code: string; +}; + +type ExtendedDataType = + | InsertDataType + | TokenDataType + | InviteDataType + | InsertDataType[]; + +export class ResponseUtils { + private static messages = new Map([ + [HttpStatus.OK, 'Success'], + [HttpStatus.CREATED, 'Created'], + [HttpStatus.NOT_FOUND, 'Not Found'], + [HttpStatus.NO_CONTENT, 'No Content'], + ]); + + static createResponse(status: HttpStatus, data?: ExtendedDataType) { + const response: any = { + statusCode: status, + message: this.messages.get(status), + }; + if (data) response.data = data; + + return response; + } +}