From 37df847d7597106e4c0797e986389b85c45ae97b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=EC=A4=80=ED=9D=A0?= Date: Tue, 30 Aug 2022 15:53:40 +0900 Subject: [PATCH] =?UTF-8?q?NestJS=20=EC=88=98=EC=A0=951..?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 2 +- src/logger.middleware.ts | 6 +++ src/main.ts | 36 ++++++++++++------ src/todo/todo.controller.ts | 73 +++++++++++++++++++++++-------------- src/todo/todo.service.ts | 54 +++++++++++++++++++-------- src/user/user.service.ts | 14 +++---- 6 files changed, 123 insertions(+), 62 deletions(-) create mode 100644 src/logger.middleware.ts diff --git a/.env b/.env index 03e60fe..2f6bd20 100644 --- a/.env +++ b/.env @@ -11,5 +11,5 @@ JWT_SECURITY_KEY = "security_key" JWT_EXPIRE_MAX = "600s" AUTH_USERNAME_FIELD="email" -DEFAULT_TABLE_PER_PAGE = 5 +DEFAULT_TABLE_PERPAGE = 5 DEFAULT_TABLE_PAGE = 1 diff --git a/src/logger.middleware.ts b/src/logger.middleware.ts new file mode 100644 index 0000000..42facf0 --- /dev/null +++ b/src/logger.middleware.ts @@ -0,0 +1,6 @@ +import { Request, Response, NextFunction } from 'express' + +export function logger(req: Request, res: Response, next: NextFunction) { + console.log('Request...') + next() +} diff --git a/src/main.ts b/src/main.ts index 2af6381..cae1d04 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,24 +1,36 @@ //참고 : https://wikidocs.net/book/7059 +import { HttpException, HttpStatus } from '@nestjs/common' import { NestFactory } from '@nestjs/core' import { AppModule } from './app.module' +import { logger } from './logger.middleware' async function bootstrap() { - const app = await NestFactory.create(AppModule) //Enable All CORS Requests : https://docs.nestjs.com/security/cors - const corsOptions = function (req, callback) { - const origin = req.header('Origin') - let corsOptions - if (process.env.CORS_ALLOW_LIST.indexOf(origin) !== -1) { - corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response - console.log('Allowed Origin URL: ' + origin) - } else { - corsOptions = { origin: false } // disable CORS for this request - console.log('Not Allowed Origin URL: ' + origin) + const corsOptions = { + origin: (origin, callback) => { + //origin URL이 허용된 경우 또는 orgin자체가 없는 경우(postman tool) 통과 + if (process.env.CORS_ALLOW_LIST.includes(origin) || !origin) { + console.log( + 'Allowed Origin URL: ' + !origin ? 'JSON tool 사용' : origin + ) + callback(null, true) + } else { + callback( + new HttpException( + { + status: HttpStatus.FORBIDDEN, + error: origin + '에서는 접근이 허용되지 않습니다.' + }, + HttpStatus.FORBIDDEN + ) + ) + } } - callback(null, corsOptions) // callback expects two parameters: error and options } - app.enableCors(corsOptions) + const app = await NestFactory.create(AppModule) + app.enableCors({ ...corsOptions }) + //app.use(logger) await app.listen(3000, function () { console.log( '[CORS-enabled->npm install -g webpack webpack-cli] web server listening on port 3000' diff --git a/src/todo/todo.controller.ts b/src/todo/todo.controller.ts index 5e74a7f..ea54de8 100644 --- a/src/todo/todo.controller.ts +++ b/src/todo/todo.controller.ts @@ -14,7 +14,6 @@ import { HasRoles } from 'src/auth/decorators/has-roles.decorator' import { JwtAuthGuard } from 'src/auth/guards/jwt.authguard' import { Role } from 'src/auth/guards/role.enum' import { RolesGuard } from 'src/auth/guards/roles.guard' -import { TodoDTO } from './dtos/todo.dto' import { TodoService } from './todo.service' @Controller('todo') @@ -23,61 +22,81 @@ export class TodoController { @Get() async fetchAll(@Query() query): Promise { - //Sql용 console.log(query) - const searchSql = query.search - ? { - OR: [ - { title: { contains: query.search as string } }, - { content: { contains: query.search as string } } - ] - } - : {} + //Field별 filter AND Sql용 + const filterSql = {} + console.log(filterSql) + + //Field별 search OR Sql용 + const searchFieldSQL = [] + for (const index in query.searchFields) { + const temp = { + [query.searchFields[index]]: { contains: query.search as string } + } + searchFieldSQL.push(temp) + } + const searchSql = query.search ? { OR: searchFieldSQL } : {} + console.log(searchSql) + + //fetch SQL용 const page = query.page - ? parseInt(query.page) + ? parseInt(query.page) - 1 : parseInt(process.env.DEFAULT_TABLE_PAGE) - const per_page = query.per_page - ? parseInt(query.per_page) - : parseInt(process.env.DEFAULT_TABLE_PER_PAGE) + const perPage = query.perPage + ? parseInt(query.perPage) + : parseInt(process.env.DEFAULT_TABLE_PERPAGE) const fetchSQL = { - skip: (page - 1) * per_page, - take: per_page, + skip: page * perPage, + take: perPage, where: { - //is_done: true, + ...filterSql, ...searchSql }, - orderBy: { id: 'desc' } + orderBy: { [query.sortBy]: query.sortDirectioin } } console.log(fetchSQL) - return this.todoService.fetchAll(fetchSQL) + + //전체 갯수 및 fetched Data + const total = await this.todoService.count(fetchSQL) + const rows = await this.todoService.fetchAll(fetchSQL) + const result = { + total: total, + perPage: perPage, + page: page + 1, + rows: rows + } + //console.log(result) + console.log('--------------------------------------------') + return result } @HasRoles(Role.USER) @UseGuards(JwtAuthGuard, RolesGuard) @Get(':id') async fetchOne(@Param('id') id: number): Promise { - return this.todoService.fetchOne(id) + return await this.todoService.fetchOne(id) } @HasRoles(Role.USER) @UseGuards(JwtAuthGuard, RolesGuard) @Delete(':id') async delete(@Param('id') id: number): Promise { - return this.todoService.remove(id) + return await this.todoService.remove(id) } - @HasRoles(Role.USER) - @UseGuards(JwtAuthGuard, RolesGuard) + // @HasRoles(Role.USER) + // @UseGuards(JwtAuthGuard, RolesGuard) + //@UseGuards(JwtAuthGuard) @Post() - async add(@Body() data: Todo): Promise { - return this.todoService.add(data) + async add(@Body() todo: Todo): Promise { + return await this.todoService.add(todo) } @HasRoles(Role.USER) @UseGuards(JwtAuthGuard, RolesGuard) @Put(':id') - async update(@Param('id') id: number, @Body() data: TodoDTO): Promise { - return this.todoService.update(id, data) + async update(@Param('id') id: number, @Body() todo: Todo): Promise { + return await this.todoService.update(id, todo) } } diff --git a/src/todo/todo.service.ts b/src/todo/todo.service.ts index a9d363f..72df864 100644 --- a/src/todo/todo.service.ts +++ b/src/todo/todo.service.ts @@ -1,43 +1,67 @@ import { Injectable } from '@nestjs/common' -import { Todo } from '@prisma/client' +import { Prisma, Todo } from '@prisma/client' import { PrismaService } from 'src/prisma.service' -import { TodoDTO } from './dtos/todo.dto' @Injectable() export class TodoService { - todo: any - constructor(private prismaService: PrismaService) {} + constructor(private prisma: PrismaService) {} //참고: https://intrepidgeeks.com/tutorial/05-instagram-clone-code-5-user-summary //전체조회 - async count(sql: any): Promise { - return this.prismaService.todo.count(sql) + async count(params: { + skip?: number + take?: number + cursor?: Prisma.TodoWhereUniqueInput + where?: Prisma.TodoWhereInput + orderBy?: Prisma.TodoOrderByWithRelationInput + }): Promise { + const { skip, take, cursor, where, orderBy } = params + return this.prisma.todo.count({ + cursor, + where, + orderBy + }) } - async fetchAll(sql: any): Promise { - return this.prismaService.todo.findMany(sql) + async fetchAll(params: { + skip?: number + take?: number + cursor?: Prisma.TodoWhereUniqueInput + where?: Prisma.TodoWhereInput + orderBy?: Prisma.TodoOrderByWithRelationInput + }): Promise { + const { skip, take, cursor, where, orderBy } = params + return this.prisma.todo.findMany({ + skip, + take, + cursor, + where, + orderBy + }) } //단일 조회 async fetchOne(id: number): Promise { - return this.prismaService.todo.findUnique({ where: { id: Number(id) } }) + return this.prisma.todo.findUnique({ + where: { id: Number(id) } + }) } //단일 삭제 async remove(id: number): Promise { - return this.prismaService.todo.delete({ where: { id: Number(id) } }) + return this.prisma.todo.delete({ where: { id: Number(id) } }) } //단일 추가 - async add(data: Todo): Promise { - return this.prismaService.todo.create({ data: data }) + async add(todo: Prisma.TodoCreateInput): Promise { + return this.prisma.todo.create({ data: todo }) } //단일 수정 - async update(id: number, data: TodoDTO): Promise { - return this.prismaService.todo.update({ + async update(id: number, todo: Todo): Promise { + return this.prisma.todo.update({ where: { id: Number(id) }, - data: data + data: todo }) } } diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 2387d51..b3f9c22 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -5,36 +5,36 @@ import { UserDTO } from './dtos/user.dto' @Injectable() export class UserService { - constructor(private prismaService: PrismaService) {} + constructor(private prisma: PrismaService) {} //단일 조회 ByEmail async fetchOneByEmail(email: string): Promise { - return this.prismaService.user.findUnique({ where: { email: email } }) + return this.prisma.user.findUnique({ where: { email: email } }) } //전체조회 async fetchAll(sql: any): Promise { - return this.prismaService.user.findMany(sql) + return this.prisma.user.findMany(sql) } //단일 조회 async fetchOne(id: number): Promise { - return this.prismaService.user.findUnique({ where: { id: Number(id) } }) + return this.prisma.user.findUnique({ where: { id: Number(id) } }) } //단일 삭제 async remove(id: number): Promise { - return this.prismaService.user.delete({ where: { id: Number(id) } }) + return this.prisma.user.delete({ where: { id: Number(id) } }) } //단일 추가 async add(data: User): Promise { - return this.prismaService.user.create({ data: data }) + return this.prisma.user.create({ data: data }) } //단일 수정 async update(id: number, data: UserDTO): Promise { - return this.prismaService.user.update({ + return this.prisma.user.update({ where: { id: Number(id) }, data: data })