-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
…-및-프로필-정보-조회 [feat] 팔로우 언팔로우 관련 기능 구현 및 프로필 정보 조회
- Loading branch information
Showing
41 changed files
with
608 additions
and
322 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
src/main/java/com/leets/xcellentbe/domain/follow/controller/FollowController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package com.leets.xcellentbe.domain.follow.controller; | ||
|
||
import org.springframework.data.domain.Page; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import com.leets.xcellentbe.domain.follow.dto.FollowRequestDto; | ||
import com.leets.xcellentbe.domain.follow.dto.FollowInfoResponseDto; | ||
import com.leets.xcellentbe.domain.follow.service.FollowService; | ||
import com.leets.xcellentbe.global.response.GlobalResponseDto; | ||
|
||
import io.swagger.v3.oas.annotations.Operation; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@RestController | ||
@RequestMapping("/api/profile") | ||
@RequiredArgsConstructor | ||
public class FollowController { | ||
private final FollowService followService; | ||
|
||
@PostMapping("/follow") | ||
@Operation(summary = "팔로우", description = "다른 사용자를 팔로우합니다.") | ||
public ResponseEntity<GlobalResponseDto<FollowRequestDto>> followUser(@RequestBody FollowRequestDto requestDto, | ||
HttpServletRequest request) { | ||
followService.followUser(requestDto, request); | ||
return ResponseEntity.status(HttpStatus.OK) | ||
.body(GlobalResponseDto.success()); | ||
} | ||
|
||
@DeleteMapping("/follow") | ||
@Operation(summary = "언팔로우", description = "다른 사용자를 언팔로우합니다.") | ||
public ResponseEntity<GlobalResponseDto<FollowRequestDto>> unfollowerUser(@RequestBody FollowRequestDto requestDto, | ||
HttpServletRequest request) { | ||
followService.unfollowUser(requestDto, request); | ||
return ResponseEntity.status(HttpStatus.OK) | ||
.body(GlobalResponseDto.success()); | ||
} | ||
|
||
@GetMapping("/following") | ||
@Operation(summary = "팔로잉 조회", description = "사용자가 팔로우하는 사용자 목록을 조회합니다.") | ||
public ResponseEntity<GlobalResponseDto<Page<FollowInfoResponseDto>>> getFollowingList( | ||
@RequestParam(required = false, defaultValue = "1") int pageNo, @RequestParam String customId) { | ||
return ResponseEntity.status(HttpStatus.OK) | ||
.body(GlobalResponseDto.success(followService.getFollowingList(customId, pageNo - 1))); | ||
} | ||
|
||
@GetMapping("/follower") | ||
@Operation(summary = "팔로워 조회", description = "사용자를 팔로우하는 사용자 목록을 조회합니다.") | ||
public ResponseEntity<GlobalResponseDto<Page<FollowInfoResponseDto>>> getFollowerList( | ||
@RequestParam(required = false, defaultValue = "1") int pageNo, @RequestParam String customId) { | ||
return ResponseEntity.status(HttpStatus.OK) | ||
.body(GlobalResponseDto.success(followService.getFollowerList(customId, pageNo - 1))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
src/main/java/com/leets/xcellentbe/domain/follow/domain/repository/FollowRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,18 @@ | ||
package com.leets.xcellentbe.domain.follow.domain.repository; | ||
|
||
import java.util.Optional; | ||
|
||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
import com.leets.xcellentbe.domain.follow.domain.Follow; | ||
import com.leets.xcellentbe.domain.user.domain.User; | ||
|
||
public interface FollowRepository extends JpaRepository<Follow, Long> { | ||
Optional<Follow> findByFollowerAndFollowing(User user, User targetUser); | ||
|
||
Page<Follow> findByFollower(User user, Pageable pageable); | ||
|
||
Page<Follow> findByFollowing(User user, Pageable pageable); | ||
} |
28 changes: 28 additions & 0 deletions
28
src/main/java/com/leets/xcellentbe/domain/follow/dto/FollowInfoResponseDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.leets.xcellentbe.domain.follow.dto; | ||
|
||
import com.leets.xcellentbe.domain.follow.domain.Follow; | ||
import com.leets.xcellentbe.domain.user.domain.User; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
public class FollowInfoResponseDto { | ||
private String customId; | ||
private String userName; | ||
|
||
@Builder | ||
public FollowInfoResponseDto(String customId, String userName) { | ||
this.customId = customId; | ||
this.userName = userName; | ||
} | ||
|
||
public static FollowInfoResponseDto from(Follow follow) { | ||
User user = follow.getFollowing(); | ||
return FollowInfoResponseDto.builder() | ||
.customId(user.getCustomId()) | ||
.userName(user.getUserName()) | ||
.build(); | ||
} | ||
|
||
} |
8 changes: 8 additions & 0 deletions
8
src/main/java/com/leets/xcellentbe/domain/follow/dto/FollowRequestDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.leets.xcellentbe.domain.follow.dto; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public class FollowRequestDto { | ||
private String customId; | ||
} |
10 changes: 10 additions & 0 deletions
10
src/main/java/com/leets/xcellentbe/domain/follow/exception/FollowOperationError.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.leets.xcellentbe.domain.follow.exception; | ||
|
||
import com.leets.xcellentbe.global.error.ErrorCode; | ||
import com.leets.xcellentbe.global.error.exception.CommonException; | ||
|
||
public class FollowOperationError extends CommonException { | ||
public FollowOperationError() { | ||
super(ErrorCode.FOLLOW_OPERATION_ERROR); | ||
} | ||
} |
114 changes: 114 additions & 0 deletions
114
src/main/java/com/leets/xcellentbe/domain/follow/service/FollowService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package com.leets.xcellentbe.domain.follow.service; | ||
|
||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.PageRequest; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.data.domain.Sort; | ||
import org.springframework.stereotype.Service; | ||
|
||
import com.leets.xcellentbe.domain.follow.domain.Follow; | ||
import com.leets.xcellentbe.domain.follow.domain.repository.FollowRepository; | ||
import com.leets.xcellentbe.domain.follow.dto.FollowInfoResponseDto; | ||
import com.leets.xcellentbe.domain.follow.dto.FollowRequestDto; | ||
import com.leets.xcellentbe.domain.follow.exception.FollowOperationError; | ||
import com.leets.xcellentbe.domain.user.domain.User; | ||
import com.leets.xcellentbe.domain.user.domain.repository.UserRepository; | ||
import com.leets.xcellentbe.domain.user.exception.UserNotFoundException; | ||
import com.leets.xcellentbe.global.auth.jwt.JwtService; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.transaction.Transactional; | ||
import lombok.AllArgsConstructor; | ||
|
||
@Service | ||
@Transactional | ||
@AllArgsConstructor | ||
public class FollowService { | ||
|
||
private static final int PAGE_SIZE = 10; | ||
private final UserRepository userRepository; | ||
private final JwtService jwtService; | ||
private final FollowRepository followRepository; | ||
|
||
// 팔로우 | ||
public void followUser(FollowRequestDto requestDto, HttpServletRequest request) { | ||
User user = getUser(request); | ||
User targetUser = getTargetUser(requestDto); | ||
|
||
if (isFollowing(user, targetUser)) { | ||
throw new FollowOperationError(); | ||
} | ||
|
||
Follow follow = Follow.create(user, targetUser); | ||
followRepository.save(follow); | ||
} | ||
|
||
// 이미 팔로우 중인지 확인 | ||
private boolean isFollowing(User user, User targetUser) { | ||
return followRepository.findByFollowerAndFollowing(user, targetUser).isPresent(); | ||
} | ||
|
||
// 언팔로우 | ||
public void unfollowUser(FollowRequestDto requestDto, HttpServletRequest request) { | ||
User user = getUser(request); | ||
User targetUser = getTargetUser(requestDto); | ||
|
||
Follow follow = getFollowRelation(user, targetUser); | ||
|
||
followRepository.delete(follow); | ||
} | ||
|
||
// 팔로우 관계 조회 | ||
private Follow getFollowRelation(User user, User targetUser) { | ||
Follow follow = followRepository.findByFollowerAndFollowing(user, targetUser) | ||
.orElseThrow(FollowOperationError::new); | ||
return follow; | ||
} | ||
|
||
// 팔로우(언팔로우) 대상 유저 조회 | ||
private User getTargetUser(FollowRequestDto requestDto) { | ||
User targetUser = userRepository.findByCustomId(requestDto.getCustomId()) | ||
.orElseThrow(UserNotFoundException::new); | ||
return targetUser; | ||
} | ||
|
||
// 팔로잉 목록 조회 | ||
public Page<FollowInfoResponseDto> getFollowingList(String customId, int pageNo) { | ||
User user = findUserByCustomId(customId); | ||
Pageable pageable = createPageable(pageNo); | ||
|
||
return followRepository.findByFollower(user, pageable) | ||
.map(FollowInfoResponseDto::from); | ||
} | ||
|
||
// 팔로워 목록 조회 | ||
public Page<FollowInfoResponseDto> getFollowerList(String customId, int pageNo) { | ||
User user = findUserByCustomId(customId); | ||
Pageable pageable = createPageable(pageNo); | ||
|
||
return followRepository.findByFollowing(user, pageable) | ||
.map(FollowInfoResponseDto::from); | ||
} | ||
|
||
// 커스텀아이디로 유저 검색 | ||
private User findUserByCustomId(String customId) { | ||
return userRepository.findByCustomId(customId) | ||
.orElseThrow(UserNotFoundException::new); | ||
} | ||
|
||
// 페이지네이션 객체 생성 | ||
private Pageable createPageable(int pageNo) { | ||
return PageRequest.of(pageNo, PAGE_SIZE, Sort.by(Sort.Direction.DESC, "following")); | ||
} | ||
|
||
//JWT 토큰 해독하여 사용자 정보 반환 메소드 | ||
private User getUser(HttpServletRequest request) { | ||
User user = jwtService.extractAccessToken(request) | ||
.filter(jwtService::isTokenValid) | ||
.flatMap(jwtService::extractEmail) | ||
.flatMap(userRepository::findByEmail) | ||
.orElseThrow(UserNotFoundException::new); | ||
|
||
return user; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.