diff --git a/src/main/java/team/wego/wegobackend/common/exception/AppErrorCode.java b/src/main/java/team/wego/wegobackend/common/exception/AppErrorCode.java index f450031..135b623 100644 --- a/src/main/java/team/wego/wegobackend/common/exception/AppErrorCode.java +++ b/src/main/java/team/wego/wegobackend/common/exception/AppErrorCode.java @@ -27,8 +27,10 @@ public enum AppErrorCode implements ErrorCode { INVALID_PASSWORD_VALUE(HttpStatus.BAD_REQUEST, "회원 : 비밀번호가 일치하지 않습니다."), DELETED_USER(HttpStatus.BAD_REQUEST, "회원 : 탈퇴한 회원입니다."), NOT_SAME_FOLLOW(HttpStatus.BAD_REQUEST, "회원 : 자기 자신을 팔로우할 수 없습니다."), + NOT_SAME_UNFOLLOW(HttpStatus.BAD_REQUEST, "회원 : 팔로우 취소 대상은 본인 될 수 없습니다."), ALREADY_EXIST_FOLLOW(HttpStatus.BAD_REQUEST, "회원 : 이미 팔로우 중입니다."), ALREADY_EXIST_NICKNAME(HttpStatus.BAD_REQUEST, "회원 : 이미 존재하는 닉네임입니다."), + NOT_FOUND_FOLLOW(HttpStatus.BAD_REQUEST, "회원 : 팔로우 관계를 찾을 수 없습니다."), EXPIRED_TOKEN(HttpStatus.UNAUTHORIZED, "인증 : 만료된 토큰입니다."), INVALID_TOKEN(HttpStatus.UNAUTHORIZED, "인증 : 유효하지 않은 토큰입니다.") diff --git a/src/main/java/team/wego/wegobackend/user/application/FollowService.java b/src/main/java/team/wego/wegobackend/user/application/FollowService.java index c6835d0..d1424f3 100644 --- a/src/main/java/team/wego/wegobackend/user/application/FollowService.java +++ b/src/main/java/team/wego/wegobackend/user/application/FollowService.java @@ -4,9 +4,12 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import team.wego.wegobackend.user.domain.Follow; import team.wego.wegobackend.user.domain.User; import team.wego.wegobackend.user.exception.ExistFollowException; +import team.wego.wegobackend.user.exception.NotFoundFollowException; import team.wego.wegobackend.user.exception.SameFollowException; +import team.wego.wegobackend.user.exception.SameUnFollowException; import team.wego.wegobackend.user.exception.UserNotFoundException; import team.wego.wegobackend.user.repository.FollowRepository; import team.wego.wegobackend.user.repository.UserRepository; @@ -35,5 +38,28 @@ public void follow(String followNickname, Long followerId) { if (followRepository.existsByFollowerIdAndFolloweeId(followerId, follow.getId())) { throw new ExistFollowException(); } + + followRepository.save(Follow.builder() + .follower(follower) + .follow(follow) + .build()); + } + + public void unFollow(String unFollowNickname, Long followerId) { + User follower = userRepository.findById(followerId) + .orElseThrow(UserNotFoundException::new); + + if (unFollowNickname.equals(follower.getNickName())) { + throw new SameUnFollowException(); + } + + User follow = userRepository.findByNickName(unFollowNickname) + .orElseThrow(UserNotFoundException::new); + + Follow followEntity = followRepository.findByFollowerIdAndFolloweeId(followerId, + follow.getId()) + .orElseThrow(NotFoundFollowException::new); + + followRepository.delete(followEntity); } } \ No newline at end of file diff --git a/src/main/java/team/wego/wegobackend/user/application/UserService.java b/src/main/java/team/wego/wegobackend/user/application/UserService.java index beab03f..8172d36 100644 --- a/src/main/java/team/wego/wegobackend/user/application/UserService.java +++ b/src/main/java/team/wego/wegobackend/user/application/UserService.java @@ -47,7 +47,7 @@ public UserInfoResponse updateProfileInfo(Long userId, ProfileUpdateRequest requ User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); - if (request.getNickName() != null) { + if (request.getNickName() != null && !request.getNickName().equals(user.getNickName())) { boolean isExistNickname = userRepository.existsByNickName(request.getNickName()); if (isExistNickname) { throw new SameNicknameException(); diff --git a/src/main/java/team/wego/wegobackend/user/exception/NotFoundFollowException.java b/src/main/java/team/wego/wegobackend/user/exception/NotFoundFollowException.java new file mode 100644 index 0000000..5ecb97f --- /dev/null +++ b/src/main/java/team/wego/wegobackend/user/exception/NotFoundFollowException.java @@ -0,0 +1,11 @@ +package team.wego.wegobackend.user.exception; + +import team.wego.wegobackend.common.exception.AppErrorCode; +import team.wego.wegobackend.common.exception.AppException; + +public class NotFoundFollowException extends AppException { + + public NotFoundFollowException() { + super(AppErrorCode.NOT_FOUND_FOLLOW); + } +} diff --git a/src/main/java/team/wego/wegobackend/user/exception/SameUnFollowException.java b/src/main/java/team/wego/wegobackend/user/exception/SameUnFollowException.java new file mode 100644 index 0000000..21a54ad --- /dev/null +++ b/src/main/java/team/wego/wegobackend/user/exception/SameUnFollowException.java @@ -0,0 +1,11 @@ +package team.wego.wegobackend.user.exception; + +import team.wego.wegobackend.common.exception.AppErrorCode; +import team.wego.wegobackend.common.exception.AppException; + +public class SameUnFollowException extends AppException { + + public SameUnFollowException() { + super(AppErrorCode.NOT_SAME_UNFOLLOW); + } +} diff --git a/src/main/java/team/wego/wegobackend/user/presentation/UserController.java b/src/main/java/team/wego/wegobackend/user/presentation/UserController.java index 5112d97..345f55b 100644 --- a/src/main/java/team/wego/wegobackend/user/presentation/UserController.java +++ b/src/main/java/team/wego/wegobackend/user/presentation/UserController.java @@ -114,6 +114,17 @@ public ResponseEntity> follow( } //TODO : 팔로우 삭제 API + @DeleteMapping("/unfollow") + public ResponseEntity> unFollow( + @AuthenticationPrincipal CustomUserDetails userDetails, + @Valid @RequestParam("unFollowNickname") String unFollowNickname + ) { + followService.unFollow(unFollowNickname, userDetails.getId()); + + return ResponseEntity + .status(HttpStatus.CREATED) + .body(ApiResponse.success(201, "팔로우 취소 성공")); + } //TODO : 팔로우 목록 조회 API diff --git a/src/main/java/team/wego/wegobackend/user/presentation/UserControllerDocs.java b/src/main/java/team/wego/wegobackend/user/presentation/UserControllerDocs.java index 6393127..b31c249 100644 --- a/src/main/java/team/wego/wegobackend/user/presentation/UserControllerDocs.java +++ b/src/main/java/team/wego/wegobackend/user/presentation/UserControllerDocs.java @@ -43,9 +43,15 @@ ResponseEntity> changeNotificationConfig( @RequestParam(required = true) Boolean isNotificationEnabled ); - @Operation(summary = "팔로우 등록 API", description = "요청 ID에 해당하는 사용자를 팔로우합니다.") + @Operation(summary = "팔로우 등록 API", description = "요청 닉네임에 해당하는 사용자를 팔로우합니다.") ResponseEntity> follow( @AuthenticationPrincipal CustomUserDetails userDetails, @Valid @RequestParam("followNickname") String followNickname ); + + @Operation(summary = "팔로우 취소 API", description = "요청 닉네임에 해당하는 사용자를 팔로우 취소합니다.") + ResponseEntity> unFollow( + @AuthenticationPrincipal CustomUserDetails userDetails, + @Valid @RequestParam("unFollowNickname") String unFollowNickname + ); } diff --git a/src/main/java/team/wego/wegobackend/user/repository/FollowRepository.java b/src/main/java/team/wego/wegobackend/user/repository/FollowRepository.java index 23bff89..c5672a8 100644 --- a/src/main/java/team/wego/wegobackend/user/repository/FollowRepository.java +++ b/src/main/java/team/wego/wegobackend/user/repository/FollowRepository.java @@ -1,9 +1,11 @@ package team.wego.wegobackend.user.repository; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import team.wego.wegobackend.user.domain.Follow; public interface FollowRepository extends JpaRepository { + Optional findByFollowerIdAndFolloweeId(Long followerId, Long followingId); boolean existsByFollowerIdAndFolloweeId(Long followerId, Long followingId); } diff --git a/src/test/http/user/user-api.http b/src/test/http/user/user-api.http index 02d6e30..6497256 100644 --- a/src/test/http/user/user-api.http +++ b/src/test/http/user/user-api.http @@ -66,3 +66,7 @@ Content-Type: application/json ### 팔로우 요청 POST http://localhost:8080/api/v1/users/follow?followNickname=팔로우 대상 Authorization: Bearer {{accessToken}} + +### 팔로우 취소 +DELETE http://localhost:8080/api/v1/users/unfollow?unFollowNickname=예은 +Authorization: Bearer {{accessToken}} \ No newline at end of file