Skip to content

Commit

Permalink
🚀 feat(user) : 회원탈퇴 로직추가 , 인증 singOut status 확인 (#88) (#92)
Browse files Browse the repository at this point in the history
  • Loading branch information
ImNM authored Jun 16, 2022
1 parent bf0aa7a commit 1420ea4
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 12 deletions.
3 changes: 3 additions & 0 deletions src/apis/letter/letter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
53 changes: 53 additions & 0 deletions src/apis/users/dto/UserProfileClick.dto.ts
Original file line number Diff line number Diff line change
@@ -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;
}
20 changes: 15 additions & 5 deletions src/apis/users/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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 업데이트하기',
})
Expand Down Expand Up @@ -103,7 +116,7 @@ export class UserController {
@ApiResponse({
status: 200,
description: '요청 성공시',
type: UserProfileDto,
type: UserProfileClickDto,
})
@ApiResponse({
status: 400,
Expand All @@ -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: '상대방 유저를 차단한다' })
Expand Down
2 changes: 2 additions & 0 deletions src/apis/users/user.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -20,6 +21,7 @@ import { UserService } from './user.service';
]),
forwardRef(() => AuthModule),
forwardRef(() => AlarmModule),
forwardRef(() => RoomsModule),
],
controllers: [UserController],
providers: [
Expand Down
32 changes: 26 additions & 6 deletions src/apis/users/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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) {
Expand All @@ -57,18 +61,34 @@ export class UserService {
return user;
}

@returnValueToDto(UserProfileDto)
@returnValueToDto(UserProfileClickDto)
async getOtherUserInfo(
userIdDto: UserIdDto,
blockedUserDto: BlockedUserDto,
): Promise<UserProfileDto> {
// 유저 차단해도 프로필 조회가능 --> 채팅 로그 내부에서
// this.checkBlocked(userIdDto, blockedUserDto);
// auto 시리얼 라이징
myUser: User,
): Promise<UserProfileClickDto> {
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;
}

Expand Down
2 changes: 2 additions & 0 deletions src/auth/strategies/jwt.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
)} 까지 정지된 유저입니다. 문의사항은 고객센터로 연락주세요.`,
);
}
} else if (user.status === STATUS_TYPE.SIGNOUT) {
throw new UnauthorizedException('탈퇴한 유저');
}
return user;
} else {
Expand Down
1 change: 1 addition & 0 deletions src/common/consts/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ function getEnumTypeValues(enumType) {
enum STATUS_TYPE {
NORMAL = 'normal',
FORBIDDEN = 'forbidden',
SIGNOUT = 'signOut',
}

//카테고리 타입 한글로
Expand Down
18 changes: 17 additions & 1 deletion src/common/dtos/UserProfile.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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' })
Expand All @@ -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,
};
12 changes: 12 additions & 0 deletions src/repositories/user.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<User | null> {
const user = await this.userModel
.findOne({ _id: userIdDto.userId })
Expand Down

0 comments on commit 1420ea4

Please sign in to comment.