Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

친구리스트 관련 로직, 간단한 상태 로직 추가 #32

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ export class AuthService {

// 회원가입
async signUp(signupDto: SignupDto) {
const { email, password } = signupDto;
this.logger.info(`Attempting to sign up user: ${signupDto.email}`);
const { email, password, nickname } = signupDto;
const params = {
ClientId: this.clientId,
Username: email,
Expand All @@ -64,10 +64,7 @@ export class AuthService {
this.logger.info(`User ${signupDto.email} signed up successfully.`);
return await this.cognitoClient.signUp(params).promise();

return await this.userService.createUser({
email,
nickname,
});
return await this.userService.createUser(signupDto);
} catch (e) {
this.logger.error(`Signup failed for ${signupDto.email}: ${e.message}`);
throw new HttpException('회원가입에 실패했습니다.', HttpStatus.CONFLICT);
Expand Down
4 changes: 2 additions & 2 deletions src/dto/changePassword.dto.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { IsString, Length } from 'class-validator';

export class ChangePasswordDto {
@IsString({ message: '비밀번호는 문자열이어야 합니다.' })
@IsString({ message: '새로운 비밀번호는 필수 입니다.' })
@Length(8, 20, { message: '비밀번호는 8자 이상 20자 이하이어야 합니다.' })
newPassword: string;

@IsString({ message: '비밀번호는 문자열이어야 합니다.' })
@IsString({ message: '현재 비밀번호는 필수입니다.' })
@Length(8, 20, { message: '비밀번호는 8자 이상 20자 이하이어야 합니다.' })
currentPassword: string;
}
2 changes: 1 addition & 1 deletion src/dto/forgotPassword.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { IsString, Length } from 'class-validator';
import { ConfirmSignupDto } from './confirmSignup.dto';

export class ForgotPasswordDto extends ConfirmSignupDto {
@IsString({ message: '비밀번호는 문자열이어야 합니다.' })
@IsString({ message: '비밀번호는 필수입니다.' })
@Length(8, 20, { message: '비밀번호는 8자 이상 20자 이하이어야 합니다.' })
newPassword: string;
}
9 changes: 9 additions & 0 deletions src/dto/friendOne.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { IsNumber } from 'class-validator';

export class FriendOneDto {
@IsNumber({}, { message: '유저 아이디는 필수 입니다.' })
userId: number;

@IsNumber({}, { message: '보낸 사람 아이디는 필수 입니다.' })
friendId: number;
}
2 changes: 1 addition & 1 deletion src/dto/login.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { IsString, Length } from 'class-validator';
import { EmailDto } from './email.dto';

export class LoginDto extends EmailDto {
@IsString({ message: '비밀번호는 문자열이어야 합니다.' })
@IsString({ message: '비밀번호는 필수입니다.' })
@Length(8, 20, { message: '비밀번호는 8자 이상 20자 이하이어야 합니다.' })
password: string;
}
2 changes: 1 addition & 1 deletion src/dto/sendFriend.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ import { IsNumber } from 'class-validator';
import { EmailDto } from './email.dto';

export class SendFriendDto extends EmailDto {
@IsNumber({}, { message: '받는 유저아이디는 숫자형이어야 합니다.' })
@IsNumber({}, { message: '아이디는 필수 입니다.' })
userId: number;
}
2 changes: 1 addition & 1 deletion src/dto/signup.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ import { IsString } from 'class-validator';
import { LoginDto } from './login.dto';

export class SignupDto extends LoginDto {
@IsString({ message: '닉네임은 문자열이어야 합니다.' })
@IsString({ message: '닉네임은 필수입니다.' })
nickname: string;
}
6 changes: 6 additions & 0 deletions src/dto/state.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { IsString } from 'class-validator';

export class StateDto {
@IsString({ message: '필수입니다.' })
state: string;
}
7 changes: 7 additions & 0 deletions src/dto/updateFriendRequset.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { IsBoolean } from 'class-validator';
import { FriendOneDto } from './friendOne.dto';

export class UpdateFriendRequest extends FriendOneDto {
@IsBoolean({ message: '필수입니다.' })
isAccepted: boolean;
}
22 changes: 17 additions & 5 deletions src/friend/friend.controller.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
import { Body, Controller, Get, Post } from '@nestjs/common';
import { Body, Controller, Get, Param, Post, Put } from '@nestjs/common';
import { FriendService } from './friend.service';

import { SendFriendDto } from './../dto/sendFriend.dto';
import { UpdateFriendRequest } from './../dto/updateFriendRequset.dto';

@Controller('api/user/v1/friend')
export class FriendController {
constructor(private readonly friendService: FriendService) {}
@Get()
test() {
return 'hello';
}

@Post('send')
async sendFriend(@Body() sendFriendDto: SendFriendDto) {
return await this.friendService.sendFriend(sendFriendDto);
}

@Get('receive/:id')
async getReceiveFriendRequest(@Param('id') id) {
return await this.friendService.getReceiveFriendRequest(+id);
}

@Put('accepted')
async updateFriendRequest(@Body() updateFriendRequest: UpdateFriendRequest) {
await this.friendService.updateFriendRequest(updateFriendRequest);
}

@Get('list/:id')
async getFriendList(@Param('id') id) {
return await this.friendService.getFriendList(+id);
}
}
124 changes: 113 additions & 11 deletions src/friend/friend.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma.service';
import { SendFriendDto } from './../dto/sendFriend.dto';
import { UserService } from '../user/user.service';
import { FriendOneDto } from './../dto/friendOne.dto';
import { UpdateFriendRequest } from './../dto/updateFriendRequset.dto';

@Injectable()
export class FriendService {
Expand All @@ -11,26 +13,29 @@ export class FriendService {
private readonly userService: UserService,
) {}

// 친구요청 보내기
async sendFriend(sendFriendDto: SendFriendDto) {
const { email, userId } = sendFriendDto;

if (!email || !userId) {
throw new HttpException(
'이메일 혹은 유저 아이디는 필수입니다.',
HttpStatus.BAD_REQUEST,
);
}

try {
const owner = await this.userService.getUserById(userId);
const friend = await this.userService.getUserByEmail(email);

if (!owner || !friend) {
throw new HttpException('없는 유저입니다.', HttpStatus.NOT_FOUND);
if (owner.id === friend.id) {
throw new HttpException('본인입니다.', HttpStatus.BAD_REQUEST);
}

if (owner.id === friend.id) {
throw new HttpException('본인입니다..', HttpStatus.NOT_FOUND);
const res = await this.prismaService.friendList.findUnique({
where: {
userId_friendId: {
userId: owner.id,
friendId: friend.id,
},
},
});

if (res) {
throw new HttpException('이미 친구입니다.', HttpStatus.CONFLICT);
}

return await this.prismaService.sendFriend.create({
Expand All @@ -44,4 +49,101 @@ export class FriendService {
throw new HttpException(e.response, e.status);
}
}

// 받은 친구 요청 보기(전체) - 나중에 페이지 네이션 구현할듯?
async getReceiveFriendRequest(id: number) {
await this.userService.getUserById(id);

const res = await this.prismaService.sendFriend.findMany({
where: { receiveUserId: id },
});

// map으로 id => userInfo 변환 (value에 null 또는 유저정보 들어감)
const ReceiveFriendList = await Promise.allSettled(
res.map(async (user) => {
try {
return await this.userService.getUserById(user.sendUserId);
} catch (_) {
return null;
}
}),
);

// 유저 정보 클라이언트에서 사용하기 편하게 map과 filter 사용
return ReceiveFriendList.map((result) => result['value']).filter(
(result) => result !== null,
);
}

// 요청 목록에서 일치하는 값 삭제
async deleteFriendRequest(friendOneDto: FriendOneDto) {
const { friendId, userId } = friendOneDto;

try {
await this.prismaService.sendFriend.delete({
where: {
sendUserId_receiveUserId: {
sendUserId: friendId,
receiveUserId: userId,
},
},
});
} catch (e) {
throw new HttpException('삭제하는데 실패했습니다.', HttpStatus.CONFLICT);
}
}

// 친구 추가
async addFriend(friendOneDto: FriendOneDto) {
const { userId, friendId } = friendOneDto;

// 존재하는지 체크
await this.userService.getUserById(userId);
await this.userService.getUserById(friendId);

try {
await this.prismaService.friendList.create({
data: { userId, friendId },
});

await this.prismaService.friendList.create({
data: { userId: friendId, friendId: userId },
});
} catch (e) {
throw new HttpException('이미 친구입니다.', HttpStatus.CONFLICT);
}
}

// 친구 요청 응답
async updateFriendRequest(updateFriendRequest: UpdateFriendRequest) {
const { userId, friendId, isAccepted } = updateFriendRequest;

if (isAccepted) {
await this.addFriend({ userId, friendId });
}

await this.deleteFriendRequest({ userId, friendId });
}

// 친구목록 모두 불러오기
async getFriendList(id: number) {
await this.userService.getUserById(id);

const res = await this.prismaService.friendList.findMany({
where: { userId: id },
});

const ReceiveFriendList = await Promise.allSettled(
res.map(async (user) => {
try {
return await this.userService.getUserById(user.friendId);
} catch (_) {
return null;
}
}),
);
return ReceiveFriendList.map((result) => result['value']).filter(
(result) => result !== null,
);
}
}
13 changes: 12 additions & 1 deletion src/user/user.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Controller, Get, Param } from '@nestjs/common';
import { Body, Controller, Get, Param, Put } from '@nestjs/common';
import { UserService } from './user.service';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { StateDto } from './../dto/state.dto';

@ApiTags('user')
@Controller('api/user/v1/user')
Expand All @@ -14,4 +15,14 @@ export class UserController {
async getUser(@Param('id') id: string) {
return await this.userService.getUserById(+id);
}

@Get(':id/state')
async getState(@Param('id') id) {
return await this.userService.getState(+id);
}

@Put(':id/state')
async changeState(@Param('id') id, @Body() stateDto: StateDto) {
return await this.userService.changeState(+id, stateDto);
}
}
Loading
Loading