Node.js/Nest.js

[NestJS] 접근 권한 처리 (CRUD)

ヽ(°ᴥ°)ノ 2022. 10. 13. 16:34

원래 공식문서 보고하다가 중간에 John Ann님 강의로 틀어서 강의에서의 Board는 내 코드에서 Cat이라고 보면됨

(user : 주인, cat : 고양이 라고 생각해야지 ex.주인1만 고양이1에게 접근 가능)

 

유저에게 고양이 접근 권한 주기

 

인증 관련 모듈인 Auth module을 Cat에서 쓸 수 있어야하기 때문에 Cat module에서 Auth module을 import 해와야한다

// cats.module.ts

Module({
  imports: [TypeOrmModule.forFeature([Cat]), AuthModule], // auth module 추가
  exports: [TypeOrmModule],
  controllers: [CatsController],
  providers: [CatsService],
})
export class CatsModule {}

 

 

현재 client가 cat에 접근하기에 유효한 client 인지 본 후에 권한을 줘야하기 때문에 cat controller에 모든 핸들러에 대해 Guard를 씌워주기 ! (이전 게시물에서 했던 것 처럼)

@Controller("cats")
@UseGuards(AuthGuard()) // 밑에 있는 모든 핸들러가 영향을 받는다
export class CatsController {...}

>> 올바른 토큰을 안넣으면 401 Unauthorized 에러나게됨

 


 유저와 고양이의 관계 형성해주기

나와 내 고양이의 관계를 정립해줘야함. 고양이 정보를 넣을때도 이 고양이의 주인이 누구인지 등등 정보를 넣어줘야함. 

 

 

🔽 TypeOrm의 관계 설정 방법

@OneToMany, @ManyToOne, @ManyToMany, @OneToOne

 

1. user-cat 엔티티간에 서로의 필드를 넣어줘야함

  • 1명의 User는 여러 Cat과 관계 (1 : N)
  • 여러마리 Cat이 1명의 User와 관계됨 ( N : 1 )
// user.entity.ts

@Entity("user")
@Unique(["username"])
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  username: string;

  @Column()
  password: string;

  @OneToMany((type) => Cat, (cat) => cat.user, { eager: true })
  cats: Cat;
}
  • { eager : true } : User 정보 가져올 때 cat도 같이 가져옴
// cat.entity.ts

@Entity()
export class Cat {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  age: number;

  @Column()
  breed: string;

  @ManyToOne((type) => User, (user) => user.cats, { eager: false })
  user: User;
}

 


Cat 정보 넣어줄 때 User 정보 넣어주기 (Post)

"이 cat의 주인은 어떤user다" 라는 정보도 같이 넣어줘야함

// cats.controller.ts
@Post()
  create(@Body() cat: Cat, @GetUser() user: User) {
    return this.catsService.create(cat, user);
  }
  
// cats.service.ts
async create(cat: Cat, user: User): Promise<void> {
    const { name, age, breed } = cat;

    const catt = new Cat();
    catt.age = age;
    catt.breed = breed;
    catt.name = name;
    catt.user = user;

    await this.catsRepository.save(catt);
  }
 // cats은 repository와 service를 따로 나누지 않았음

 

🔽 테스트

더보기

1. user1로 로그인 후 반환되는 토큰 복사

2. cat post request보낼때 Authorization(type: bearor Token)에 복사한 토큰 넣어주고 Body에 고양이 정보 넣어서 보내기

3. DB에 cat 테이블에 userId 라는 칼럼 새로 생기며 정보 제대로 들어간 것 확인


해당 User의 고양이만 가져오기 (Get)

내 고양이들의 정보만 조회해야할때 (약간 마이페이지 기능 구현할 때 쓸 듯?)

현재는 로그인 성공한 모든 유저는 모든 고양이 정보를 볼 수 있음

// cats.controller.ts
@Get()
  findAll(@GetUser() user: User): Promise<Cat[]> {
    return this.catsService.findAll(user);
  }
  
// cats.service.ts

async findAll(user: User): Promise<Cat[]> {
    const query = this.catsRepository.createQueryBuilder("cat"); // cat에 접근할것
    query.where("cat.userId = :userId", { userId: user.id });

    const cats = await query.getMany(); //여기서 나오는 것들 전부다 가져오라는 뜻 이 조건에 맞는 모든 cat이 들어간다
    return cats;
  }

🔽 테스트

더보기

1. user1로 로그인 후 토큰 복사

2. GET localhost:3000/cats 요청에 복사한 토큰 넣어서 전송

3. user1가 등록한 고양이 정보만 볼 수 있음


자신이 생성한 고양이 정보 수정하기 (Patch)

수정하고자하는 고양이의 아이디를 이용해 내가 작성한 고양이 정보만 수정

// cats.controller.ts
// age만 수정할 것
@Patch(":id")
  update( @Param("id") id: number, @Body("age") age: number, @GetUser() user: User) {
    this.catsService.update(id, age, user);
    return `This action updates a #${id} cat`;
  }
  
// cats.service.ts

async update(id: number, age: number, user: User): Promise<Cat> {
    const cat = await this.findCatById(id, user);
    cat.age = age;
    await this.catsRepository.save(cat);
    return cat;
  }
  
async findCatById(id: number, user: User): Promise<Cat> {
    const found = await this.catsRepository.findOne({
      where: { id, userId: user.id },
    });
    return found;
  }

 


 자신이 생성한 고양이 정보 삭제하기 (Delete)

삭제하고자하는 고양이의 아이디를 이용해 내가 작성한 고양이 정보만 삭제

// cats.controller.ts

@Delete(":id")
  remove(@Param("id") id: number, @GetUser() user: User) {
    this.catsService.remove(id, user);
  }
  
// cats.service.ts

async remove(id: number, user: User): Promise<void> {
    // 해당 cat을 가진 user만이 삭제할 수 있음
    await this.catsRepository.delete({ id, user });
  }