nestjs_auth ...
This commit is contained in:
parent
64cd01b669
commit
a1be293719
2
.env
2
.env
@ -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
40
package-lock.json
generated
@ -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",
|
||||||
|
|||||||
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
@ -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
|
||||||
}
|
}
|
||||||
@ -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 여부 확인용
|
||||||
|
|||||||
@ -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],
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
export enum Role {
|
|
||||||
USER = 'USER',
|
|
||||||
ADMIN = 'ADMIN'
|
|
||||||
}
|
|
||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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()
|
||||||
])
|
])
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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> {
|
||||||
|
|||||||
@ -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 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user