게시글의 소유주를 표시하기 위하여 Board-User 간에 many-to-one relationship을 만들어주자.
User에서는 Board 배열인 boards를 가지고(OneToMany), Board에서는 User를 가진다(ManyToOne).
//User.entity
@Entity() @Unique(['username'])
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
username: string;
@Column()
password: string;
@OneToMany(() => Board, board => board.user, {eager:true})
boards: Board[]
}
//Board.entity
@Entity()
export class Board extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
description : string;
@Column()
status : BoardStatus;
@ManyToOne(() => User, user => user.boards, {eager:false})
user: User
}
eager 옵션을 true로 해주면 해당 column이 reference한 테이블의 정보도 다른 컬럼들과 함께 가져온다.
이제 createBoard에서 헤더 안에 들어있는 User 정보를 사용하여 Board와의 관계를 생성한다. 컨트롤러 단에서 만들어둔 @GetUser 데코레이터로 user 정보를 가져와 repository에 정의된 createBoard함수에 넘겨주어 사용한다.
//boards.controller
@Post() //Create new Board
@UsePipes(ValidationPipe) //validate
createBoard(@Body() createBoardDto: CreateBoardDto, @GetUser() user: User) : Promise<Board>{
return this.boardService.createBoard(createBoardDto,user);
}
//board.repository
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;
}
로그인하여 토큰을 생성한 뒤 creatBoard 요청을 보내면 아래와 같이 board 객체에 User 정보도 포함된 것을 볼 수 있다.

이번엔 getAllBoards에 요청한 user의 board만 가져올 수 있도록 접근 제어를 해보자. 컨트롤러 단에서 user 정보를 받아 board repository의 getAllBoards 매서드에 넘겨준다. 기존의 find 대신 user가 일치하는 board만 가져오기 위하여 querybuilder를 사용한다.
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;
}
createQueryBuilder로 쿼리문을 생성할 수 있다. where 절에 보드의 userID가 주어진 user의 id와 일치하는 조건을 추가한다. getMany()를 통하여 조건에 맞는 모든 row를 가져올 수 있다.

다른 user로 로그인하면 board가 반환되지 않고 생성한 user로 요청하면 board가 제대로 반환된다.

사실 이러한 접근 제어가 필요한 부분은 deleteBoard이다. 자신이 생성한 board만 삭제할 수 있도록 한다.
async deleteBoard(id:number,user: User): Promise<void> {
const result = await this.boardRepository.delete({id, user:{id: user.id}})
console.log('[delete]',result);
if(result.affected==0){
throw new NotFoundException(`Cannot Find Board Id: ${id}`)
}
}
다음과 같이 작성자가 아닌 경우 에러메시지가 반환된다.
