• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

스웨거 문서를 PickType으로 만들 수 있나요?

22.08.12 12:48 작성 조회수 647

0

1. Users.ts(엔티티)

import {
  Column,
  CreateDateColumn,
  DeleteDateColumn,
  Entity,
  Index,
  JoinTable,
  ManyToMany,
  OneToMany,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
} from 'typeorm';
import { ChannelChats } from './ChannelChats';
import { ChannelMembers } from './ChannelMembers';
import { Channels } from './Channels';
import { DMs } from './DMs';
import { Mentions } from './Mentions';
import { WorkspaceMembers } from './WorkspaceMembers';
import { Workspaces } from './Workspaces';
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';

@Index('email', ['email'], { unique: true })
@Entity({ schema: 'sleact', name: 'users' })
export class Users {
  @PrimaryGeneratedColumn({ type: 'int', name: 'id' })
  id: number;

  @ApiProperty({
    example: `aaa123@google.com`,
    description: '이메일',
    required: true,
  })
  @IsEmail()
  @IsNotEmpty()
  @Column('varchar', { name: 'email', unique: true, length: 30 })
  email: string;

  @ApiProperty({
    example: `홍길동`,
    description: '닉네임',
    required: true,
  })
  @IsString()
  @IsNotEmpty()
  @Column('varchar', { name: 'nickname', length: 30 })
  nickname: string;

  @ApiProperty({
    example: `123123`,
    description: '비밀번호',
    required: true,
  })
  @IsString()
  @IsNotEmpty()
  @Column('varchar', { name: 'password', length: 100, select: false })
  password: string;

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;

  @DeleteDateColumn()
  deletedAt: Date | null;

  @OneToMany(() => ChannelChats, (channelchats) => channelchats.User)
  ChannelChats: ChannelChats[];

  @OneToMany(() => ChannelMembers, (channelmembers) => channelmembers.User)
  ChannelMembers: ChannelMembers[];

  @OneToMany(() => DMs, (dms) => dms.Sender)
  DMs: DMs[];

  @OneToMany(() => DMs, (dms) => dms.Receiver)
  DMs2: DMs[];

  @OneToMany(() => Mentions, (mentions) => mentions.Sender)
  Mentions: Mentions[];

  @OneToMany(() => Mentions, (mentions) => mentions.Receiver)
  Mentions2: Mentions[];

  @OneToMany(
    () => WorkspaceMembers,
    (workspacemembers) => workspacemembers.User,
  )
  WorkspaceMembers: WorkspaceMembers[];

  @OneToMany(() => Workspaces, (workspaces) => workspaces.Owner)
  OwnedWorkspaces: Workspaces[];

  @ManyToMany(() => Workspaces, (workspaces) => workspaces.Members)
  @JoinTable({
    name: 'workspacemembers',
    joinColumn: {
      name: 'UserId',
      referencedColumnName: 'id',
    },
    inverseJoinColumn: {
      name: 'WorkspaceId',
      referencedColumnName: 'id',
    },
  })
  Workspaces: Workspaces[];

  @ManyToMany(() => Channels, (channels) => channels.Members)
  @JoinTable({
    name: 'channelmembers',
    joinColumn: {
      name: 'UserId',
      referencedColumnName: 'id',
    },
    inverseJoinColumn: {
      name: 'ChannelId',
      referencedColumnName: 'id',
    },
  })
  Channels: Channels[];
}

 

2. join.request.dto

import { PickType } from '@nestjs/mapped-types';
import { Users } from '../../entities/Users';

export class JoinRequestDto extends PickType(Users, [
  'email',
  'nickname',
  'password',
] as const) {}

 

3. user.dto

import { JoinRequestDto } from './join.request.dto';
import { ApiProperty } from '@nestjs/swagger';

export class UserDto extends JoinRequestDto {
  @ApiProperty({
    example: `1`,
    description: '아이디',
    required: true,
  })
  id: number;
}

 

4. users.controller

import {
  Body,
  Controller,
  ForbiddenException,
  Get,
  NotFoundException,
  Post,
  Req,
  Res,
  UseGuards,
  UseInterceptors,
} from '@nestjs/common';
import { UsersService } from './users.service';
import { JoinRequestDto } from './dto/join.request.dto';
import { User } from '../common/decorators/user.decorator';
import { UndefinedToNullInterceptor } from '../common/interceptors/undefinedToNull.interceptor';
import { LocalAuthGuard } from '../auth/local-auth.guard';
import { NotLoggedInGuard } from '../auth/not-logged-in.guard';
import { LoggedInGuard } from '../auth/logged-in.guard';
import {
  ApiCookieAuth,
  ApiOperation,
  ApiResponse,
  ApiTags,
} from '@nestjs/swagger';
import { Users } from '../entities/Users';
import { UserDto } from './dto/user.dto';

@ApiTags('USERS')
@UseInterceptors(UndefinedToNullInterceptor)
@Controller('api/users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @ApiCookieAuth('connect.sid')
  @ApiOperation({ summary: '내 정보 가져오기' })
  @ApiResponse({
    type: UserDto,
  })
  @Get()
  async getMyProfile(@User() user: Users) {
    return user || false;
  }

  @ApiResponse({
    status: 500,
    description: 'Server Error..',
  })
  @ApiResponse({
    status: 200,
    description: '성공!',
  })
  @ApiOperation({ summary: '회원가입' })
  @UseGuards(NotLoggedInGuard)
  @Post()
  async join(@Body() body: JoinRequestDto) {
    const user = this.usersService.findByEmail(body.email);
    if (!user) {
      throw new NotFoundException();
    }
    const result = await this.usersService.join(
      body.email,
      body.nickname,
      body.password,
    );
    if (result) {
      return 'ok';
    } else {
      throw new ForbiddenException();
    }
  }

  @ApiResponse({
    status: 200,
    description: '성공',
    type: UserDto,
  })
  @ApiOperation({ summary: '로그인' })
  @UseGuards(LocalAuthGuard)
  @Post('login')
  async login(@User() user: Users) {
    return user;
  }

  @ApiCookieAuth('connect.sid')
  @ApiOperation({ summary: '로그아웃' })
  @UseGuards(LoggedInGuard)
  @Post('logout')
  async logout(@Req() req, @Res() res) {
    req.logOut();
    res.clearCookie('connect.sid', { httpOnly: true });
    res.send('ok');
  }
}

----------------------------

스웨거 문서

1. Dto 관련 스키마

 

2. usersDto를 사용한 결과

 

3. joinRequestDto를 사용한 결과

마지막 결과 쪽에 제가 생각한 것은 빈칸이 아니라
{

      email : "aaa123@google.com"

      nickname: "홍길동"

      passwork: "123123"
}

이었는데 빈칸으로 나오네요.. 혹시 잘못한 부분이 있을까요?

 

 

답변 2

·

답변을 작성해보세요.

0

jun hyeong park님의 프로필

jun hyeong park

2023.03.26

삭제된 글입니다

이게 안 되면 그냥 복사해서 다시 넣거나 아니면 공통으로 쓰는 것들 모아두고 extends하는 수밖에 없습니다.

0

코드 상에 잘못은 없는 것 같은데요. extends가 문제인지 PickType이 문제인지 테스트 한 번 해봐야할 것 같습니다.

jun hyeong park님의 프로필

jun hyeong park

2023.03.26

PickType import 가 잘 못되어 있는 문제였습니다.

import { PickType } from '@nestjs/swagger'

import { PickType } from '@nestjs/mapped-types'

이 두개가 있는데 mapped-types로 import 되어 있으면 swagger 문서에 출력되지 않습니다.

@nestjs/swagger 로 변경해주세요~~!

오.. 저 두 차이로 안 될 수 있다는 건 저도 몰랐네요. 감사합니다.