유저(OneToMany)와 게시물(ManyToOne)의 관계 형성 해주기
user.entity.ts
import { type } from 'os';
import { Board } from 'src/boards/board.entity';
import {
BaseEntity,
Column,
Entity,
OneToMany,
PrimaryGeneratedColumn,
Unique,
} from 'typeorm';
@Entity()
@Unique(['username'])
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
username: string;
@Column()
password: string;
@OneToMany((type) => Board, (board) => board.user, { eager: true })
boards: Board[];
}
board.entity.ts
import { User } from 'src/auth/user.entity';
import {
BaseEntity,
Column,
Entity,
ManyToOne,
PrimaryGeneratedColumn,
} from 'typeorm';
import { BoardStatus } from './board-status.enum';
@Entity()
export class Board extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
description: string;
@Column()
status: BoardStatus;
@ManyToOne((type) => User, (user) => user.boards, { eager: false })
user: User;
}
유저, 보트 엔티티에 OneToMany, ManyToOne 관계를 설정해준다.
eager → eager옵션을 true로 두게 된다면 상위 엔티티를 로드 했을 때, 그 하위 엔티티까지 모두 로드되게 한다.
게시물 생성 할 때 유저 정보 넣어주기
boards.controller.ts
@Controller('boards')
@UseGuards(AuthGuard())
export class BoardsController {
constructor(private boardsService: BoardsService) {}
@Post()
@UsePipes(ValidationPipe)
createBoard(
@Body() createBoardDto: CreateBoardDto,
@GetUser() user: User,
): Promise<Board> {
return this.boardsService.createBoard(createBoardDto, user);
}
}
boards.controller 안에 토큰값 안에 들어있는 유저의 정보를 가져와서(커스텀 데코레이터를 이용하여 가져올 수 있다.) 보드를 생성 할 때 유저를 포함해서 생성하게 해준다.
boards.service.ts
@Injectable()
export class BoardsService {
constructor(
@InjectRepository(BoardRepository)
private boardRepository: BoardRepository,
) {}
createBoard(createBoardDto: CreateBoardDto, user: User): Promise<Board> {
return this.boardRepository.createBoard(createBoardDto, user);
}
}
service 파일로 가서 user 정보를 넣어준다.(레포지토리에 접근하여 넣을 수 있게)
board.repository.ts
@Injectable()
export class BoardRepository extends Repository<Board> {
constructor(private dataSource: DataSource) {
super(Board, dataSource.createEntityManager());
}
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;
}
}
이후 repository로 접근해서 DB에 저장될 때 유저의 정보를 포함하여 저장할 수 있게 코드를 수정해준다.
이후 생성 요청을 보내게 되면
{
"title": "new board(add user)",
"description": "new description(add user)",
"status": "PUBLIC",
"user": {
"id": 10,
"username": "GHGHgh",
"password": "$2a$10$JQYn2m5zYOaybzYUMw8BteEb3TWEkFYILU8sPyw2JtPhLS37jZnPm",
"boards": []
},
"id": 8
}
위와 같이 유저의 정보가 담긴 json이 리턴된다.
실제 DB에는 어떻게 저장이 돼 있는지 확인을 해보면(pgAdmin)
이와 같이 userId를 가진 컬럼이 추가가 된다.
해당 유저의 게시물만 가져오기(getAllBoards) - QueryBuilder 사용하기
boards.controller.ts
@Controller('boards')
@UseGuards(AuthGuard())
export class BoardsController {
constructor(private boardsService: BoardsService) {}
@Get()
getAllBoard(@GetUser() user: User): Promise<Board[]> {
return this.boardsService.getAllBoards(user);
}
}
컨트롤러에서 커스텀 데코레이터를 통해 유저 정보를 가져오고 유저 정보를 service에 넘겨준다.
boards.service.ts
@Injectable()
export class BoardsService {
constructor(
@InjectRepository(BoardRepository)
private boardRepository: BoardRepository,
) {}
async getAllBoards(@GetUser() 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;
}
}
이후 쿼리빌더를 통해 보드 안의 유저 아이디가 넘겨받은 유저의 아이디와 같으면, 해당되는 객체들을 boards 변수 안에 담아서 리턴해준다.
결과(user2가 가진 게시물은 3, 4번 게시물).
[
{
"id": 3,
"title": "board3",
"description": "board3",
"status": "PUBLIC"
},
{
"id": 4,
"title": "board4",
"description": "board4",
"status": "PUBLIC"
}
]
자신이 생성한 게시물만 삭제 할 수 있는 기능 구현
방식은 위와 같다(삭제 함수들 안에 user객체와 타입을 넣어준다) 하지만 delete 또한 쿼리셀렉터를 만들어 줘서 해결해야 한다.
https://orkhan.gitbook.io/typeorm/docs/delete-query-builder
boards.service.ts
@Injectable()
export class BoardsService {
constructor(
@InjectRepository(BoardRepository)
private boardRepository: BoardRepository,
) {}
async deleteBoard(id: number, user: User): Promise<void> {
const result = await this.boardRepository
.createQueryBuilder('board')
.delete()
.from(Board)
.where('userId = :userId', { userId: user.id })
.andWhere('id = :id', { id })
.execute();
if (result.affected == 0) {
throw new NotFoundException(`Can't find Board with id ${id}`);
}
}
}
위와 같이 토큰에서 가져온 유저 정보의 id와 생성한 게시물 유저의 id가 일치하고, 해당 게시물의 id와 삭제하고자 하는 게시물의 id가 일치한다면 삭제가 가능하다.
결과.(user2의 정보로 board3을 지운 결과)
'Nest.js' 카테고리의 다른 글
[Nest.js] 인증된 유저만 게시물 보고 쓸 수 있게 만들기 (0) | 2023.01.30 |
---|---|
[Nest.js] Passport, JWT 이용해서 토큰 인증 후 유저 정보 가져오기 (0) | 2023.01.30 |
[Nest.js] 회원가입과 로그인 구현 2 (0) | 2023.01.27 |
[Nest.js] 회원가입과 로그인 구현 1 (0) | 2023.01.27 |
[Nest.js] Nest.js + PostgreSQL + typeORM CRUD 구현하기 3 (0) | 2023.01.26 |