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

[Feature/followers] follower, follow 정보 요청 시 데이터 전달 #61

Closed
wants to merge 9 commits into from
2 changes: 1 addition & 1 deletion server/apps/api/src/user/dto/follower.dto.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IsString } from 'class-validator';

export class followerDto {
export class FollowerDto {
@IsString()
myId: string;

Expand Down
36 changes: 24 additions & 12 deletions server/apps/api/src/user/user.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Body, Controller, Delete, Get, Inject, LoggerService, Param, Post } from '@nestjs/common';
import { UserService } from './user.service';
import { followerDto } from '@user/dto/follower.dto';
import { FollowerDto } from '@user/dto/follower.dto';
import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';
import { responseForm } from '@utils/responseForm';
import { ObjectIdValidationPipe } from '@custom_pipe/mongodbObjectIdValidation.pipe';
Expand All @@ -22,28 +22,40 @@ export class UserController {
@Post('following/:id')
async addFollowing(@Param('id', ObjectIdValidationPipe) id: string) {
try {
const myId = '63734e98384f478a32c3a1cc';
const myId = '63739b643969101c3fec8849';
// TODO: Request Header에서 access token으로 현재 사용자 알아내기
const addFollowingDto: followerDto = { myId, followId: id };
await this.userService.addFollowing(addFollowingDto);
return responseForm(200, {});
const addFollowingDto: FollowerDto = { myId, followId: id };
const result = await this.userService.toggleFollowing(addFollowingDto);
return responseForm(200, result);
} catch (error) {
this.logger.error(JSON.stringify(error.response));
return error.response;
}
}

@Delete('following/:id')
async unFollowing(@Param('id', ObjectIdValidationPipe) id: string) {
@Get('followers')
async getFollowers() {
try {
const myId = '63734e98384f478a32c3a1cc';
const _id = '63734f4eca63eaf1876a2c3b';
// TODO: Request Header에서 access token으로 현재 사용자 알아내기
const unFollowingDto: followerDto = { myId, followId: id };
await this.userService.unFollowing(unFollowingDto);
return responseForm(200, {});
const result = await this.userService.getRelatedUsers(_id, 'followers');
return responseForm(200, { followers: result });
} catch (error) {
this.logger.error(JSON.stringify(error.response));
return error.response;
return error.response ?? error;
}
}

@Get('followings')
async getFollowings() {
try {
const _id = '63739b643969101c3fec8849';
// TODO: Request Header에서 access token으로 현재 사용자 알아내기
const result = await this.userService.getRelatedUsers(_id, 'followings');
return responseForm(200, { followings: result });
} catch (error) {
this.logger.error(JSON.stringify(error.response));
return error.response ?? error;
}
}

Expand Down
91 changes: 48 additions & 43 deletions server/apps/api/src/user/user.service.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,48 @@
import { BadRequestException, ConflictException, Injectable, Param } from '@nestjs/common';
import { followerDto } from '@user/dto/follower.dto';
import { FollowerDto } from '@user/dto/follower.dto';
import { UserRepository } from '@repository/user.repository';
import { getUserBasicInfo } from '@user/dto/user-basic-info.dto';

@Injectable()
export class UserService {
constructor(private readonly userRepository: UserRepository) {}

// createUser(createUserDto: CreateUserDto) {
// this.userRepository.create(createUserDto);
// }

async addFollowing(addFollowingDto: followerDto) {
const user = await this.userRepository.findById(addFollowingDto.myId);
const otherUser = await this.userRepository.findById(addFollowingDto.followId);
if (!user || !otherUser) {
throw new BadRequestException('해당하는 사용자의 _id가 올바르지 않습니다.');
} else if (user.followings.includes(addFollowingDto.followId)) {
throw new BadRequestException('팔로우 요청한 사용자는 이미 팔로우되어있습니다.');
} else if (otherUser.followers.includes(addFollowingDto.myId)) {
throw new ConflictException('상대방의 팔로워 목록에 이미 있습니다.');
}

this.userRepository.appendElementAtArr(
{ _id: addFollowingDto.myId },
{ followings: addFollowingDto.followId },
);
this.userRepository.appendElementAtArr(
{ _id: addFollowingDto.followId },
{ followers: addFollowingDto.myId },
);
}

async unFollowing(unFollowingDto: followerDto) {
const user = await this.userRepository.findById(unFollowingDto.myId);
const otherUser = await this.userRepository.findById(unFollowingDto.followId);
async toggleFollowing(followerDto: FollowerDto) {
const user = await this.userRepository.findById(followerDto.myId);
const otherUser = await this.userRepository.findById(followerDto.followId);
const isAlreadyFollow = user.followings.includes(followerDto.followId);
const isAlreadyFollowAtOther = otherUser.followers.includes(followerDto.myId);
if (!user || !otherUser) {
throw new BadRequestException('해당하는 사용자의 _id가 올바르지 않습니다.');
} else if (!user.followings.includes(unFollowingDto.followId)) {
throw new BadRequestException(
`팔로우 요청한 사용자 ${user.nickname}은 ${otherUser.nickname}을 팔로우하고 있지 않습니다.`,
);
} else if (!otherUser.followers.includes(unFollowingDto.myId)) {
} else if (!isAlreadyFollow && isAlreadyFollowAtOther) {
throw new ConflictException('갱신 이상! (팔로우 안되어있으나, 상대방에겐 내가 팔로우됨)');
} else if (isAlreadyFollow && !isAlreadyFollowAtOther) {
throw new ConflictException(
`${otherUser.nickname}의 팔로워 목록에 ${user.nickname}가 없습니다.`,
'갱신 이상! (팔로우 되어있으나, 상대방에겐 내가 팔로우되어있지 않음)',
);
} else if (!isAlreadyFollow && !isAlreadyFollowAtOther) {
// 팔로우 되어있지 않은 경우 팔로우 필요
this.userRepository.appendElementAtArr(
{ _id: followerDto.myId },
{ followings: followerDto.followId },
);
this.userRepository.appendElementAtArr(
{ _id: followerDto.followId },
{ followers: followerDto.myId },
);
return { message: '팔로우 신청 완료' };
} else if (isAlreadyFollow && isAlreadyFollowAtOther) {
// 팔로우 되어있어 언팔로우 필요
this.userRepository.deleteElementAtArr(
{ _id: followerDto.myId },
{ followings: [followerDto.followId] },
);
this.userRepository.deleteElementAtArr(
{ _id: followerDto.followId },
{ followers: [followerDto.myId] },
);
return { message: '언팔로우 완료' };
}
this.userRepository.deleteElementAtArr(
{ _id: unFollowingDto.myId },
{ followings: [unFollowingDto.followId] },
);
this.userRepository.deleteElementAtArr(
{ _id: unFollowingDto.followId },
{ followers: [unFollowingDto.myId] },
);
}

async getUser(_id: string) {
Expand All @@ -63,4 +52,20 @@ export class UserService {
}
return getUserBasicInfo(user);
}

async getRelatedUsers(_id: string, option: string) {
const user = await this.userRepository.findById(_id);
if (!user) {
throw new BadRequestException('요청한 사용자는 없는 사용자입니다.');
}

const { followings, followers } = user;
const userIdList = option == 'followers' ? followers : followings;
// TODO: 배열을 순회하면서 찾지 않고 한번에 db에서 찾도록하는 mongoose 명령 있는지 확인하기
return await Promise.all(
userIdList.map(async (userId) => {
return getUserBasicInfo(await this.userRepository.findById(userId));
}),
);
}
}
10 changes: 9 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4061,6 +4061,14 @@ class-transformer@^0.5.1:
resolved "https://registry.yarnpkg.com/class-transformer/-/class-transformer-0.5.1.tgz#24147d5dffd2a6cea930a3250a677addf96ab336"
integrity sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==

class-validator-mongo-object-id@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/class-validator-mongo-object-id/-/class-validator-mongo-object-id-1.3.0.tgz#87ff0226da8132cbaf05cc470dcbe9203e2a803e"
integrity sha512-LiXaZkhPoqZ2TvXV7duHsbed/cdM7uU/EOOIV53ZjsuS4N03e+wbQ64fxBr0AA3psrdhrD8llWe5FdttcqRqRA==
dependencies:
class-validator "^0.13.2"
mongoose "^6.2.1"

class-validator@^0.13.2:
version "0.13.2"
resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.13.2.tgz#64b031e9f3f81a1e1dcd04a5d604734608b24143"
Expand Down Expand Up @@ -7933,7 +7941,7 @@ [email protected]:
"@aws-sdk/credential-providers" "^3.186.0"
saslprep "^1.0.3"

mongoose@^6.7.2:
mongoose@^6.2.1, mongoose@^6.7.2:
version "6.7.2"
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-6.7.2.tgz#457994b254a2afd1e03dd8f0b3046ff3d2ed276e"
integrity sha512-lrP2V5U1qhaf+z33fiIn7aYAZZ1fVDly+TkFRjTujNBF/FIHESATj2RbgAOSlWqv32fsZXkXejXzeVfjbv35Ow==
Expand Down