Skip to content

Commit

Permalink
fix: commit to unfinished merge
Browse files Browse the repository at this point in the history
  • Loading branch information
koreaioi committed Nov 6, 2024
2 parents aab03c4 + 1b334c6 commit c3e8f22
Show file tree
Hide file tree
Showing 13 changed files with 340 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.leets.X.domain.follow.controller;

import com.leets.X.domain.follow.dto.response.FollowResponse;
import com.leets.X.domain.follow.service.FollowService;
import com.leets.X.global.common.response.ResponseDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.List;

import static com.leets.X.domain.follow.controller.ResponseMessage.*;

@Tag(name = "FOLLOW")
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/follows")
public class FollowController {
private final FollowService followService;

@PostMapping("/{userId}")
@Operation(summary = "팔로우 하기")
public ResponseDto<String> follow(@PathVariable Long userId, @AuthenticationPrincipal String email){
followService.follow(userId, email);
return ResponseDto.response(FOLLOW_SUCCESS.getCode(), FOLLOW_SUCCESS.getMessage());
}

@GetMapping("follower/{userId}")
@Operation(summary = "해당 유저의 팔로워 조회(해당 유저를 팔로우 하는 사용자 목록")
public ResponseDto<List<FollowResponse>> getFollowers(@PathVariable Long userId){
return ResponseDto.response(GET_FOLLOWER_SUCCESS.getCode(), GET_FOLLOWER_SUCCESS.getMessage(), followService.getFollowers(userId));
}

@GetMapping("following/{userId}")
@Operation(summary = "해당 유저의 팔로잉 조회(해당 유저가 팔로우 하는 사용자 목록")
public ResponseDto<List<FollowResponse>> getFollowings(@PathVariable Long userId){
return ResponseDto.response(GET_FOLLOWING_SUCCESS.getCode(), GET_FOLLOWING_SUCCESS.getMessage(), followService.getFollowings(userId));
}

@DeleteMapping("/{userId}")
@Operation(summary = "언팔로우 하기")
public ResponseDto<String> unfollow(@PathVariable Long userId, @AuthenticationPrincipal String email){
followService.unfollow(userId, email);
return ResponseDto.response(UNFOLLOW_SUCCESS.getCode(), UNFOLLOW_SUCCESS.getMessage());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.leets.X.domain.follow.controller;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum ResponseMessage {

FOLLOW_SUCCESS(200, "팔로우에 성공했습니다."),
GET_FOLLOWER_SUCCESS(200, "팔로워 목록 조회에 성공했습니다."),
GET_FOLLOWING_SUCCESS(200, "팔로잉 목록 조회에 성공했습니다."),
UNFOLLOW_SUCCESS(200, "언팔로우에 성공했습니다.");

private final int code;
private final String message;
}
35 changes: 34 additions & 1 deletion src/main/java/com/leets/X/domain/follow/domain/Follow.java
Original file line number Diff line number Diff line change
@@ -1,2 +1,35 @@
package com.leets.X.domain.follow.domain;public class Follow {
package com.leets.X.domain.follow.domain;

import com.leets.X.domain.user.domain.User;
import com.leets.X.global.common.domain.BaseTimeEntity;
import jakarta.persistence.*;
import lombok.*;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@Getter
public class Follow extends BaseTimeEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "follow_id")
private Long id;

@ManyToOne
@JoinColumn(name = "follower_id")
private User follower;

@ManyToOne
@JoinColumn(name = "followed_id")
private User followed;

public static Follow of(User follower, User followed) {
return Follow.builder()
.follower(follower)
.followed(followed)
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.leets.X.domain.follow.dto.response;

import com.leets.X.domain.user.domain.User;
import lombok.Builder;

@Builder
public record FollowResponse(
Long id,
String name,
String customId,
String introduce
// boolean followStatus
) {
public static FollowResponse from(User user) {
return FollowResponse.builder()
.id(user.getId())
.name(user.getName())
.customId(user.getCustomId())
.introduce(user.getIntroduce())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.leets.X.domain.follow.exception;

import com.leets.X.global.common.exception.BaseException;

import static com.leets.X.domain.follow.exception.ErrorMessage.*;

public class AlreadyFollowException extends BaseException {
public AlreadyFollowException() {
super(ALREADY_FOLLOW.getCode(), ALREADY_FOLLOW.getMessage());
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.leets.X.domain.follow.exception;


import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum ErrorMessage {

ALREADY_FOLLOW(400,"이미 팔로우한 상태입니다."),
INVALID_FOLLOW(400, "자기 자신은 팔로우 할 수 없습니다."),
FOLLOW_NOT_FOUND(404, "팔로우 데이터를 찾을 수 없습니다."),
INVALID_UNFOLLOW(400, "팔로우 하지 않은 상대는 언팔로우 할 수 없습니다.");


private final int code;
private final String message;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.leets.X.domain.follow.exception;

import com.leets.X.global.common.exception.BaseException;

import static com.leets.X.domain.follow.exception.ErrorMessage.*;

public class FollowNotFoundException extends BaseException {
public FollowNotFoundException() {
super(FOLLOW_NOT_FOUND.getCode(), FOLLOW_NOT_FOUND.getMessage());
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.leets.X.domain.follow.exception;

import com.leets.X.global.common.exception.BaseException;

import static com.leets.X.domain.follow.exception.ErrorMessage.*;

public class InvalidFollowException extends BaseException {
public InvalidFollowException() {
super(INVALID_FOLLOW.getCode(), INVALID_FOLLOW.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.leets.X.domain.follow.exception;

import com.leets.X.global.common.exception.BaseException;

import static com.leets.X.domain.follow.exception.ErrorMessage.*;

public class InvalidUnfollowException extends BaseException {
public InvalidUnfollowException() {
super(INVALID_UNFOLLOW.getCode(), INVALID_UNFOLLOW.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.leets.X.domain.follow.repository;

import com.leets.X.domain.follow.domain.Follow;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;

public interface FollowRepository extends JpaRepository<Follow, Long> {

Optional<Follow> findByFollowerIdAndFollowedId(Long followerId, Long followedId);

// followerId가 포함된 객체 리스트 반환
List<Follow> findByFollowerId(Long followerId);

// followedId가 포함된 객체 리스트 반환
List<Follow> findByFollowedId(Long followedId);

boolean existsByFollowerIdAndFollowedId(Long followerId, Long followedId);

}
96 changes: 96 additions & 0 deletions src/main/java/com/leets/X/domain/follow/service/FollowService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.leets.X.domain.follow.service;

import com.leets.X.domain.follow.domain.Follow;
import com.leets.X.domain.follow.dto.response.FollowResponse;
import com.leets.X.domain.follow.exception.AlreadyFollowException;
import com.leets.X.domain.follow.exception.FollowNotFoundException;
import com.leets.X.domain.follow.exception.InvalidFollowException;
import com.leets.X.domain.follow.exception.InvalidUnfollowException;
import com.leets.X.domain.follow.repository.FollowRepository;
import com.leets.X.domain.user.domain.User;
import com.leets.X.domain.user.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor
public class FollowService {
private final FollowRepository followRepository;
private final UserService userService;

@Transactional
public void follow(Long userId, String email){
User follower = userService.find(email);
User followed = userService.find(userId);

validate(follower.getId(), followed.getId());

Follow follow = followRepository.save(Follow.of(follower, followed));

follower.addFollowing(follow);
followed.addFollower(follow);
}

public List<FollowResponse> getFollowers(Long userId){
User user = userService.find(userId);

List<Follow> followerList = user.getFollowerList();

return followerList.stream()
.map(follow -> {
return FollowResponse.from(follow.getFollower()); })
.toList();
}

public List<FollowResponse> getFollowings(Long userId){
User user = userService.find(userId);

List<Follow> followingList = user.getFollowingList();

return followingList.stream()
.map(follow -> {
return FollowResponse.from(follow.getFollowed()); })
.toList();
}

@Transactional
public void unfollow(Long userId, String email){
User follower = userService.find(email);
User followed = userService.find(userId);

Follow follow = check(follower.getId(), followed.getId());

follower.removeFollowing(follow);
followed.removeFollower(follow);

followRepository.delete(follow);
}

public Follow find(Long followerId, Long followedId){
return followRepository.findByFollowerIdAndFollowedId(followerId, followedId)
.orElseThrow(FollowNotFoundException::new);
}

// 기존 팔로우 정보가 있는지, 나한테 요청을 하지 않는지 검증
private void validate(Long followerId, Long followedId){
if(followRepository.existsByFollowerIdAndFollowedId(followerId, followedId)){
throw new AlreadyFollowException();
}
if(followerId.equals(followedId)){
throw new InvalidFollowException();
}
}

// 팔로우 되어 있는지 확인
private Follow check(Long followerId, Long followedId){
if(!followRepository.existsByFollowerIdAndFollowedId(followerId, followedId)){
throw new InvalidUnfollowException();
}
return find(followerId, followedId);
}

}
25 changes: 25 additions & 0 deletions src/main/java/com/leets/X/domain/user/domain/User.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.leets.X.domain.user.domain;

import com.leets.X.domain.follow.domain.Follow;
import com.leets.X.domain.like.domain.Like;
import com.leets.X.domain.post.domain.Post;
import com.leets.X.domain.user.dto.request.UserInitializeRequest;
Expand Down Expand Up @@ -55,6 +56,12 @@ public class User extends BaseTimeEntity {
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, orphanRemoval = true)
private List<Like> likes = new ArrayList<>();

@OneToMany(mappedBy = "followed", cascade = CascadeType.REMOVE, orphanRemoval = true)
private List<Follow> followerList = new ArrayList<>();

@OneToMany(mappedBy = "follower", cascade = CascadeType.REMOVE, orphanRemoval = true)
private List<Follow> followingList = new ArrayList<>();

public void initProfile(UserInitializeRequest dto){
this.birth = dto.birth();
this.customId = dto.customId();
Expand All @@ -67,4 +74,22 @@ public void update(UserUpdateRequest dto){
this.webSite = dto.webSite();
}

public void addFollower(Follow follow) {
this.followerList.add(follow);
}

public void addFollowing(Follow follow) {
this.followingList.add(follow);
}

public void removeFollower(Follow follow) {
this.followerList.remove(follow);
}

public void removeFollowing(Follow follow) {
this.followingList.remove(follow);
}



}
10 changes: 10 additions & 0 deletions src/main/java/com/leets/X/domain/user/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ public UserProfileResponse getProfile(Long userId, String email){
// 아니라면 false
return UserProfileResponse.from(user, false);
}
//
// @Transactional
// public void delete(Long userId){
// userRepository.deleteById(userId);
// }

private UserSocialLoginResponse loginUser(String email) {
User user = find(email);
Expand Down Expand Up @@ -111,6 +116,11 @@ public User find(String email){
.orElseThrow(UserNotFoundException::new);
}

public User find(Long userId){
return userRepository.findById(userId)
.orElseThrow(UserNotFoundException::new);
}

public boolean existUser(String email){
return userRepository.existsByEmail(email);
}
Expand Down

0 comments on commit c3e8f22

Please sign in to comment.