npm i -g @nestjs/cli
nest new [project-name]
npm 선택!
@Get()
: 엔드 포인트(주소의 마지막 ex. localhost:3000/)가 '/'로 들어간다는 의미.app.module.ts
와 main.ts
만 남기고 삭제nest g module boards
--명령어 해석--
nest : using nestcli
g : generate (생성한다)
module: schematic that i want to create
boards: name of the schematic (생성하는 모듈의 이름)
nest g controller boards --no-spec
--명령어 해석--
nest : using nestcli
g : generate
controller : controller schematic
boards : name of the schematic
--no-spec : 테스트를 위한 소스 코드 생성 x
nest g service boards --no-spec
프로퍼티?
- 일부 객체 지향 프로그래밍 언어에서 필드(데이터 멤버)와 메소드 간 기능의 중간인 클래스 멤버ㅓ의 특수한 유형. 프로퍼티의 읽기와 쓰기는 일반적으로 게터(getter)와 세터(setter) 메소드 호출로 변환된다.
boards.service.ts 파일
import { Injectable } from '@nestjs/common';
@Injectable()
export class BoardsService {
private boards = [];
getAllBoards() {
return this.boards;
}
}
boards.controller.ts
파일import { Controller, Get } from '@nestjs/common';
import { BoardsService } from './boards.service';
@Controller('boards')
export class BoardsController {
constructor(private boardsService: BoardsService) {}
@Get()
getAllBoard() {
return this.boardsService.getAllBoards();
}
}
결과값
BoardStatus란?
- 이 게시물이 공개, 비공개 인지 나눠주는 것
- 이 두가지 상태 이외에는 나오면 안되기 때문에 타입스크립트의 기능 enumeration을 이용.
-
Service
에서 로직을 처리해준 후 Controller
에서 서비스를 불러오겠다.boards.service.ts 파일
import { Injectable } from '@nestjs/common';
import { Board, BoardStatus } from './boards.model';
@Injectable()
export class BoardsService {
private boards: Board[] = [];
getAllBoards(): Board[] {
return this.boards;
}
createBoard(title: string, description: string) {
const board: Board = {
title// = title: title,
description// = description: description,
status: BoardStatus.PUBLIC
}
}
}
//board 부분 에러 -> id 값 없기 때문!!
npm install uuid --save
만약 오류(ERR)가 발생한다면 --legacy-peer-deps
붙여보기
import { Injectable } from '@nestjs/common';
import { Board, BoardStatus } from './boards.model';
import { v1 as uuid } from 'uuid';
@Injectable()
export class BoardsService {
private boards: Board[] = [];
getAllBoards(): Board[] {
return this.boards;
}
createBoard(title: string, description: string) {
const board: Board = {
id: uuid(),
title,
description,
status: BoardStatus.PUBLIC
}
this.boards.push(board); //boards배열에 넣는다.
return board; //어떤 board가 생성되었는지 return
}
}
--legacy-peer-deps란?
- peerDependency가 맞지 않아도 일단 설치
// 1번째 방법
@Post()
createBoard(@Body() body) {
console.log('body', body);
}
// 2번째 방법
@Post()
createBoard(
@Body('title') title: string,
@Body('description') description: string,
) {
return this.boardsService.createBoard(title, description);
}
import { Controller, Get, Post, Body } from '@nestjs/common';
import { BoardsService } from './boards.service';
import { Board } from './boards.model';
import { CreateBoardDto } from './dto/create-Board.dto'
@Controller('boards')
export class BoardsController {
constructor(private boardsService: BoardsService) {}
@Get()
getAllBoard(): Board[] {
return this.boardsService.getAllBoards();
}
@Post()
createBoard(
@Body() createBoardDto: CreateBoardDto
): Board {
return this.boardsService.createBoard(createBoardDto);
}
}
import { Injectable } from '@nestjs/common';
import { Board, BoardStatus } from './boards.model';
import { v1 as uuid } from 'uuid';
import { CreateBoardDto } from './dto/create-Board.dto'
@Injectable()
export class BoardsService {
private boards: Board[] = [];
getAllBoards(): Board[] {
return this.boards;
}
createBoard(createBoardDto: CreateBoardDto): Board {
const {title, description } = createBoardDto;
const board: Board = {
id: uuid(),
title,
description,
status: BoardStatus.PUBLIC,
};
this.boards.push(board);
return board;
}
}
getBoardById(id: string): Board {
return this.boards.find((board) => board.id === id);
}
@Get('/:id')
getBoardById(@Param('id') id: string): Board {
return this.boardsService.getBoardById(id);
}
localhost:5000?id=alkjdf&title=werdf
라고 나와있을 때
@Param() params: string[]
으로 얻고
id 만 얻고 싶다면
@Param('id') id: string
으로 얻는다.
deleteBoard(id: string): void {
this.boards = this.boards.filter((board) => board.id !== id);
} // 특정 id가 아니면 남기겠다는 뜻!
@Delete('/:id')
deleteBoard(@Param('id') id: string): void {
this.boardsService.deleteBoard(id);
}
updateBoardStatus(id: string, status: BoardStatus): Board {
const board = this.getBoardById(id);
board.status = status;
return board;
}
@Patch('/:id/status')
updateBoardSatus(
@Param('id') id: string,
@Body('status') status: BoardStatus,
) {
return this.boardsService.updateBoardStatus(id, status);
}
main.ts
에 넣어주면 된다.npm install class-validator class-transformer --save
여기도 오류(ERR)발생한다면 --legacy-peer-deps
붙여보기
import { IsNotEmpty } from "class-validator";
export class CreateBoardDto {
@IsNotEmpty()
title: string;
@IsNotEmpty()
description: string;
}
@Post()
@UsePipes(ValidationPipe) //파이프를 사용하겠다고 말해줘야함
createBoard(
@Body() createBoardDto: CreateBoardDto
): Board {
return this.boardsService.createBoard(createBoardDto);
}
getBoardById(id: string): Board {
const found = this.boards.find((board) => board.id === id);
if (!found) {
throw new NotFoundException(`Can't find Board with id ${id}` //원하는 에러문구 넣는 곳);
}
return found;
}
import { PipeTransform, ArgumentMetadata } from "@nestjs/common";
export class BoardStatusValidationPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata){
console.log('value', value);
console.log('metadata', metadata);
return value;
}
}
@Patch('/:id/status')
updateBoardSatus(
@Param('id') id: string,
@Body('status', BoardStatusValidationPipe) status: BoardStatus,
) {
return this.boardsService.updateBoardStatus(id, status);
}
brew install postgres
pgAdmin홈페이지 가서 다운받고 goinfre에 넣기!
pgAdmin 켜서 서버 만든후에 postgresql 이름을 yejsong으로 바꾸기
brew services start posgres
해주면 오류 해결 가능
ORM이란?
- 객체와 관계형 데이터베이스의 데이터를 자동으로 변형 및 연결하는 작업이다.
- ORM을 이용한 개발은 객체와 데이터베이스의 변형에 유연하게 사용할 수 있다.
-
typeorm : typeorm 모듈 (@0.2.45 버전 쓰기)
@nestjs/typeorm : nestjs에서 typeorm을 사용하기 위한 모듈 (@8.0.3 버전)
npm pg typeorm@0.2.45 @nestjs/typeorm @8.0.3 --save --legacy-peer-deps
import { TypeOrmModuleOptions } from "@nestjs/typeorm";
export const typeORMConfig : TypeOrmModuleOptions = {
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'yejsong',
password: 'postgres',
database: 'board-app',
entities: [__dirname + '/../**/*.entity.{js,ts}'], //엔티티를 이용해서 데이터베이스 테이블을 생성해준다. 그래서 엔티티 파일이 어디있는지 설정해준다.
synchronize: true //true값을 주면 애플리케이션을 다시 실행할 떄 엔티티안에서 수정된 컬럼의 길이 타입 변경값등을 해당 테이블을 Drop한 후 다시 생성해줌
}
import { Module } from '@nestjs/common';
import { BoardsModule } from './boards/boards.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { typeORMConfig } from './configs/typeorm.config';
@Module({
imports: [
TypeOrmModule.forRoot(typeORMConfig),
BoardsModule],
})
export class AppModule {}
forRoot안에 넣어준 설정은 모든 sub-module 부수적인 모듈들에 다 적용된다.
import { BaseEntity, PrimaryGeneratedColumn, Column } from "typeorm";
import { BoardStatus } from "./boards.model";
@Entity()
export class Board extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
description: string;
@Column()
status: BoardStatus;
}
import { EntityRepository, Repository } from "typeorm";
import { Board } from "./boards.entity";
@EntityRepository(Board)
export class BoardRepository extends Repository<Board> {
}
@EntityRepository()
-클래스를 사용자 정의(CUSTOM) 저장소로 선언하는 데 사용된다. 사용자 지정 저장소는 일부 특정 엔티티를 관리하거나 일반 저장소 일 수 있다.
import { Module } from '@nestjs/common';
import { BoardsController } from './boards.controller';
import { BoardsService } from './boards.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { BoardRepository } from './boards.repository';
@Module({
imports: [
TypeOrmModule.forFeature([BoardRepository]),
],
controllers: [BoardsController],
providers: [BoardsService]
})
export class BoardsModule {}
@Injectable()
: 이 데코레이터를 이용해서 이 서비스에서 BoardRepository를 이용한다고 이걸 boardRepository 변수에 넣어준다. async getBoardById(id: number): Promise <Board> {
const found = await this.boardRepository.findOne(id);
if (!found){
throw new NotFoundException(`Can't find Board with id ${id}`);
}
return found;
}
@Get('/:id')
getBoardById(@Param('id')id: number): Promise<Board> {
return this.boardsService.getBoardById(id);
}
async createBoard(createBoardDto: CreateBoardDto) : Promise<Board> {
const { title, description } = createBoardDto;
const board = this.boardRepository.create({
title,
description,
status: BoardStatus.PUBLIC
})
await this.boardRepository.save(board);
return board;
}
@Post()
@UsePipes(ValidationPipe)
createBoard(@Body() createBoardDto: CreateBoardDto): Promise<Board> {
return this.boardsService.createBoard(createBoardDto);
}
import { EntityRepository, Repository } from "typeorm";
import { Board } from "./boards.entity";
import { CreateBoardDto } from "./dto/create-Board.dto";
import { BoardStatus } from "./board-status.enum";
@EntityRepository(Board)
export class BoardRepository extends Repository<Board> {
async createBoard(createBoardDto: CreateBoardDto): Promise<Board> {
const { title, description } = createBoardDto;
const board = this.create({
title,
description,
status: BoardStatus.PUBLIC
})
await this.save(board);
return board;
}
}
createBoard(createBoardDto: CreateBoardDto) : Promise<Board> {
return this.boardRepository.createBoard(createBoardDto);
}
async deleteBoard(id: number): Promise<void> {
const result = await this.boardRepository.delete(id);
console.log('result', result);
}
@Delete(':id')
deleteBoard(@Param('id', ParseIntPipe) id: number): Promise<void> {
return this.boardsService.deleteBoard(id);
}
async deleteBoard(id: number): Promise<void> {
const result = await this.boardRepository.delete(id);
if (result.affected === 0) {
throw new NotFoundException(`Can't find Board with id ${id}`);
}
console.log('result', result);
}
async updateBoardStatus(id: number, status: BoardStatus): Promise<Board> {
const board = await this.getBoardById(id);
board.status = status;
await board.save();
return (board);
}
@Patch('/:id/status')
updateBoardStatus(
@Param('id', ParseIntPipe) id: number,
@Body('status', BoardStatusValidationPipe) status: BoardStatus,
): Promise<Board> {
return this.boardsService.updateBoardStatus(id, status);
}
async getAllBoards(): Promise<Board[]> {
return this.boardRepository.find();
}
@Get()
getAllTask(): Promise<Board[]> {
return this.boardsService.getAllBoards();
}
4에서는 BoardModule을 만들었다.
5부터는 AuthModule을 만든다.
=> 게시판을 생성한 사람만 게시물을 삭제할 수 있도록 권한을 처리하게 하기 위한 모듈임.
nest g module auth
nest g controller auth --no-spec
nest g service auth --no-spec
import { BaseEntity, PrimaryGeneratedColumn, Column, Entity } from "typeorm";
@Entity()
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
username: string;
@Column()
password: string;
}
import { EntityRepository, Repository } from "typeorm";
import { User } from "./user.entity";
@EntityRepository(User)
export class UserRepository extends Repository<User> {
}
import { Module } from '@nestjs/common';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserRepository } from './user.repository';
@Module({
imports: [
TypeOrmModule.forFeature([UserRepository]) //forFeature은 이 모듈안에 UserRepository 등록을 해주는 것
],
controllers: [AuthController],
providers: [AuthService]
})
export class AuthModule {}
import { Injectable, Inject } from '@nestjs/common';
import { UserRepository } from './user.repository';
@Injectable()
export class AuthService {
constructor(
@Inject(UserRepository)
private userRepository: UserRepository
){ }
}
import { EntityRepository, Repository } from "typeorm";
import { User } from "./user.entity";
import { AuthCredentialDto } from "./dto/auth-credential.dto";
@EntityRepository(User)
export class UserRepository extends Repository<User> {
async createUser(authCredentialDto: AuthCredentialDto): Promise<void> {
const {username, password} = authCredentialDto;
const user = this.create({ username, password });
await this.save(user);
}
}
export class AuthCredentialDto {
username: string;
password: string;
}
import { Injectable, Inject } from '@nestjs/common';
import { UserRepository } from './user.repository';
import { AuthCredentialsDto } from "./dto/auth-credential.dto";
@Injectable()
export class AuthService {
constructor(
@Inject(UserRepository)
private userRepository: UserRepository
){ }
async signUp(authCredentialsDto: AuthCredentialsDto): Promise<void> {
return this.userRepository.createUser(authCredentialsDto);
}
}
import { Controller, Post, Body } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthCredentialsDto } from './dto/auth-credential.dto';
@Controller('auth')
export class AuthController {
constructor ( private authService: AuthService ) {}
@Post('/signup')
signUp(@Body() authcredentialsDto: AuthCredentialsDto): Promise <void> {
return this.authService.signUp(authcredentialsDto);
}
}
import { IsString, MinLength, MaxLength, Matches } from "class-validator";
export class AuthCredentialsDto {
@IsString()
@MinLength(4)
@MaxLength(20)
username: string;
@IsString()
@MinLength(4)
@MaxLength(20)
//영어랑 숫자만 가능한 유효성 체크, (옵션)유효성 체크를 통과하지 못할 경우 나올 메세지
@Matches(/^[a-zA-Z0-9]*$/, {
message: 'password only accepts english and number'})
password: string;
}
@Post('/signup')
signUp(@Body(ValidationPipe) authcredentialsDto: AuthCredentialsDto): Promise <void> {
return this.authService.signUp(authcredentialsDto);
}
import { BaseEntity, PrimaryGeneratedColumn, Column, Entity, Unique } from "typeorm";
@Entity()
@Unique(['username'])
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
username: string;
@Column()
password: string;
}
import { EntityRepository, Repository } from "typeorm";
import { User } from "./user.entity";
import { AuthCredentialsDto } from "./dto/auth-credential.dto";
import { ConflictException, InternalServerErrorException } from "@nestjs/common";
@EntityRepository(User)
export class UserRepository extends Repository<User> {
async createUser(authcredentialsDto: AuthCredentialsDto): Promise<void> {
const {username, password} = authcredentialsDto;
const user = this.create({ username, password });
try {
await this.save(user);
} catch (error) {
if (error.code === '23505') {
throw new ConflictException('Existing username')
} else {
throw new InternalServerErrorException();
}
}
}
}
npm install bcryptjs --save --legacy-peer-deps
레인보우 테이블
-
import { EntityRepository, Repository } from "typeorm";
import { User } from "./user.entity";
import { AuthCredentialsDto } from "./dto/auth-credential.dto";
import { ConflictException, InternalServerErrorException } from "@nestjs/common";
import * as bcrypt from 'bcryptjs';
@EntityRepository(User)
export class UserRepository extends Repository<User> {
async createUser(authcredentialsDto: AuthCredentialsDto): Promise<void> {
const {username, password} = authcredentialsDto;
const salt = await bcrypt.genSalt();
const hashedPassword = await bcrypt.hash(password, salt);
const user = this.create({ username, password: hashedPassword });
try {
await this.save(user);
} catch (error) {
if (error.code === '23505') {
throw new ConflictException('Existing username')
} else {
throw new InternalServerErrorException();
}
}
}
}
async singIn(authcredentialsDto: AuthCredentialsDto): Promise<string> {
const { username, password } = authcredentialsDto;
const user = await this.userRepository.findOne({username});
if (user && (await (await bcrypt.compare(password, user.password)))) {
return 'login success';
} else {
throw new UnauthorizedException('login Failed')
}
}
@Post('/signin')
signin(@Body(ValidationPipe) authCredentialsDto: AuthCredentialsDto) {
return this.authService.singIn(authCredentialsDto);
}
@nestjs/jwt
: nestjs에서 jwt를 사용하기 위한 모듈@nestjs/passport
: nestjs에서 passport를 사용하기 위해 필요한 모듈passport
: passport 모듈passport-jwt
: jwt모듈npm install @nestjs/jwt @nestjs/passport passport passport-jwt -save --legacy-peer-deps
import { Module } from '@nestjs/common';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserRepository } from './user.repository';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
@Module({
imports: [
JwtModule.register({
secret: 'Secret1234',
signOptions: {
expiresIn: 60 * 60, //토큰의 유효시간 3600 = 1시간
}
}),
TypeOrmModule.forFeature([UserRepository])
],
controllers: [AuthController],
providers: [AuthService]
})
export class AuthModule {}
@Module({
imports: [
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.register({
secret: 'Secret1234',
signOptions: {
expiresIn: 60 * 60, //토큰의 유효시간 3600 = 1시간
}
}),
TypeOrmModule.forFeature([UserRepository])
],
controllers: [AuthController],
providers: [AuthService]
})
export class AuthModule {}
import { Injectable, Inject, UnauthorizedException } from '@nestjs/common';
import { UserRepository } from './user.repository';
import { AuthCredentialsDto } from "./dto/auth-credential.dto";
import * as bcrypt from 'bcryptjs';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class AuthService {
constructor(
@Inject(UserRepository)
private userRepository: UserRepository,
private jwtService: JwtService
){ }
async signUp(authcredentialsDto: AuthCredentialsDto): Promise<void> {
return this.userRepository.createUser(authcredentialsDto);
}
async singIn(authcredentialsDto: AuthCredentialsDto): Promise<{accessToken: string}> {
const { username, password } = authcredentialsDto;
const user = await this.userRepository.findOne({username});
if (user && (await (await bcrypt.compare(password, user.password)))) {
// 유저 토큰 생성 ( Secret + Payload )
const payload = { username } //payload에는 중요한 정보는 넣지 않는다. 정보를 가져가기 쉬워서
const accessToken = await this.jwtService.sign(payload);
return { accessToken };
} else {
throw new UnauthorizedException('login Failed');
}
}
}
@Post('/signin')
signin(@Body(ValidationPipe) authCredentialsDto: AuthCredentialsDto): Promise<{accessToken: string}> {
return this.authService.singIn(authCredentialsDto);
}
@types/passport-jwt
: passport-jwt 모듈을 위한 타입 정의 모듈 npm install @types/passport-jwt --save --legacy-peer-deps
import { Injectable, UnauthorizedException } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { InjectRepository } from "@nestjs/typeorm";
import { ExtractJwt, Strategy } from "passport-jwt";
import { UserRepository } from "./user.repository";
import { User } from "./user.entity";
@Injectable()
// 주입을 해서 다른 곳에서도 사용할 수 있게 하기 위해서
export class JwtStrategy extends PassportStrategy(Strategy) {
// PassportStrategy 안에 있는 기능을 이용하기 위해 이를 상속해 JwtStrategy class를 만든다.
// passport-jwt Strategy를 사용하기 위해 넣어준다. = 이름은 Strategy이지만 import 되는 곳은 passport-jwt이다.
constructor (
@InjectRepository(UserRepository) //UserRepository를 주입시켜주는 이유 = 나중에 토큰이 유효한지 확인 후 payload안에 username으로 유저 객체를 데이터베이스에서 가져옴을 구현하기 위해
private userRepository: UserRepository
) {
super({
secretOrKey: 'Secret1234',
// auth.module이랑 똑같이 넣어준다. 토큰을 유효한지 체크할 때 쓰는 것.
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken()
// 토큰이 어디에서 가져오는지 알아낼때 Header에서 BearerToken타입으로 넘어오는걸 가져와서 유효성을 체크하겠다는 뜻.
});
}
// 토큰이 유효한지 확인한 후 페이로드 안에 있는 유저 이름으로 유저 정보가 데이터베이스에 있는지 확인.
async validate(payload) {
const {username} = payload;
const user: User = await this.userRepository.findOne({username});
if (!user) { //없다면 오류
throw new UnauthorizedException();
}
return user; //있다면 유저 정보 리턴 -> 리퀘스트 객체 안에서 사용가능 (몇가지 더 필요 6.2 참고)
}
}
import { Module } from '@nestjs/common';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserRepository } from './user.repository';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { JwtStrategy } from './jwt.strategy';
@Module({
imports: [
PassportModule.register({defaultStrategy: 'jwt'}),
JwtModule.register({
secret: 'Secret1234', // 토큰을 생성할 때 씀
signOptions: {
expiresIn: 60 * 60, //토큰의 유효시간 3600 = 1시간
}
}),
TypeOrmModule.forFeature([UserRepository])
],
controllers: [AuthController],
providers: [AuthService, JwtStrategy], //auth모듈에서 사용할 때
exports: [JwtStrategy, PassportModule] //auth모듈 뿐만아니라 다른 모듈에서도 사용하기 위해
})
export class AuthModule {}
@Post('/test')
test(@Req() req) {
console.log('req', req);
Q. validate 메소드에서 return 값을 user객체로 주었다. 그래서 요청값 안에 user객체가 들어있으면 하는데 현재 요청을 보낼 때는 user객체가 없다. 어떠한 방식으로 가져와야하는가?
A. UseGuards안에 @nestjs/passport에서 가져온 AuthGuard()를 이용하면 요청 안에 유저 정보를 넣어줄 수 있다.
NestJS에서 Middleware들에 대해
- Pipes: 파이프는 요청 유효성 거사 및 페이로드 변환을 위해 만들어진다. 데이터를 예상한 대로 직렬화.
- Filters: 필터는 오류 처리 미들웨어이다. 특정 오류 처리기를 사용할 경로와 각 경로 주변의 복잡성을 관리하는 방법을 알 수 있다.
- Guards: 가드는 인증 미들웨이다. 지정된 경로로 통과할 수 있는 사람과 허용되지 않는 사람을 서버에 알려줌.
- Interceptors: 인터셉터는 응답 매핑 및 캐시 관리와 함께 요청 로깅과 같은 전후 미들웨어이다. 각 요청 전후에 이를 실행하는 기능은 매우 강력하고 유용합니다.각각의 미들웨어가 불러지는 순서
middleware -> guard -> interceptor(befor) -> pipe -> controller -> service -> controller -> interceptor(after) -> filter(if applicable) -> client
@Post('/test')
@UseGuards(AuthGuard())
test(@Req() req) {
console.log('req', req);
}
import { createParamDecorator, ExecutionContext } from "@nestjs/common";
import { User } from "./user.entity";
export const GetUser = createParamDecorator((data, ctx: ExecutionContext): User => {
const req = ctx.switchToHttp().getRequest();
return req.user;
})
@Post('/test')
@UseGuards(AuthGuard())
test(@GetUser() user: User) {
console.log('user', user);
}
@Module({
imports: [
TypeOrmModule.forFeature([BoardRepository]),
AuthModule
],
controllers: [BoardsController],
providers: [BoardsService]
})
export class BoardsModule {}
@Controller('boards')
@UseGuards(AuthGuard())
@OneToMany(type => Board, board => board.user, { eager: true })
boards: Board[];//여러개가 들어갈 수 있으니 배열
@ManyToOne(type => User, user => user.boards, { eager: false })
user: User;
@Post()
@UsePipes(ValidationPipe)
createBoard(
@Body() createBoardDto: CreateBoardDto,
@GetUser() user:User
): Promise<Board> {
return this.boardsService.createBoard(createBoardDto, user);
}
createBoard(createBoardDto: CreateBoardDto,
user: User) : Promise<Board> {
return this.boardRepository.createBoard(createBoardDto, user);
}
async createBoard(createBoardDto: CreateBoardDto,
user: User): Promise<Board> {
const { title, description } = createBoardDto;
const board = this.create({
title,
description,
status: BoardStatus.PUBLIC,
user
})
await this.save(board);
return board;
}
@Get()
getAllBoard(
@GetUser() user: User
): Promise<Board[]> {
return this.boardsService.getAllBoards(user);
}
async getAllBoards(
user: User
): Promise<Board[]> {
const query = this.boardRepository.createQueryBuilder('board');
query.where('board.userId = :userId', { userId: user.id });
const boards = await query.getMany();
return boards;
}