diff --git a/.prettierrc b/.prettierrc index dcb7279..00f15e3 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,8 @@ { + "semi": false, + "bracketSapcing": true, "singleQuote": true, - "trailingComma": "all" -} \ No newline at end of file + "useTabs": false, + "trailingComma": "none", + "printWith": 80 +} diff --git a/prisma/migrations/20220809023948_create_todo_table/migration.sql b/prisma/migrations/20220809023948_create_todo_table/migration.sql deleted file mode 100644 index 2a6dedd..0000000 --- a/prisma/migrations/20220809023948_create_todo_table/migration.sql +++ /dev/null @@ -1,9 +0,0 @@ --- CreateTable -CREATE TABLE `Todo` ( - `id` INTEGER NOT NULL AUTO_INCREMENT, - `title` VARCHAR(191) NOT NULL, - `content` VARCHAR(191) NULL, - `is_don` BOOLEAN NULL DEFAULT false, - - PRIMARY KEY (`id`) -) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; diff --git a/prisma/migrations/20220809102152_create_user_table/migration.sql b/prisma/migrations/20220809102152_create_user_table/migration.sql deleted file mode 100644 index c8a8435..0000000 --- a/prisma/migrations/20220809102152_create_user_table/migration.sql +++ /dev/null @@ -1,19 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `is_don` on the `todo` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE `todo` DROP COLUMN `is_don`, - ADD COLUMN `is_done` BOOLEAN NULL DEFAULT false; - --- CreateTable -CREATE TABLE `User` ( - `id` INTEGER NOT NULL AUTO_INCREMENT, - `username` VARCHAR(191) NOT NULL, - `password` VARCHAR(191) NOT NULL, - `is_done` BOOLEAN NULL DEFAULT false, - - PRIMARY KEY (`id`) -) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; diff --git a/prisma/migrations/20220812062434_add_user_role/migration.sql b/prisma/migrations/20220812062434_add_user_role/migration.sql deleted file mode 100644 index 278e287..0000000 --- a/prisma/migrations/20220812062434_add_user_role/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE `user` ADD COLUMN `role` VARCHAR(191) NULL DEFAULT 'user'; diff --git a/prisma/migrations/20220817070421_init/migration.sql b/prisma/migrations/20220817070421_init/migration.sql new file mode 100644 index 0000000..00427cd --- /dev/null +++ b/prisma/migrations/20220817070421_init/migration.sql @@ -0,0 +1,26 @@ +-- CreateTable +CREATE TABLE `User` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `email` VARCHAR(191) NOT NULL, + `password` VARCHAR(191) NOT NULL, + `name` VARCHAR(191) NOT NULL, + `role` VARCHAR(191) NOT NULL DEFAULT 'USER', + `is_done` BOOLEAN NULL DEFAULT false, + `updatedAt` TIMESTAMP(0) NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + + UNIQUE INDEX `User_email_key`(`email`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `Todo` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `title` VARCHAR(191) NOT NULL, + `content` VARCHAR(191) NULL, + `is_done` BOOLEAN NULL DEFAULT false, + `updatedAt` TIMESTAMP(0) NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 0a429c5..ad23dd6 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -3,6 +3,7 @@ generator client { provider = "prisma-client-js" + previewFeatures = ["interactiveTransactions"] } //데이터베이스 연동 @@ -11,18 +12,23 @@ datasource db { url = env("DATABASE_URL") } +model User { + id Int @id @default(autoincrement()) + email String @unique + password String + name String + role String @default("USER") + is_done Boolean? @default(false) + updatedAt DateTime? @db.Timestamp(0) + createdAt DateTime @default(now()) +} + //만들려는 모델 model Todo { - id Int @id @default(autoincrement()) + id Int @id @default(autoincrement()) title String content String? is_done Boolean? @default(false) -} - -model User { - id Int @id @default(autoincrement()) - username String - password String - role String? @default("user") - is_done Boolean? @default(false) -} + updatedAt DateTime? @db.Timestamp(0) + createdAt DateTime @default(now()) +} \ No newline at end of file diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 7296464..f9b6586 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -1,27 +1,27 @@ -import { Injectable } from '@nestjs/common'; -import { UserService } from 'src/user/user.service'; -import { JwtService } from '@nestjs/jwt'; +import { Injectable } from '@nestjs/common' +import { UserService } from 'src/user/user.service' +import { JwtService } from '@nestjs/jwt' @Injectable() export class AuthService { constructor( private userService: UserService, - private jwtService: JwtService, + private jwtService: JwtService ) {} //app.controller.ts에서 @UseGuards(AuthGuard('local'))용 - async validateUser(username: string, password: string): Promise { - const user = await this.userService.findOne(username); + async validateUser(email: string, password: string): Promise { + const user = await this.userService.fetchOneByEmail(email) if (user && user.password === password) { - const { password, ...result } = user; + const { password, ...result } = user // result는 password 를 제외한 user의 모든 정보를 포함한다. - return result; + return result } - return null; + return null } async login(user: any) { - const payload = { id: user.id, username: user.username, role: user.role }; - return { access_token: this.jwtService.sign(payload) }; + const payload = { id: user.id, username: user.username, role: user.role } + return { access_token: this.jwtService.sign(payload) } } } diff --git a/src/todo/todo.controller.ts b/src/todo/todo.controller.ts index c66fda0..ddee226 100644 --- a/src/todo/todo.controller.ts +++ b/src/todo/todo.controller.ts @@ -6,37 +6,44 @@ import { Param, Post, Put, -} from '@nestjs/common'; -import { Todo } from '@prisma/client'; -import { TodoDTO } from './dtos/todo.dto'; -import { TodoService } from './todo.service'; + Query +} from '@nestjs/common' +import { Todo } from '@prisma/client' +import { TodoDTO } from './dtos/todo.dto' +import { TodoService } from './todo.service' @Controller('todo') export class TodoController { constructor(private readonly todoService: TodoService) {} @Get() - async fetchAll(): Promise { - return this.todoService.fetchAll(); + async fetchAll( + @Query() queries: { page?: number; per_page?: number } + ): Promise { + queries.per_page = isNaN(queries.per_page) ? 20 : Number(queries.per_page) + queries.page = isNaN(queries.page) + ? 0 + : Number(queries.page) * queries.per_page + return this.todoService.fetchAll(queries) } @Get(':id') async fetchOne(@Param('id') id: number): Promise { - return this.todoService.fetchOne(id); + return this.todoService.fetchOne(id) } @Delete(':id') async delete(@Param('id') id: number): Promise { - return this.todoService.remove(id); + return this.todoService.remove(id) } @Post() async add(@Body() data: Todo): Promise { - return this.todoService.add(data); + return this.todoService.add(data) } @Put(':id') async update(@Param('id') id: number, @Body() data: TodoDTO): Promise { - return this.todoService.update(id, data); + return this.todoService.update(id, data) } } diff --git a/src/todo/todo.service.ts b/src/todo/todo.service.ts index ab8b245..1e883eb 100644 --- a/src/todo/todo.service.ts +++ b/src/todo/todo.service.ts @@ -1,37 +1,48 @@ -import { Injectable } from '@nestjs/common'; -import { Todo } from '@prisma/client'; -import { PrismaService } from 'src/prisma.service'; -import { TodoDTO } from './dtos/todo.dto'; +import { Injectable } from '@nestjs/common' +import { Todo, Prisma } from '@prisma/client' +import { PrismaService } from 'src/prisma.service' +import { TodoDTO } from './dtos/todo.dto' @Injectable() export class TodoService { constructor(private prismaService: PrismaService) {} + //참고: https://intrepidgeeks.com/tutorial/05-instagram-clone-code-5-user-summary //전체조회 - async fetchAll(): Promise { - return this.prismaService.todo.findMany(); + async fetchAll(params: { + page?: number + per_page?: number + }): Promise { + const { page, per_page } = params + + return this.prismaService.todo.findMany({ + skip: page, + take: per_page, + //where: { is_done: true }, + orderBy: { id: 'desc' } + }) } //단일 조회 async fetchOne(id: number): Promise { - return this.prismaService.todo.findUnique({ where: { id: Number(id) } }); + return this.prismaService.todo.findUnique({ where: { id: Number(id) } }) } //단일 삭제 async remove(id: number): Promise { - return this.prismaService.todo.delete({ where: { id: Number(id) } }); + return this.prismaService.todo.delete({ where: { id: Number(id) } }) } //단일 추가 async add(data: Todo): Promise { - return this.prismaService.todo.create({ data: data }); + return this.prismaService.todo.create({ data: data }) } //단일 수정 async update(id: number, data: TodoDTO): Promise { return this.prismaService.todo.update({ where: { id: Number(id) }, - data: data, - }); + data: data + }) } } diff --git a/src/user/dtos/user.dto.ts b/src/user/dtos/user.dto.ts index 9d89999..bdd35f3 100644 --- a/src/user/dtos/user.dto.ts +++ b/src/user/dtos/user.dto.ts @@ -1,6 +1,7 @@ export class UserDTO { - username: string; - password: string; - role: string; - is_done: boolean; + email: string + password: string + name: string + role: string + is_done: boolean } diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 4942b2d..ed921ae 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -6,37 +6,44 @@ import { Param, Post, Put, -} from '@nestjs/common'; -import { User } from '@prisma/client'; -import { UserDTO } from './dtos/user.dto'; -import { UserService } from './user.service'; + Query +} from '@nestjs/common' +import { User } from '@prisma/client' +import { UserDTO } from './dtos/user.dto' +import { UserService } from './user.service' @Controller('user') export class UserController { constructor(private readonly userService: UserService) {} @Get() - async fetchAll(): Promise { - return this.userService.fetchAll(); + async fetchAll( + @Query() queries: { page?: number; per_page?: number } + ): Promise { + queries.per_page = isNaN(queries.per_page) ? 20 : Number(queries.per_page) + queries.page = isNaN(queries.page) + ? 0 + : Number(queries.page) * queries.per_page + return this.userService.fetchAll(queries) } @Get(':id') async fetchOne(@Param('id') id: number): Promise { - return this.userService.fetchOne(id); + return this.userService.fetchOne(id) } @Delete(':id') async delete(@Param('id') id: number): Promise { - return this.userService.remove(id); + return this.userService.remove(id) } @Post() async add(@Body() data: User): Promise { - return this.userService.add(data); + return this.userService.add(data) } @Put(':id') async update(@Param('id') id: number, @Body() data: UserDTO): Promise { - return this.userService.update(id, data); + return this.userService.update(id, data) } } diff --git a/src/user/user.service.ts b/src/user/user.service.ts index cc38e55..3d311cd 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -1,41 +1,52 @@ -import { Injectable } from '@nestjs/common'; -import { User } from '@prisma/client'; -import { PrismaService } from 'src/prisma.service'; -import { UserDTO } from './dtos/user.dto'; +import { Injectable } from '@nestjs/common' +import { User } from '@prisma/client' +import { PrismaService } from 'src/prisma.service' +import { UserDTO } from './dtos/user.dto' @Injectable() export class UserService { constructor(private prismaService: PrismaService) {} - async findOne(username: string): Promise { - return this.prismaService.user.findFirst({ where: { username: username } }); + //단일 조회 ByEmail + async fetchOneByEmail(email: string): Promise { + return this.prismaService.user.findUnique({ where: { email: email } }) } //전체조회 - async fetchAll(): Promise { - return this.prismaService.user.findMany(); + async fetchAll(params: { + page?: number + per_page?: number + }): Promise { + const { page, per_page } = params + + return this.prismaService.user.findMany({ + skip: page, + take: per_page, + //where: { is_done: true }, + orderBy: { id: 'desc' } + }) } //단일 조회 async fetchOne(id: number): Promise { - return this.prismaService.user.findUnique({ where: { id: Number(id) } }); + return this.prismaService.user.findUnique({ where: { id: Number(id) } }) } //단일 삭제 async remove(id: number): Promise { - return this.prismaService.user.delete({ where: { id: Number(id) } }); + return this.prismaService.user.delete({ where: { id: Number(id) } }) } //단일 추가 async add(data: User): Promise { - return this.prismaService.user.create({ data: data }); + return this.prismaService.user.create({ data: data }) } //단일 수정 async update(id: number, data: UserDTO): Promise { return this.prismaService.user.update({ where: { id: Number(id) }, - data: data, - }); + data: data + }) } } diff --git a/test/init_todo.ts b/test/init_todo.ts new file mode 100644 index 0000000..0657b67 --- /dev/null +++ b/test/init_todo.ts @@ -0,0 +1,85 @@ +import { Prisma, PrismaClient } from '@prisma/client' + +const prisma = new PrismaClient() + +//실행 방법: npx ts-node scripts.ts +async function main() { + let todos: Prisma.TodoCreateInput[] = [ + { + title: '타이틀_1', + content: '내용_1' + }, + { + title: '타이틀_2', + content: '내용_2' + }, + { + title: '타이틀_3', + content: '내용_3' + }, + { + title: '타이틀_4', + content: '내용_4' + }, + { + title: '타이틀_5', + content: '내용_5' + }, + { + title: '타이틀_6', + content: '내용_6' + }, + { + title: '타이틀_7', + content: '내용_7' + }, + { + title: '타이틀_8', + content: '내용_8' + }, + { + title: '타이틀_9', + content: '내용_9' + }, + { + title: '타이틀_10', + content: '내용_10' + }, + { + title: '타이틀_11', + content: '내용_11' + }, + { + title: '타이틀_12', + content: '내용_12' + }, + { + title: '타이틀_13', + content: '내용_13' + }, + { + title: '타이틀_14', + content: '내용_14' + }, + { + title: '타이틀_15', + content: '내용_15' + } + ] + + await Promise.all( + todos.map(async (todo) => { + await prisma.todo.create({ data: todo }) + }) + ) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) diff --git a/test/init_user.ts b/test/init_user.ts new file mode 100644 index 0000000..bb8677b --- /dev/null +++ b/test/init_user.ts @@ -0,0 +1,49 @@ +import { Prisma, PrismaClient } from '@prisma/client' + +const prisma = new PrismaClient() + +//실행 방법: npx ts-node scripts.ts +async function main() { + let users: Prisma.UserCreateInput[] = [ + { + email: 'choi.jh@idcjp.jp', + name: '최준흠', + password: '1234', + role: 'ADMIN' + }, + { + email: 'user1@idcjp.jp', + name: '사용자1', + password: '1234', + role: 'USER' + }, + { + email: 'user2@idcjp.jp', + name: '사용자2', + password: '1234', + role: 'USER' + }, + { + email: 'user3@idcjp.jp', + name: '사용자3', + password: '1234', + role: 'USER' + } + ] + + await Promise.all( + users.map(async (user) => { + await prisma.user.create({ data: user }) + }) + ) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + })