Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] issue187: 특정 스터디에서 나의 role을 확인하는 API 생성 #193

Merged
merged 19 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
43b3b40
test: 특정 스터디에서 나의 role을 확인하는 API 인수 테스트 작성
jaejae-yoo Aug 3, 2022
3c41971
refactor: api 명세 변경
jaejae-yoo Aug 3, 2022
ed84cd4
feat: 스터디에서 사용자의 role을 확인하는 기능
jaejae-yoo Aug 3, 2022
588edcf
fix: 충돌 해결
jaejae-yoo Aug 3, 2022
184bd65
feat: 스터디에서 사용자의 역할을 조회하는 rest docs API 생성
jaejae-yoo Aug 4, 2022
d5fed86
refactor: 스터디에서 나의 역할을 조회하는 서비스 로직 메서드 분리
jaejae-yoo Aug 4, 2022
2bef2b1
fix: 충돌 해결
jaejae-yoo Aug 4, 2022
220a59c
fix: rest docs 문제 해결
jaejae-yoo Aug 4, 2022
4fd28f8
fix: 충돌 해결
jaejae-yoo Aug 4, 2022
dbcc5ad
refactor: MyRole -> MemberRole 클래스명 변경
jaejae-yoo Aug 4, 2022
8a26d57
refactor: 스터디 사용자 역할을 판별하는 로직 스터디 객체로 이동
jaejae-yoo Aug 4, 2022
785d1d7
test: 사용자 역할 조회 사용자 인증 테스트 추가
jaejae-yoo Aug 4, 2022
7b678f4
Merge branch 'develop' into feat/187-check-is-my-study
jaejae-yoo Aug 4, 2022
f9e5a04
refactor: rest docs 변경
jaejae-yoo Aug 4, 2022
12bfe15
refactor: rest docs Mock Mvc -> RestAssuerd로 변경
jaejae-yoo Aug 4, 2022
7102615
test: 사용자가 존재하지 않을 때, 스터디가 존재하지 않을 때 예외 추가
jaejae-yoo Aug 4, 2022
2237674
test: study Id가 string일 경우 400 에러 테스트 추가
jaejae-yoo Aug 4, 2022
99b3c86
fix: 충돌 해결
jaejae-yoo Aug 4, 2022
19ed32e
fix: 충돌 해결
jaejae-yoo Aug 4, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions backend/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ operation::auth/login[snippets='http-request,http-response']
== 회원

=== 스터디에서 나의 Role 확인
//operation::studies/summary[snippets='http-request,http-response']

=== 로그인한 사용자 정보 조회
//operation::studies/summary[snippets='http-request,http-response']
operation::members/me/role[snippets='http-request,request-headers,request-parameters,http-response,response-fields']

[[Study]]
== 스터디
Expand Down
893 changes: 893 additions & 0 deletions backend/src/docs/asciidoc/index.html

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class AuthRequestMatchConfig {
@Bean
public AuthenticationRequestMatcher authenticationRequestMatcher() {
return new AuthenticationRequestMatcherBuilder()
.addUpAuthenticationPath(HttpMethod.POST, "/api/studies", "/api/studies/\\d+/reviews")
.addUpAuthenticationPath(HttpMethod.GET, "/api/my/studies", "/api/members/me/role")
.addUpAuthenticationPath(HttpMethod.POST, "/api/studies", "/api/studies/\\d+/reviews", "/api/studies/\\d+/reviews/\\d+")
.addUpAuthenticationPath(HttpMethod.GET, "/api/my/studies")
.addUpAuthenticationPath(HttpMethod.PUT, "/api/studies/\\d+/reviews/\\d+")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response,
final Object handler) {

if (isPreflight(request)) {
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import com.woowacourse.moamoa.auth.config.AuthenticationPrincipal;
import com.woowacourse.moamoa.study.service.MyStudyService;
import com.woowacourse.moamoa.study.service.response.MyRoleResponse;
import com.woowacourse.moamoa.study.service.response.MyStudiesResponse;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;
Expand All @@ -17,8 +19,15 @@ public class MyStudyController {
private final MyStudyService myStudyService;

@GetMapping("/api/my/studies")
public ResponseEntity<MyStudiesResponse> getMyStudies(@AuthenticationPrincipal Long githubId) {
public ResponseEntity<MyStudiesResponse> getMyStudies(@AuthenticationPrincipal final Long githubId) {
final MyStudiesResponse myStudiesResponse = myStudyService.getStudies(githubId);
return ResponseEntity.ok().body(myStudiesResponse);
}

@GetMapping("/api/members/me/role")
public ResponseEntity<MyRoleResponse> getMyRoleInStudy(
@AuthenticationPrincipal final Long githubId, @RequestParam(name = "study-id") final Long studyId
) {
return ResponseEntity.ok().body(myStudyService.findMyRoleInStudy(githubId, studyId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.woowacourse.moamoa.study.domain;

public enum MemberRole {

MEMBER, NON_MEMBER, OWNER
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Embeddable
@ToString
@NoArgsConstructor(access = PROTECTED)
@Getter
@ToString
public class Participants {

@Column(name = "current_member_count")
Expand Down Expand Up @@ -51,6 +53,10 @@ boolean isAlreadyParticipated(Long memberId) {
return participants.contains(new Participant(memberId)) || ownerId.equals(memberId);
}

public boolean isParticipate(Long memberId) {
return participants.contains(new Participant(memberId));
}
Comment on lines +56 to +58
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

기존에 존재하는 isAlreadyParticipated 메소드를 활용해도 Service 로직에 이상이 없을 것 같아요!
(owner 를 먼저 검사하고 있어서)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

물론 로직 자체로는 문제가 없지만, 해당 사용자가 참여자인지 확인하는 메서드로 분리하는 게 더 명확하다고 생각해서 나누는 게 좋을 것 같아요! 기존의 isAlreadyParticipated의 메서드명 때문에 헷갈릴 것 같아서요!


int getSize() {
return size;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@

import com.woowacourse.moamoa.study.domain.exception.InvalidPeriodException;
import com.woowacourse.moamoa.study.service.exception.FailureParticipationException;
import com.woowacourse.moamoa.study.service.response.MyRoleResponse;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
Expand Down Expand Up @@ -115,4 +117,14 @@ public boolean isCloseStudy() {
private boolean isFullOfCapacity() {
return recruitPlanner.hasCapacity() && recruitPlanner.getCapacity() == participants.getSize();
}

public MemberRole getRole(final Long memberId) {
if (Objects.equals(participants.getOwnerId(), memberId)) {
return MemberRole.OWNER;
}
if (participants.isParticipate(memberId)) {
return MemberRole.MEMBER;
}
return MemberRole.NON_MEMBER;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

import com.woowacourse.moamoa.member.domain.Member;
import com.woowacourse.moamoa.member.domain.repository.MemberRepository;
import com.woowacourse.moamoa.member.service.exception.MemberNotFoundException;
import com.woowacourse.moamoa.study.domain.Study;
import com.woowacourse.moamoa.study.domain.repository.StudyRepository;
import com.woowacourse.moamoa.study.query.MyStudyDao;
import com.woowacourse.moamoa.study.service.exception.StudyNotFoundException;
import com.woowacourse.moamoa.study.service.response.MyRoleResponse;
import com.woowacourse.moamoa.member.service.exception.MemberNotFoundException;
import com.woowacourse.moamoa.study.query.data.StudyOwnerAndTagsData;
import com.woowacourse.moamoa.study.service.response.MyStudyResponse;
import com.woowacourse.moamoa.study.query.data.MyStudySummaryData;
Expand All @@ -27,6 +31,8 @@ public class MyStudyService {

private final MemberRepository memberRepository;

private final StudyRepository studyRepository;

public MyStudiesResponse getStudies(final Long githubId) {
final Member member = memberRepository.findByGithubId(githubId)
.orElseThrow(MemberNotFoundException::new);
Expand All @@ -51,4 +57,13 @@ private List<MyStudyResponse> mapToResponse(final List<MyStudySummaryData> myStu
))
.collect(Collectors.toList());
}

public MyRoleResponse findMyRoleInStudy(final Long githubId, final Long studyId) {
final Member member = memberRepository.findByGithubId(githubId)
.orElseThrow(MemberNotFoundException::new);
final Study study = studyRepository.findById(studyId)
.orElseThrow(StudyNotFoundException::new);

return new MyRoleResponse(study.getRole(member.getId()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.woowacourse.moamoa.study.service.response;

import com.woowacourse.moamoa.study.domain.MemberRole;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Getter
public class MyRoleResponse {

private MemberRole role;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.is;
import static org.springframework.http.HttpHeaders.AUTHORIZATION;
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document;

import com.woowacourse.acceptance.AcceptanceTest;
Expand Down Expand Up @@ -105,4 +108,21 @@ void getMyStudies() {
.body("studies[0].tags.id", contains(2, 4, 5))
.body("studies[0].tags.name", contains("4기", "FE", "React"));
}

@Test
@DisplayName("특정 스터디에서 나의 Role을 확인한다.")
void isMyStudy() {
final String token = getBearerTokenBySignInOrUp(new GithubProfileResponse(4L, "verus", "https://image", "github.com"));

RestAssured.given(spec).log().all()
.filter(document("members/me/role"))
.header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
.header(AUTHORIZATION, token)
.queryParam("study-id", 7)
.when()
.get("/api/members/me/role")
.then().log().all()
.statusCode(HttpStatus.OK.value())
.body("role", is("OWNER"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.woowacourse.moamoa.common.RepositoryTest;
import com.woowacourse.moamoa.member.domain.repository.MemberRepository;
import com.woowacourse.moamoa.member.query.data.MemberData;
import com.woowacourse.moamoa.study.domain.repository.StudyRepository;
import com.woowacourse.moamoa.study.query.MyStudyDao;
import com.woowacourse.moamoa.study.service.response.MyStudyResponse;
import com.woowacourse.moamoa.study.service.MyStudyService;
Expand Down Expand Up @@ -34,14 +35,17 @@ class MyStudyControllerTest {
@Autowired
private MemberRepository memberRepository;

@Autowired
private StudyRepository studyRepository;

@Autowired
private JdbcTemplate jdbcTemplate;

private MyStudyController myStudyController;

@BeforeEach
void setUp() {
myStudyController = new MyStudyController(new MyStudyService(myStudyDao, memberRepository));
myStudyController = new MyStudyController(new MyStudyService(myStudyDao, memberRepository, studyRepository));

jdbcTemplate.update("INSERT INTO member(id, github_id, username, image_url, profile_url) VALUES (1, 1, 'jjanggu', 'https://image', 'github.com')");
jdbcTemplate.update("INSERT INTO member(id, github_id, username, image_url, profile_url) VALUES (2, 2, 'greenlawn', 'https://image', 'github.com')");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,26 @@
import static com.woowacourse.moamoa.study.domain.StudyStatus.DONE;
import static com.woowacourse.moamoa.study.domain.StudyStatus.IN_PROGRESS;
import static com.woowacourse.moamoa.study.domain.StudyStatus.PREPARE;
import static java.time.LocalDateTime.now;

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

import static java.time.LocalDateTime.now;

import com.woowacourse.moamoa.study.domain.exception.InvalidPeriodException;
import com.woowacourse.moamoa.study.service.exception.FailureParticipationException;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Set;
import java.util.stream.Stream;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;

public class StudyTest {
Expand Down Expand Up @@ -257,6 +262,21 @@ void writeReviewByNotParticipant() {
assertThat(sut.isWritableReviews(2L)).isFalse();
}

@DisplayName("스터디에서 나의 역할을 조회한다.")
@ParameterizedTest
@CsvSource(value = {"2,MEMBER", "3,NON_MEMBER", "1,OWNER"})
void getMyRoleInStudy(Long memberId, MemberRole role) {
final Content content = new Content("title", "excerpt", "thumbnail", "description");
final Participants participants = Participants.createBy(1L);
final RecruitPlanner recruitPlanner = new RecruitPlanner(10, RecruitStatus.RECRUITMENT_START, LocalDate.now());
final StudyPlanner studyPlanner = new StudyPlanner(LocalDate.now(), LocalDate.now(), IN_PROGRESS);
final Study sut = new Study(content, participants, recruitPlanner, studyPlanner, AttachedTags.empty(), now());

sut.participate(2L);

assertThat(sut.getRole(memberId)).isEqualTo(role);
}

@DisplayName("스터디 종료기간이 넘으면 자동으로 종료 상태가 된다.")
@Test
public void autoCloseStudyStatus() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import java.util.List;
import java.time.LocalDateTime;

import com.woowacourse.moamoa.study.service.exception.StudyNotFoundException;
import com.woowacourse.moamoa.common.RepositoryTest;
import com.woowacourse.moamoa.member.domain.repository.MemberRepository;
import com.woowacourse.moamoa.member.query.data.MemberData;
import com.woowacourse.moamoa.study.domain.repository.StudyRepository;
import com.woowacourse.moamoa.member.service.exception.MemberNotFoundException;
import com.woowacourse.moamoa.study.query.MyStudyDao;
import com.woowacourse.moamoa.study.service.response.MyStudiesResponse;
Expand All @@ -21,6 +23,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

Expand All @@ -36,11 +39,14 @@ class MyStudyServiceTest {
@Autowired
private MemberRepository memberRepository;

@Autowired
private StudyRepository studyRepository;

private MyStudyService myStudyService;

@BeforeEach
void setUp() {
myStudyService = new MyStudyService(myStudyDao, memberRepository);
myStudyService = new MyStudyService(myStudyDao, memberRepository, studyRepository);

jdbcTemplate.update("INSERT INTO member(id, github_id, username, image_url, profile_url) VALUES (1, 1, 'jjanggu', 'https://image', 'github.com')");
jdbcTemplate.update("INSERT INTO member(id, github_id, username, image_url, profile_url) VALUES (2, 2, 'greenlawn', 'https://image', 'github.com')");
Expand Down Expand Up @@ -151,4 +157,20 @@ void getMyStudyNotExistUser() {
.isInstanceOf(MemberNotFoundException.class)
.hasMessageContaining("회원을 찾을 수 없습니다.");
}

@DisplayName("사용자 역할 조회하는 기능에서 존재하지 않는 사용자 조회 시 예외 발생")
@Test
void getMemberRoleNotExistUser() {
assertThatThrownBy(() -> myStudyService.findMyRoleInStudy(5L, 1L))
.isInstanceOf(MemberNotFoundException.class)
.hasMessageContaining("회원을 찾을 수 없습니다.");
}

@DisplayName("사용자 역할 조회하는 기능에서 존재하지 않는 스터디 조회 시 예외 발생")
@Test
void getMemberRoleNotExistStudy() {
assertThatThrownBy(() -> myStudyService.findMyRoleInStudy(1L, 10L))
.isInstanceOf(StudyNotFoundException.class)
.hasMessageContaining("스터디가 존재하지 않습니다.");
}
}
Loading