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] feat: 리뷰어 그룹 도메인 구체화, 정책 구현 #45

Merged
merged 17 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
d84a1c6
feat: Member 엔티티에 GitHub ID 속성 추가
skylar1220 Jul 18, 2024
1791df9
feat: 작성한 리뷰어가 리뷰어 그룹에 속하는지 검증
skylar1220 Jul 18, 2024
ad15c64
feat: 리뷰 작성 시, 이미 작성한 리뷰가 있지 않은지 검증
skylar1220 Jul 18, 2024
7c4f7db
refactor: Review 엔티티의 reviewer와의 연관관계 ManyToOne으로 변경
skylar1220 Jul 18, 2024
ca454df
refactor: 컬럼명 오류 수정
skylar1220 Jul 18, 2024
7201ff0
refactor: gitHub 표기 -> github으로 변경
skylar1220 Jul 19, 2024
e016c8e
refactor: GithubReviewGroup -> GithubReviewGroup 클래스명 변경
skylar1220 Jul 19, 2024
c4c481e
refactor: 누락된 @Column 추가
skylar1220 Jul 19, 2024
e8b13f8
test: 리뷰 작성 테스트 시, 깃헙 사용자 그룹 데이터 저장 부분 추가
skylar1220 Jul 19, 2024
0fa761d
refactor: 리뷰 작성 시, 중복 리뷰 검증 로직 수정
skylar1220 Jul 19, 2024
62f5287
refactor: GithubReviewerGroupNotFoundException을 UnAuthorizedException…
skylar1220 Jul 19, 2024
1e71db6
refactor: ReviewContentExistException -> ReviewAlreadySubmittedExcept…
skylar1220 Jul 19, 2024
26ec62c
feat: UnAuthorizedException 추가
skylar1220 Jul 19, 2024
6a91069
refactor: 메서드 순서 변경
skylar1220 Jul 19, 2024
9e7001d
test: 불필요한 given절 삭제
skylar1220 Jul 19, 2024
d221ebe
test: 테스트를 위한 데이터 삽입 repository를 활용하도록 변경
skylar1220 Jul 19, 2024
fa6df80
Merge branch 'develop' into be/feature/37-review-group-policy
donghoony Jul 19, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package reviewme.global.exception;

public abstract class UnAuthorizedException extends ReviewMeException {

protected UnAuthorizedException(String errorMessage) {
super(errorMessage);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package reviewme.member.domain;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "github_reviewer_group")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class GithubReviewerGroup {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "github_id", nullable = false)
private String githubId;

@ManyToOne
@JoinColumn(name = "reviewer_group_id")
private ReviewerGroup reviewerGroup;

public GithubReviewerGroup(String githubId, ReviewerGroup reviewerGroup) {
this.githubId = githubId;
this.reviewerGroup = reviewerGroup;
}
}
6 changes: 5 additions & 1 deletion backend/src/main/java/reviewme/member/domain/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ public class Member {
@Column(name = "name", nullable = false)
private String name;

Comment on lines 23 to 25
Copy link
Contributor

Choose a reason for hiding this comment

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

이것은 TODO 일수도 있지만 이 부분도 나중에 깃허브 연동하면
github_nickname 요런식으로 바뀌어야 하겠군요!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

사용자의 프로필을 아예 깃헙과 연동으로 처리한다면 그렇겠네요!

  1. id, 프로필 사진은 깃헙, 이름은 설정할 수 있게
  2. id, 프로필 사진 + 이름까지도 깃헙 닉네임과 연동

어떤 방법이 나을지 함께 얘기해보면 좋을 것 같아요!

Copy link
Contributor

@Kimprodp Kimprodp Jul 19, 2024

Choose a reason for hiding this comment

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

산초의 코멘트에 대한 의견 : 깃허브 아이디랑 닉네임이 똑같지 않나요? 그럼 둘 중 하나만 있어도 될 것 같은데, 실명 정보가 따로 필요할까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

제 기준 skylar1220이라는 것은 깃헙 기준 username이고 숫자로 된 unique한 id가 따로 있군요!(by 아루)
그렇다면 githubId, githubUserName을 갖게 하는 게 맞겠네요!

Copy link
Contributor

Choose a reason for hiding this comment

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

맞습니다! 저도 github_nickname 은 nayonsoso 인데, 고유한 id 는 1330909287 요런식이었어요

public Member(String name) {
@Column(name = "github_id", nullable = false)
private String githubId;

public Member(String name, String githubId) {
this.name = name;
this.githubId = githubId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package reviewme.member.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import reviewme.member.domain.GithubReviewerGroup;
import reviewme.member.domain.ReviewerGroup;

@Repository
public interface GithubReviewerGroupRepository extends JpaRepository<GithubReviewerGroup, Long> {

boolean existsByGithubIdAndReviewerGroup(String githubId, ReviewerGroup reviewerGroup);
}
3 changes: 1 addition & 2 deletions backend/src/main/java/reviewme/review/domain/Review.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Getter;
Expand All @@ -24,7 +23,7 @@ public class Review {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@OneToOne
@ManyToOne
Copy link
Contributor

Choose a reason for hiding this comment

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

👍👍👍👍👍

@JoinColumn(name = "reviewer_id", nullable = false)
private Member reviewer;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package reviewme.review.exception;

import reviewme.global.exception.UnAuthorizedException;

public class GithubReviewerGroupUnAuthorizedException extends UnAuthorizedException {

public GithubReviewerGroupUnAuthorizedException() {
super("리뷰어 그룹에 등록되지 않은 github 사용자입니다.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package reviewme.review.exception;

import reviewme.global.exception.BadRequestException;

public class ReviewAlreadySubmittedException extends BadRequestException {

public ReviewAlreadySubmittedException() {
super("이미 리뷰를 작성한 경우 리뷰를 작성할 수 없습니다.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
import jakarta.persistence.EntityNotFoundException;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import reviewme.member.domain.Member;
import reviewme.member.domain.ReviewerGroup;
import reviewme.review.domain.Review;

@Repository
public interface ReviewRepository extends JpaRepository<Review, Long> {

boolean existsByReviewerAndReviewerGroup(Member reviewer, ReviewerGroup reviewerGroup);

default Review getReviewById(Long id) {
return findById(id).orElseThrow(EntityNotFoundException::new);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import reviewme.member.domain.ReviewerGroup;
import reviewme.member.dto.response.MemberResponse;
import reviewme.member.dto.response.ReviewerGroupResponse;
import reviewme.member.repository.GithubReviewerGroupRepository;
import reviewme.member.repository.MemberRepository;
import reviewme.member.repository.ReviewerGroupRepository;
import reviewme.review.domain.Review;
Expand All @@ -21,6 +22,8 @@
import reviewme.review.dto.request.CreateReviewRequest;
import reviewme.review.dto.response.ReviewContentResponse;
import reviewme.review.dto.response.ReviewResponse;
import reviewme.review.exception.GithubReviewerGroupUnAuthorizedException;
import reviewme.review.exception.ReviewAlreadySubmittedException;
import reviewme.review.repository.ReviewContentRepository;
import reviewme.review.repository.ReviewKeywordRepository;
import reviewme.review.repository.ReviewRepository;
Expand All @@ -32,6 +35,7 @@ public class ReviewService {
private final ReviewRepository reviewRepository;
private final MemberRepository memberRepository;
private final ReviewerGroupRepository reviewerGroupRepository;
private final GithubReviewerGroupRepository githubReviewerGroupRepository;
private final ReviewContentRepository reviewContentRepository;
private final KeywordRepository keywordRepository;
private final ReviewKeywordRepository reviewKeywordRepository;
Expand All @@ -40,7 +44,19 @@ public class ReviewService {
public Long createReview(CreateReviewRequest request) {
Member reviewer = memberRepository.getMemberById(request.reviewerId());
ReviewerGroup reviewerGroup = reviewerGroupRepository.getReviewerGroupById(request.reviewerGroupId());

boolean isValidReviewer = githubReviewerGroupRepository.existsByGithubIdAndReviewerGroup(
reviewer.getGithubId(),
reviewerGroup
);
if (!isValidReviewer) {
throw new GithubReviewerGroupUnAuthorizedException();
}
if (reviewRepository.existsByReviewerAndReviewerGroup(reviewer, reviewerGroup)) {
throw new ReviewAlreadySubmittedException();
}
validateIsDeadlinePassed(reviewerGroup);

Review review = reviewRepository.save(new Review(reviewer, reviewerGroup));

List<ReviewContent> contents = request.contents()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class ReviewerGroupTest {
@Test
void 리뷰_그룹이_올바르게_생성된다() {
// given
Member sancho = new Member("산초");
Member sancho = new Member("산초", "sancho");
String groupName = "a".repeat(100);
String description = "a".repeat(50);
LocalDateTime createdAt = LocalDateTime.of(2024, 7, 17, 12, 0);
Expand All @@ -29,7 +29,7 @@ class ReviewerGroupTest {
void 리뷰_그룹_이름_길이_제한을_벗어나는_경우_예외를_발생한다(int length) {
// given
String groupName = "a".repeat(length);
Member sancho = new Member("산초");
Member sancho = new Member("산초", "sancho");
LocalDateTime createdAt = LocalDateTime.of(2024, 7, 17, 12, 0);
// when, then
assertThatThrownBy(() -> new ReviewerGroup(sancho, groupName, "설명", createdAt))
Expand All @@ -40,7 +40,7 @@ class ReviewerGroupTest {
void 리뷰_그룹_설명_길이_제한을_벗어나는_경우_예외를_발생한다() {
// given
String description = "a".repeat(51);
Member sancho = new Member("산초");
Member sancho = new Member("산초", "sancho");
LocalDateTime createdAt = LocalDateTime.of(2024, 7, 17, 12, 0);
// when, then
assertThatThrownBy(() -> new ReviewerGroup(sancho, "그룹 이름", description, createdAt))
Expand Down
77 changes: 70 additions & 7 deletions backend/src/test/java/reviewme/review/ReviewServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,20 @@
import org.springframework.beans.factory.annotation.Autowired;
import reviewme.keyword.domain.Keyword;
import reviewme.keyword.repository.KeywordRepository;
import reviewme.member.domain.GithubReviewerGroup;
import reviewme.member.domain.Member;
import reviewme.member.domain.ReviewerGroup;
import reviewme.member.repository.GithubReviewerGroupRepository;
import reviewme.member.repository.MemberRepository;
import reviewme.member.repository.ReviewerGroupRepository;
import reviewme.review.domain.Review;
import reviewme.review.domain.exception.DeadlineExpiredException;
import reviewme.review.dto.request.CreateReviewContentRequest;
import reviewme.review.dto.request.CreateReviewRequest;
import reviewme.review.dto.response.ReviewResponse;
import reviewme.review.exception.GithubReviewerGroupUnAuthorizedException;
import reviewme.review.exception.ReviewAlreadySubmittedException;
import reviewme.review.repository.ReviewContentRepository;
import reviewme.review.repository.ReviewRepository;
import reviewme.review.service.ReviewService;
import reviewme.support.ServiceTest;
Expand All @@ -37,17 +42,24 @@ class ReviewServiceTest {
@Autowired
ReviewerGroupRepository reviewerGroupRepository;

@Autowired
GithubReviewerGroupRepository githubReviewerGroupRepository;

@Autowired
KeywordRepository keywordRepository;

@Autowired
ReviewContentRepository reviewContentRepository;

@Test
void 리뷰를_작성한다() {
Copy link
Contributor

Choose a reason for hiding this comment

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

이 테스트 깨지는 것 같은데 확인해주세요!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

리뷰 작성 테스트 시, 깃헙 사용자 그룹 데이터 저장 부분을 추가하지 않았군요! 테스트 터지는 거 확인 꼭 하겠습니당..😂

// given
memberRepository.save(new Member("산초"));
Member reviewee = memberRepository.save(new Member("아루"));
reviewerGroupRepository.save(
new ReviewerGroup(reviewee, "그룹A", "그룹 설명", LocalDateTime.of(2099, 1, 1, 1, 1))
memberRepository.save(new Member("산초", "sancho"));
Member reviewee = memberRepository.save(new Member("아루", "aru"));
ReviewerGroup reviewerGroup = reviewerGroupRepository.save(
new ReviewerGroup(reviewee, "그룹A", "그룹 설명", LocalDateTime.of(2024, 1, 1, 1, 1))
);
githubReviewerGroupRepository.save(new GithubReviewerGroup("sancho", reviewerGroup));
Keyword keyword1 = keywordRepository.save(new Keyword("꼼꼼해요"));
Keyword keyword2 = keywordRepository.save(new Keyword("친절해요"));

Expand Down Expand Up @@ -75,9 +87,9 @@ class ReviewServiceTest {
@Test
void 리뷰를_조회한다() {
// given
Member reviewer = memberRepository.save(new Member("테드"));
Member reviewee = memberRepository.save(new Member("아루"));
memberRepository.save(new Member("산초"));
Member reviewer = memberRepository.save(new Member("테드", "ted"));
Member reviewee = memberRepository.save(new Member("아루", "aru"));
memberRepository.save(new Member("산초", "sancho"));
ReviewerGroup reviewerGroup = reviewerGroupRepository.save(new ReviewerGroup(
reviewee,
"그룹A",
Expand All @@ -95,6 +107,57 @@ class ReviewServiceTest {
}

@Test
void 리뷰어_그룹에_속하지_않는_리뷰어가_리뷰를_작성할_경우_예외를_발생한다() {
// given
Member reviewee = memberRepository.save(new Member("아루", "aru"));
Member reviewer = memberRepository.save(new Member("테드", "ted"));
ReviewerGroup reviewerGroup = reviewerGroupRepository.save(new ReviewerGroup(
reviewee,
"그룹A",
"그룹 설명",
LocalDateTime.of(2024, 1, 1, 1, 1))
);
githubReviewerGroupRepository.save(new GithubReviewerGroup("kirby", reviewerGroup));

CreateReviewRequest createReviewRequest = new CreateReviewRequest(
reviewer.getId(),
reviewerGroup.getId(),
List.of(),
List.of()
);

// when, then
assertThatThrownBy(() -> reviewService.createReview(createReviewRequest))
.isInstanceOf(GithubReviewerGroupUnAuthorizedException.class);
}

@Test
void 이미_작성한_리뷰가_있는데_리뷰를_작성할_경우_예외를_발생한다() {
// given
Member reviewee = memberRepository.save(new Member("아루", "aru"));
Member reviewer = memberRepository.save(new Member("테드", "ted"));
ReviewerGroup reviewerGroup = reviewerGroupRepository.save(new ReviewerGroup(
reviewee,
"그룹A",
"그룹 설명",
LocalDateTime.of(2024, 1, 1, 1, 1))
);
githubReviewerGroupRepository.save(new GithubReviewerGroup("ted", reviewerGroup));

CreateReviewRequest createReviewRequest = new CreateReviewRequest(
reviewer.getId(),
reviewerGroup.getId(),
List.of(),
List.of()
);

reviewRepository.save(new Review(reviewer, reviewerGroup));

// when, then
assertThatThrownBy(() -> reviewService.createReview(createReviewRequest))
.isInstanceOf(ReviewAlreadySubmittedException.class);
}

void 데드라인이_지난_리뷰그룹에_대해_리뷰를_작성하려하면_예외가_발생한다() {
// given
memberRepository.save(new Member("산초"));
Expand Down