Skip to content

Commit

Permalink
코레아 1.23v 배포 (#674)
Browse files Browse the repository at this point in the history
* [FE] 헤더 리팩터링하기(#642) (#651)

* feat: 메뉴와 클로즈 아이콘 추가

* feat: 버튼에 흰 배경의 default 타입 추가

* feat: 모바일 버전에서 나타낼 SideNavBar 컴포넌트 구현

* refactor: 디바이스에 따라 헤더와 사이드바 렌더링

* feat: createPortal 방식으로 sidenavbar 열기, backdrop 추가하기

* fix: 잘못 들어간 , 삭제

* feat: sidenavbar가 오픈상태일 때는 스크롤 막기

* feat: sidenavbar 컴포넌트에 fadeIn, fadeOut 애니메이션 추가

* design: 가이드페이지 line-height 조정

* design: 사이드바 폰트 크기 수정

* feat: z-index 삭제

* fix: 사이드바가 열린채로 디바이스 크기가 커져도 여전히 사이드바가 나타나는 문제 해결

---------

Co-authored-by: 00kang <[email protected]>

* [BE] FailedMatching 엔티티에 생성된 시간 필드 추가 및 로그 추가(#656) (#657)

* feat: FailedMatching 생성 시점에 대한 필드 값 추가

* feat: 매칭 실패 시 로그 추가

---------

Co-authored-by: gyungchan Jo <[email protected]>

* feat: 개발 서버 토큰 변경

* feat: 개발 서버 설정 추가

* [BE] Member 내 리뷰어 인지 나타내는 칼럼 추가, 리뷰어가 아닌데 리뷰어로 참여시 예외 발생(#660) (#662)

* feat: authRole 추가

* feat: 참가 시 리뷰어 검증 추가

---------

Co-authored-by: youngsu5582 <[email protected]>

* fix: Enum 문자열로 저장하게 변경

* [FE] 부족한 일부 기능 추가(#659) (#661)

* feat: 헤더에 문의 탭 추가

* test: 방 참여자 리스트 불러오는 요청에 대한 MSW 추가

* feat: 남은 시간은 초 단위로 카운트다운하는 훅 추가

* feat: 참여자 리스트 요청을 5초에 한 번씩 가능하도록 추가

* feat: 모바일 사이드바에서 문의 탭 추가

* feat: 리뷰어로 등록된 계정만 리뷰어로 참여가 가능하도록 변경

* test: 방정보 더미데이터 값 수정

* style: 중복된 cursor style 제거

* chore: 상수명을 UPPER_SNAKECASE로 변경

---------

Co-authored-by: Lee sang Yeop <[email protected]>

* refactor: 운영 서버 설정 변경

* [FE] �모달 웹 접근성 추가(#644) (#658)

* feat: FocusTrap의 children이 DOM 변경을 추적하도록 추가

* style: 피드백 모달 내 키워드 스타일 변경

* feat: 모달이 열리면 모달만 보이스오버가 읽을 수 있도록 추가

* style: 피드백 모달 키워드 텍스트 색상 추가

* feat: 피드백 작성 모달 보이스오버로 동작 가능하도록 추가

* test: MSW로 피드백 수정도 확인이 가능하도록 추가

* chore: 모달이 열리면 가장먼저 닫기가 선택되도록 변경

* fix: 불필요한 ,(쉼표) 삭제

* test: 작성된 리뷰이 피드백 데이터를 반환하는 MSW 추가

* refactor: 피드백 모달 페이지 접근성을 위해 시멘틱태그 활용하도록 변경

* feat: 룸카드 뱃지의 접근성 추가

* style: 깃허브 링크 주소에 패딩 추가

* feat: 날짜를 한국어로 바꿔주는 유틸함수 추가

* feat: 룸 카드를 div에서 버튼으로 변경

* feat: 방정보 모달에 접근성 추가

* chore: 텍스트 띄어쓰기 추가

* chore: 보이스오버에서 모달 닫기 버튼을 인식할 수 있도록 개선

* feat: 토스트 메시지가 발생하면 보이스오버에서 읽을 수 있도록 추가

* refactor: 뱃지의 종류를 한국어로 변환해주는 로직을 유틸 함수로 분리

* feat: 토스트모달은 aria-hidden 처리가 안되도록 변경

---------

Co-authored-by: Lee sang Yeop <[email protected]>

* [BE] 코멘트를 달아도 리뷰 완료되게 변경(#626) (#665)

* feat: pr에 작성된 모든 커멘트들을 가져오는 기능 구현

* refactor: pr에 작성된 모든 리뷰들을 가져오는 기능 수정

* feat: pr에 작성된 리뷰와 커멘트를 확인하는 기능 구현

* refactor: 변수명 수정

* style: 코드 포맷팅 적용

* refactor: GithubPullRequestUrlExchanger를 컴포넌트로 변경

* refactor: 메서드명 변경

* test: 테스트가 통과하도록 수정

* test: 깃헙 api를 사용하는 테스트 Disabled 처리

* refactor: 변수명 변경

* style: TODO 추가

* feat: RestClient 타임아웃 설정 추가

---------

Co-authored-by: gyungchan Jo <[email protected]>

* [BE] Member 객체가 가지는 MemberRole 관련 리팩터링 제안(#663) (#664)

* feat: 리뷰어 엔티티 작성

* refactor: 리뷰어 엔티티 활용해서 기존 로직 수정

* refactor: Member 엔티티에서 authRole 삭제

* refactor: 에러 문구 수정

* refactor: 사용 enum 수정

* style: 클래스 선언 이후 개행 추가

* refactor: 조이썬 피드백 반영

---------

Co-authored-by: ashsty <[email protected]>

* [FE] 서비스 가이드를 설명하는 메인페이지 구현(#413) (#537)

* feat: IntroPage에 scroll-snap 적용

* feat: intro에서 현재 페이지 위치를 알 수 있도록 네비게이션 바 추가

* feat: intro 페이지에서는 헤더 안보이도록 수정

* feat: intro 페이지 라우터 추가

* style: 네비게이션바 스타일 수정

* feat: intro 페이지의 컨텐츠 추가

* design: 모바일 반응형 디자인 추가

* feat: 헤더 네비게이션에 서비스소개 intro 추가

* fix: 링크 공유시 미리보기에 이미지 안뜨는 문제 해결

* design: svg 이미지 색 있는 버전으로 변경

* fix: 테스트코드에서 놓친 message 속성 추가

* feat: 인트로페이지에 필요한 이미지 추가

* design: 모바일, 태블릿 반응형 디자인 추가

* design: 높이 수정

* feat: 사이드바에 소개페이지 추가

* feat: 반응형 디자인에 맞게 디테일 수정

---------

Co-authored-by: 00kang <[email protected]>

* [BE] QA 발생 중 발견한 버그 해결(#669) (#670)

* feat: github api 요청 시 헤더에 토큰 추가

* refactor: 결과가 없으면 빈 배열로 만드는 기능 구현

---------

Co-authored-by: gyungchan Jo <[email protected]>

* [BE] 운영 서버 Swagger 비활성화 & 액츄에이터 내부 포트로 이동(#666) (#671)

* feat: 헬스체크 포트 변경

* feat: 서브모듈 변경 반영

---------

Co-authored-by: youngsu5582 <[email protected]>

* [FE] 서비스 운영 전 QA(#667) (#673)

* design: 피드백 작성 모달 디자인 반영 안된부분 추가

* fix: 방 참여자 요청 쿼리문의 staleTime 제거

* style: 사이드바 radius 추가

* feat: 안드로이드 코드 가이드 추가

* fix: PR 링크 클릭 시 해당 링크로 이동하지 않던 문제 해결

* style: 사이드바 열렸을 때 hover 시 radius 스타일링 추가

* feat: 내 리뷰이 매칭에 대한 추가정보를 테이블 아래에 추가

* fix: 방 제목이 길면 레이아웃이 꺠지는 문제 해결

* fix: 방 상태가 여러개인 경우 레이아웃이 꺠지는 문제 해결

* design: 모바일 햄버거 바 클릭 시 nav 스타일 변경

* fix: 모바일 환경에서 방 카드 정보에 뱃지가 제목을 가리는 문제 해결

* chore: 방 상세 페이지의 함께하는 참여자 제목 변경

---------

Co-authored-by: Lee sang Yeop <[email protected]>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: 00kang <[email protected]>
Co-authored-by: gyungchan Jo <[email protected]>
Co-authored-by: youngsu5582 <[email protected]>
Co-authored-by: ashsty <[email protected]>
  • Loading branch information
6 people authored Oct 23, 2024
1 parent 97f996d commit 775871e
Show file tree
Hide file tree
Showing 99 changed files with 1,921 additions and 280 deletions.
4 changes: 2 additions & 2 deletions backend/scripts/healthCheck.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/bin/bash
echo "> Health check 시작"
echo "> curl -s http://localhost:8080/actuator/health"
echo "> curl -s http://localhost:9100/actuator/health"

for RETRY_COUNT in {1..15}
do
RESPONSE=$(curl -s http://localhost:8080/actuator/health)
RESPONSE=$(curl -s http://localhost:9100/actuator/health)
UP_COUNT=$(echo $RESPONSE | grep 'UP' | wc -l)

if [ $UP_COUNT -ge 1 ]
Expand Down
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 775871e

Please sign in to comment.