Skip to content

Commit

Permalink
코레아 1.24v 배포 (#679)
Browse files Browse the repository at this point in the history
  • Loading branch information
pp449 authored Oct 23, 2024
2 parents 97f996d + af94181 commit 93357d0
Show file tree
Hide file tree
Showing 98 changed files with 1,919 additions and 278 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import corea.auth.service.GithubOAuthProvider;
import corea.auth.service.LoginService;
import corea.auth.service.LogoutService;
import corea.member.dto.MemberRoleResponse;
import corea.member.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -27,14 +29,17 @@ public class LoginController implements LoginControllerSpecification {
private final GithubOAuthProvider githubOAuthProvider;
private final LoginService loginService;
private final LogoutService logoutService;
private final MemberService memberService;

@PostMapping("/login")
public ResponseEntity<LoginResponse> login(@RequestBody LoginRequest loginRequest) {
GithubUserInfo userInfo = githubOAuthProvider.getUserInfo(loginRequest.code());
TokenInfo tokenInfo = loginService.login(userInfo);
MemberRoleResponse memberRoleResponse = memberService.getMemberRoleWithGithubUserId(userInfo.id());

return ResponseEntity.ok()
.header(AUTHORIZATION_HEADER, tokenInfo.accessToken())
.body(new LoginResponse(tokenInfo.refreshToken(), userInfo));
.body(new LoginResponse(tokenInfo.refreshToken(), userInfo, memberRoleResponse.role()));
}

@PostMapping("/refresh")
Expand Down
3 changes: 2 additions & 1 deletion backend/src/main/java/corea/auth/dto/LoginResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
@Schema(description = "로그인/로그인 유지를 위한 정보 전달")
public record LoginResponse(@Schema(description = "리프레시 JWT 토큰", example = "O1234567COREAREFRESH")
String refreshToken,
GithubUserInfo userInfo) {
GithubUserInfo userInfo,
String memberRole) {
}
2 changes: 2 additions & 0 deletions backend/src/main/java/corea/exception/ExceptionType.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public enum ExceptionType {
NOT_PARTICIPATED_ROOM(HttpStatus.BAD_REQUEST, "아직 참여하지 않은 방입니다."),
ROOM_STATUS_INVALID(HttpStatus.BAD_REQUEST, "방이 마감되었습니다."),
MEMBER_IS_NOT_MANAGER(HttpStatus.BAD_REQUEST, "매니저가 아닙니다."),
MEMBER_IS_NOT_REVIEWER(HttpStatus.BAD_REQUEST, "리뷰어로만 참여할 수 없습니다."),
MEMBER_IS_NOT_BOTH(HttpStatus.BAD_REQUEST, "리뷰어로만 참여할 수 있습니다."),
ROOM_PARTICIPANT_EXCEED(HttpStatus.BAD_REQUEST, "방 참여 인원 수가 최대입니다."),
PARTICIPANT_SIZE_LACK(HttpStatus.BAD_REQUEST, "참여 인원이 부족하여 매칭을 진행할 수 없습니다."),
PARTICIPANT_SIZE_LACK_DUE_TO_PULL_REQUEST(HttpStatus.BAD_REQUEST, "pull request 미제출로 인해 인원이 부족하여 매칭을 진행할 수 없습니다."),
Expand Down
10 changes: 9 additions & 1 deletion backend/src/main/java/corea/global/config/RestClientConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestClient;

import java.time.Duration;

@Configuration
public class RestClientConfig {

@Bean
RestClient restClient() {
public RestClient restClient() {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(Duration.ofSeconds(5));
requestFactory.setReadTimeout(Duration.ofSeconds(10));

return RestClient.builder()
.requestFactory(requestFactory)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import corea.member.domain.Member;
import corea.participation.domain.Participation;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import java.util.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package corea.matchresult.domain;

import corea.exception.ExceptionType;
import corea.global.BaseTimeEntity;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
Expand All @@ -11,7 +12,7 @@
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class FailedMatching {
public class FailedMatching extends BaseTimeEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class MatchResultReader {

private final MatchResultRepository matchResultRepository;

public MatchResult findOne(long roomId,long reviewerId,long revieweeId) {
public MatchResult findOne(long roomId, long reviewerId, long revieweeId) {
return matchResultRepository.findByRoomIdAndReviewerIdAndRevieweeId(roomId, reviewerId, revieweeId)
.orElseThrow(() -> new CoreaException(ExceptionType.NOT_MATCHED_MEMBER));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ public class MatchResultWriter {

private final MatchResultRepository matchResultRepository;

public void reviewComplete(MatchResult matchResult, String prLink) {
public void reviewComplete(MatchResult matchResult, String reviewLink) {
matchResult.reviewComplete();
matchResult.updateReviewLink(prLink);
matchResult.updateReviewLink(reviewLink);
}

public MatchResult completeDevelopFeedback(long roomId, long deliverId, long receiverId) {
Expand Down
11 changes: 11 additions & 0 deletions backend/src/main/java/corea/member/domain/AuthRole.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package corea.member.domain;

public enum AuthRole {

REVIEWEE,
REVIEWER;

public boolean isReviewer() {
return this == REVIEWER;
}
}
6 changes: 6 additions & 0 deletions backend/src/main/java/corea/member/domain/MemberReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import corea.exception.CoreaException;
import corea.exception.ExceptionType;
import corea.member.repository.MemberRepository;
import corea.member.repository.ReviewerRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -13,9 +14,14 @@
public class MemberReader {

private final MemberRepository memberRepository;
private final ReviewerRepository reviewerRepository;

public Member findOne(long memberId) {
return memberRepository.findById(memberId)
.orElseThrow(() -> new CoreaException(ExceptionType.MEMBER_NOT_FOUND));
}

public boolean isReviewer(String githubUserId) {
return reviewerRepository.existsByGithubUserId(githubUserId);
}
}
4 changes: 4 additions & 0 deletions backend/src/main/java/corea/member/domain/MemberRole.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public boolean isReviewer() {
return this == REVIEWER;
}

public boolean isBoth(){
return this == BOTH;
}

public ParticipationStatus getParticipationStatus() {
return switch (this) {
case REVIEWER, REVIEWEE, BOTH -> ParticipationStatus.PARTICIPATED;
Expand Down
24 changes: 24 additions & 0 deletions backend/src/main/java/corea/member/domain/Reviewer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package corea.member.domain;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import static jakarta.persistence.GenerationType.IDENTITY;

@Entity
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Reviewer {

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

private String githubUserId;
}
11 changes: 11 additions & 0 deletions backend/src/main/java/corea/member/dto/MemberRoleResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package corea.member.dto;

import corea.member.domain.AuthRole;

public record MemberRoleResponse(String role) {

public static MemberRoleResponse from(boolean isReviewer) {
AuthRole role = isReviewer ? AuthRole.REVIEWER : AuthRole.REVIEWEE;
return new MemberRoleResponse(role.name());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package corea.member.repository;

import corea.member.domain.Reviewer;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ReviewerRepository extends JpaRepository<Reviewer, Long> {

boolean existsByGithubUserId(String githubUserId);
}
20 changes: 20 additions & 0 deletions backend/src/main/java/corea/member/service/MemberService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package corea.member.service;

import corea.member.domain.MemberReader;
import corea.member.dto.MemberRoleResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class MemberService {

private final MemberReader memberReader;

public MemberRoleResponse getMemberRoleWithGithubUserId(String githubUserId) {
boolean isReviewer = memberReader.isReviewer(githubUserId);
return MemberRoleResponse.from(isReviewer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import corea.exception.CoreaException;
import corea.exception.ExceptionType;
import corea.member.domain.Member;
import corea.member.domain.MemberReader;
import corea.member.domain.MemberRole;
import corea.member.repository.MemberRepository;
import corea.participation.domain.Participation;
Expand All @@ -25,6 +26,8 @@ public class ParticipationService {
private final ParticipationWriter participationWriter;
private final RoomRepository roomRepository;
private final MemberRepository memberRepository;
//TODO: memberRepository -> Reader/Writer
private final MemberReader memberReader;

@Transactional
public ParticipationResponse participate(ParticipationRequest request) {
Expand All @@ -35,7 +38,9 @@ public ParticipationResponse participate(ParticipationRequest request) {
private Participation saveParticipation(ParticipationRequest request) {
Member member = memberRepository.findById(request.memberId())
.orElseThrow(() -> new CoreaException(ExceptionType.MEMBER_NOT_FOUND));

MemberRole memberRole = MemberRole.from(request.role());
validateRole(member, memberRole);
Room room = getRoom(request.roomId());

return participationWriter.create(room, member, memberRole, request.matchingSize());
Expand All @@ -60,6 +65,17 @@ private void validateMemberExist(long memberId) {
}
}

private void validateRole(Member member, MemberRole memberRole) {
boolean isReviewer = memberReader.isReviewer(member.getGithubUserId());

if (!isReviewer && memberRole.isReviewer()) {
throw new CoreaException(ExceptionType.MEMBER_IS_NOT_REVIEWER);
}
if (isReviewer && memberRole.isBoth()) {
throw new CoreaException(ExceptionType.MEMBER_IS_NOT_BOTH);
}
}

private Room getRoom(long roomId) {
return roomRepository.findById(roomId)
.orElseThrow(() -> new CoreaException(ExceptionType.ROOM_NOT_FOUND));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package corea.review.infrastructure;

import corea.auth.infrastructure.GithubProperties;
import corea.review.dto.GithubPullRequestReview;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;

import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.stream.Stream;

import static org.springframework.http.MediaType.APPLICATION_JSON;

@EnableConfigurationProperties(GithubProperties.class)
@Component
public class GithubCommentClient {

private static final Random RANDOM = new Random();

private final RestClient restClient;
private final GithubPullRequestUrlExchanger githubPullRequestUrlExchanger;
private final List<String> personalAccessTokens;

public GithubCommentClient(RestClient restClient, GithubPullRequestUrlExchanger githubPullRequestUrlExchanger, GithubProperties githubProperties) {
this.restClient = restClient;
this.githubPullRequestUrlExchanger = githubPullRequestUrlExchanger;
this.personalAccessTokens = githubProperties.pullRequest()
.tokens();
}

public List<GithubPullRequestReview> getPullRequestComments(String prLink) {
String commentApiUrl = githubPullRequestUrlExchanger.pullRequestUrlToComment(prLink);

return Stream.iterate(1, page -> page + 1)
.map(page -> getPullRequestCommentsForPage(page, commentApiUrl))
.takeWhile(this::hasMoreComments)
.flatMap(Arrays::stream)
.toList();
}

private GithubPullRequestReview[] getPullRequestCommentsForPage(int page, String commentApiUrl) {
String url = buildPageUrl(page, commentApiUrl);

return restClient.get()
.uri(url)
.header(HttpHeaders.AUTHORIZATION, getRandomPersonalAccessToken())
.accept(APPLICATION_JSON)
.retrieve()
.body(GithubPullRequestReview[].class);
}

private String buildPageUrl(int page, String commentApiUrl) {
return commentApiUrl + "?page=" + page + "&per_page=100";
}

private boolean hasMoreComments(GithubPullRequestReview[] comments) {
return comments.length > 0;
}

private String getRandomPersonalAccessToken() {
if (personalAccessTokens.isEmpty()) {
return "";
}
return "Bearer " + personalAccessTokens.get(RANDOM.nextInt(personalAccessTokens.size()));
}
}
Loading

0 comments on commit 93357d0

Please sign in to comment.