From 693f5e33baa34254d1afb6ff2b9bdcbd5cee973d Mon Sep 17 00:00:00 2001 From: niamu01 Date: Thu, 14 Dec 2023 23:04:08 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20:recycle:=20=EB=B3=80=EC=88=98?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=ED=95=A8=EC=88=98?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit login -> target, FollowListByMe -> FollowList, FollowUserList -> FollowListWithCount, followUser->followLser, cursusUserService에 유저 아이디 찾는 함수 추가, 중복되는 함수 분리 - #405 --- app/src/api/cursusUser/cursusUser.service.ts | 43 ++++ app/src/follow/follow.module.ts | 1 - app/src/follow/follow.resolve.ts | 40 ++-- app/src/follow/follow.service.ts | 204 +++++++++---------- app/src/follow/model/follow.model.ts | 10 +- app/src/schema.gql | 16 +- 6 files changed, 175 insertions(+), 139 deletions(-) diff --git a/app/src/api/cursusUser/cursusUser.service.ts b/app/src/api/cursusUser/cursusUser.service.ts index a7cf18c2..d6f7b94d 100644 --- a/app/src/api/cursusUser/cursusUser.service.ts +++ b/app/src/api/cursusUser/cursusUser.service.ts @@ -77,6 +77,18 @@ export class CursusUserService { return this.cursusUserModel.aggregate(); } + async getuserIdByLogin(login: string): Promise { + const userId = await this.findOneAndLean({ + filter: { 'user.login': login }, + }).then((user) => user?.user.id); + + if (!userId) { + return null; + } + + return userId; + } + async findAllAndLean( queryArgs?: QueryArgs, ): Promise { @@ -116,6 +128,37 @@ export class CursusUserService { })); } + async findOneUserPreviewAndLean( + queryArgs?: Omit, 'select'>, + ): Promise { + const cursusUsers: { + user: { + id: number; + login: string; + image: { + link?: string; + }; + }; + } | null = await this.findOneAndLean({ + ...queryArgs, + select: { + 'user.id': 1, + 'user.login': 1, + 'user.image.link': 1, + }, + }); + + if (!cursusUsers) { + return null; + } + + return { + id: cursusUsers.user.id, + login: cursusUsers.user.login, + imgUrl: cursusUsers.user.image.link, + }; + } + async userFullProfile( filter?: FilterQuery, ): Promise { diff --git a/app/src/follow/follow.module.ts b/app/src/follow/follow.module.ts index 6534f310..c7ed7746 100644 --- a/app/src/follow/follow.module.ts +++ b/app/src/follow/follow.module.ts @@ -11,7 +11,6 @@ import { FollowService } from './follow.service'; CursusUserModule, ], providers: [FollowResolver, FollowService], - //exports: [FollowService], }) // eslint-disable-next-line export class FollowModule {} diff --git a/app/src/follow/follow.resolve.ts b/app/src/follow/follow.resolve.ts index b62282c5..e0f1c575 100644 --- a/app/src/follow/follow.resolve.ts +++ b/app/src/follow/follow.resolve.ts @@ -4,7 +4,7 @@ import { MyUserId } from 'src/auth/myContext'; import { StatAuthGuard } from 'src/auth/statAuthGuard'; import { HttpExceptionFilter } from 'src/http-exception.filter'; import { FollowService } from './follow.service'; -import { FollowResult, FollowUserList } from './model/follow.model'; +import { FollowListWithCount, FollowResult } from './model/follow.model'; @UseFilters(HttpExceptionFilter) @UseGuards(StatAuthGuard) @@ -26,44 +26,50 @@ export class FollowResolver { @Mutation((_returns) => FollowResult) async followUser( @MyUserId() userId: number, - @Args('login') login: string, + @Args('target') target: string, ): Promise { - return await this.followService.followUser(userId, login); + return await this.followService.followUser(userId, target); } @Mutation((_returns) => FollowResult) async unfollowUser( @MyUserId() userId: number, - @Args('login') login: string, + @Args('target') target: string, ): Promise { - return await this.followService.unfollowUser(userId, login); + return await this.followService.unfollowUser(userId, target); } - @Mutation((_returns) => FollowUserList) + @Mutation((_returns) => FollowListWithCount) async getFollowerList( @MyUserId() userId: number, - @Args('login') login: string, - ): Promise { - const followUser = await this.followService.getFollowerList(userId, login); - const count = await this.followService.getFollowerCount(login); + @Args('target') target: string, + ): Promise { + const followerList = await this.followService.getFollowerList( + userId, + target, + ); + const count = await this.followService.getFollowerCount(target); return { count, - followUser, + followList: followerList, }; } - @Mutation((_returns) => FollowUserList) + @Mutation((_returns) => FollowListWithCount) async getFollowingList( @MyUserId() userId: number, - @Args('login') login: string, - ): Promise { - const followUser = await this.followService.getFollowingList(userId, login); - const count = await this.followService.getFollowingCount(login); + @Args('target') target: string, + ): Promise { + const followingList = await this.followService.getFollowingList( + userId, + target, + ); + const count = await this.followService.getFollowingCount(target); return { count, - followUser, + followList: followingList, }; } } diff --git a/app/src/follow/follow.service.ts b/app/src/follow/follow.service.ts index 43d617fc..3f3a766e 100644 --- a/app/src/follow/follow.service.ts +++ b/app/src/follow/follow.service.ts @@ -1,10 +1,14 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; import { UserPreview } from 'src/common/models/common.user.model'; +import { + QueryArgs, + findAllAndLean, +} from 'src/database/mongoose/database.mongoose.query'; import { CursusUserService } from '../api/cursusUser/cursusUser.service'; import { follow } from './db/follow.database.schema'; -import { FollowListByMe, FollowResult } from './model/follow.model'; +import { FollowList, FollowResult } from './model/follow.model'; @Injectable() export class FollowService { @@ -14,6 +18,10 @@ export class FollowService { private readonly cursusUserService: CursusUserService, ) {} + async findAllAndLean(queryArgs?: QueryArgs): Promise { + return await findAllAndLean(this.followModel, queryArgs); + } + // 프론트 테스트용 임시 함수 async MakeFollowUser( to: string, @@ -59,36 +67,24 @@ export class FollowService { return { message: 'fail' }; } - // input으로 들어온 유저를 팔로우 함 async followUser( - followerId: number, - followingLogin: string, + userId: number, + target: string, ): Promise { - //const follower = await this.cursusUserService - // .findOneAndLean({ - // filter: { 'user.id': followerId }, - // }) - // .then((follower) => follower?.user.id); - - const following = await this.cursusUserService - .findOneAndLean({ - filter: { 'user.login': followingLogin }, - }) - .then((following) => following?.user.id); + const following = await this.cursusUserService.getuserIdByLogin(target); const alreadyFollow = await this.followModel.find({ - userId: followerId, + userId: userId, followId: following, }); - console.log(alreadyFollow.length); - - if (!following || followerId === following || alreadyFollow.length) { + // !following은 throw notfound 이긴 함 + if (!following || userId === following || alreadyFollow.length) { return { message: 'fail' }; } const result = await this.followModel - .create({ userId: followerId, followId: following }) + .create({ userId: userId, followId: following }) .then((result) => result.toObject()); return { @@ -98,31 +94,20 @@ export class FollowService { }; } - // input으로 들어온 유저를 언팔로우 함 // todo: unfollow 성공도 같은걸 (상태) 반환해서 이름 다시 지어야함 async unfollowUser( - followerId: number, - followingLogin: string, + userId: number, + target: string, ): Promise { - //const follower = await this.cursusUserService - // .findOneAndLean({ - // filter: { 'user.id': followerId }, - // }) - // .then((follower) => follower?.user.id); + const following = await this.cursusUserService.getuserIdByLogin(target); - const following = await this.cursusUserService - .findOneAndLean({ - filter: { 'user.login': followingLogin }, - }) - .then((following) => following?.user.id); - - if (!following || followerId === following) { + if (!following || userId === following) { return { message: 'fail' }; } const deletedCount = await this.followModel .deleteOne({ - userId: followerId, + userId: userId, followId: following, }) .then((result) => result.deletedCount); @@ -130,101 +115,83 @@ export class FollowService { if (deletedCount === 1) { return { message: 'OK', - userId: followerId, + userId: userId, followId: following, }; - } else { - return { - message: 'fail', - }; } + + return { message: 'fail' }; } - // input 유저 <- 팔로워 목록을 찾아옴 // getFollowerList("yeju") -> yeju를 팔로우 하는 사람들 - async getFollowerList(me: number, target: string): Promise { + async getFollowerList(userId: number, target: string): Promise { //target의 id - const targetId = await this.cursusUserService - .findOneAndLean({ - filter: { 'user.login': target }, - }) - .then((user) => user?.user.id); + const targetId = await this.cursusUserService.getuserIdByLogin(target); + + if (!targetId) { + throw new NotFoundException(); + } //target을 팔로우 하는 사람들 - const follower: follow[] = await this.followModel.find({ - followId: targetId, + const follower: follow[] = await this.findAllAndLean({ + filter: { followId: targetId }, }); - const targetFollowingUserPreview: Promise[] = follower.map( - async (follower) => { + const followerUserPreview: UserPreview[] = await Promise.all( + follower.map(async (follower) => { //target을 팔로우 하는 사람의 preview - const user = await this.cursusUserService - .findAllUserPreviewAndLean({ + const userPreview = + await this.cursusUserService.findOneUserPreviewAndLean({ filter: { 'user.id': follower.userId }, - }) - //findOne으로 바꾸기 - .then((a) => a[0]); - - return user; - }, - ); - - const followListByMeArray: Promise[] = - targetFollowingUserPreview.map(async (targetFollowingUser) => { - const user = await targetFollowingUser; - let follow: boolean = true; - - const isFollowed = await this.followModel.find({ - userId: me, - followId: user.id, - }); + }); - if (!isFollowed) { - follow = false; + if (!userPreview) { + throw new NotFoundException(); } - return { follow, user }; - }); + return userPreview; + }), + ); + + const followerList = await this.checkFollowingStatus( + userId, + followerUserPreview, + ); - return await Promise.all(followListByMeArray); + return followerList; } - // input 유저 -> 팔로잉 목록을 찾아옴 // getFollowingList("yeju") -> yeju(target)가 팔로우 하는 사람들 - async getFollowingList( - me: number, - target: string, - ): Promise { - //target의 id - const targetId = await this.cursusUserService - .findOneAndLean({ - filter: { 'user.login': target }, - }) - .then((user) => user?.user.id); + async getFollowingList(me: number, target: string): Promise { + const targetId = await this.cursusUserService.getuserIdByLogin(target); + + if (!targetId) { + throw new NotFoundException(); + } //target이 팔로우 하는 사람들 - const following: follow[] = await this.followModel.find({ - userId: targetId, + const following: follow[] = await this.findAllAndLean({ + filter: { userId: targetId }, }); - const targetFollowingUserPreview: Promise[] = following.map( + const followingUserPreview: Promise[] = following.map( async (following) => { - //target이 팔로우 하는 사람의 preview - const user = await this.cursusUserService - .findAllUserPreviewAndLean({ - filter: { 'user.id': following.followId }, - }) - //findOne으로 바꾸기 - .then((a) => a[0]); - - return user; + //target을 팔로우 하는 사람의 preview + return await this.cursusUserService.findOneUserPreviewAndLean({ + filter: { 'user.id': following.userId }, + }); }, ); - const followListByMeArray: Promise[] = - targetFollowingUserPreview.map(async (targetFollowingUser) => { - const user = await targetFollowingUser; - let follow: boolean = true; + const followingList: Promise[] = followingUserPreview.map( + async (following) => { + const user = await following; + + if (!user) { + throw new NotFoundException(); + } + + let isFollowing: boolean = true; const isFollowed = await this.followModel.find({ userId: me, @@ -232,13 +199,14 @@ export class FollowService { }); if (!isFollowed) { - follow = false; + isFollowing = false; } - return { follow, user }; - }); + return { isFollowing, user }; + }, + ); - return await Promise.all(followListByMeArray); + return await Promise.all(followingList); } async getFollowerCount(login: string): Promise { @@ -256,4 +224,24 @@ export class FollowService { return await this.followModel.countDocuments({ userId: id?.user.id }); //login filter } + + async checkFollowingStatus( + userId: number, + userPreview: UserPreview[], + ): Promise { + const followList = userPreview.map(async (user) => { + if (!user) { + throw new NotFoundException(); + } + + const isFollowed = await this.followModel.findOne({ + userId: userId, + followId: user.id, + }); + + return { isFollowing: !!isFollowed, user }; + }); + + return Promise.all(followList); + } } diff --git a/app/src/follow/model/follow.model.ts b/app/src/follow/model/follow.model.ts index 5884ebb5..928f7bc4 100644 --- a/app/src/follow/model/follow.model.ts +++ b/app/src/follow/model/follow.model.ts @@ -2,18 +2,18 @@ import { Field, ObjectType, createUnionType } from '@nestjs/graphql'; import { UserPreview } from 'src/common/models/common.user.model'; @ObjectType() -export class FollowListByMe { +export class FollowList { @Field() - follow: boolean; + isFollowing: boolean; @Field() user: UserPreview; } @ObjectType() -export class FollowUserList { - @Field((_type) => [FollowListByMe]) - followUser: FollowListByMe[]; +export class FollowListWithCount { + @Field((_type) => [FollowList]) + followList: FollowList[]; @Field() count: number; diff --git a/app/src/schema.gql b/app/src/schema.gql index 5add589a..41945f97 100644 --- a/app/src/schema.gql +++ b/app/src/schema.gql @@ -59,13 +59,13 @@ type UserRankingIndexPaginated { pageNumber: Int! } -type FollowListByMe { - follow: Boolean! +type FollowList { + isFollowing: Boolean! user: UserPreview! } -type FollowUserList { - followUser: [FollowListByMe!]! +type FollowListWithCount { + followList: [FollowList!]! count: Int! } @@ -649,10 +649,10 @@ type Mutation { """프론트 테스트용 임시 함수""" MakeFollow(to: String!, from: String!, type: String!): FollowResult! - followUser(login: String!): FollowResult! - unfollowUser(login: String!): FollowResult! - getFollowerList(login: String!): FollowUserList! - getFollowingList(login: String!): FollowUserList! + followUser(target: String!): FollowResult! + unfollowUser(target: String!): FollowResult! + getFollowerList(target: String!): FollowListWithCount! + getFollowingList(target: String!): FollowListWithCount! } union LoginResult = LoginSuccess | LoginNotLinked