diff --git a/src/apis/letter/letter.service.ts b/src/apis/letter/letter.service.ts index 4ba2b75..650d301 100644 --- a/src/apis/letter/letter.service.ts +++ b/src/apis/letter/letter.service.ts @@ -52,6 +52,9 @@ export class LetterService { throw new BadRequestException('수신자가 존재하지 않음'); } + //TODO : 400 번대 + // 보낼 수 없는 사용자 추가 + const letterRoom = await this.upsertUserListToLetterRoom(twoUserList); const newLetter = await this.letterRepository.sendLetterToReciever( new LetterRoomIdDto(letterRoom._id), diff --git a/src/apis/users/dto/UserProfileClick.dto.ts b/src/apis/users/dto/UserProfileClick.dto.ts new file mode 100644 index 0000000..6a20911 --- /dev/null +++ b/src/apis/users/dto/UserProfileClick.dto.ts @@ -0,0 +1,53 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { Expose, Transform, Type } from 'class-transformer'; +import { Profile, User } from 'src/models/user.model'; +import { Types } from 'mongoose'; +import { TransformObjectIdToString } from 'src/common/decorators/Expose.decorator'; +import { STATUS_TYPE } from 'src/common/consts/enum'; + +export class UserProfileClickDto { + constructor(user: User) { + if (user) { + this._id = user._id; + this.nickname = user.nickname; + this.profile = user.profile; + this.level = user.level; + } + } + @ApiProperty({ type: String, example: '626cf238b51596721c21289b' }) + @Expose() + @Transform((value) => value.obj._id, { toClassOnly: true }) + @TransformObjectIdToString({ toPlainOnly: true }) + _id: Types.ObjectId; + + @ApiProperty({ type: String, example: 'nickname' }) + @Expose() + nickname: string; + + @ApiProperty({ type: String, example: 'profile' }) + @Type(() => Profile) + @Expose() + profile: Profile; + + @ApiProperty({ + type: Number, + description: '유저의 확성기 레벨', + }) + @Expose() + level: number; + + @ApiProperty({ + enum: STATUS_TYPE, + description: + '유저의 상태 ( 노말 : 정상 , 정지 : forbidden , 탈퇴 : signOut', + }) + @Expose() + status: string; + + @ApiProperty({ + type: Boolean, + description: '내가 차단한 유저인지에 대한 정보 제공', + }) + @Expose() + iBlock: boolean; +} diff --git a/src/apis/users/user.controller.ts b/src/apis/users/user.controller.ts index 0637712..7107c0d 100644 --- a/src/apis/users/user.controller.ts +++ b/src/apis/users/user.controller.ts @@ -30,6 +30,7 @@ import { NewAlarmStateResDto } from './dto/newAlarmState.res.dto'; import { SendLightningSuccessDtoResDto } from './dto/sendLigningSuccessDto.res.dto'; import { AlarmService } from '../alarm/alarm.service'; import { FCMUpdateDto } from './dto/fcmUpdate.dto'; +import { UserProfileClickDto } from './dto/UserProfileClick.dto'; @ApiTags('user') @Controller('user') @@ -70,6 +71,18 @@ export class UserController { ); } + @ApiOperation({ summary: '유저 탈퇴를 한다.' }) + @ApiResponse({ + status: 200, + description: '요청 성공시', + }) + @Delete('') + async singOut(@ReqUser() user: User) { + // findOneByUserId + await this.userService.signOutUser(user); + return; + } + @ApiOperation({ summary: 'FCM 업데이트하기', }) @@ -103,7 +116,7 @@ export class UserController { @ApiResponse({ status: 200, description: '요청 성공시', - type: UserProfileDto, + type: UserProfileClickDto, }) @ApiResponse({ status: 400, @@ -112,10 +125,7 @@ export class UserController { @Get(':userId') async getOtherUserInfo(@Param() UserIdDto: UserIdDto, @ReqUser() user: User) { // findOneByUserId - return await this.userService.getOtherUserInfo( - UserIdDto, - user.blockedUserDto, - ); + return await this.userService.getOtherUserInfo(UserIdDto, user); } @ApiOperation({ summary: '상대방 유저를 차단한다' }) diff --git a/src/apis/users/user.module.ts b/src/apis/users/user.module.ts index 0af9427..6ac26e0 100644 --- a/src/apis/users/user.module.ts +++ b/src/apis/users/user.module.ts @@ -8,6 +8,7 @@ import { LightningRepository } from 'src/repositories/lightning.repository'; import { ReportRepository } from 'src/repositories/report.repository'; import { UserRepository } from 'src/repositories/user.repository'; import { AlarmModule } from '../alarm/alarm.module'; +import { RoomsModule } from '../rooms/rooms.module'; import { UserController } from './user.controller'; import { UserService } from './user.service'; @@ -20,6 +21,7 @@ import { UserService } from './user.service'; ]), forwardRef(() => AuthModule), forwardRef(() => AlarmModule), + forwardRef(() => RoomsModule), ], controllers: [UserController], providers: [ diff --git a/src/apis/users/user.service.ts b/src/apis/users/user.service.ts index 820e826..5fdc88b 100644 --- a/src/apis/users/user.service.ts +++ b/src/apis/users/user.service.ts @@ -27,6 +27,9 @@ import { } from 'src/common/consts/enum'; import { AlarmService } from '../alarm/alarm.service'; import { FCMUpdateDto } from './dto/fcmUpdate.dto'; +import { RoomsService } from '../rooms/rooms.service'; +import { RoomIdDto } from 'src/common/dtos/RoomId.dto'; +import { UserProfileClickDto } from './dto/UserProfileClick.dto'; @Injectable() export class UserService { @@ -37,6 +40,7 @@ export class UserService { private authService: AuthService, private lightnignRepository: LightningRepository, private alarmService: AlarmService, + private roomService: RoomsService, ) {} private checkBlocked(userIdDto: UserIdDto, blockedUserDto: BlockedUserDto) { @@ -57,18 +61,34 @@ export class UserService { return user; } - @returnValueToDto(UserProfileDto) + @returnValueToDto(UserProfileClickDto) async getOtherUserInfo( userIdDto: UserIdDto, - blockedUserDto: BlockedUserDto, - ): Promise { - // 유저 차단해도 프로필 조회가능 --> 채팅 로그 내부에서 - // this.checkBlocked(userIdDto, blockedUserDto); - // auto 시리얼 라이징 + myUser: User, + ): Promise { const user = await this.userRepository.findOneByUserId(userIdDto); if (!user) { throw new BadRequestException('유저 없음'); } + const iBlock = myUser.iBlockUsers.find((e) => + e._id.equals(userIdDto.userId), + ) + ? true + : false; + return { ...user, iBlock: iBlock }; + } + + // @returnValueToDto(UserProfileDto) + async signOutUser(user: User) { + if (user.myRoom) { + //유저가 들어간 방이있으면 + await this.roomService.pullUserFromRoom( + new RoomIdDto(user.myRoom._id), + user.userIdDto, + ); + } + + await this.userRepository.signOutUser(user.userIdDto); return user; } diff --git a/src/auth/strategies/jwt.strategy.ts b/src/auth/strategies/jwt.strategy.ts index 82a0864..c5cca18 100644 --- a/src/auth/strategies/jwt.strategy.ts +++ b/src/auth/strategies/jwt.strategy.ts @@ -53,6 +53,8 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') { )} 까지 정지된 유저입니다. 문의사항은 고객센터로 연락주세요.`, ); } + } else if (user.status === STATUS_TYPE.SIGNOUT) { + throw new UnauthorizedException('탈퇴한 유저'); } return user; } else { diff --git a/src/common/consts/enum.ts b/src/common/consts/enum.ts index 5109bce..8b16ff9 100644 --- a/src/common/consts/enum.ts +++ b/src/common/consts/enum.ts @@ -13,6 +13,7 @@ function getEnumTypeValues(enumType) { enum STATUS_TYPE { NORMAL = 'normal', FORBIDDEN = 'forbidden', + SIGNOUT = 'signOut', } //카테고리 타입 한글로 diff --git a/src/common/dtos/UserProfile.dto.ts b/src/common/dtos/UserProfile.dto.ts index 31d586b..d4f1121 100644 --- a/src/common/dtos/UserProfile.dto.ts +++ b/src/common/dtos/UserProfile.dto.ts @@ -3,6 +3,7 @@ import { Expose, Transform, Type } from 'class-transformer'; import { Profile, User } from 'src/models/user.model'; import { Types } from 'mongoose'; import { TransformObjectIdToString } from '../decorators/Expose.decorator'; +import { STATUS_TYPE } from '../consts/enum'; export class UserProfileDto { constructor(user: User) { @@ -11,6 +12,7 @@ export class UserProfileDto { this.nickname = user.nickname; this.profile = user.profile; this.level = user.level; + this.status = user.status; } } @ApiProperty({ type: String, example: '626cf238b51596721c21289b' }) @@ -34,6 +36,20 @@ export class UserProfileDto { }) @Expose() level: number; + + @ApiProperty({ + enum: STATUS_TYPE, + description: + '유저의 상태 ( 노말 : 정상 , 정지 : forbidden , 탈퇴 : signOut', + }) + @Expose() + status: string; } -export const UserProfileSelect = { _id: 1, nickname: 1, profile: 1, level: 1 }; +export const UserProfileSelect = { + _id: 1, + nickname: 1, + profile: 1, + level: 1, + status: 1, +}; diff --git a/src/repositories/user.repository.ts b/src/repositories/user.repository.ts index fadc7aa..b4faef1 100644 --- a/src/repositories/user.repository.ts +++ b/src/repositories/user.repository.ts @@ -44,6 +44,18 @@ export class UserRepository { ); } + async signOutUser(userIdDto: UserIdDto) { + return await this.userModel.findOneAndUpdate( + { _id: userIdDto.userId }, + { + status: STATUS_TYPE.SIGNOUT, + phoneNumber: null, + nickname: '(탈퇴한 사용자)', + FCMToken: '', + }, + ); + } + async findOneByUserId(userIdDto: UserIdDto): Promise { const user = await this.userModel .findOne({ _id: userIdDto.userId })