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

[Team#04][BE] 3주차 PR입니다 #45

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
83db405
feat #37 : issue TextColor, BackgroundColor 추가
JJONSOO Aug 4, 2023
69575b7
fix #37 : 에러 메세지를 ErrorResponse가 가지도록 수정
JJONSOO Aug 4, 2023
627b4e4
fix #37 : FilterMapper에서 Label ID만 가져오고 title, textColor, backgroundC…
JJONSOO Aug 4, 2023
fc42634
fix #37 : LabelRepository 에서 Label ID만 가져오고 title, textColor, backgro…
JJONSOO Aug 4, 2023
feae50c
fix #37 : null이 아닌 빈 List가 반환되도록 한다.
JJONSOO Aug 7, 2023
4988ab0
fix #37 : 코드 리뷰 반영
JJONSOO Aug 7, 2023
f9ceea5
Merge pull request #42 from codesquad-team4-issue-tracker/feat/#37-re…
JJONSOO Aug 7, 2023
93b182b
fix #43 : Label Test 코드 작성
JJONSOO Aug 7, 2023
2186a57
fix #43 : Label CRUD 코드 작성
JJONSOO Aug 7, 2023
4236397
fix #43 : milestone 개수 가져오기
JJONSOO Aug 7, 2023
2dbbd12
fix #43 : 비밀번호 길이 두 번 검증은 취소한다.
JJONSOO Aug 7, 2023
d654d33
Merge pull request #44 from codesquad-team4-issue-tracker/feat/#43-label
JJONSOO Aug 7, 2023
7066c9e
chore #46: Dockerfile-dev생성
yhpark95 Aug 7, 2023
de57a53
chore #46: cors설정
yhpark95 Aug 7, 2023
20ba97b
Merge pull request #48 from codesquad-team4-issue-tracker/chore/#46-cors
yhpark95 Aug 7, 2023
4b37305
feat #45 : nginx 경로 설정을 위해 모든 Path앞에 /api 추가
JJONSOO Aug 7, 2023
efc9d66
feat #45 : milestone 테스트 작성
JJONSOO Aug 7, 2023
74de407
feat #45 : milestone API
JJONSOO Aug 7, 2023
20d7820
Merge pull request #51 from codesquad-team4-issue-tracker/feat/#45-mi…
JJONSOO Aug 7, 2023
5caf076
test #31: repository 메서드 일부 테스트코드 추가
Ojeegu Aug 8, 2023
1624345
fix #54 : url method path 수정
JJONSOO Aug 8, 2023
5be72c9
feat #54 : 로그아웃 API
JJONSOO Aug 8, 2023
096f3b9
feat #54 : 로그아웃 API
JJONSOO Aug 8, 2023
624ff3b
fix #54 : @Transactional 추가
JJONSOO Aug 8, 2023
7c8f326
refactor #31: 메서드 분리
Ojeegu Aug 8, 2023
76bb90a
Merge pull request #56 from codesquad-team4-issue-tracker/faet/#54-lo…
JJONSOO Aug 8, 2023
493bcbb
Merge branch 'be' of https://github.com/codesquad-team4-issue-tracker…
Ojeegu Aug 8, 2023
caa2dd3
refactor #31: service class method 호출하도록 변경
Ojeegu Aug 8, 2023
df301d8
refactor #31: 오타 수정
Ojeegu Aug 8, 2023
56751a0
refactor #31: 오타 수정
Ojeegu Aug 8, 2023
3c42fe9
Merge pull request #57 from codesquad-team4-issue-tracker/test/#31-is…
JJONSOO Aug 8, 2023
73525c5
refactor #31: 테스트코드 수정
Ojeegu Aug 8, 2023
2c4becc
feat #55: 히스토리 생성 기능 구현(AOP) + 테스트 구현
yhpark95 Aug 8, 2023
c343a44
feat #55: 테스트 추가 & 수정
yhpark95 Aug 8, 2023
bfbf521
feat #55: aop의존성 추가
yhpark95 Aug 8, 2023
aea02fc
fix #55 : FilterMapperTest 수정
JJONSOO Aug 8, 2023
689aa2c
Merge branch 'be' of https://github.com/codesquad-team4-issue-tracker…
Ojeegu Aug 8, 2023
6cd0b45
test #31: issueService 테스트 코드 작성
Ojeegu Aug 8, 2023
8b0afa0
Merge pull request #58 from codesquad-team4-issue-tracker/feat/#55-hi…
JJONSOO Aug 9, 2023
f1cc30c
Merge branch 'be' of https://github.com/codesquad-team4-issue-tracker…
Ojeegu Aug 9, 2023
337c4b8
test #31: issueController 테스트 코드 작성
Ojeegu Aug 9, 2023
383fe62
refactor #31: ControllerTestSupport 수정
Ojeegu Aug 9, 2023
4df1977
Merge pull request #59 from codesquad-team4-issue-tracker/test/#31-is…
Ojeegu Aug 9, 2023
5287c72
feat #61 : 각 도메인별 Validator 추가
JJONSOO Aug 9, 2023
ad02c39
feat #61 : issue validator 추가
JJONSOO Aug 9, 2023
571ba30
feat #61 : milestone validator 추가
JJONSOO Aug 9, 2023
1872ede
feat #61 : member validator 추가
JJONSOO Aug 9, 2023
bc7cc96
feat #61 : label validator 추가
JJONSOO Aug 9, 2023
64d43c7
feat #61 : Jwt validator 추가
JJONSOO Aug 9, 2023
fb0048b
feat #61 : History validator 추가
JJONSOO Aug 9, 2023
59cb563
feat #61 : Assignee validator 추가
JJONSOO Aug 9, 2023
1f6bd77
feat #61 : Filter validator 추가
JJONSOO Aug 9, 2023
81f0f28
feat #61 : Comment validator 추가
JJONSOO Aug 9, 2023
b207575
Merge pull request #62 from codesquad-team4-issue-tracker/feat/#61-va…
JJONSOO Aug 9, 2023
54be6bc
feat : cors preflight가 jwt필터를 타지 않도록 수정
yhpark95 Aug 10, 2023
52fe03f
feat #69 : mileStoneCount -> milestoneCount로 네이밍 수정
JJONSOO Aug 11, 2023
181ea54
feat #69 : milestone open/closed 을 opposite로 통일
JJONSOO Aug 11, 2023
ebd4d37
Merge pull request #71 from codesquad-team4-issue-tracker/feat/#69-ma…
JJONSOO Aug 11, 2023
af41b45
feat #69 : issue, milestone name을 title로 수정
JJONSOO Aug 11, 2023
311feff
Merge pull request #73 from codesquad-team4-issue-tracker/feat/#69-ma…
JJONSOO Aug 11, 2023
0e0e2d6
feat #78 : issue 저장시 name을 title로 수정
JJONSOO Aug 11, 2023
13edeb9
feat #78 : 마일스톤 저장시 name을 title로 수정
JJONSOO Aug 11, 2023
699f125
feat #78 : 같은 이름의 Issue 존재시 예외를 발생시킨다.
JJONSOO Aug 11, 2023
56d2d5f
feat #78 : 같은 이름의 Milestone 존재시 예외를 발생시킨다.
JJONSOO Aug 11, 2023
7b7e565
feat #78 : 같은 이름의 Issue 존재시 예외를 발생시키는 테스트.
JJONSOO Aug 11, 2023
c802731
feat #78 : 같은 이름의 Milestone 존재시 예외를 발생시키는 테스.
JJONSOO Aug 11, 2023
ca2a15a
Merge pull request #79 from codesquad-team4-issue-tracker/feat/#78-la…
JJONSOO Aug 11, 2023
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
6 changes: 6 additions & 0 deletions be/Dockerfile-dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM openjdk:11
WORKDIR /app
COPY . .
ARG JAR_FILE=./build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Dspring.profiles.active=dev","-Dserver.port=8080","-jar","app.jar"]
2 changes: 2 additions & 0 deletions be/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-aop'

// lombok
compileOnly 'org.projectlombok:lombok'
Expand All @@ -50,6 +51,7 @@ dependencies {
implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.2'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.2'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.2'

}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,9 @@ public class ApiException extends RuntimeException {
public ApiException(CustomException customException) {
this.customException = customException;
}

@Override
public String getMessage() {
return customException.getMessage();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@
public class GlobalExceptionHandler {
@ExceptionHandler(ApiException.class)
public ErrorResponse apiExceptionHandler(ApiException e) {
return new ErrorResponse(e.getCustomException().getHttpStatus().value(), e.getMessage());
return new ErrorResponse(e.getCustomException().getHttpStatus().value(), e.getCustomException().getMessage());
}


@ExceptionHandler(MethodArgumentNotValidException.class)
public ErrorResponse validationExceptionHandler(MethodArgumentNotValidException e) {
String message = e.getBindingResult()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import org.springframework.http.HttpStatus;

public enum LabelException implements CustomException {
NOT_FOUND_LABEL(HttpStatus.NOT_FOUND, "존재하지 않는 라벨입니다.");
NOT_FOUND_LABEL(HttpStatus.NOT_FOUND, "존재하지 않는 라벨입니다."),
INVALID_LABEL_TITLE(HttpStatus.BAD_REQUEST, "같은 제목의 라벨이 존재합니다.");

private final HttpStatus httpStatus;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
public enum LoginException implements CustomException {
INVALID_LOGIN_ID(HttpStatus.BAD_REQUEST, "같은 아이디가 존재합니다."),
INVALID_PASSWORD(HttpStatus.BAD_REQUEST, "비밀번호는 8글자 이상 입니다."),
INCORRECT_PASSWORD(HttpStatus.BAD_REQUEST, "올바르지 않은 패스워드 입니다.");
INCORRECT_LOGIN_INFORMATION(HttpStatus.BAD_REQUEST, "올바르지 않은 아이디 또는 패스워드 입니다.");

private final HttpStatus httpStatus;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.issuetrackermax.common.exception.domain;

import org.springframework.http.HttpStatus;

public enum MemberException implements CustomException {
NOT_FOUND_MEMBER(HttpStatus.NOT_FOUND, "존재하지 않는 회원입니다.");

private final HttpStatus httpStatus;
private final String message;

MemberException(HttpStatus httpStatus, String message) {
this.httpStatus = httpStatus;
this.message = message;
}

@Override
public HttpStatus getHttpStatus() {
return httpStatus;
}

@Override
public String getMessage() {
return message;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import org.springframework.http.HttpStatus;

public enum MilestoneException implements CustomException {
NOT_FOUND_MILESTONE(HttpStatus.NOT_FOUND, "존재하지 않는 마일스톤입니다.");
NOT_FOUND_MILESTONE(HttpStatus.NOT_FOUND, "존재하지 않는 마일스톤입니다."),
INVALID_MILESTONE_TITLE(HttpStatus.BAD_REQUEST, "같은 제목의 마일스톤이 존재합니다.");

private final HttpStatus httpStatus;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.PatternMatchUtils;
import org.springframework.web.cors.CorsUtils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.issuetrackermax.common.exception.response.ErrorResponse;
import com.issuetrackermax.common.exception.domain.JwtException;
import com.issuetrackermax.common.exception.response.ErrorResponse;
import com.issuetrackermax.service.jwt.JwtProvider;

import io.jsonwebtoken.Claims;
Expand All @@ -26,8 +27,8 @@ public class JwtAuthorizationFilter implements Filter {
private static final String TOKEN_PREFIX = "Bearer ";
private static final String HEADER_AUTHORIZATION = "Authorization";
private static final String MEMBER_ID = "memberId";
private static final String[] whiteListUris = new String[] {"/h2-console/**", "/signin", "/signup",
"/reissue-access-token", "/oauth/**", "/redirect/**"};
private static final String[] whiteListUris = {"/h2-console/**", "/api/signin", "/api/signup",
"/api/reissue-access-token", "/api/oauth/**", "/api/redirect/**"};

private final JwtProvider jwtProvider;
private final ObjectMapper objectMapper;
Expand All @@ -42,7 +43,10 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
throws ServletException, IOException {

HttpServletRequest httpServletRequest = (HttpServletRequest)request;

if (CorsUtils.isPreFlightRequest(httpServletRequest)) {
chain.doFilter(request, response);
return;
}
if (whiteListCheck(httpServletRequest.getRequestURI())) {
chain.doFilter(request, response);
return;
Expand Down
16 changes: 16 additions & 0 deletions be/src/main/java/com/issuetrackermax/config/CorsConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.issuetrackermax.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH");
}
}
56 changes: 56 additions & 0 deletions be/src/main/java/com/issuetrackermax/config/HistoryAspect.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.issuetrackermax.config;

import static com.issuetrackermax.domain.issue.IssueStatus.*;

import java.util.List;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import com.issuetrackermax.controller.history.dto.HistoryRequest;
import com.issuetrackermax.controller.issue.dto.request.IssuePostRequest;
import com.issuetrackermax.controller.issue.dto.request.IssuesStatusRequest;
import com.issuetrackermax.controller.issue.dto.response.IssuePostResponse;
import com.issuetrackermax.domain.member.MemberRepository;
import com.issuetrackermax.service.history.HistoryService;

import lombok.RequiredArgsConstructor;

@Aspect
@Component
@RequiredArgsConstructor
public class HistoryAspect {
private final HistoryService historyService;
private final MemberRepository memberRepository;

@Around("execution(* com.issuetrackermax.service.issue.IssueService.post(..)) && args(request,writerId)")
public Object save(ProceedingJoinPoint joinPoint, IssuePostRequest request, Long writerId) throws Throwable {
IssuePostResponse issuePostResponse = (IssuePostResponse)joinPoint.proceed();
Long issueId = issuePostResponse.getId();

historyService.save(HistoryRequest.builder()
.issueId(issueId)
.editor(memberRepository.findById(writerId).get().getNickName())
.issueIsOpen(true)
.build());
return issuePostResponse;
}

@Around("execution(* com.issuetrackermax.service.issue.IssueService.updateStatus(..)) && args(request, memberId)")
Comment on lines +28 to +41

Choose a reason for hiding this comment

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

aspect를 직접 사용하셧군요 changeStatus에는 왜 사용하셨나요?

Copy link
Author

Choose a reason for hiding this comment

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

이슈 상태를 바꾸는 것도 History에 저장하기 위해 사용하였습니다.
ex) A에 의해 5분전에 변경되었습니다.

public void changeStatus(ProceedingJoinPoint joinPoint, IssuesStatusRequest request, Long memberId) throws
Throwable {
joinPoint.proceed();
List<Long> ids = request.getIssueIds();
String status = request.getIssueStatus();
String editor = memberRepository.findById(memberId).get().getNickName();
ids.forEach(id -> historyService.save(
HistoryRequest.builder()
.issueId(id)
.editor(editor)
.issueIsOpen(status.equals(OPEN_ISSUE.getStatus()))
.build()));
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.issuetrackermax.controller.assignee;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.issuetrackermax.service.assignee.AssigneeService;
Expand All @@ -8,6 +9,7 @@

@RequiredArgsConstructor
@RestController
@RequestMapping("/api")
public class AssigneeController {
private final AssigneeService assigneeService;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.issuetrackermax.controller.ApiResponse;
import com.issuetrackermax.controller.auth.dto.request.JwtRefreshTokenRequest;
import com.issuetrackermax.controller.auth.dto.request.LoginRequest;
import com.issuetrackermax.controller.auth.dto.request.LogoutRequest;
import com.issuetrackermax.controller.auth.dto.response.JwtResponse;
import com.issuetrackermax.service.jwt.JwtService;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@RestController
@RequestMapping("/api")
public class AuthController {
private final JwtService jwtService;

Expand All @@ -28,6 +31,14 @@ public ApiResponse<JwtResponse> login(
);
}

@PostMapping("/logout")
public ApiResponse<Void> logout(
@RequestBody
@Valid LogoutRequest request) {
jwtService.logout(request.getRefreshToken());
return ApiResponse.success();
}

@PostMapping("/reissue-access-token")
public ApiResponse<JwtResponse> reissueAccessToken(
@RequestBody
Expand All @@ -36,4 +47,5 @@ public ApiResponse<JwtResponse> reissueAccessToken(
JwtResponse.from(jwtService.reissueAccessToken(request.getRefreshToken()))
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

Expand All @@ -13,6 +14,7 @@

@RequiredArgsConstructor
@RestController
@RequestMapping("/api")
public class OAuthController {
private final OauthService oauthService;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.issuetrackermax.controller.auth.dto.request;

import javax.validation.constraints.NotBlank;

import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class LogoutRequest {
@NotBlank
private String refreshToken;

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.issuetrackermax.controller.comment;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.issuetrackermax.service.comment.CommentService;
Expand All @@ -8,6 +9,7 @@

@RequiredArgsConstructor
@RestController
@RequestMapping("/api")
public class CommentController {
private final CommentService commentService;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.issuetrackermax.controller.ApiResponse;
Expand All @@ -16,6 +17,7 @@

@RequiredArgsConstructor
@RestController
@RequestMapping("/api")
public class FilterController {
private static final String MEMBER_ID = "memberId";
private final FilterService filterService;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.issuetrackermax.controller.filter.dto.response;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
Expand All @@ -21,7 +22,7 @@ public AssigneeResponse(Long id, String name) {

public static List<AssigneeResponse> convertToAssigneeResponseList(String assigneeIds, String assigneeNames) {
if (assigneeIds == null) {
return null;
return new ArrayList<>();

Choose a reason for hiding this comment

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

null에서 빈리스트를 돌려주기로 했군요

Copy link
Author

Choose a reason for hiding this comment

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

넵 null로 반환하는게 어색하다고 생각하여 빈 리스트를 반환하도록 코드를 수정하였습니다.

}
List<String> ids = List.of(assigneeIds.split(","));
List<String> names = List.of(assigneeNames.split(","));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@
@NoArgsConstructor
public class FilterResponse {
private Long labelCount;
private Long mileStoneCount;
private Long milestoneCount;
private Long openIssueCount;
private Long closedIssueCount;
private List<IssueResponse> issues;

@Builder
public FilterResponse(Long labelCount, Long mileStoneCount, Long openIssueCount, Long closedIssueCount,
public FilterResponse(Long labelCount, Long milestoneCount, Long openIssueCount, Long closedIssueCount,
List<IssueResponse> issues) {
this.labelCount = labelCount;
this.mileStoneCount = mileStoneCount;
this.milestoneCount = milestoneCount;
this.openIssueCount = openIssueCount;
this.closedIssueCount = closedIssueCount;
this.issues = issues;
Expand Down
Loading