Skip to content

Commit d88a06e

Browse files
authored
친구 따라가기 기능 추가 (#105)
* docs: 친구 따라가기 기능 Swagger 명세 추가 * add : 친구 따라가기 기능 엔드포인트 추가 * feat: 친구 따라가기 관련 에러 enum 추가 style: error status 코드 오름차순 정렬 * feat : 응답 요청 시, 응답 반환 시 사용될 dto 클래스 추가 * feat : 친구 따라가기 로직 추가 * fix: Proxy 엔티티에서 equals()가 오동작하는 문제 해결 * feat : 친구 따라가기 로직 기능 업로드 * fix: 친구 기능 에러 코드 정의 불일치 문제 수정
1 parent 06b9ae1 commit d88a06e

File tree

6 files changed

+97
-16
lines changed

6 files changed

+97
-16
lines changed

gotcha-domain/src/main/java/gotcha_domain/user/User.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public class User extends BaseTimeEntity {
121121
private Set<BugReport> bugReports = new HashSet<>();
122122

123123
@Builder
124-
public User(Long id, String email, String password, String nickname, Role role, String uuid){
124+
public User(Long id, String email, String password, String nickname, Role role, String uuid) {
125125
this.id = id;
126126
this.email = email;
127127
this.password = password;
@@ -139,16 +139,22 @@ public void updateChatSettings(ChatOption chatOption, PrivateChatOption privateC
139139
this.privateChatOption = privateChatOption;
140140
}
141141

142+
142143
@Override
143144
public boolean equals(Object o) {
144-
if (this == o) return true;
145-
if (o == null || getClass() != o.getClass()) return false;
145+
if (this == o) {
146+
return true;
147+
}
148+
if (!(o instanceof User)) {
149+
return false;
150+
}
146151
User user = (User) o;
147-
return id != null && id.equals(user.id);
152+
153+
return id != null && id.equals(user.getId());
148154
}
149155

150156
@Override
151157
public int hashCode() {
152158
return (id != null) ? id.hashCode() : 0;
153159
}
154-
}
160+
}

gotcha/src/main/java/Gotcha/domain/friend/api/FriendApi.java

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public interface FriendApi {
2323
@ApiResponse(responseCode = "200", description = "친구 목록 조회 성공",
2424
content = @Content(mediaType = "application/json", examples = {
2525
@ExampleObject(value = """
26-
26+
2727
""")
2828
}))
2929
})
@@ -50,7 +50,7 @@ public interface FriendApi {
5050
}))
5151
})
5252
ResponseEntity<?> searchUser(@AuthenticationPrincipal SecurityUserDetails userDetails,
53-
@RequestParam(value = "keyword") String keyword);
53+
@RequestParam(value = "keyword") String keyword);
5454

5555
@Operation(summary = "친구 신청 목록 조회", description = "친구 신청 목록 조회 API")
5656
@ApiResponses({
@@ -158,7 +158,8 @@ ResponseEntity<?> requestFriend(@AuthenticationPrincipal SecurityUserDetails use
158158
}))
159159
})
160160
ResponseEntity<?> acceptFriend(@PathVariable(value = "id") Long friendRequestId,
161-
@AuthenticationPrincipal SecurityUserDetails userDetails);
161+
@AuthenticationPrincipal SecurityUserDetails userDetails)
162+
throws NoSuchMethodException;
162163

163164
@Operation(summary = "친구 요청 거절", description = "친구 요청 거절 API")
164165
@ApiResponses({
@@ -200,7 +201,7 @@ ResponseEntity<?> rejectFriend(@PathVariable(value = "id") Long friendRequestId,
200201
@ApiResponse(responseCode = "204", description = "친구 삭제 성공",
201202
content = @Content(mediaType = "application/json", examples = {
202203
@ExampleObject(value = """
203-
204+
204205
""")
205206
})),
206207
@ApiResponse(responseCode = "400", description = "친구가 아닌 사용자",
@@ -216,4 +217,38 @@ ResponseEntity<?> rejectFriend(@PathVariable(value = "id") Long friendRequestId,
216217
})
217218
ResponseEntity<?> deleteFriend(@PathVariable(value = "uuid") String uuid,
218219
@AuthenticationPrincipal SecurityUserDetails userDetails);
220+
221+
@Operation(summary = "친구 따라가기", description = "친구 따라가기 클릭 시, 해당 친구가 속한 ROOM_ID 반환 기능 API")
222+
@ApiResponses({
223+
@ApiResponse(responseCode = "200", description = "친구가 속한 방 id 정상 반환",
224+
content = @Content(mediaType = "application/json", examples = {
225+
@ExampleObject(value = """
226+
{
227+
"roomId": "1111"
228+
}
229+
""")
230+
})),
231+
@ApiResponse(responseCode = "403", description = "친구 관계가 아니라 따라가기 기능 불가.",
232+
content = @Content(mediaType = "application/json", examples = {
233+
@ExampleObject(value = """
234+
{
235+
"code": "FRIEND-403-002",
236+
"status": "FORBIDDEN",
237+
"message": "친구 관계가 아닙니다. 친구 추가 후 다시 시도해주세요."
238+
}
239+
""")
240+
})),
241+
@ApiResponse(responseCode = "404", description = "친구가 방에 속해있지 않음.",
242+
content = @Content(mediaType = "application/json", examples = {
243+
@ExampleObject(value = """
244+
{
245+
"code": "FRIEND-404-002",
246+
"status": "NOT_FOUND",
247+
"message": "친구가 방에 속해있지 않습니다."
248+
}
249+
""")
250+
}))
251+
})
252+
ResponseEntity<?> followingFriend(@PathVariable(value = "uuid") String friendUuid,
253+
@AuthenticationPrincipal SecurityUserDetails securityUserDetails);
219254
}

gotcha/src/main/java/Gotcha/domain/friend/controller/FriendController.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
@RestController
2323
@RequiredArgsConstructor
2424
@RequestMapping("/api/v1/friends")
25-
public class FriendController implements FriendApi{
25+
public class FriendController implements FriendApi {
2626
private final FriendService friendService;
2727

2828
@GetMapping()
@@ -32,7 +32,7 @@ public ResponseEntity<?> getFriends(@AuthenticationPrincipal SecurityUserDetails
3232

3333
@GetMapping("/search")
3434
public ResponseEntity<?> searchUser(@AuthenticationPrincipal SecurityUserDetails userDetails,
35-
@RequestParam(value = "keyword") String keyword) {
35+
@RequestParam(value = "keyword") String keyword) {
3636
return ResponseEntity.ok(friendService.searchUser(userDetails.getId(), keyword));
3737
}
3838

@@ -68,4 +68,12 @@ public ResponseEntity<?> deleteFriend(@PathVariable(value = "uuid") String frien
6868
friendService.deleteFriend(userDetails.getId(), friendUuid);
6969
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
7070
}
71+
72+
@PostMapping("/follow/{uuid}")
73+
public ResponseEntity<?> followingFriend(@PathVariable(value = "uuid") String friendUuid,
74+
@AuthenticationPrincipal SecurityUserDetails userDetails) {
75+
return ResponseEntity.ok(friendService.followFriend(userDetails.getUuid(), friendUuid));
76+
}
77+
78+
7179
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package Gotcha.domain.friend.dto;
2+
3+
public record FriendFollowingRes(
4+
String roomId
5+
) {
6+
public static FriendFollowingRes from(String roomId){
7+
return new FriendFollowingRes(roomId);
8+
}
9+
}

gotcha/src/main/java/Gotcha/domain/friend/exception/FriendExceptionCode.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
import org.springframework.http.HttpStatus;
66

77
@AllArgsConstructor
8-
public enum FriendExceptionCode implements ExceptionCode {
8+
public enum FriendExceptionCode implements ExceptionCode {
99
SELF_REQUEST_NOT_ALLOWED(HttpStatus.BAD_REQUEST, "FRIEND-400-001", "자기 자신에게는 친구 요청을 보낼 수 없습니다."),
1010
NOT_FRIEND(HttpStatus.BAD_REQUEST, "FRIEND-400-002", "해당 사용자와는 친구가 아닙니다."),
11+
INVALID_REQUEST_ACCESS(HttpStatus.FORBIDDEN, "FRIEND-403-001", "해당 친구 요청에 접근 권한이 없습니다."),
12+
FRIENDSHIP_REQUIRED(HttpStatus.FORBIDDEN, "FRIEND-403-002", "친구 관계가 아닙니다. 친구 추가 후 다시 시도해주세요."),
13+
FRIEND_REQUEST_NOT_FOUND(HttpStatus.NOT_FOUND, "FRIEND-404-001", "친구 요청을 찾을 수 없습니다."),
14+
FRIEND_NOT_IN_ROOM(HttpStatus.NOT_FOUND, "FRIEND-404-002", "친구가 방에 속해있지 않습니다."),
1115
FRIEND_REQUEST_ALREADY_EXISTS(HttpStatus.CONFLICT, "FRIEND-409-001", "이미 친구 요청을 보낸 상태입니다."),
12-
FRIEND_REQUEST_NOT_FOUND(HttpStatus.NOT_FOUND, "FIREND-404-001", "친구 요청을 찾을 수 없습니다."),
13-
ALREADY_FRIENDS(HttpStatus.CONFLICT, "FRIEND-409-002", "이미 친구인 사용자입니다."),
14-
INVALID_REQUEST_ACCESS(HttpStatus.FORBIDDEN,"FRIEND-403-001", "해당 친구 요청에 접근 권한이 없습니다.");
15-
16+
ALREADY_FRIENDS(HttpStatus.CONFLICT, "FRIEND-409-002", "이미 친구인 사용자입니다.");
1617

1718
private final HttpStatus status;
1819
private final String code;

gotcha/src/main/java/Gotcha/domain/friend/service/FriendService.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package Gotcha.domain.friend.service;
22

3+
import Gotcha.domain.friend.dto.FriendFollowingRes;
34
import Gotcha.domain.friend.dto.FriendReq;
45
import Gotcha.domain.friend.dto.FriendRequestRes;
56
import Gotcha.domain.friend.dto.FriendRes;
@@ -12,6 +13,7 @@
1213
import gotcha_domain.user.User;
1314
import gotcha_user.service.UserService;
1415
import lombok.RequiredArgsConstructor;
16+
import lombok.extern.slf4j.Slf4j;
1517
import org.springframework.stereotype.Service;
1618
import gotcha_common.util.RedisUtil;
1719
import org.springframework.transaction.annotation.Transactional;
@@ -20,7 +22,9 @@
2022
import socket_server.domain.friend.service.FriendSocketService;
2123

2224
import java.util.List;
25+
import socket_server.domain.room.service.RoomUserService;
2326

27+
@Slf4j
2428
@Service
2529
@RequiredArgsConstructor
2630
public class FriendService {
@@ -29,6 +33,7 @@ public class FriendService {
2933
private final UserService userService;
3034
private final FriendSocketService friendSocketService;
3135
private final RedisUtil redisUtil;
36+
private final RoomUserService roomUserService;
3237

3338
private static final String FRIEND_CACHE_PREFIX = "user:";
3439

@@ -169,4 +174,21 @@ public void deleteFriend(Long userId, String friendUuid) {
169174

170175
friendSocketService.sendFriendAlert(user.getUuid(), friendUuid, user.getUuid(), FriendEventType.DELETE);
171176
}
177+
178+
public FriendFollowingRes followFriend(String userUuid, String friendUuid) {
179+
boolean isFriend = redisUtil.isSetMember("user:" + userUuid + ":friends", friendUuid);
180+
181+
if (!isFriend) {
182+
throw new CustomException(FriendExceptionCode.FRIENDSHIP_REQUIRED);
183+
}
184+
185+
String friendRoomId = roomUserService.findRoomIdByUserUuid(friendUuid);
186+
187+
if (friendRoomId == null) {
188+
throw new CustomException(FriendExceptionCode.FRIEND_NOT_IN_ROOM);
189+
}
190+
191+
return FriendFollowingRes.from(friendRoomId);
192+
}
193+
172194
}

0 commit comments

Comments
 (0)