Skip to content

Commit

Permalink
feat: 리뷰 등록시 모임 참여 유저 조회 API 수정 (#229)
Browse files Browse the repository at this point in the history
* refactor: MeetingController getCurrentUserId() 메소드로 통일 (#228)

* feat: 리뷰에 자신 포함 확인 로직 추가 (#195)

* feat: 모임 참여자 자신 포함 여부 확인 로직 추가(#228)

* test: 단위 테스트 추가 (#228)

* test: 통합 테스트 수정 및 실패 케이스 추가 (#228)
  • Loading branch information
choidongkuen authored Feb 16, 2024
1 parent f5874bc commit 641ee6e
Show file tree
Hide file tree
Showing 9 changed files with 327 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import net.teumteum.meeting.domain.Topic;
import net.teumteum.meeting.domain.request.CreateMeetingRequest;
import net.teumteum.meeting.domain.request.UpdateMeetingRequest;
import net.teumteum.meeting.domain.response.MeetingParticipantsResponse;
import net.teumteum.meeting.domain.response.MeetingParticipantResponse;
import net.teumteum.meeting.domain.response.MeetingResponse;
import net.teumteum.meeting.domain.response.MeetingsResponse;
import net.teumteum.meeting.model.PageDto;
Expand Down Expand Up @@ -43,14 +43,14 @@ public class MeetingController {
public MeetingResponse createMeeting(
@RequestPart @Valid CreateMeetingRequest meetingRequest,
@RequestPart List<MultipartFile> images) {
Long userId = securityService.getCurrentUserId();
Long userId = getCurrentUserId();
return meetingService.createMeeting(images, meetingRequest, userId);
}

@GetMapping("/{meetingId}")
@ResponseStatus(HttpStatus.OK)
public MeetingResponse getMeetingById(@PathVariable("meetingId") Long meetingId) {
Long userId = securityService.getCurrentUserId();
Long userId = getCurrentUserId();
return meetingService.getMeetingById(meetingId, userId);
}

Expand All @@ -64,7 +64,7 @@ public PageDto<MeetingsResponse> getMeetingsByCondition(
@RequestParam(value = "participantUserId", required = false) Long participantUserId,
@RequestParam(value = "isBookmarked", required = false) Boolean isBookmarked,
@RequestParam(value = "searchWord", required = false) String searchWord) {
Long userId = securityService.getCurrentUserId();
Long userId = getCurrentUserId();
return meetingService.getMeetingsBySpecification(pageable, topic, meetingAreaStreet, participantUserId,
searchWord, isBookmarked, isOpen, userId);
}
Expand All @@ -74,55 +74,56 @@ public PageDto<MeetingsResponse> getMeetingsByCondition(
public MeetingResponse updateMeeting(@PathVariable Long meetingId,
@RequestPart @Valid UpdateMeetingRequest request,
@RequestPart List<MultipartFile> images) {
Long userId = securityService.getCurrentUserId();
Long userId = getCurrentUserId();
return meetingService.updateMeeting(meetingId, images, request, userId);
}

@DeleteMapping("/{meetingId}")
@ResponseStatus(HttpStatus.OK)
public void deleteMeeting(@PathVariable("meetingId") Long meetingId) {
Long userId = securityService.getCurrentUserId();
Long userId = getCurrentUserId();
meetingService.deleteMeeting(meetingId, userId);
}

@PostMapping("/{meetingId}/participants")
@ResponseStatus(HttpStatus.CREATED)
public MeetingResponse addParticipant(@PathVariable("meetingId") Long meetingId) {
Long userId = securityService.getCurrentUserId();
Long userId = getCurrentUserId();
return meetingService.addParticipant(meetingId, userId);
}

@DeleteMapping("/{meetingId}/participants")
@ResponseStatus(HttpStatus.OK)
public void deleteParticipant(@PathVariable("meetingId") Long meetingId) {
Long userId = securityService.getCurrentUserId();
Long userId = getCurrentUserId();
meetingService.cancelParticipant(meetingId, userId);
}

@GetMapping("/{meetingId}/participants")
@ResponseStatus(HttpStatus.OK)
public List<MeetingParticipantsResponse> getParticipants(@PathVariable("meetingId") Long meetingId) {
return meetingService.getParticipants(meetingId);
public List<MeetingParticipantResponse> getParticipants(@PathVariable("meetingId") Long meetingId) {
Long userId = getCurrentUserId();
return meetingService.getParticipants(meetingId, userId);
}

@PostMapping("/{meetingId}/reports")
@ResponseStatus(HttpStatus.CREATED)
public void reportMeeting(@PathVariable("meetingId") Long meetingId) {
Long userId = securityService.getCurrentUserId();
Long userId = getCurrentUserId();
meetingService.reportMeeting(meetingId, userId);
}

@PostMapping("/{meetingId}/bookmarks")
@ResponseStatus(HttpStatus.CREATED)
public void addBookmark(@PathVariable("meetingId") Long meetingId) {
Long userId = securityService.getCurrentUserId();
Long userId = getCurrentUserId();
meetingService.addBookmark(meetingId, userId);
}

@DeleteMapping("/{meetingId}/bookmarks")
@ResponseStatus(HttpStatus.OK)
public void deleteBookmark(@PathVariable("meetingId") Long meetingId) {
Long userId = securityService.getCurrentUserId();
Long userId = getCurrentUserId();
meetingService.cancelBookmark(meetingId, userId);
}

Expand All @@ -132,4 +133,8 @@ public ErrorResponse handleIllegalArgumentException(IllegalArgumentException ill
Sentry.captureException(illegalArgumentException);
return ErrorResponse.of(illegalArgumentException);
}

private Long getCurrentUserId() {
return securityService.getCurrentUserId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

import net.teumteum.user.domain.User;

public record MeetingParticipantsResponse(
public record MeetingParticipantResponse(
Long id,
Long characterId,
String name,
String job
) {

public static MeetingParticipantsResponse of(
public static MeetingParticipantResponse of(
User user
) {
return new MeetingParticipantsResponse(
return new MeetingParticipantResponse(
user.getId(),
user.getCharacterId(),
user.getName(),
Expand Down
18 changes: 14 additions & 4 deletions src/main/java/net/teumteum/meeting/service/MeetingService.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import net.teumteum.meeting.domain.Topic;
import net.teumteum.meeting.domain.request.CreateMeetingRequest;
import net.teumteum.meeting.domain.request.UpdateMeetingRequest;
import net.teumteum.meeting.domain.response.MeetingParticipantsResponse;
import net.teumteum.meeting.domain.response.MeetingParticipantResponse;
import net.teumteum.meeting.domain.response.MeetingResponse;
import net.teumteum.meeting.domain.response.MeetingsResponse;
import net.teumteum.meeting.model.PageDto;
Expand Down Expand Up @@ -94,7 +94,8 @@ public void deleteMeeting(Long meetingId, Long userId) {
}

@Transactional(readOnly = true)
public PageDto<MeetingsResponse> getMeetingsBySpecification(Pageable pageable, Topic topic, String meetingAreaStreet,
public PageDto<MeetingsResponse> getMeetingsBySpecification(Pageable pageable, Topic topic,
String meetingAreaStreet,
Long participantUserId, String searchWord, Boolean isBookmarked, Boolean isOpen, Long userId) {

Specification<Meeting> spec = MeetingSpecification.withIsOpen(isOpen);
Expand Down Expand Up @@ -153,13 +154,16 @@ public void cancelParticipant(Long meetingId, Long userId) {
}

@Transactional(readOnly = true)
public List<MeetingParticipantsResponse> getParticipants(Long meetingId) {
public List<MeetingParticipantResponse> getParticipants(Long meetingId, Long userId) {
var existMeeting = getMeeting(meetingId);

checkMeetingContainUser(existMeeting, userId);

return existMeeting.getParticipantUserIds().stream()
.filter(id -> !id.equals(userId))
.map(userConnector::findUserById)
.flatMap(Optional::stream)
.map(MeetingParticipantsResponse::of)
.map(MeetingParticipantResponse::of)
.toList();
}

Expand Down Expand Up @@ -207,4 +211,10 @@ public void reportMeeting(Long meetingId, Long userId) {
throw new IllegalArgumentException("모임 개설자는 모임을 신고할 수 없습니다.");
}
}

private void checkMeetingContainUser(Meeting meeting, Long userId) {
if (!meeting.getParticipantUserIds().contains(userId)) {
throw new IllegalArgumentException("모임에 참여하지 않은 회원입니다.");
}
}
}
118 changes: 73 additions & 45 deletions src/test/java/net/teumteum/integration/MeetingIntegrationTest.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package net.teumteum.integration;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;
import net.teumteum.core.error.ErrorResponse;
import net.teumteum.meeting.domain.Meeting;
import net.teumteum.meeting.domain.Topic;
import net.teumteum.meeting.domain.response.MeetingResponse;
import net.teumteum.meeting.domain.response.MeetingsResponse;
import net.teumteum.meeting.model.PageDto;
import org.assertj.core.api.Assertions;
import org.assertj.core.api.Condition;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
Expand Down Expand Up @@ -42,10 +44,10 @@ void Return_meeting_info_if_exist_meeting_id_received() {
// when
var result = api.getMeetingById(VALID_TOKEN, meeting.getId());
// then
Assertions.assertThat(
result.expectStatus().isOk()
.expectBody(MeetingResponse.class)
.returnResult().getResponseBody())
assertThat(
result.expectStatus().isOk()
.expectBody(MeetingResponse.class)
.returnResult().getResponseBody())
.usingRecursiveComparison()
.isEqualTo(expected);
}
Expand Down Expand Up @@ -75,10 +77,10 @@ void Return_is_bookmarked_true_if_user_bookmarked_meeting() {
// when
var result = api.getMeetingById(VALID_TOKEN, meeting.getId());
// then
Assertions.assertThat(
result.expectStatus().isOk()
.expectBody(MeetingResponse.class)
.returnResult().getResponseBody())
assertThat(
result.expectStatus().isOk()
.expectBody(MeetingResponse.class)
.returnResult().getResponseBody())
.extracting(MeetingResponse::isBookmarked)
.isEqualTo(true);
}
Expand Down Expand Up @@ -158,11 +160,11 @@ void Return_meeting_list_if_topic_and_page_nation_received() {
// when
var result = api.getMeetingsByTopic(VALID_TOKEN, FIRST_PAGE_NATION, true, Topic.스터디);
// then
Assertions.assertThat(
result.expectStatus().isOk()
.expectBody(new ParameterizedTypeReference<PageDto<MeetingsResponse>>() {
})
.returnResult().getResponseBody())
assertThat(
result.expectStatus().isOk()
.expectBody(new ParameterizedTypeReference<PageDto<MeetingsResponse>>() {
})
.returnResult().getResponseBody())
.usingRecursiveComparison()
.isEqualTo(expected);
}
Expand Down Expand Up @@ -192,11 +194,11 @@ void Return_meeting_list_if_search_word_and_page_nation_received() {
// when
var result = api.getMeetingsByTopic(VALID_TOKEN, FIRST_PAGE_NATION, true, Topic.스터디);
// then
Assertions.assertThat(
result.expectStatus().isOk()
.expectBody(new ParameterizedTypeReference<PageDto<MeetingsResponse>>() {
})
.returnResult().getResponseBody())
assertThat(
result.expectStatus().isOk()
.expectBody(new ParameterizedTypeReference<PageDto<MeetingsResponse>>() {
})
.returnResult().getResponseBody())
.usingRecursiveComparison()
.isEqualTo(expected);
}
Expand All @@ -222,11 +224,11 @@ void Return_meeting_list_if_participant_user_id_and_page_nation_received() {
// when
var result = api.getMeetingsByTopic(VALID_TOKEN, FIRST_PAGE_NATION, true, Topic.스터디);
// then
Assertions.assertThat(
result.expectStatus().isOk()
.expectBody(new ParameterizedTypeReference<PageDto<MeetingsResponse>>() {
})
.returnResult().getResponseBody())
assertThat(
result.expectStatus().isOk()
.expectBody(new ParameterizedTypeReference<PageDto<MeetingsResponse>>() {
})
.returnResult().getResponseBody())
.usingRecursiveComparison()
.isEqualTo(expected);
}
Expand All @@ -252,11 +254,11 @@ void Return_has_next_true_if_more_data_exists_than_requested_size_and_page() {
// when
var result = api.getMeetingsByTopic(VALID_TOKEN, FIRST_PAGE_NATION, true, Topic.스터디);
// then
Assertions.assertThat(
result.expectStatus().isOk()
.expectBody(new ParameterizedTypeReference<PageDto<MeetingsResponse>>() {
})
.returnResult().getResponseBody())
assertThat(
result.expectStatus().isOk()
.expectBody(new ParameterizedTypeReference<PageDto<MeetingsResponse>>() {
})
.returnResult().getResponseBody())
.usingRecursiveComparison()
.isEqualTo(expected);
}
Expand All @@ -277,11 +279,11 @@ void Join_meeting_if_exist_meeting_id_received() {
// when
var result = api.joinMeeting(VALID_TOKEN, existMeeting.getId());
// then
Assertions.assertThat(
result.expectStatus().isCreated()
.expectBody(MeetingResponse.class)
.returnResult()
.getResponseBody())
assertThat(
result.expectStatus().isCreated()
.expectBody(MeetingResponse.class)
.returnResult()
.getResponseBody())
.extracting(MeetingResponse::participantIds)
.has(new Condition<>(ids -> ids.contains(me.getId()), "참여자 목록에 나를 포함한다.")
);
Expand Down Expand Up @@ -380,11 +382,11 @@ void Return_400_bad_request_if_not_joined_meeting_id_received() {
// when
var result = api.cancelMeeting(VALID_TOKEN, meeting.getId());
// then
Assertions.assertThat(result.expectStatus().isBadRequest()
.expectBody(ErrorResponse.class)
.returnResult()
.getResponseBody()
)
assertThat(result.expectStatus().isBadRequest()
.expectBody(ErrorResponse.class)
.returnResult()
.getResponseBody()
)
.extracting(ErrorResponse::getMessage)
.isEqualTo("참여하지 않은 모임입니다.");
}
Expand All @@ -400,11 +402,11 @@ void Return_400_bad_request_if_closed_meeting_id_received() {
// when
var result = api.cancelMeeting(VALID_TOKEN, meeting.getId());
// then
Assertions.assertThat(result.expectStatus().isBadRequest()
.expectBody(ErrorResponse.class)
.returnResult()
.getResponseBody()
)
assertThat(result.expectStatus().isBadRequest()
.expectBody(ErrorResponse.class)
.returnResult()
.getResponseBody()
)
.extracting(ErrorResponse::getMessage)
.isEqualTo("종료된 모임에서 참여를 취소할 수 없습니다.");
}
Expand Down Expand Up @@ -488,11 +490,37 @@ class Get_meeting_participants_api {
@DisplayName("참여한 meeting id 가 주어지면, 참여한 참가자들의 정보가 주어진다.")
void Get_participants_if_exist_meeting_id_received() {
// given
var meeting = repository.saveAndGetOpenMeeting();
var me = repository.saveAndGetUser();
var meeting = repository.saveAndGetClosedMetingWithParticipantUserIds(List.of(me.getId(), 2L));

securityContextSetting.set(me.getId());

// when
var result = api.getMeetingParticipants(VALID_TOKEN, meeting.getId());

// then
result.expectStatus().isOk();
}

@Test
@DisplayName("API 호출한 회원이 모임에 참여하지 않았다면, 400 bad request 을 응답한다.")
void Return_400_bad_request_if_meeting_not_contain_user() {
// given
var me = repository.saveAndGetUser();
var meeting = repository.saveAndGetClosedMetingWithParticipantUserIds(List.of(100L, 101L));

securityContextSetting.set(me.getId());

// when
var result = api.getMeetingParticipants(VALID_TOKEN, meeting.getId());

// then
assertThat(result.expectStatus().isBadRequest()
.expectBody(ErrorResponse.class)
.returnResult()
.getResponseBody())
.extracting(ErrorResponse::getMessage)
.isEqualTo("모임에 참여하지 않은 회원입니다.");
}
}
}
Loading

0 comments on commit 641ee6e

Please sign in to comment.