nestjs_auth ...

This commit is contained in:
최준흠 2022-09-10 12:02:23 +09:00
parent 64cd01b669
commit a1be293719
16 changed files with 110 additions and 78 deletions

2
.env
View File

@ -4,7 +4,7 @@
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings # See the documentation for all the connection string options: https://pris.ly/d/connection-strings
DATABASE_URL="mysql://root:@localhost:3306/test" DATABASE_URL="mysql://root:@localhost:3306/test_user"
CORS_ALLOW_ORIGINS = ['http://localhost:8080'] CORS_ALLOW_ORIGINS = ['http://localhost:8080']
CORS_ALLOW_METHOD = "GET,PUT,POST,DELETE,PATCH,OPTIONS" CORS_ALLOW_METHOD = "GET,PUT,POST,DELETE,PATCH,OPTIONS"

40
package-lock.json generated
View File

@ -14,7 +14,7 @@
"@nestjs/jwt": "^9.0.0", "@nestjs/jwt": "^9.0.0",
"@nestjs/passport": "^9.0.0", "@nestjs/passport": "^9.0.0",
"@nestjs/platform-express": "^9.0.0", "@nestjs/platform-express": "^9.0.0",
"@prisma/client": "^4.3.0", "@prisma/client": "^4.3.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"passport": "^0.6.0", "passport": "^0.6.0",
"passport-jwt": "^4.0.0", "passport-jwt": "^4.0.0",
@ -37,7 +37,7 @@
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"jest": "28.1.2", "jest": "28.1.2",
"prettier": "^2.3.2", "prettier": "^2.3.2",
"prisma": "^4.3.0", "prisma": "^4.3.1",
"source-map-support": "^0.5.20", "source-map-support": "^0.5.20",
"supertest": "^6.1.3", "supertest": "^6.1.3",
"ts-jest": "28.0.5", "ts-jest": "28.0.5",
@ -3053,9 +3053,9 @@
} }
}, },
"node_modules/ci-info": { "node_modules/ci-info": {
"version": "3.3.2", "version": "3.4.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz",
"integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==",
"dev": true "dev": true
}, },
"node_modules/cjs-module-lexer": { "node_modules/cjs-module-lexer": {
@ -3469,9 +3469,9 @@
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.4.246", "version": "1.4.247",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.246.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.247.tgz",
"integrity": "sha512-/wFCHUE+Hocqr/LlVGsuKLIw4P2lBWwFIDcNMDpJGzyIysQV4aycpoOitAs32FT94EHKnNqDR/CVZJFbXEufJA==", "integrity": "sha512-FLs6R4FQE+1JHM0hh3sfdxnYjKvJpHZyhQDjc2qFq/xFvmmRt/TATNToZhrcGUFzpF2XjeiuozrA8lI0PZmYYw==",
"dev": true "dev": true
}, },
"node_modules/emittery": { "node_modules/emittery": {
@ -4014,9 +4014,9 @@
"dev": true "dev": true
}, },
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.2.11", "version": "3.2.12",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
"integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.stat": "^2.0.2",
@ -10791,9 +10791,9 @@
"dev": true "dev": true
}, },
"ci-info": { "ci-info": {
"version": "3.3.2", "version": "3.4.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz",
"integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==",
"dev": true "dev": true
}, },
"cjs-module-lexer": { "cjs-module-lexer": {
@ -11119,9 +11119,9 @@
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
}, },
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.4.246", "version": "1.4.247",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.246.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.247.tgz",
"integrity": "sha512-/wFCHUE+Hocqr/LlVGsuKLIw4P2lBWwFIDcNMDpJGzyIysQV4aycpoOitAs32FT94EHKnNqDR/CVZJFbXEufJA==", "integrity": "sha512-FLs6R4FQE+1JHM0hh3sfdxnYjKvJpHZyhQDjc2qFq/xFvmmRt/TATNToZhrcGUFzpF2XjeiuozrA8lI0PZmYYw==",
"dev": true "dev": true
}, },
"emittery": { "emittery": {
@ -11535,9 +11535,9 @@
"dev": true "dev": true
}, },
"fast-glob": { "fast-glob": {
"version": "3.2.11", "version": "3.2.12",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
"integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.stat": "^2.0.2",

View File

@ -26,7 +26,7 @@
"@nestjs/jwt": "^9.0.0", "@nestjs/jwt": "^9.0.0",
"@nestjs/passport": "^9.0.0", "@nestjs/passport": "^9.0.0",
"@nestjs/platform-express": "^9.0.0", "@nestjs/platform-express": "^9.0.0",
"@prisma/client": "^4.3.0", "@prisma/client": "^4.3.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"passport": "^0.6.0", "passport": "^0.6.0",
"passport-jwt": "^4.0.0", "passport-jwt": "^4.0.0",
@ -49,7 +49,7 @@
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"jest": "28.1.2", "jest": "28.1.2",
"prettier": "^2.3.2", "prettier": "^2.3.2",
"prisma": "^4.3.0", "prisma": "^4.3.1",
"source-map-support": "^0.5.20", "source-map-support": "^0.5.20",
"supertest": "^6.1.3", "supertest": "^6.1.3",
"ts-jest": "28.0.5", "ts-jest": "28.0.5",
@ -74,5 +74,8 @@
], ],
"coverageDirectory": "../coverage", "coverageDirectory": "../coverage",
"testEnvironment": "node" "testEnvironment": "node"
},
"prisma": {
"seed": "ts-node prisma/seed.ts"
} }
} }

View File

@ -4,11 +4,12 @@ CREATE TABLE `User` (
`email` VARCHAR(191) NOT NULL, `email` VARCHAR(191) NOT NULL,
`password` VARCHAR(191) NOT NULL, `password` VARCHAR(191) NOT NULL,
`name` VARCHAR(191) NOT NULL, `name` VARCHAR(191) NOT NULL,
`role` VARCHAR(191) NOT NULL DEFAULT 'USER', `role` ENUM('USER', 'ADMIN') NOT NULL DEFAULT 'USER',
`is_done` BOOLEAN NULL DEFAULT false, `is_done` BOOLEAN NULL DEFAULT false,
`updatedAt` TIMESTAMP(0) NULL, `updatedAt` TIMESTAMP(0) NULL,
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
UNIQUE INDEX `User_email_key`(`email`), UNIQUE INDEX `User_email_key`(`email`),
INDEX `email`(`email`),
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

View File

@ -1,6 +1,3 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client { generator client {
provider = "prisma-client-js" provider = "prisma-client-js"
} }
@ -10,14 +7,20 @@ datasource db {
url = env("DATABASE_URL") url = env("DATABASE_URL")
} }
//만들려는 모델
model User { model User {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
email String @unique email String @unique(map: "User_email_key")
password String password String
name String name String
role String @default("USER") role ROLE @default(USER)
is_done Boolean? @default(false) is_done Boolean? @default(false)
updatedAt DateTime? @db.Timestamp(0) updatedAt DateTime? @db.Timestamp(0)
createdAt DateTime @default(now()) createdAt DateTime @default(now())
@@index([email], name: "email")
}
enum ROLE {
USER
ADMIN
} }

View File

@ -1,5 +1,13 @@
/* eslint-disable prettier/prettier */ /* eslint-disable prettier/prettier */
import { Body, Controller, Get, Post, Request, UseGuards } from '@nestjs/common' import {
Body,
Controller,
Get,
Param,
Post,
UseGuards,
Request
} from '@nestjs/common'
import { User } from '@prisma/client' import { User } from '@prisma/client'
import { UserDTO } from 'src/user/dtos/user.dto' import { UserDTO } from 'src/user/dtos/user.dto'
import { AuthService } from './auth.service' import { AuthService } from './auth.service'
@ -13,9 +21,9 @@ export class AuthController {
//Login용 //Login용
@UseGuards(LocalAuthGuard) @UseGuards(LocalAuthGuard)
@Post('login') @Post('login')
login(@Request() req) { login(@Param('email') email: string, @Param('password') password: string) {
//console.log(req) //console.log(req)
return this.authService.login(req.user) return this.authService.login(email, password)
} }
//Profile 여부 확인용 //Profile 여부 확인용

View File

@ -6,7 +6,7 @@ import { Module } from '@nestjs/common'
import { PassportModule } from '@nestjs/passport' import { PassportModule } from '@nestjs/passport'
import { AuthService } from './auth.service' import { AuthService } from './auth.service'
import { JwtModule } from '@nestjs/jwt' import { JwtModule } from '@nestjs/jwt'
import { jwtAcceesTokenTypes } from './guards/jwt.constants' import { jwtAcceesTokenOptions } from './guards/jwt.constants'
import { AuthController } from './auth.controller' import { AuthController } from './auth.controller'
import { LocalStrategy } from './guards/local.strategy' import { LocalStrategy } from './guards/local.strategy'
import { JwtStrategy } from './guards/jwt.strategy' import { JwtStrategy } from './guards/jwt.strategy'
@ -17,8 +17,8 @@ import { UsersModule } from '../user/user.module'
UsersModule, UsersModule,
PassportModule, PassportModule,
JwtModule.register({ JwtModule.register({
secret: jwtAcceesTokenTypes.secret, secret: jwtAcceesTokenOptions.secret,
signOptions: { expiresIn: jwtAcceesTokenTypes.expiresIn } signOptions: { expiresIn: jwtAcceesTokenOptions.expiresIn }
}) })
], ],
controllers: [AuthController], controllers: [AuthController],

View File

@ -4,6 +4,10 @@ import { JwtService } from '@nestjs/jwt'
import { User } from '@prisma/client' import { User } from '@prisma/client'
import { UserDTO } from 'src/user/dtos/user.dto' import { UserDTO } from 'src/user/dtos/user.dto'
import { UserService } from '../user/user.service' import { UserService } from '../user/user.service'
import {
jwtAcceesTokenOptions,
jwtRefreshTokenTypes
} from './guards/jwt.constants'
@Injectable() @Injectable()
export class AuthService { export class AuthService {
@ -13,8 +17,8 @@ export class AuthService {
) {} ) {}
//app.controller.ts에서 @UseGuards(AuthGuard('local'))용 //app.controller.ts에서 @UseGuards(AuthGuard('local'))용
async validateUser(email: string, password: string): Promise<any> { async validateUser(email: string, password: string): Promise<any> | null {
const user = await this.userService.fetchOneByEmail(email) const user = await this.userService.fetchOne({ email: email })
if (user && user.password === password) { if (user && user.password === password) {
const { password, ...result } = user const { password, ...result } = user
// result는 password 를 제외한 user의 모든 정보를 포함한다. // result는 password 를 제외한 user의 모든 정보를 포함한다.
@ -25,17 +29,37 @@ export class AuthService {
return null return null
} }
async login(user: any) { async getTokens(user: User): Promise<any> {
//console.log(user) //console.log(user)
const payload = { const access_token_payload = {
email: user.email, email: user.email,
name: user.name name: user.name
} }
const refresh_token_payload = {}
// console.log(payload) // console.log(payload)
return await { access_token: this.jwtService.sign(payload) } return {
tokens: {
access_token: this.jwtService.sign(
access_token_payload,
jwtAcceesTokenOptions
),
refresh_token: this.jwtService.sign(
refresh_token_payload,
jwtRefreshTokenTypes
)
}
}
} }
async register(data: UserDTO): Promise<User> { async login(email: string, password: string): Promise<any> | null {
return await this.userService.add(data) const user = await this.validateUser(email, password)
if (!user) return null
return await this.getTokens(user)
}
async register(data: UserDTO): Promise<any> | null {
const user = await this.userService.add(data)
if (!user) return null
return await this.getTokens(user)
} }
} }

View File

@ -1,4 +0,0 @@
export enum Role {
USER = 'USER',
ADMIN = 'ADMIN'
}

View File

@ -1,5 +1,5 @@
import { SetMetadata } from '@nestjs/common' import { SetMetadata } from '@nestjs/common'
import { Role } from './role.enum' import { ROLE } from '@prisma/client'
export const ROLES_KEY = 'roles' export const ROLES_KEY = 'roles'
export const Roles = (...roles: Role[]) => SetMetadata(ROLES_KEY, roles) export const Roles = (...roles: ROLE[]) => SetMetadata(ROLES_KEY, roles)

View File

@ -1,4 +1,4 @@
export const jwtAcceesTokenTypes = { export const jwtAcceesTokenOptions = {
secret: process.env.JWT_ACCESS_TOKEN_SECRET, secret: process.env.JWT_ACCESS_TOKEN_SECRET,
expiresIn: process.env.JWT_ACCESS_TOKEN_EXPIREIN, expiresIn: process.env.JWT_ACCESS_TOKEN_EXPIREIN,
issuer: process.env.JWT_ACCESS_TOKEN_ISSUER issuer: process.env.JWT_ACCESS_TOKEN_ISSUER

View File

@ -1,7 +1,7 @@
import { ExtractJwt, Strategy } from 'passport-jwt' import { ExtractJwt, Strategy } from 'passport-jwt'
import { PassportStrategy } from '@nestjs/passport' import { PassportStrategy } from '@nestjs/passport'
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
import { jwtAcceesTokenTypes } from './jwt.constants' import { jwtAcceesTokenOptions } from './jwt.constants'
@Injectable() @Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) { export class JwtStrategy extends PassportStrategy(Strategy) {
@ -9,7 +9,7 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
super({ super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false, ignoreExpiration: false,
secretOrKey: jwtAcceesTokenTypes.secret secretOrKey: jwtAcceesTokenOptions.secret
}) })
} }

View File

@ -1,8 +1,8 @@
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common' import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'
import { Reflector } from '@nestjs/core' import { Reflector } from '@nestjs/core'
import { ROLE } from '@prisma/client'
import { Observable } from 'rxjs' import { Observable } from 'rxjs'
import { ROLES_KEY } from '../decorators/roles.decorator' import { ROLES_KEY } from '../decorators/roles.decorator'
import { Role } from '../decorators/role.enum'
//참고: https://shpota.com/2022/07/16/role-based-authorization-with-jwt-using-nestjs.html //참고: https://shpota.com/2022/07/16/role-based-authorization-with-jwt-using-nestjs.html
@Injectable() @Injectable()
@ -12,7 +12,7 @@ export class RolesGuard implements CanActivate {
canActivate( canActivate(
context: ExecutionContext context: ExecutionContext
): boolean | Promise<boolean> | Observable<boolean> { ): boolean | Promise<boolean> | Observable<boolean> {
const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [ const requiredRoles = this.reflector.getAllAndOverride<ROLE[]>(ROLES_KEY, [
context.getHandler(), context.getHandler(),
context.getClass() context.getClass()
]) ])

View File

@ -1,8 +1,10 @@
import { ROLE, User } from '@prisma/client'
export class UserDTO { export class UserDTO {
email: string email: string
password: string password: string
name: string name: string
role?: string | 'USER' role?: ROLE | 'USER'
is_done?: boolean | false is_done?: boolean | false
updatedAt?: Date | null updatedAt?: Date | null
createdAt?: Date createdAt?: Date

View File

@ -15,14 +15,14 @@ import { UserDTO } from './dtos/user.dto'
import { UserService } from './user.service' import { UserService } from './user.service'
import { Roles } from '../auth/decorators/roles.decorator' import { Roles } from '../auth/decorators/roles.decorator'
import { JwtAuthGuard } from '../auth/guards/jwt.auth.guard' import { JwtAuthGuard } from '../auth/guards/jwt.auth.guard'
import { Role } from '../auth/decorators/role.enum'
import { RolesGuard } from '../auth/guards/roles.guard' import { RolesGuard } from '../auth/guards/roles.guard'
import { ROLE } from '@prisma/client'
@Controller('user') @Controller('user')
export class UserController { export class UserController {
constructor(private readonly userService: UserService) {} constructor(private readonly userService: UserService) {}
@Roles(Role.ADMIN) @Roles(ROLE.ADMIN)
@UseGuards(JwtAuthGuard, RolesGuard) @UseGuards(JwtAuthGuard, RolesGuard)
@Get() @Get()
async fetchAll(@Query() query): Promise<any> { async fetchAll(@Query() query): Promise<any> {
@ -129,21 +129,21 @@ export class UserController {
return result return result
} }
@Roles(Role.ADMIN) @Roles(ROLE.ADMIN)
@UseGuards(JwtAuthGuard, RolesGuard) @UseGuards(JwtAuthGuard, RolesGuard)
@Get(':id') @Get(':id')
async fetchOne(@Param('id') id: string): Promise<User | undefined> { async fetchOne(@Param('id') id: string): Promise<User | undefined> {
return await this.userService.fetchOne({ id: Number(id) }) return await this.userService.fetchOne({ id: Number(id) })
} }
@Roles(Role.ADMIN) @Roles(ROLE.ADMIN)
@UseGuards(JwtAuthGuard, RolesGuard) @UseGuards(JwtAuthGuard, RolesGuard)
@Post('add') @Post('add')
async add(@Body() data: UserDTO): Promise<User> { async add(@Body() data: UserDTO): Promise<User> {
return await this.userService.add(data) return await this.userService.add(data)
} }
@Roles(Role.ADMIN) @Roles(ROLE.ADMIN)
@UseGuards(JwtAuthGuard, RolesGuard) @UseGuards(JwtAuthGuard, RolesGuard)
@Put(':id') @Put(':id')
async update(@Param('id') id: string, @Body() data: UserDTO): Promise<User> { async update(@Param('id') id: string, @Body() data: UserDTO): Promise<User> {
@ -154,7 +154,7 @@ export class UserController {
}) })
} }
@Roles(Role.ADMIN) @Roles(ROLE.ADMIN)
@UseGuards(JwtAuthGuard, RolesGuard) @UseGuards(JwtAuthGuard, RolesGuard)
@Delete(':id') @Delete(':id')
async delete(@Param('id') id: string): Promise<User | undefined> { async delete(@Param('id') id: string): Promise<User | undefined> {

View File

@ -1,7 +1,7 @@
/* eslint-disable prettier/prettier */ /* eslint-disable prettier/prettier */
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
import { Prisma, User } from '@prisma/client' import { Prisma, User } from '@prisma/client'
import { PrismaService } from '../prisma.service' import { PrismaService } from 'src/prisma.service'
@Injectable() @Injectable()
export class UserService { export class UserService {
@ -12,18 +12,13 @@ export class UserService {
}) })
} }
//단일 조회 ByEmail
async fetchOneByEmail(email: string): Promise<User | undefined> {
return this.prisma.user.findUnique({ where: { email: email } })
}
//전체조회 //전체조회
async count(params: { async count(params: {
cursor?: Prisma.UserWhereUniqueInput cursor?: Prisma.UserWhereUniqueInput
where?: Prisma.UserWhereInput where?: Prisma.UserWhereInput
}): Promise<number> { }): Promise<number> {
const { cursor, where } = params const { cursor, where } = params
return this.prisma.user.count({ return await this.prisma.user.count({
cursor, cursor,
where where
}) })
@ -38,7 +33,7 @@ export class UserService {
orderBy?: Prisma.UserOrderByWithRelationInput orderBy?: Prisma.UserOrderByWithRelationInput
}): Promise<User[]> { }): Promise<User[]> {
const { skip, take, cursor, where, orderBy } = params const { skip, take, cursor, where, orderBy } = params
return this.prisma.user.findMany({ return await this.prisma.user.findMany({
skip, skip,
take, take,
cursor, cursor,
@ -49,12 +44,12 @@ export class UserService {
//단일 조회 //단일 조회
async fetchOne(where: Prisma.UserWhereUniqueInput): Promise<User | null> { async fetchOne(where: Prisma.UserWhereUniqueInput): Promise<User | null> {
return this.prisma.user.findUnique({ where }) return await this.prisma.user.findUnique({ where })
} }
//단일 추가 //단일 추가
async add(data: Prisma.UserCreateInput): Promise<User> { async add(data: Prisma.UserCreateInput): Promise<User> {
return this.prisma.user.create({ data }) return await this.prisma.user.create({ data })
} }
//단일 수정 //단일 수정
@ -63,7 +58,7 @@ export class UserService {
data: Prisma.UserUpdateInput data: Prisma.UserUpdateInput
}): Promise<User | null> { }): Promise<User | null> {
const { where, data } = params const { where, data } = params
return this.prisma.user.update({ return await this.prisma.user.update({
data, data,
where where
}) })
@ -71,6 +66,6 @@ export class UserService {
//단일 삭제 //단일 삭제
async remove(where: Prisma.UserWhereUniqueInput): Promise<User | null> { async remove(where: Prisma.UserWhereUniqueInput): Promise<User | null> {
return this.prisma.user.delete({ where }) return await this.prisma.user.delete({ where })
} }
} }