From 338e0ecabaff4b35bc5c8458fee38eff6f711faf Mon Sep 17 00:00:00 2001 From: YangGwangSeong Date: Fri, 13 Dec 2024 14:00:38 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20refresh-token=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20jwt=20=EB=9D=BC=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC?= =?UTF-8?q?=20=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (#54) --- package-lock.json | 18 ++++++++-- package.json | 2 ++ src/database/factories/category.factory.ts | 9 +++++ src/database/seeds/category.seeder.ts | 38 ++++++++++++++++++++++ src/database/seeds/refresh-token.seeder.ts | 17 ++++++++++ 5 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 src/database/factories/category.factory.ts create mode 100644 src/database/seeds/category.seeder.ts create mode 100644 src/database/seeds/refresh-token.seeder.ts diff --git a/package-lock.json b/package-lock.json index 468acf1..71d78af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "cross-env": "^7.0.3", "dotenv": "^16.4.7", "express": "^4.21.1", + "jsonwebtoken": "^9.0.2", "multer": "^1.4.5-lts.1", "mysql2": "^3.11.4", "nodemailer": "^6.9.16", @@ -40,6 +41,7 @@ "@types/bcrypt": "^5.0.2", "@types/express": "^5.0.0", "@types/jest": "^29.5.14", + "@types/jsonwebtoken": "^9.0.7", "@types/multer": "^1.4.12", "@types/node": "^22.9.0", "@types/nodemailer": "^6.4.17", @@ -2528,6 +2530,15 @@ "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0" } }, + "node_modules/@nestjs/jwt/node_modules/@types/jsonwebtoken": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz", + "integrity": "sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@nestjs/mapped-types": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.6.tgz", @@ -3146,9 +3157,10 @@ "license": "MIT" }, "node_modules/@types/jsonwebtoken": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz", - "integrity": "sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==", + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz", + "integrity": "sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" diff --git a/package.json b/package.json index 20bbef6..69923c7 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "cross-env": "^7.0.3", "dotenv": "^16.4.7", "express": "^4.21.1", + "jsonwebtoken": "^9.0.2", "multer": "^1.4.5-lts.1", "mysql2": "^3.11.4", "nodemailer": "^6.9.16", @@ -52,6 +53,7 @@ "@types/bcrypt": "^5.0.2", "@types/express": "^5.0.0", "@types/jest": "^29.5.14", + "@types/jsonwebtoken": "^9.0.7", "@types/multer": "^1.4.12", "@types/node": "^22.9.0", "@types/nodemailer": "^6.4.17", diff --git a/src/database/factories/category.factory.ts b/src/database/factories/category.factory.ts new file mode 100644 index 0000000..d5ae2d7 --- /dev/null +++ b/src/database/factories/category.factory.ts @@ -0,0 +1,9 @@ +import { setSeederFactory } from "typeorm-extension"; + +import { CategoryEntity } from "@APP/entities/category.entity"; + +export default setSeederFactory(CategoryEntity, async () => { + const category = new CategoryEntity(); + + return category; +}); diff --git a/src/database/seeds/category.seeder.ts b/src/database/seeds/category.seeder.ts new file mode 100644 index 0000000..f86aacc --- /dev/null +++ b/src/database/seeds/category.seeder.ts @@ -0,0 +1,38 @@ +import { DataSource } from "typeorm"; +import { Seeder, SeederFactoryManager } from "typeorm-extension"; + +import { CategoryEntity } from "@APP/entities/category.entity"; + +const CATEGORY_NAMES = [ + "치킨", + "고기", + "한식", + "중식", + "일식", + "양식", + "족발,보쌈", + "찜,탕,찌개", + "피자", + "아시안", + "도시락", + "분식", + "카페,디저트", + "패스트푸드", + "야식", + "기타", +]; + +export default class CategorySeeder implements Seeder { + public async run( + _dataSource: DataSource, + factoryManager: SeederFactoryManager, + ): Promise { + const categoryFactory = factoryManager.get(CategoryEntity); + + await Promise.all( + CATEGORY_NAMES.map((name) => categoryFactory.save({ name })), + ); + + console.log(`카테고리 생성 완료`); + } +} diff --git a/src/database/seeds/refresh-token.seeder.ts b/src/database/seeds/refresh-token.seeder.ts new file mode 100644 index 0000000..2848a29 --- /dev/null +++ b/src/database/seeds/refresh-token.seeder.ts @@ -0,0 +1,17 @@ +import { DataSource } from "typeorm"; +import { Seeder, SeederFactoryManager } from "typeorm-extension"; + +import { RefreshTokenEntity } from "@APP/entities/refresh-token.entity"; + +export default class RefreshTokenSeeder implements Seeder { + public async run( + _dataSource: DataSource, + factoryManager: SeederFactoryManager, + ): Promise { + const refreshTokenFactory = factoryManager.get(RefreshTokenEntity); + + await refreshTokenFactory.save(); + + console.log(`리프레시토큰 생성 완료`); + } +} From 6abef2306c34e40e29d3b28443e2ae024aa1d698 Mon Sep 17 00:00:00 2001 From: YangGwangSeong Date: Fri, 13 Dec 2024 14:21:17 +0900 Subject: [PATCH 2/2] =?UTF-8?q?:sparkles:=20feat:=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20seeder=20=EC=83=9D=EC=84=B1=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/database/factories/member.factory.ts | 2 +- .../factories/refresh-token.factory.ts | 17 ++++++++++++++--- .../factories/verification-code.factory.ts | 16 ++++++++++++++++ .../seeds/verification-code.seeder.ts | 19 +++++++++++++++++++ 4 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 src/database/factories/verification-code.factory.ts create mode 100644 src/database/seeds/verification-code.seeder.ts diff --git a/src/database/factories/member.factory.ts b/src/database/factories/member.factory.ts index 6a97aa5..9ec95bd 100644 --- a/src/database/factories/member.factory.ts +++ b/src/database/factories/member.factory.ts @@ -4,7 +4,7 @@ import { setSeederFactory } from "typeorm-extension"; import { MemberEntity } from "../../entities/member.entity"; export default setSeederFactory(MemberEntity, async (faker) => { - const hashedPassword = await bcrypt.hash(faker.internet.password(), 10); + const hashedPassword = await bcrypt.hash("123456", 10); const member = new MemberEntity(); member.name = faker.person.firstName(); diff --git a/src/database/factories/refresh-token.factory.ts b/src/database/factories/refresh-token.factory.ts index 36c44e0..3ef48f9 100644 --- a/src/database/factories/refresh-token.factory.ts +++ b/src/database/factories/refresh-token.factory.ts @@ -1,13 +1,24 @@ import * as bcrypt from "bcrypt"; +import jwt from "jsonwebtoken"; import { setSeederFactory } from "typeorm-extension"; +import { ENV_JWT_SECRET_KEY } from "@APP/common/constants/env-keys.const"; import { RefreshTokenEntity } from "@APP/entities/refresh-token.entity"; -export default setSeederFactory(RefreshTokenEntity, async (faker) => { +export default setSeederFactory(RefreshTokenEntity, async () => { + const payload = { + email: "Alisha_Dibbert@hotmail.com", + sub: 8, + type: "refresh", + }; + + const secret = process.env[ENV_JWT_SECRET_KEY] || "secret"; + const expiresIn = "3600"; + const refreshToken = new RefreshTokenEntity(); - const fakeToken = faker.string.alphanumeric(32); - refreshToken.token = await bcrypt.hash(fakeToken, 10); + const token = jwt.sign(payload, secret, { expiresIn }); + refreshToken.token = await bcrypt.hash(token, 10); return refreshToken; }); diff --git a/src/database/factories/verification-code.factory.ts b/src/database/factories/verification-code.factory.ts new file mode 100644 index 0000000..c74ce6a --- /dev/null +++ b/src/database/factories/verification-code.factory.ts @@ -0,0 +1,16 @@ +import * as crypto from "crypto"; +import { setSeederFactory } from "typeorm-extension"; + +import { VerificationCodeEntity } from "@APP/entities/verification-code.entity"; + +export default setSeederFactory(VerificationCodeEntity, () => { + const verificationCode = crypto + .randomBytes(3) + .toString("hex") + .toUpperCase(); + + const verificationCodeEntity = new VerificationCodeEntity(); + verificationCodeEntity.code = verificationCode; + + return verificationCodeEntity; +}); diff --git a/src/database/seeds/verification-code.seeder.ts b/src/database/seeds/verification-code.seeder.ts new file mode 100644 index 0000000..b3e2e29 --- /dev/null +++ b/src/database/seeds/verification-code.seeder.ts @@ -0,0 +1,19 @@ +import { DataSource } from "typeorm"; +import { Seeder, SeederFactoryManager } from "typeorm-extension"; + +import { VerificationCodeEntity } from "@APP/entities/verification-code.entity"; + +export default class VerificationCodeSeeder implements Seeder { + public async run( + _dataSource: DataSource, + factoryManager: SeederFactoryManager, + ): Promise { + const verificationCodeFactory = factoryManager.get( + VerificationCodeEntity, + ); + + await verificationCodeFactory.save(); + + console.log(`인증코드 생성 완료`); + } +}