From 6bbd935477fd867120dc8909cd90720617fd986a Mon Sep 17 00:00:00 2001 From: donghquinn Date: Thu, 14 Mar 2024 15:49:29 +0900 Subject: [PATCH 1/8] wip: error combining --- src/errors/geek.error.ts | 13 ------ src/errors/hacker.error.ts | 13 ------ src/errors/machine.error.ts | 13 ------ src/errors/news.error.ts | 41 +++++++++++++++++++ src/providers/news/geek/geek-prisma.lib.ts | 2 +- src/providers/news/geek/geek.pvd.ts | 2 +- .../news/hacker/hacker-prisma.lib.ts | 2 +- src/providers/news/hacker/hacker.pvd.ts | 2 +- src/providers/news/ml/machine.pvd.ts | 2 +- src/providers/news/ml/ml-prisma.lib.ts | 2 +- 10 files changed, 47 insertions(+), 45 deletions(-) delete mode 100755 src/errors/geek.error.ts delete mode 100755 src/errors/hacker.error.ts delete mode 100644 src/errors/machine.error.ts create mode 100644 src/errors/news.error.ts diff --git a/src/errors/geek.error.ts b/src/errors/geek.error.ts deleted file mode 100755 index 8890601..0000000 --- a/src/errors/geek.error.ts +++ /dev/null @@ -1,13 +0,0 @@ -export class GeekError extends Error { - type: string; - - constructor(type: string, message: string, cause?: Error) { - super(message); - - this.type = type; - - this.name = '[Geek Error]'; - - this.cause = cause; - } -} diff --git a/src/errors/hacker.error.ts b/src/errors/hacker.error.ts deleted file mode 100755 index 9d7bf8b..0000000 --- a/src/errors/hacker.error.ts +++ /dev/null @@ -1,13 +0,0 @@ -export class HackerError extends Error { - type: string; - - constructor(type: string, message: string, cause?: Error) { - super(message); - - this.type = type; - - this.name = '[Hacker News Error]'; - - this.cause = cause; - } -} diff --git a/src/errors/machine.error.ts b/src/errors/machine.error.ts deleted file mode 100644 index 9e383aa..0000000 --- a/src/errors/machine.error.ts +++ /dev/null @@ -1,13 +0,0 @@ -export class MachineLearningError extends Error { - type: string; - - constructor(type: string, message: string, cause?: Error) { - super(message); - - this.type = type; - - this.name = '[Machine Learning Error]'; - - this.cause = cause; - } -} diff --git a/src/errors/news.error.ts b/src/errors/news.error.ts new file mode 100644 index 0000000..6ad1ab1 --- /dev/null +++ b/src/errors/news.error.ts @@ -0,0 +1,41 @@ +export class GeekError extends Error { + type: string; + + constructor(type: string, message: string, cause?: Error) { + super(message); + + this.type = type; + + this.name = '[Geek Error]'; + + this.cause = cause; + } +} + +export class HackerError extends Error { + type: string; + + constructor(type: string, message: string, cause?: Error) { + super(message); + + this.type = type; + + this.name = '[Hacker News Error]'; + + this.cause = cause; + } +} + +export class MachineLearningError extends Error { + type: string; + + constructor(type: string, message: string, cause?: Error) { + super(message); + + this.type = type; + + this.name = '[Machine Learning Error]'; + + this.cause = cause; + } +} diff --git a/src/providers/news/geek/geek-prisma.lib.ts b/src/providers/news/geek/geek-prisma.lib.ts index 4f2bdeb..b42b158 100644 --- a/src/providers/news/geek/geek-prisma.lib.ts +++ b/src/providers/news/geek/geek-prisma.lib.ts @@ -1,4 +1,4 @@ -import { GeekError } from '@errors/geek.error'; +import { GeekError } from '@errors/news.error'; import { Injectable } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; import { NewsLogger } from '@utils/logger.util'; diff --git a/src/providers/news/geek/geek.pvd.ts b/src/providers/news/geek/geek.pvd.ts index 2c5ddfb..765c6e6 100644 --- a/src/providers/news/geek/geek.pvd.ts +++ b/src/providers/news/geek/geek.pvd.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable no-underscore-dangle */ -import { GeekError } from '@errors/geek.error'; +import { GeekError } from '@errors/news.error'; import { Injectable } from '@nestjs/common'; import { NewsLogger } from '@utils/logger.util'; import { endOfDay, startOfDay } from 'date-fns'; diff --git a/src/providers/news/hacker/hacker-prisma.lib.ts b/src/providers/news/hacker/hacker-prisma.lib.ts index 4cb86c1..6270122 100644 --- a/src/providers/news/hacker/hacker-prisma.lib.ts +++ b/src/providers/news/hacker/hacker-prisma.lib.ts @@ -1,4 +1,4 @@ -import { HackerError } from '@errors/hacker.error'; +import { HackerError } from '@errors/news.error'; import { Injectable } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; import { NewsLogger } from '@utils/logger.util'; diff --git a/src/providers/news/hacker/hacker.pvd.ts b/src/providers/news/hacker/hacker.pvd.ts index 10bde96..a949139 100755 --- a/src/providers/news/hacker/hacker.pvd.ts +++ b/src/providers/news/hacker/hacker.pvd.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { HackerError } from '@errors/hacker.error'; +import { HackerError } from '@errors/news.error'; import { Injectable } from '@nestjs/common'; import { NewsLogger } from '@utils/logger.util'; import { endOfDay, startOfDay } from 'date-fns'; diff --git a/src/providers/news/ml/machine.pvd.ts b/src/providers/news/ml/machine.pvd.ts index fc99a0c..8313f7e 100644 --- a/src/providers/news/ml/machine.pvd.ts +++ b/src/providers/news/ml/machine.pvd.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { MachineLearningError } from '@errors/machine.error'; +import { MachineLearningError } from '@errors/news.error'; import { Injectable } from '@nestjs/common'; import { NewsLogger } from '@utils/logger.util'; import { endOfDay, startOfDay } from 'date-fns'; diff --git a/src/providers/news/ml/ml-prisma.lib.ts b/src/providers/news/ml/ml-prisma.lib.ts index 763e0d3..132f57f 100644 --- a/src/providers/news/ml/ml-prisma.lib.ts +++ b/src/providers/news/ml/ml-prisma.lib.ts @@ -1,4 +1,4 @@ -import { MachineLearningError } from '@errors/machine.error'; +import { MachineLearningError } from '@errors/news.error'; import { PrismaError } from '@errors/prisma.error'; import { Injectable } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; From c66f60e4e243f7e354c676099a10e934dadf846c Mon Sep 17 00:00:00 2001 From: donghquinn Date: Thu, 14 Mar 2024 15:50:51 +0900 Subject: [PATCH 2/8] wip: dto --- src/dto/response.dto.ts | 10 ++-------- src/errors/auth.error.ts | 13 ------------- 2 files changed, 2 insertions(+), 21 deletions(-) delete mode 100644 src/errors/auth.error.ts diff --git a/src/dto/response.dto.ts b/src/dto/response.dto.ts index 3af71ef..1a725be 100755 --- a/src/dto/response.dto.ts +++ b/src/dto/response.dto.ts @@ -1,8 +1,5 @@ -import { AuthError } from '@errors/auth.error'; import { ClientError } from '@errors/client.error'; -import { GeekError } from '@errors/geek.error'; -import { HackerError } from '@errors/hacker.error'; -import { MachineLearningError } from '@errors/machine.error'; +import { GeekError, HackerError, MachineLearningError } from '@errors/news.error'; import { PrismaError } from '@errors/prisma.error'; import { ValidatorError } from '@errors/validator.error'; @@ -36,10 +33,7 @@ export class SetErrorResponse implements ResponseObject { constructor(error: unknown) { const errorArray = []; - if (error instanceof AuthError) { - this.resCode = '401'; - errorArray.push(error.type, error.message); - } else if (error instanceof ClientError) { + if (error instanceof ClientError) { this.resCode = '402'; errorArray.push(error.type, error.message); } else if (error instanceof HackerError) { diff --git a/src/errors/auth.error.ts b/src/errors/auth.error.ts deleted file mode 100644 index c6b8a27..0000000 --- a/src/errors/auth.error.ts +++ /dev/null @@ -1,13 +0,0 @@ -export class AuthError extends Error { - type: string; - - constructor(type: string, message: string, cause?: Error) { - super(message); - - this.type = type; - - this.name = '[Auth ERROR]'; - - this.cause = cause; - } -} From b3e177485f98d0fde24092755143d860b27f5047 Mon Sep 17 00:00:00 2001 From: donghquinn Date: Thu, 14 Mar 2024 15:51:24 +0900 Subject: [PATCH 3/8] wip --- src/middlewares/header.middleware.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/middlewares/header.middleware.ts b/src/middlewares/header.middleware.ts index 6bc0654..b599366 100755 --- a/src/middlewares/header.middleware.ts +++ b/src/middlewares/header.middleware.ts @@ -14,7 +14,5 @@ export const globalMiddleware = (request: Request, res: Response, next: NextFunc Logger.debug('Auth Key Detected'); next(); - } else { - throw new HttpException('Authorize Key Not Match', HttpStatus.BAD_REQUEST); - } + } else throw new HttpException('Authorize Key Not Match', HttpStatus.BAD_REQUEST); }; From d2c536cccfdd9d4ff38fd91a4daf8f4256bacc7b Mon Sep 17 00:00:00 2001 From: donghquinn Date: Thu, 14 Mar 2024 15:53:02 +0900 Subject: [PATCH 4/8] wip: return data variablized --- src/providers/crypto.pvd.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/providers/crypto.pvd.ts b/src/providers/crypto.pvd.ts index 45737c7..1e5a179 100644 --- a/src/providers/crypto.pvd.ts +++ b/src/providers/crypto.pvd.ts @@ -89,7 +89,12 @@ export class CryptoProvider { const encryptedString = Buffer.concat([encrypted, cipher.final()]).toString('hex'); - return { encodedToken: iv.toString('hex'), encodedData: encryptedString }; + const returnData = { + encodedToken: iv.toString('hex'), + encodedData: encryptedString, + }; + + return returnData; } /** From 297789f173d499dcf5f396cfe586080fdc2395fa Mon Sep 17 00:00:00 2001 From: donghquinn Date: Thu, 14 Mar 2024 16:07:27 +0900 Subject: [PATCH 5/8] wip: error wrapping fixing --- src/providers/account-manager.pvd.ts | 10 +- src/providers/client/client.pvd.ts | 236 +++++++++++---------------- src/providers/client/search.pvd.ts | 2 +- src/providers/crypto.pvd.ts | 87 +++++++--- src/providers/news/geek/geek.pvd.ts | 130 ++++++--------- src/providers/news/ml/machine.pvd.ts | 2 +- 6 files changed, 210 insertions(+), 257 deletions(-) diff --git a/src/providers/account-manager.pvd.ts b/src/providers/account-manager.pvd.ts index df1f414..41e5dcc 100644 --- a/src/providers/account-manager.pvd.ts +++ b/src/providers/account-manager.pvd.ts @@ -46,7 +46,7 @@ export class AccountManager { * REDIS 에 등록된 회원 정보(로그인 상태 정보) 삭제 * @param encodedEmail 암호화된 유저 이메일(REDIS 키) */ - public async deleteItem(encodedEmail: string) { + public async deleteItem(encodedEmail: string): Promise { try { const index = this.keyList.findIndex((item) => item === encodedEmail); @@ -56,7 +56,11 @@ export class AccountManager { await this.redis.del(encodedEmail); await this.redis.disconnect(); ManagerLogger.info('[DELETE] Deleted User Info from Key List and Cache Data'); + + return true; } + + return false; } catch (error) { ManagerLogger.error('[DELETE] Delete User Item Error: %o', { error, @@ -134,7 +138,7 @@ export class AccountManager { userKey: this.keyList, }); - if (key === undefined) return null; + if (key === undefined) return false; ManagerLogger.info('[GET] Found key from keyList'); @@ -142,7 +146,7 @@ export class AccountManager { const gotItem = await this.redis.get(key); await this.redis.disconnect(); - if (gotItem === null) return null; + if (gotItem === null) return false; const returnData = JSON.parse(gotItem) as ClientLoginItem; diff --git a/src/providers/client/client.pvd.ts b/src/providers/client/client.pvd.ts index 0205e61..efabe7a 100644 --- a/src/providers/client/client.pvd.ts +++ b/src/providers/client/client.pvd.ts @@ -46,207 +46,159 @@ export class ClientProvider { } async login(email: string, password: string) { - try { - const userInfo = await this.prisma.selectUserInfo(email); + const userInfo = await this.prisma.selectUserInfo(email); - if (userInfo === null) { - ClientLogger.debug('[LOGIN] No Matching User Found: %o', { - email, - }); + if (userInfo === null) { + ClientLogger.debug('[LOGIN] No Matching User Found: %o', { + email, + }); - throw new ClientError('[LOGIN] Finding Matching User Info', 'No Matching User Found'); - } + throw new ClientError('[LOGIN] Finding Matching User Info', 'No Matching User Found'); + } - const { password: foundPassword, password_token: passwordToken, uuid } = userInfo; + const { password: foundPassword, password_token: passwordToken, uuid } = userInfo; - const isMatch = this.crypto.comparePassword(password, foundPassword, passwordToken); + const isMatch = this.crypto.comparePassword(password, foundPassword, passwordToken); - if (!isMatch) { - ClientLogger.error('[LOGIN] Password Matching Given Password is Not Match. Reject.'); + if (!isMatch) { + ClientLogger.error('[LOGIN] Password Matching Given Password is Not Match. Reject.'); - throw new ClientError('[LOGIN] Password Matching ', ' Password Matching is Not Match. Reject.'); - } + throw new ClientError('[LOGIN] Password Matching ', ' Password Matching is Not Match. Reject.'); + } - // Set User Info into REDIS - const { encodedData: encodedEmail, encodedToken: encodedEmailToken } = this.crypto.cryptData(email); + // Set User Info into REDIS + const { encodedData: encodedEmail, encodedToken: encodedEmailToken } = this.crypto.cryptData(email); - ClientLogger.debug('[ACCOUNT] Searching User Info: %o', { - encodedEmail, - }); - - const isLogined = await this.accountManager.getItem(encodedEmail); + ClientLogger.debug('[ACCOUNT] Searching User Info: %o', { + encodedEmail, + }); - if (isLogined === null) { - await this.accountManager.setItem(encodedEmail, encodedEmailToken, uuid, foundPassword); + const isLogined = await this.accountManager.getItem(encodedEmail); - ClientLogger.info('[ACCOUNT] Set Finished'); + if (isLogined === null) { + await this.accountManager.setItem(encodedEmail, encodedEmailToken, uuid, foundPassword); - return encodedEmail; - } + ClientLogger.info('[ACCOUNT] Set Finished'); - ClientLogger.debug('[ACCOUNT] Found User Key: %o', { - uuid, - }); + return encodedEmail; + } - const interval = 1000 * 60 * 60; + ClientLogger.debug('[ACCOUNT] Found User Key: %o', { + uuid, + }); - const timer = setIntervalAsync(async () => { - const isExsit = await this.accountManager.getItem(encodedEmail); + const interval = 1000 * 60 * 60; - if (isExsit === null) { - ClientLogger.info('[ACCOUNT] It is not existing user. Clear Interval.'); + const timer = setIntervalAsync(async () => { + const isExsit = await this.accountManager.getItem(encodedEmail); - ClientLogger.debug('[ACCOUNT] Client Map Inspection: %o', { - isExsit, - uuid, - }); + if (isExsit === null) { + ClientLogger.info('[ACCOUNT] It is not existing user. Clear Interval.'); - clearIntervalAsync(timer); - } else { - ClientLogger.info('[ACCOUNT] Expiration time. Delete user.'); + ClientLogger.debug('[ACCOUNT] Client Map Inspection: %o', { + isExsit, + uuid, + }); - ClientLogger.debug('[ACCOUNT] Client Map Inspection: %o', { - uuid, - }); + clearIntervalAsync(timer); + } else { + ClientLogger.info('[ACCOUNT] Expiration time. Delete user.'); - await this.accountManager.deleteItem(encodedEmail); - } - }, interval); + ClientLogger.debug('[ACCOUNT] Client Map Inspection: %o', { + uuid, + }); - await this.prisma.updateClientLoginStatus(email, uuid, true); + await this.accountManager.deleteItem(encodedEmail); + } + }, interval); - return encodedEmail; - } catch (error) { - ClientLogger.error('[LOGIN] Login Error: %o', { - error, - }); + await this.prisma.updateClientLoginStatus(email, uuid, true); - throw new ClientError( - '[LOGIN] Login', - 'Login Error. Please try again.', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + return encodedEmail; } async logout(encodedEmail: string) { - try { - const foundKey = await this.accountManager.getItem(encodedEmail); - - if (foundKey === null) { - ClientLogger.debug('[LOGIN] No Matching User Found: %o', { - encodedEmail, - }); + const foundKey = await this.accountManager.getItem(encodedEmail); - throw new ClientError('[LOGIN] Finding Matching User Info', 'No Matching User Found'); - } + if (foundKey === false) { + ClientLogger.debug('[LOGIN] No Matching User Found: %o', { + encodedEmail, + }); - const { token, uuid } = foundKey; + throw new ClientError('[LOGIN] Finding Matching User Info', 'No Matching User Found'); + } - const email = this.crypto.decrypt(encodedEmail, token); + const { token, uuid } = foundKey; - await this.prisma.updateClientLoginStatus(email, uuid, false); + const email = this.crypto.decrypt(encodedEmail, token); - const deleteItem = await this.accountManager.deleteItem(encodedEmail); + await this.prisma.updateClientLoginStatus(email, uuid, false); - if (deleteItem === null) throw new ClientError('[LOGOUT] Logout', 'No Data Found. Ignore.'); + const deleteItem = await this.accountManager.deleteItem(encodedEmail); - return 'Logout'; - } catch (error) { - ClientLogger.error('[LOGIN] Login Error: %o', { - error, - }); + if (deleteItem === false) throw new ClientError('[LOGOUT] Logout', 'No Data Found. Ignore.'); - throw new ClientError( - '[LOGIN] Logout', - 'Logout Error. Please try again.', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + return 'Logout'; } async myPage(encodedEmail: string) { - try { - const foundKey = await this.accountManager.getItem(encodedEmail); - - if (foundKey === null) { - ClientLogger.debug('[MYPAGE] No Matching User Found: %o', { - encodedEmail, - }); + const foundKey = await this.accountManager.getItem(encodedEmail); - throw new ClientError('[MYPAGE] Finding Matching User Info', 'No Matching User Found'); - } - - ClientLogger.debug('[MYPAGE] Found Key Item: %o', { + if (foundKey === false) { + ClientLogger.debug('[MYPAGE] No Matching User Found: %o', { encodedEmail, - foundKey, }); - const { token, uuid } = foundKey; - const email = this.crypto.decrypt(encodedEmail, token); + throw new ClientError('[MYPAGE] Finding Matching User Info', 'No Matching User Found'); + } - const result = await this.prisma.getMyPageInfo(email, uuid); + ClientLogger.debug('[MYPAGE] Found Key Item: %o', { + encodedEmail, + foundKey, + }); - ClientLogger.info('[MYPAGE] Got My Starred News'); + const { token, uuid } = foundKey; + const email = this.crypto.decrypt(encodedEmail, token); - return result; - } catch (error) { - ClientLogger.error('[MYPAGE] Get My Page Error: %o', { - error, - }); + const result = await this.prisma.getMyPageInfo(email, uuid); - throw new ClientError( - '[MYPAGE] Get My Page', - 'Get My Page Error. Please try again.', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + ClientLogger.info('[MYPAGE] Got My Starred News'); + + return result; } async changePassword(encodedEmail: string, password: string, newPassword: string) { - try { - const loginInfo = await this.accountManager.getItem(encodedEmail); + const loginInfo = await this.accountManager.getItem(encodedEmail); - if (loginInfo === null) throw new NoUserError('[CHANGE_PASS] Change Password', 'No User Data Found'); + if (loginInfo === false) throw new NoUserError('[CHANGE_PASS] Change Password', 'No User Data Found'); - const { token: redisToken } = loginInfo; + const { token: redisToken } = loginInfo; - const email = this.crypto.decrypt(encodedEmail, redisToken); + const email = this.crypto.decrypt(encodedEmail, redisToken); - // 찾기 - const result = await this.prisma.selectUserInfo(email); + // 찾기 + const result = await this.prisma.selectUserInfo(email); - if (result === null) { - ClientLogger.error('[CHANGE_PASS] Error. No matching User Found.: %o', { - email, - }); - - throw new NoUserError('[CHANGE_PASS] Login', 'No Matching Info. Please Make sure you Logged Out Before.'); - } + if (result === null) { + ClientLogger.error('[CHANGE_PASS] Error. No matching User Found.: %o', { + email, + }); - const { password: dbPassword, password_token: token, uuid } = result; + throw new NoUserError('[CHANGE_PASS] Login', 'No Matching Info. Please Make sure you Logged Out Before.'); + } - const isMatch = this.crypto.comparePassword(password, dbPassword, token); + const { password: dbPassword, password_token: token, uuid } = result; - if (!isMatch) throw new PasswordError('[CHANGE_PASS] Changing Password', 'Password Is Not Match'); + const isMatch = this.crypto.comparePassword(password, dbPassword, token); - const { encodedData: encodedPassword, encodedToken: passwordToken } = this.crypto.cryptData(newPassword); + if (!isMatch) throw new PasswordError('[CHANGE_PASS] Changing Password', 'Password Is Not Match'); - await this.prisma.updateNewPassword(uuid, encodedPassword, passwordToken); + const { encodedData: encodedPassword, encodedToken: passwordToken } = this.crypto.cryptData(newPassword); - ClientLogger.info('[CHANGE_PASS] Changing Password Complete'); + await this.prisma.updateNewPassword(uuid, encodedPassword, passwordToken); - return 'success'; - } catch (error) { - ClientLogger.error('[CHANGE_PASS] Change Password Error: %o', { - error, - }); + ClientLogger.info('[CHANGE_PASS] Changing Password Complete'); - throw new ClientError( - '[CHANGE_PASS] Change Password', - 'Change Password Error', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + return 'success'; } } diff --git a/src/providers/client/search.pvd.ts b/src/providers/client/search.pvd.ts index 6f69de7..4bfa4b5 100644 --- a/src/providers/client/search.pvd.ts +++ b/src/providers/client/search.pvd.ts @@ -156,7 +156,7 @@ export class ClientSearchProvider { try { const loginInfo = await this.accountManager.getItem(encodedEmail); - if (loginInfo === null) throw new NoUserError('[CHANGE_PASS] Change Password', 'No User Data Found'); + if (loginInfo === false) throw new NoUserError('[CHANGE_PASS] Change Password', 'No User Data Found'); const { token: emailToken } = loginInfo; diff --git a/src/providers/crypto.pvd.ts b/src/providers/crypto.pvd.ts index 1e5a179..968452e 100644 --- a/src/providers/crypto.pvd.ts +++ b/src/providers/crypto.pvd.ts @@ -23,25 +23,48 @@ export class CryptoProvider { * @returns boolean값 */ public comparePassword(receivedPassword: string, encodedPassword: string, passwordToken: string): boolean { - const decryptedPassword = this.decrypt(encodedPassword, passwordToken); + try { + const decryptedPassword = this.decrypt(encodedPassword, passwordToken); + + return receivedPassword === decryptedPassword; + } catch (error) { + CryptoLogger.error('[COMPARE] Comparing Encrypted - Decrypted Password: %o', { + error, + }); - return receivedPassword === decryptedPassword; + throw new CryptoError( + '[COMPARE] Comparing Encrypted - Decrypted Password', + 'Comparing Password got error', + error instanceof Error ? error : new Error(JSON.stringify(error)), + ); + } } public decrypt(encryptedString: string, token: string): string { - if (this.secretKey === undefined || !this.secretKey) { + if (this.secretKey === undefined || !this.secretKey) throw new CryptoError('[ENCRYPT] Decrypt Data Key Validation', 'Secret key is undefined'); - } - const iv = Buffer.from(token, 'hex'); - const encText = Buffer.from(encryptedString, 'hex'); + try { + const iv = Buffer.from(token, 'hex'); + const encText = Buffer.from(encryptedString, 'hex'); + + const decipher = createDecipheriv('aes-256-cbc', Buffer.from(this.secretKey), iv); - const decipher = createDecipheriv('aes-256-cbc', Buffer.from(this.secretKey), iv); + const decrypted = decipher.update(encText); + const decryptedString = Buffer.concat([decrypted, decipher.final()]).toString(); - const decrypted = decipher.update(encText); - const decryptedString = Buffer.concat([decrypted, decipher.final()]).toString(); + return decryptedString; + } catch (error) { + CryptoLogger.error('[DECRYPT] Decrypt Data Error: %o', { + error, + }); - return decryptedString; + throw new CryptoError( + '[DECRYPT] Decrypt Data', + 'Decrypt Data Error.', + error instanceof Error ? error : new Error(JSON.stringify(error)), + ); + } } /** @@ -50,17 +73,16 @@ export class CryptoProvider { * @returns 원본 패스워드 */ public decryptPassword(encryptedData: string): string { - try { - if (this.cipherKey === undefined || !this.cipherKey) { - throw new CryptoError('[DECRYPT] Decrypt Password Key Validation', 'Cipher key is undefined'); - } + if (this.cipherKey === undefined || !this.cipherKey) + throw new CryptoError('[DECRYPT] Decrypt Password Key Validation', 'Cipher key is undefined'); + try { const bytes = CryptoJS.AES.decrypt(encryptedData, this.cipherKey); const originalText = bytes.toString(CryptoJS.enc.Utf8); return originalText; } catch (error) { - CryptoLogger.error('[DECRYPT] Decrypt Encrypted Data Error:', { + CryptoLogger.error('[DECRYPT] Decrypt Password Error:', { error, }); @@ -78,23 +100,34 @@ export class CryptoProvider { * @returns { hashToken - token 필드에 들어갈 값, uuid - 고객 uuid} */ public cryptData(data: string) { - if (this.secretKey === undefined || !this.secretKey) { + if (this.secretKey === undefined || !this.secretKey) throw new CryptoError('[ENCRYPT] Encrypt Data Key Validation', 'Secret key is undefined'); - } - const iv = randomBytes(16); // Initialization vector - const cipher = createCipheriv('aes-256-cbc', Buffer.from(this.secretKey), iv); + try { + const iv = randomBytes(16); // Initialization vector + const cipher = createCipheriv('aes-256-cbc', Buffer.from(this.secretKey), iv); + + const encrypted = cipher.update(data); - const encrypted = cipher.update(data); + const encryptedString = Buffer.concat([encrypted, cipher.final()]).toString('hex'); - const encryptedString = Buffer.concat([encrypted, cipher.final()]).toString('hex'); + const returnData = { + encodedToken: iv.toString('hex'), + encodedData: encryptedString, + }; - const returnData = { - encodedToken: iv.toString('hex'), - encodedData: encryptedString, - }; + return returnData; + } catch (error) { + CryptoLogger.error('[ENCRYPT] Encrypt Data Error: %o', { + error, + }); - return returnData; + throw new CryptoError( + '[ENCRYPT] Encrypt Data', + 'Encrypt Data Error.', + error instanceof Error ? error : new Error(JSON.stringify(error)), + ); + } } /** @@ -114,7 +147,7 @@ export class CryptoProvider { return encryptedText; } catch (error) { - CryptoLogger.error('[ENCRYPT] Encrypt Encrypted Data Error:', { + CryptoLogger.error('[ENCRYPT] Encrypt Password Error:', { error, }); diff --git a/src/providers/news/geek/geek.pvd.ts b/src/providers/news/geek/geek.pvd.ts index 765c6e6..3b754d3 100644 --- a/src/providers/news/geek/geek.pvd.ts +++ b/src/providers/news/geek/geek.pvd.ts @@ -17,115 +17,79 @@ export class GeekProvider { ) {} async getNews(today: string, page: number, size: number) { - try { - const yesterday = moment(today).subtract(1, 'day').toDate(); + const yesterday = moment(today).subtract(1, 'day').toDate(); - const startDate = startOfDay(new Date(yesterday)); - const endDate = endOfDay(new Date(yesterday)); + const startDate = startOfDay(new Date(yesterday)); + const endDate = endOfDay(new Date(yesterday)); - NewsLogger.debug('[GEEK] YesterDay: %o', { - start: startDate, - end: endDate, - page, - size, - }); + NewsLogger.debug('[GEEK] YesterDay: %o', { + start: startDate, + end: endDate, + page, + size, + }); - const result = await this.prisma.bringGeekNews(startDate, endDate, page, size); + const result = await this.prisma.bringGeekNews(startDate, endDate, page, size); - const returnData: Array = result.map((item) => { - const isUrlUndefined = item.descLink.split('.io/')[1]; + const returnData: Array = result.map((item) => { + const isUrlUndefined = item.descLink.split('.io/')[1]; - const { post, descLink, uuid, link, _count, founded } = item; - const { liked_model: likedCount } = _count; - - if (isUrlUndefined === 'undefined') - return { - post, - uuid, - descLink: link, - founded, - likedCount, - }; + const { post, descLink, uuid, link, _count, founded } = item; + const { liked_model: likedCount } = _count; + if (isUrlUndefined === 'undefined') return { post, uuid, - descLink, + descLink: link, founded, likedCount, }; - }); - - const total = await this.prisma.geekNewsCount(startDate, endDate, size); - - NewsLogger.info('[GEEK] Get Total Count: %o', { - total, - }); - - return { result: returnData, total }; - } catch (error) { - NewsLogger.error('[GEEK] Bring Hada News Error: %o', { - error, - }); - - throw new GeekError( - '[GEEK] Bring news', - 'Bring Hada News Error. Please Try Again.', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + + return { + post, + uuid, + descLink, + founded, + likedCount, + }; + }); + + const total = await this.prisma.geekNewsCount(startDate, endDate, size); + + NewsLogger.info('[GEEK] Get Total Count: %o', { + total, + }); + + return { result: returnData, total }; } async giveStar(postUuid: string, email: string): Promise { - try { - const isLogined = await this.account.getItem(email); - - if (isLogined === null) throw new GeekError('[GEEK] Give Star on the Stars', 'No Logined User Found.'); + const isLogined = await this.account.getItem(email); - const { uuid: clientUuid } = isLogined; + if (isLogined === false) throw new GeekError('[GEEK] Give Star on the Stars', 'No Logined User Found.'); - const isStarred = await this.prisma.checkGeekNewsIsLiked(postUuid, clientUuid); - const { geek_news: isLiked } = isStarred; + const { uuid: clientUuid } = isLogined; - if (isLiked === undefined) await this.prisma.createGeekNewsLiked(postUuid, clientUuid); - } catch (error) { - NewsLogger.error('[GEEK] Star Update Error: %o', { - error, - }); + const isStarred = await this.prisma.checkGeekNewsIsLiked(postUuid, clientUuid); + const { geek_news: isLiked } = isStarred; - throw new GeekError( - '[GEEK] Give Star on the news', - 'Failed to vie star news', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + if (isLiked === undefined) await this.prisma.createGeekNewsLiked(postUuid, clientUuid); } async unStar(postUuid: string, email: string): Promise { - try { - const isLogined = await this.account.getItem(email); - - if (isLogined === null) throw new GeekError('[GEEK] Give Star on the Stars', 'No Logined User Found.'); + const isLogined = await this.account.getItem(email); - const { uuid: clientUuid } = isLogined; - const isStarred = await this.prisma.checkGeekNewsIsLiked(postUuid, clientUuid); + if (isLogined === false) throw new GeekError('[GEEK] Give Star on the Stars', 'No Logined User Found.'); - const { geek_news: isLiked } = isStarred; + const { uuid: clientUuid } = isLogined; + const isStarred = await this.prisma.checkGeekNewsIsLiked(postUuid, clientUuid); - const { uuid: likedUuid } = isLiked; - if (likedUuid) await this.prisma.deleteGeekNewsLiked(likedUuid, postUuid, clientUuid); + const { geek_news: isLiked } = isStarred; - NewsLogger.info('[GEEK] Finished UnStar Geek News'); - } catch (error) { - NewsLogger.error('[GEEK] Finished UnStar Geek News Error: %o', { - error, - }); + const { uuid: likedUuid } = isLiked; + if (likedUuid) await this.prisma.deleteGeekNewsLiked(likedUuid, postUuid, clientUuid); - throw new GeekError( - '[GEEK] Finished UnStar Geek News', - 'Failed to Finished UnStar Geek News. Please Try Again.', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + NewsLogger.info('[GEEK] Finished UnStar Geek News'); } } diff --git a/src/providers/news/ml/machine.pvd.ts b/src/providers/news/ml/machine.pvd.ts index 8313f7e..27106c8 100644 --- a/src/providers/news/ml/machine.pvd.ts +++ b/src/providers/news/ml/machine.pvd.ts @@ -95,7 +95,7 @@ export class MachineLearningProvider { try { const isLogined = await this.account.getItem(email); - if (isLogined === null) throw new MachineLearningError('[ML] UnStar on the Stars', 'No Logined User Found.'); + if (isLogined === false) throw new MachineLearningError('[ML] UnStar on the Stars', 'No Logined User Found.'); const { uuid: clientUuid } = isLogined; const isStarred = await this.prisma.checkIsMlNewsLiked(postUuid, clientUuid); From 3f2f93bad16048e2baf4b055d0ab2de3dc63bc9e Mon Sep 17 00:00:00 2001 From: donghquinn Date: Thu, 14 Mar 2024 17:04:21 +0900 Subject: [PATCH 6/8] mailing test --- src/providers/client/search.pvd.ts | 6 +----- src/providers/mailer.pvd.ts | 23 +++++++++++++-------- test/libraries/search/password/mail.test.ts | 17 +++++++++++++++ 3 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 test/libraries/search/password/mail.test.ts diff --git a/src/providers/client/search.pvd.ts b/src/providers/client/search.pvd.ts index 4bfa4b5..9726f7e 100644 --- a/src/providers/client/search.pvd.ts +++ b/src/providers/client/search.pvd.ts @@ -2,7 +2,6 @@ import { ClientError, NoUserError } from '@errors/client.error'; import { NoValidateKeyError, PasswordError } from '@errors/password.error'; import { Injectable } from '@nestjs/common'; import { ClientLogger } from '@utils/logger.util'; -import { randomBytes } from 'crypto'; import { AccountManager } from 'providers/account-manager.pvd'; import { CryptoProvider } from 'providers/crypto.pvd'; import { MailerProvider } from 'providers/mailer.pvd'; @@ -30,16 +29,13 @@ export class ClientSearchProvider { const result = await this.prisma.selectUserInfo(email, name); if (result === null) throw new NoUserError('[SEARCH_PASS] Search Password', 'No User Found'); - - const randomKey = randomBytes(8).toString('hex'); // const { encodedData: encodedPassword, dataToken: passwordToken } = cryptData(randomPassword); const { password, password_token: token } = result; + const randomKey = await this.mailer.sendSearchPassword(email, 'Search Password'); await this.accountManager.setTempData(randomKey, email, password, token); - await this.mailer.sendSearchPassword(email, 'Search Password', randomKey); - ClientLogger.info('[SEARCH_PASS] Sending New Password Complete'); return 'Sent'; diff --git a/src/providers/mailer.pvd.ts b/src/providers/mailer.pvd.ts index 7f04eba..1996d58 100644 --- a/src/providers/mailer.pvd.ts +++ b/src/providers/mailer.pvd.ts @@ -1,6 +1,7 @@ import { MailerError } from '@errors/mail.error'; import { Injectable } from '@nestjs/common'; import { MailerLogger } from '@utils/logger.util'; +import { randomBytes } from 'crypto'; import * as nodemailer from 'nodemailer'; @Injectable() @@ -43,20 +44,24 @@ export class MailerProvider { } } - private static createSearchPasswordMailcontent(rawPassword: string): string { + private static createSearchPasswordMailcontent(authKey: string): string { return ` -
-
-

Validate Key:

${rawPassword} -
-
-`; +
+
+

Validate Key:

${authKey} +
+
+ `; } - public async sendSearchPassword(to: string, subject: string, rawPassword: string) { - const content = MailerProvider.createSearchPasswordMailcontent(rawPassword); + public async sendSearchPassword(to: string, subject: string) { + const randomKey = randomBytes(8).toString('hex'); + + const content = MailerProvider.createSearchPasswordMailcontent(randomKey); await this.sendMail(to, subject, content); + + return randomKey; } public static createNewsdMailcontent(newsData: string): string { diff --git a/test/libraries/search/password/mail.test.ts b/test/libraries/search/password/mail.test.ts new file mode 100644 index 0000000..bece016 --- /dev/null +++ b/test/libraries/search/password/mail.test.ts @@ -0,0 +1,17 @@ +import { MailerProvider } from 'providers/mailer.pvd'; + +describe('Sending Mail Validator', () => { + const receiver = process.env.GMAIL_USER; + + test('GMAIL User must be defined', () => { + expect(receiver).toBeDefined(); + }); + + const mailer = new MailerProvider(); + + test('Sending Searching Password Validate Key', async () => { + const randomKey = await mailer.sendSearchPassword(receiver!, 'Searching Password'); + + expect(randomKey).toBeDefined(); + }); +}); From d98045ebe9aa256e21c13a092e7730736fb5c6e4 Mon Sep 17 00:00:00 2001 From: donghquinn Date: Thu, 14 Mar 2024 17:06:14 +0900 Subject: [PATCH 7/8] wip: search --- src/providers/client/search.pvd.ts | 184 ++++++++++------------------- 1 file changed, 62 insertions(+), 122 deletions(-) diff --git a/src/providers/client/search.pvd.ts b/src/providers/client/search.pvd.ts index 9726f7e..c442095 100644 --- a/src/providers/client/search.pvd.ts +++ b/src/providers/client/search.pvd.ts @@ -1,4 +1,4 @@ -import { ClientError, NoUserError } from '@errors/client.error'; +import { NoUserError } from '@errors/client.error'; import { NoValidateKeyError, PasswordError } from '@errors/password.error'; import { Injectable } from '@nestjs/common'; import { ClientLogger } from '@utils/logger.util'; @@ -24,32 +24,20 @@ export class ClientSearchProvider { * @returns 전송 성공 메세지 */ async searchPassword(email: string, name: string) { - try { - // 찾기 - const result = await this.prisma.selectUserInfo(email, name); + // 찾기 + const result = await this.prisma.selectUserInfo(email, name); - if (result === null) throw new NoUserError('[SEARCH_PASS] Search Password', 'No User Found'); - // const { encodedData: encodedPassword, dataToken: passwordToken } = cryptData(randomPassword); + if (result === null) throw new NoUserError('[SEARCH_PASS] Search Password', 'No User Found'); + // const { encodedData: encodedPassword, dataToken: passwordToken } = cryptData(randomPassword); - const { password, password_token: token } = result; + const { password, password_token: token } = result; - const randomKey = await this.mailer.sendSearchPassword(email, 'Search Password'); - await this.accountManager.setTempData(randomKey, email, password, token); + const randomKey = await this.mailer.sendSearchPassword(email, 'Search Password'); + await this.accountManager.setTempData(randomKey, email, password, token); - ClientLogger.info('[SEARCH_PASS] Sending New Password Complete'); + ClientLogger.info('[SEARCH_PASS] Sending New Password Complete'); - return 'Sent'; - } catch (error) { - ClientLogger.error('[SEARCH_PASS] Search Password Error: %o', { - error, - }); - - throw new ClientError( - '[SEARCH_PASS] Search Password', - 'Search Password Error', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + return 'Sent'; } /** @@ -58,33 +46,21 @@ export class ClientSearchProvider { * @returns 암호화 된 패스워드 전송. 프론트단에서 복호화 실시 */ async validateSearchingPasswordKey(tempKey: string) { - try { - // 찾기 - const tempItem = await this.accountManager.getTempData(tempKey); + // 찾기 + const tempItem = await this.accountManager.getTempData(tempKey); - if (tempItem === null) - throw new NoValidateKeyError('[VALIDATE_KEY] Validate Password Searching Key', 'No Matching Key Found'); + if (tempItem === null) + throw new NoValidateKeyError('[VALIDATE_KEY] Validate Password Searching Key', 'No Matching Key Found'); - const { password, token } = tempItem; + const { password, token } = tempItem; - const rawPassword = this.crypto.decrypt(password, token); + const rawPassword = this.crypto.decrypt(password, token); - const encryptedPassword = this.crypto.encryptOriginalPassword(rawPassword); + const encryptedPassword = this.crypto.encryptOriginalPassword(rawPassword); - ClientLogger.info('[VALIDATE_KEY] Validate Password Searching Key Complete'); - - return encryptedPassword; - } catch (error) { - ClientLogger.error('[VALIDATE_KEY] Validate Password Searching Key Error: %o', { - error, - }); + ClientLogger.info('[VALIDATE_KEY] Validate Password Searching Key Complete'); - throw new ClientError( - '[VALIDATE_KEY] Validate Password Searching Key', - 'Validate Password Searching Key Error', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + return encryptedPassword; } /** @@ -96,48 +72,36 @@ export class ClientSearchProvider { * @returns 성공 여부 메세지 */ async changeSearchingPassword(email: string, name: string, password: string, newPassword: string) { - try { - // 찾기 - const result = await this.prisma.findUser(email, name); - - if (result === null) { - ClientLogger.error('[CHANGE_PASS] Error. No matching User Found.: %o', { - email, - }); + // 찾기 + const result = await this.prisma.findUser(email, name); - throw new NoUserError('[CHANGE_PASS] Login', 'No Matching Info. Please Make sure you Logged Out Before.'); - } + if (result === null) { + ClientLogger.error('[CHANGE_PASS] Error. No matching User Found.: %o', { + email, + }); - const decryptedPassword = this.crypto.decryptPassword(password); + throw new NoUserError('[CHANGE_PASS] Login', 'No Matching Info. Please Make sure you Logged Out Before.'); + } - const { password: dbPassword, password_token: token, uuid } = result; + const decryptedPassword = this.crypto.decryptPassword(password); - const dbRawPassword = this.crypto.decrypt(dbPassword, token); + const { password: dbPassword, password_token: token, uuid } = result; - if (decryptedPassword !== dbRawPassword) - throw new PasswordError('[CHANGE_PASS] Changing Password', 'Password Is Not Match'); + const dbRawPassword = this.crypto.decrypt(dbPassword, token); - const decryptedNewPassword = this.crypto.decryptPassword(newPassword); + if (decryptedPassword !== dbRawPassword) + throw new PasswordError('[CHANGE_PASS] Changing Password', 'Password Is Not Match'); - const { encodedData: encodedNewPassword, encodedToken: passwordNewToken } = - this.crypto.cryptData(decryptedNewPassword); + const decryptedNewPassword = this.crypto.decryptPassword(newPassword); - await this.prisma.updateNewPassword(uuid, encodedNewPassword, passwordNewToken); + const { encodedData: encodedNewPassword, encodedToken: passwordNewToken } = + this.crypto.cryptData(decryptedNewPassword); - ClientLogger.info('[CHANGE_PASS] Changing Password Complete'); + await this.prisma.updateNewPassword(uuid, encodedNewPassword, passwordNewToken); - return 'success'; - } catch (error) { - ClientLogger.error('[CHANGE_PASS] Change Password Error: %o', { - error, - }); + ClientLogger.info('[CHANGE_PASS] Changing Password Complete'); - throw new ClientError( - '[CHANGE_PASS] Change Password', - 'Change Password Error', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + return 'success'; } /** @@ -149,50 +113,38 @@ export class ClientSearchProvider { * @returns 성공 여부 메세지 */ async changePassword(encodedEmail: string, password: string, newPassword: string) { - try { - const loginInfo = await this.accountManager.getItem(encodedEmail); - - if (loginInfo === false) throw new NoUserError('[CHANGE_PASS] Change Password', 'No User Data Found'); + const loginInfo = await this.accountManager.getItem(encodedEmail); - const { token: emailToken } = loginInfo; + if (loginInfo === false) throw new NoUserError('[CHANGE_PASS] Change Password', 'No User Data Found'); - const email = this.crypto.decrypt(encodedEmail, emailToken); + const { token: emailToken } = loginInfo; - // 찾기 - const result = await this.prisma.findUser(email); + const email = this.crypto.decrypt(encodedEmail, emailToken); - if (result === null) { - ClientLogger.error('[CHANGE_PASS] Error. No matching User Found.: %o', { - email, - }); + // 찾기 + const result = await this.prisma.findUser(email); - throw new NoUserError('[CHANGE_PASS] Login', 'No Matching Info. Please Make sure you Logged Out Before.'); - } + if (result === null) { + ClientLogger.error('[CHANGE_PASS] Error. No matching User Found.: %o', { + email, + }); - const { password: dbPassword, password_token: token, uuid } = result; + throw new NoUserError('[CHANGE_PASS] Login', 'No Matching Info. Please Make sure you Logged Out Before.'); + } - const isMatch = this.crypto.comparePassword(password, dbPassword, token); + const { password: dbPassword, password_token: token, uuid } = result; - if (!isMatch) throw new PasswordError('[CHANGE_PASS] Changing Password', 'Password Is Not Match'); + const isMatch = this.crypto.comparePassword(password, dbPassword, token); - const { encodedData: encodedPassword, encodedToken: passwordToken } = this.crypto.cryptData(newPassword); + if (!isMatch) throw new PasswordError('[CHANGE_PASS] Changing Password', 'Password Is Not Match'); - await this.prisma.updateNewPassword(uuid, encodedPassword, passwordToken); + const { encodedData: encodedPassword, encodedToken: passwordToken } = this.crypto.cryptData(newPassword); - ClientLogger.info('[CHANGE_PASS] Changing Password Complete'); + await this.prisma.updateNewPassword(uuid, encodedPassword, passwordToken); - return 'success'; - } catch (error) { - ClientLogger.error('[CHANGE_PASS] Change Password Error: %o', { - error, - }); + ClientLogger.info('[CHANGE_PASS] Changing Password Complete'); - throw new ClientError( - '[CHANGE_PASS] Change Password', - 'Change Password Error', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + return 'success'; } /** @@ -201,26 +153,14 @@ export class ClientSearchProvider { * @returns 유저 이메일 */ async searchEmail(name: string) { - try { - const result = await this.prisma.findEmail(name); - - if (result === null) throw new NoUserError('[SEARCH_EMAIL] Find Email', 'No Matching Data Found'); + const result = await this.prisma.findEmail(name); - const { email } = result; + if (result === null) throw new NoUserError('[SEARCH_EMAIL] Find Email', 'No Matching Data Found'); - ClientLogger.debug('[SEARCH_EMAIL] Finding Email Complete'); + const { email } = result; - return email; - } catch (error) { - ClientLogger.error('[SEARCH_EMAIL] Finding Email Error: %o', { - error, - }); + ClientLogger.debug('[SEARCH_EMAIL] Finding Email Complete'); - throw new ClientError( - '[SEARCH_EMAIL] Finding Email', - 'Finding Email Error', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + return email; } } From d89ceec33fb7211d4cb636f941a3f98d851be176 Mon Sep 17 00:00:00 2001 From: donghquinn Date: Thu, 14 Mar 2024 17:17:39 +0900 Subject: [PATCH 8/8] wip: error wrapping --- .../news/hacker/hacker-prisma.lib.ts | 16 +- src/providers/news/hacker/hacker.pvd.ts | 142 +++++------------- src/providers/news/ml/machine.pvd.ts | 122 +++++---------- src/providers/news/ml/ml-prisma.lib.ts | 17 ++- 4 files changed, 104 insertions(+), 193 deletions(-) diff --git a/src/providers/news/hacker/hacker-prisma.lib.ts b/src/providers/news/hacker/hacker-prisma.lib.ts index 6270122..a1c78b3 100644 --- a/src/providers/news/hacker/hacker-prisma.lib.ts +++ b/src/providers/news/hacker/hacker-prisma.lib.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { HackerError } from '@errors/news.error'; import { Injectable } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; @@ -30,7 +31,20 @@ export class HackerPrismaLibrary extends PrismaClient { skip: (Number(page) - 1) * Number(size), }); - return result; + const returnData = result.map((item) => { + const { uuid, post, link, founded, _count } = item; + const { liked_model: count } = _count; + + return { + uuid, + post, + link, + likedCount: count, + founded, + }; + }); + + return returnData; } catch (error) { NewsLogger.error('[HACKER] Bring Hacker News Error: %o', { error, diff --git a/src/providers/news/hacker/hacker.pvd.ts b/src/providers/news/hacker/hacker.pvd.ts index a949139..85b0604 100755 --- a/src/providers/news/hacker/hacker.pvd.ts +++ b/src/providers/news/hacker/hacker.pvd.ts @@ -14,129 +14,61 @@ export class HackersNewsProvider { private readonly account: AccountManager, ) {} - async getHackerNewsCount() { - try { - const count = await this.prisma.hackers.count(); - - NewsLogger.info('[Hackers] News Total Count: %o', { count }); - - return count; - } catch (error) { - NewsLogger.error('[Hackers] Get Hacker News Count Error: %o', { - error, - }); - - throw new HackerError( - '[Hackers] Hacker News', - 'Hacker News Count Error', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } - } - async bringTodayHackerPosts(today: string, page: number, size: number) { - try { - const yesterday = moment(today).subtract(1, 'day').toDate(); - - const startDate = startOfDay(new Date(yesterday)); - const endDate = endOfDay(new Date(yesterday)); - - NewsLogger.debug('[Hackers] YesterDay: %o', { - start: startDate, - end: endDate, - page, - size, - }); - - const result = await this.prisma.bringHackerNews(startDate, endDate, page, size); - - const returnData = result.map((item) => { - const { uuid, post, link, founded, _count } = item; - const { liked_model: count } = _count; - - return { - uuid, - post, - link, - likedCount: count, - founded, - }; - }); - const total = await this.prisma.hackerNewsCount(startDate, endDate, size); - - NewsLogger.info('[Hackers] Get Total Count: %o', { - total, - }); - - return { result: returnData, total }; - } catch (error) { - NewsLogger.error('[Hackers] Bring Hacker News Error: %o', { - error, - }); - - throw new HackerError( - '[Hackers] Hacker News', - 'Hacker News Bringing Error. Please Try Again.', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + const yesterday = moment(today).subtract(1, 'day').toDate(); + + const startDate = startOfDay(new Date(yesterday)); + const endDate = endOfDay(new Date(yesterday)); + + NewsLogger.debug('[Hackers] YesterDay: %o', { + start: startDate, + end: endDate, + page, + size, + }); + + const returnData = await this.prisma.bringHackerNews(startDate, endDate, page, size); + + const total = await this.prisma.hackerNewsCount(startDate, endDate, size); + + NewsLogger.info('[Hackers] Get Total Count: %o', { + total, + }); + + return { result: returnData, total }; } async giveStar(postUuid: string, email: string): Promise { - try { - const isLogined = await this.account.getItem(email); + const isLogined = await this.account.getItem(email); - if (!isLogined) throw new HackerError('[Hackers] Give Star on the Stars', 'No Logined User Found.'); + if (!isLogined) throw new HackerError('[Hackers] Give Star on the Stars', 'No Logined User Found.'); - const { uuid: clientUuid } = isLogined; - const isStarred = await this.prisma.checkHackerNewsIsLiked(postUuid, clientUuid); + const { uuid: clientUuid } = isLogined; + const isStarred = await this.prisma.checkHackerNewsIsLiked(postUuid, clientUuid); - if (isStarred === null) throw new HackerError('[HACKER] Get Star Info', 'No Star Info Found.'); + if (isStarred === null) throw new HackerError('[HACKER] Get Star Info', 'No Star Info Found.'); - const { hacker_news: isLiked } = isStarred; + const { hacker_news: isLiked } = isStarred; - if (isLiked.uuid === undefined) await this.prisma.createHackerNewsLiked(postUuid, clientUuid); - } catch (error) { - NewsLogger.error('[Hackers] Star Update Error: %o', { - error, - }); - - throw new HackerError( - '[Hackers] Give Star on the news', - 'Failed to vie star news. Please Try Again.', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + if (isLiked.uuid === undefined) await this.prisma.createHackerNewsLiked(postUuid, clientUuid); } // Pagination async unStar(postUuid: string, email: string) { - try { - const isLogined = await this.account.getItem(email); - - if (!isLogined) throw new HackerError('[Hackers] Give Star on the Stars', 'No Logined User Found.'); + const isLogined = await this.account.getItem(email); - const { uuid: clientUuid } = isLogined; - const isStarred = await this.prisma.checkHackerNewsIsLiked(postUuid, clientUuid); + if (!isLogined) throw new HackerError('[Hackers] Give Star on the Stars', 'No Logined User Found.'); - if (isStarred === null) throw new HackerError('[HACKER] Get Star Info', 'No Star Info Found.'); + const { uuid: clientUuid } = isLogined; + const isStarred = await this.prisma.checkHackerNewsIsLiked(postUuid, clientUuid); - const { hacker_news: isLiked } = isStarred; - const { uuid: likedUuid } = isLiked; + if (isStarred === null) throw new HackerError('[HACKER] Get Star Info', 'No Star Info Found.'); - if (likedUuid) await this.prisma.deleteHackerNewsLiked(likedUuid, postUuid, clientUuid); + const { hacker_news: isLiked } = isStarred; + const { uuid: likedUuid } = isLiked; - NewsLogger.info('[Hackers] Unstar Hacker News Finished'); - } catch (error) { - NewsLogger.error('[Hackers] Unstar Hacker News Error: %o', { - error, - }); + if (likedUuid) await this.prisma.deleteHackerNewsLiked(likedUuid, postUuid, clientUuid); - throw new HackerError( - '[Hackers] Unstar Hacker News', - 'Failed to Unstar Hacker News', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + NewsLogger.info('[Hackers] Unstar Hacker News Finished'); } } diff --git a/src/providers/news/ml/machine.pvd.ts b/src/providers/news/ml/machine.pvd.ts index 27106c8..1f186b0 100644 --- a/src/providers/news/ml/machine.pvd.ts +++ b/src/providers/news/ml/machine.pvd.ts @@ -15,108 +15,58 @@ export class MachineLearningProvider { ) {} async bringLatestMachineLearningNews(today: string, page: number, size: number) { - try { - const yesterday = moment(today).subtract(1, 'day').toDate(); - - const startDate = startOfDay(new Date(yesterday)); - const endDate = endOfDay(new Date(yesterday)); - - NewsLogger.debug('[ML] YesterDay: %o', { - start: startDate, - end: endDate, - page, - size, - }); - - const result = await this.prisma.bringMlNews(startDate, endDate, page, size); - - const returnData = result.map((item) => { - const { uuid, link, title, founded, _count, category } = item; - const { liked_model: count } = _count; - - return { - uuid, - title, - category, - link, - likedCount: count, - founded, - }; - }); - - const total = await this.prisma.mlTotalCount(startDate, endDate, size); - - NewsLogger.info('[ML] Get Total Count: %o', { - total, - }); - - return { result: returnData, total }; - } catch (error) { - NewsLogger.error('[ML] Get Latest Machine Learning News Error: %o', { - error, - }); - - throw new MachineLearningError( - 'Get Latest Machine Learning News', - 'Failed to Get Latest Machine Learning News. Please Try Again.', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + const yesterday = moment(today).subtract(1, 'day').toDate(); + + const startDate = startOfDay(new Date(yesterday)); + const endDate = endOfDay(new Date(yesterday)); + + NewsLogger.debug('[ML] YesterDay: %o', { + start: startDate, + end: endDate, + page, + size, + }); + + const returnData = await this.prisma.bringMlNews(startDate, endDate, page, size); + + const total = await this.prisma.mlTotalCount(startDate, endDate, size); + + NewsLogger.info('[ML] Get Total Count: %o', { + total, + }); + + return { result: returnData, total }; } async giveStar(postUuid: string, email: string): Promise { - try { - const isLogined = await this.account.getItem(email); + const isLogined = await this.account.getItem(email); - if (!isLogined) throw new MachineLearningError('[ML] Give Star on the Stars', 'No Logined User Found.'); + if (!isLogined) throw new MachineLearningError('[ML] Give Star on the Stars', 'No Logined User Found.'); - const { uuid: clientUuid } = isLogined; - const isStarred = await this.prisma.checkIsMlNewsLiked(postUuid, clientUuid); + const { uuid: clientUuid } = isLogined; + const isStarred = await this.prisma.checkIsMlNewsLiked(postUuid, clientUuid); - if (isStarred === null) throw new MachineLearningError('[ML] Get Star Info', 'No Star Info Found.'); + if (isStarred === null) throw new MachineLearningError('[ML] Get Star Info', 'No Star Info Found.'); - const { ml_news: isLiked } = isStarred; + const { ml_news: isLiked } = isStarred; - if (isLiked === undefined) await this.prisma.createMlNewsLiked(postUuid, clientUuid); - } catch (error) { - NewsLogger.error('[ML] Give Star on the ML News Error: %o', { - error, - }); - - throw new MachineLearningError( - '[ML] Give Star on the ML news', - 'Failed to vie star ML news', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + if (isLiked === undefined) await this.prisma.createMlNewsLiked(postUuid, clientUuid); } async unStar(postUuid: string, email: string): Promise { - try { - const isLogined = await this.account.getItem(email); - - if (isLogined === false) throw new MachineLearningError('[ML] UnStar on the Stars', 'No Logined User Found.'); + const isLogined = await this.account.getItem(email); - const { uuid: clientUuid } = isLogined; - const isStarred = await this.prisma.checkIsMlNewsLiked(postUuid, clientUuid); + if (isLogined === false) throw new MachineLearningError('[ML] UnStar on the Stars', 'No Logined User Found.'); - if (isStarred === null) throw new MachineLearningError('[ML] Get Star Info', 'No Star Info Found.'); + const { uuid: clientUuid } = isLogined; + const isStarred = await this.prisma.checkIsMlNewsLiked(postUuid, clientUuid); - const { ml_news: isLiked } = isStarred; + if (isStarred === null) throw new MachineLearningError('[ML] Get Star Info', 'No Star Info Found.'); - if (isLiked.uuid) await this.prisma.deleteMlNewsLiked(isLiked.uuid, postUuid, clientUuid); + const { ml_news: isLiked } = isStarred; - NewsLogger.info('[ML] Unstar News Finished'); - } catch (error) { - NewsLogger.error('[ML] Unstar ML News Error: %o', { - error, - }); + if (isLiked.uuid) await this.prisma.deleteMlNewsLiked(isLiked.uuid, postUuid, clientUuid); - throw new MachineLearningError( - '[ML] Unstar ML News', - 'Failed to Unstar ML News', - error instanceof Error ? error : new Error(JSON.stringify(error)), - ); - } + NewsLogger.info('[ML] Unstar News Finished'); } } diff --git a/src/providers/news/ml/ml-prisma.lib.ts b/src/providers/news/ml/ml-prisma.lib.ts index 132f57f..dd5d55e 100644 --- a/src/providers/news/ml/ml-prisma.lib.ts +++ b/src/providers/news/ml/ml-prisma.lib.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { MachineLearningError } from '@errors/news.error'; import { PrismaError } from '@errors/prisma.error'; import { Injectable } from '@nestjs/common'; @@ -31,7 +32,21 @@ export class MlPrismaLibrary extends PrismaClient { skip: (Number(page) - 1) * Number(size), }); - return result; + const returnData = result.map((item) => { + const { uuid, link, title, founded, _count, category } = item; + const { liked_model: count } = _count; + + return { + uuid, + title, + category, + link, + likedCount: count, + founded, + }; + }); + + return returnData; } catch (error) { NewsLogger.error('[ML] Bring Geek News Error: %o', { error,