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-31] 데이먼 3주차 1번째 PR 요청 #236

Open
wants to merge 106 commits into
base: team-31
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
76c7816
release 1.2.0
dukcode Jun 17, 2022
88959d8
Merge tag '1.2.0' into dev-be
dukcode Jun 17, 2022
255ea03
feat: User, Issue, Label, Milestone 컬럼 조건 적용
dukcode Jun 18, 2022
c108ed1
feat: Comment, Reaction, IssueLabel, Issue 컬럼 조건 적용
dukcode Jun 18, 2022
9f6b7f2
feat: Issue 등록 디테일 조회 API 구현
dukcode Jun 18, 2022
cf605c5
feat: Issue 삭제 API 구현
dukcode Jun 18, 2022
a45bbac
feat: Label 삭제 시 Issue에 반영되도록 구현
dukcode Jun 18, 2022
7bc2761
feat: Milestone 삭제 시 Issue에 반영되도록 구현
dukcode Jun 18, 2022
63220f0
feat: Issue 상태 변경 API 구현
dukcode Jun 18, 2022
63fbab4
feat: Issue 담당자 변경 API 구현
dukcode Jun 18, 2022
a8452c4
feat: Issue 마일스톤 변경 API 구현
dukcode Jun 18, 2022
15335aa
feat: Issue 레이블 변경 API 구현
dukcode Jun 18, 2022
0158fca
feat: Issue 관련 API 구현
dukcode Jun 18, 2022
3c5bd32
refactor: Issue 도메인에서 Comment 도메인 분리
dukcode Jun 18, 2022
3c6bcf4
feat: Comment 등록, 수정, 삭제 API 구현
dukcode Jun 18, 2022
ad584e6
feat: Reaction update API 구현
dukcode Jun 18, 2022
8720160
feat: Reaction 목록 조회 API 구현
dukcode Jun 18, 2022
2cf586a
feat: Comment, Reaction 관련 API 구현
dukcode Jun 18, 2022
ac84249
feat: User 목록 조회 API 구현
dukcode Jun 18, 2022
48eacb0
feat: 이슈 목록 조회 임시 API 구현
dukcode Jun 18, 2022
d378d61
chore: 스키마 DDL 업데이트
dukcode Jun 18, 2022
a925f97
Merge branch 'release/1.3.0'
dukcode Jun 18, 2022
bfbfd5d
Release '1.3.0'
dukcode Jun 18, 2022
4252772
feat: admin key를 토큰으로 넘기면 loginName에 admin 바인딩하도록 구현
dukcode Jun 18, 2022
fd970fe
Merge branch 'release/1.3.1'
dukcode Jun 18, 2022
71d418b
Merge tag '1.3.1' into dev-be
dukcode Jun 18, 2022
61d8f3d
docs: Swagger 명세 보강
dukcode Jun 18, 2022
d54b505
Merge branch 'release/1.3.2'
dukcode Jun 18, 2022
f327a27
Merge tag '1.3.2' into dev-be
dukcode Jun 18, 2022
980812c
feat: Issue 상태 변경시 동작 추가 구현
dukcode Jun 19, 2022
4bd74be
feat: CommentResponse DTO에 시간 관련 필드 추가
dukcode Jun 19, 2022
99dc6b9
feat: 기존 Issue status로 변경 시도 시 관련 동작 안하도록 구현
dukcode Jun 19, 2022
ea95188
fefactor: 시간 관련 response format 변경
dukcode Jun 19, 2022
8f7a2ab
feat: Issue status 변경 관련 동작 구현
dukcode Jun 19, 2022
136fb85
feat: 이슈 제목 수정 API 구현
dukcode Jun 19, 2022
cb09f89
chore: DDL 업데이트
dukcode Jun 19, 2022
55d478a
Merge branch 'release/1.3.3'
dukcode Jun 19, 2022
330e6ad
Merge tag '1.3.3' into dev-be
dukcode Jun 19, 2022
2588314
fix: JwtInterceptor /error 경로 제외
dukcode Jun 20, 2022
051e0db
Merge branch 'hotfix/1.3.4'
dukcode Jun 20, 2022
4c0ee73
Merge tag '1.3.4' into dev-be
dukcode Jun 20, 2022
e9e5ff9
fix: JwtInterceptor 에서 Method Options인 경우 true 반환
dukcode Jun 20, 2022
6ab7f22
Merge branch 'hotfix/1.3.5'
dukcode Jun 20, 2022
f2d9f42
Merge tag '1.3.5' into dev-be
dukcode Jun 20, 2022
fe5d8f1
fix: CORS 문제 해결
dukcode Jun 20, 2022
8bc243d
Merge branch 'release/1.3.6'
dukcode Jun 20, 2022
c2cf89c
Merge tag '1.3.6' into dev-be
dukcode Jun 20, 2022
d1b086c
fix: CORS 문제 해결
dukcode Jun 20, 2022
3829105
Merge branch 'release/1.3.7'
dukcode Jun 20, 2022
c255b26
Merge tag '1.3.7' into dev-be
dukcode Jun 20, 2022
175c412
fix: CORS 문제 해결
dukcode Jun 20, 2022
634cbf8
Merge branch 'release/1.3.8'
dukcode Jun 20, 2022
c5cb45c
Merge tag '1.3.8' into dev-be
dukcode Jun 20, 2022
3f331aa
fix: CORS 문제 해결
dukcode Jun 20, 2022
4b08528
Merge branch 'release/1.3.9'
dukcode Jun 20, 2022
c9766f6
Merge tag '1.3.9' into dev-be
dukcode Jun 20, 2022
e83f296
fix: CORS 문제 해결
dukcode Jun 20, 2022
268bdc3
fix: CORS 문제 해결
dukcode Jun 20, 2022
e724a99
fix: CORS 문제 해결
dukcode Jun 20, 2022
17b4f4c
feat: Issue 목록 조회 defaultValue 추가
dukcode Jun 21, 2022
2cabec0
Merge branch 'release/1.3.12'
dukcode Jun 21, 2022
d9d4cd9
chore: Querydsl 빌드 의존성 추가
dukcode Jun 23, 2022
f160e26
feat: 이슈 검색 조건 DTO 구현
dukcode Jun 24, 2022
bb3ed63
feat: 이슈 목록 필터 검색 API 구현
dukcode Jun 24, 2022
e67e54d
feat: Issue Count 조건에 따라 동적 쿼리 적용
dukcode Jun 24, 2022
2a82190
feat: 이슈 검색 필터 마일스톤 조건 추가
dukcode Jun 24, 2022
c594140
feat: 이슈 필터 목록 조회 페이징 구현
dukcode Jun 24, 2022
d93f419
feat: 카운트 쿼리 최적화
dukcode Jun 25, 2022
ab7a951
feat: Count 쿼리 맵으로 불러오도록 구현
dukcode Jun 25, 2022
4045917
refactor: 불필요한 console log 제거
dukcode Jun 25, 2022
3edc806
refactor: 마일스톤 존재 및 중복 검증 메서드 분리
dukcode Jun 25, 2022
890f5aa
refactor: 레이블 존재 및 중복 검증 메서드 분리
dukcode Jun 25, 2022
abd2cd3
refactor: Milestone 조회 쿼리 최적화
dukcode Jun 25, 2022
cfd3168
refactor: Reaction 조회시 Issue 정보 불필요하도록 변경
dukcode Jun 25, 2022
314d2cf
refactor: User 존재 검증 불필요로 제거
dukcode Jun 25, 2022
667e18c
refactor: Reaction API 조작 시 Issue 정보 불필요 하도록 변경
dukcode Jun 25, 2022
6f77896
refactor: Comment find 중복 코드 제거
dukcode Jun 25, 2022
e7c4094
feat: Reaction 등록 방식을 toggle로 변경
dukcode Jun 25, 2022
ef02b32
refactor: AssignedUser, IssueLabel 생성시 User, Label 조회 최적화
dukcode Jun 25, 2022
1b83dfc
refactor: Issue 생성 시 Cascade.ALL 옵션 활용
dukcode Jun 25, 2022
7e53aa5
refactor: Issue status 변경 시 Cascade.ALL 옵션 활용
dukcode Jun 25, 2022
fa33c1e
refactor: Issue 다중 status 변경 시 Issue 조회 최적화
dukcode Jun 25, 2022
f1279ae
refactor: Issue 조회 코드 중복 메서드화
dukcode Jun 25, 2022
8cbe36d
refactor: Milestone 삭제 시 불필요한 Lazy Loading 제거
dukcode Jun 25, 2022
fd7547c
refactor: Label 삭제시만 IssueLabel 변경(삭제) 되도록 Cascade.REMOVE로 변경
dukcode Jun 25, 2022
d944723
refactor: Issue 담당자 변경 메서드 이름 변경
dukcode Jun 25, 2022
052bc45
refactor: Milestone 삭제 시 연관 Issues batch update로 변경
dukcode Jun 25, 2022
571fe4a
feat: LoginUserArgumentResolver 생성
dukcode Jun 25, 2022
42c9c13
Merge branch 'feat-be/querydsl' into dev-be
dukcode Jun 27, 2022
1488fac
1.4.0 release 충돌 해결
dukcode Jun 27, 2022
6b66bb8
Merge tag '1.4.0' into dev-be
dukcode Jun 27, 2022
ecc2e59
refactor: Issue 생성 시 AssignedUser, IssueLabel repository 이용 저장
dukcode Jun 27, 2022
513f83a
refactor: Issue의 assignedUsers, issueLabels Set으로 변경
dukcode Jun 27, 2022
878870e
Merge branch 'release/1.4.1'
dukcode Jun 27, 2022
ed6956e
Merge tag '1.4.1' into dev-be
dukcode Jun 27, 2022
1f6bf0e
refactor: Issue 조회 시 페이지 기본값 0으로 수정
dukcode Jun 27, 2022
133172d
Merge branch 'release/1.4.2'
dukcode Jun 27, 2022
8776ded
Merge tag '1.4.2' into dev-be
dukcode Jun 27, 2022
76332a4
refactor: Issue 디테일 조회 쿼리 성능 최적화
dukcode Jun 28, 2022
c02cf28
chore: 배포 cors 설정
dukcode Jun 29, 2022
b53c17d
Merge branch 'feat-be/query-optimization' into dev-be
dukcode Jun 29, 2022
7cb228c
Merge branch 'release/1.5.0'
dukcode Jun 29, 2022
ed448a0
Merge tag '1.5.0' into dev-be
dukcode Jun 29, 2022
e041e10
chore: CORS 문제
dukcode Jun 29, 2022
d005123
Merge branch 'release/1.5.1'
dukcode Jun 29, 2022
967b48c
Merge tag '1.5.1' into dev-be
dukcode Jun 29, 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
24 changes: 24 additions & 0 deletions BE/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
buildscript {
ext {
queryDslVersion = "5.0.0"
}
}

plugins {
id 'org.springframework.boot' version '2.7.0'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
id 'java'
}

Expand All @@ -26,6 +33,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'javax.xml.bind:jaxb-api:2.3.1'
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}"
annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}"
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'mysql:mysql-connector-java'
Expand All @@ -41,3 +50,18 @@ jar {
tasks.named('test') {
useJUnitPlatform()
}

def querydslDir = "$buildDir/generated/querydsl"
querydsl {
jpa = true
querydslSourcesDir = querydslDir
}
sourceSets {
main.java.srcDir querydslDir
}
configurations {
querydsl.extendsFrom compileClasspath
}
compileQuerydsl {
options.annotationProcessorPath = configurations.querydsl
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.team31.codesquad.issuetracker.config.mvc;

import com.team31.codesquad.issuetracker.config.mvc.annotation.LoginName;
import com.team31.codesquad.issuetracker.config.mvc.annotation.LoginUser;
import com.team31.codesquad.issuetracker.domain.user.UserRepository;
import com.team31.codesquad.issuetracker.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.core.MethodParameter;
Expand All @@ -12,12 +13,13 @@

@Component
@RequiredArgsConstructor
public class LoginNameArgumentResolver implements HandlerMethodArgumentResolver {
public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {

Choose a reason for hiding this comment

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

👍


private final JwtUtil jwtUtil;
private final UserRepository userRepository;

@Override public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterAnnotation(LoginName.class) != null;
return parameter.getParameterAnnotation(LoginUser.class) != null;
}

@Override
Expand All @@ -32,10 +34,10 @@ public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer m

String token = authorizationHeader.substring(7);
if (token.equals(jwtUtil.getAdminPassword())) {
return jwtUtil.getAdminLoginName();
return userRepository.findByLoginName(jwtUtil.getAdminLoginName());
}

String loginName = jwtUtil.getPayload(token);
System.out.println("loginName = " + loginName);
return loginName;
return userRepository.findByLoginName(loginName);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Argument Resolver에서 User를 직접 검색해와서 이제 Controller에서 User를 직접 받을 수 있게 되었습니다.

따라서 서비스 레이어에서 User를 검색하는 코드를 한곳에 모을 수 있었는데

이렇게 되면 컨트롤러에서 도메인에 대한 의존성이 필연적으로 생기게 됩니다.

LINK 에서는 Service 레이어가 도메인을 캡슐화하는 계층이라고 언급하고 있는데

컨트롤러에서의 도메인 의존에 대해서 피터는 어떻게 생각하시는지 궁금합니다.

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,21 @@
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {

private final LoginNameArgumentResolver loginNameArgumentResolver;
private final LoginUserArgumentResolver loginUserArgumentResolver;

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(loginNameArgumentResolver);
resolvers.add(loginUserArgumentResolver);
}

@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowedOrigins("http://localhost:3000",
"http://ec2-3-37-163-26.ap-northeast-2.compute.amazonaws.com",
"http://localhost:80")
.allowedMethods("*")
.allowedHeaders("*")
.exposedHeaders("*")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginName {
public @interface LoginUser {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.team31.codesquad.issuetracker.config.querydsl;

import com.querydsl.jpa.impl.JPAQueryFactory;
import javax.persistence.EntityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuerydslConfig {

@Bean
public JPAQueryFactory jpaQueryFactory(EntityManager em) {
return new JPAQueryFactory(em);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,14 @@ public Comment(Issue issue, User author, String content) {
this.systemMessage = false;
}

public static Comment createStatusChangeComment(Issue issue,
IssueStatus status, User statusChangeUser) {
public Comment(User author, String content) {
this.author = author;
this.content = content;
this.systemMessage = false;
}

public static Comment createStatusChangeComment(IssueStatus status, User statusChangeUser) {
Comment comment = new Comment();
comment.issue = issue;
comment.author = statusChangeUser;
comment.content =
status.equals(IssueStatus.OPEN) ? ISSUE_OPEN_MESSAGE : ISSUE_CLOSED_MESSAGE;
Expand All @@ -79,8 +83,8 @@ public void validateIssue(Long issueId) {
}
}

public void validateAuthor(String loginName) {
if (!loginName.equals(getAuthor().getLoginName())) {
public void validateAuthor(User user) {
if (!user.equals(getAuthor())) {
Comment on lines +86 to +87

Choose a reason for hiding this comment

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

user를 전체가 비교하기보단, user의 unique한 값을 꺼내서 check하는건 어떨까요?

throw new IllegalArgumentException("작성자만 접근이 가능합니다.");
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.team31.codesquad.issuetracker.domain.comment;

import com.team31.codesquad.issuetracker.domain.issue.Issue;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CommentRepository extends JpaRepository<Comment, Long> {

List<Comment> findAllByIssue(Issue issue);
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ public class Reaction extends BaseTimeEntity {

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private ReactionEmoji reactionEmoji;
private ReactionEmoji emoji;

public Reaction(User user, Comment comment, ReactionEmoji reactionEmoji) {
public Reaction(User user, Comment comment, ReactionEmoji emoji) {
this.user = user;
this.comment = comment;
this.reactionEmoji = reactionEmoji;
this.emoji = emoji;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import com.team31.codesquad.issuetracker.domain.user.User;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ReactionRepository extends JpaRepository<Reaction, Long> {

List<Reaction> findAllByUserAndComment(User user, Comment comment);

Optional<Reaction> findByUserAndCommentAndEmoji(User user, Comment comment,
ReactionEmoji emoji);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import com.team31.codesquad.issuetracker.domain.user.User;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
Expand Down Expand Up @@ -47,10 +49,10 @@ public class Issue extends BaseTimeEntity {
private User author;

@OneToMany(mappedBy = "issue", cascade = CascadeType.ALL)
private List<AssignedUser> assignees = new ArrayList<>();
private Set<AssignedUser> assignees = new HashSet<>();

@OneToMany(mappedBy = "issue", cascade = CascadeType.ALL)
private List<IssueLabel> issueLabels = new ArrayList<>();
private Set<IssueLabel> issueLabels = new HashSet<>();

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "milestone_id")
Expand All @@ -65,21 +67,16 @@ public class Issue extends BaseTimeEntity {
@JoinColumn(name = "status_change_user_id")
private User statusChangeUser;

public static Issue createIssue(String title, User author, List<AssignedUser> assignedUsers,
List<IssueLabel> issueLabels, Milestone milestone) {
public static Issue createIssue(String title, User author, Milestone milestone,
Comment comment) {
Issue issue = new Issue();
issue.status = IssueStatus.OPEN;
issue.title = title;
issue.author = author;
for (AssignedUser assignedUser : assignedUsers) {
issue.addAssignedUser(assignedUser);
}
for (IssueLabel issueLabel : issueLabels) {
issue.addIssueLabel(issueLabel);
}
issue.milestone = milestone;
issue.statusChangedAt = LocalDateTime.now();
issue.statusChangeUser = author;
issue.addComment(comment);

return issue;
}
Expand All @@ -91,7 +88,7 @@ private void addIssueLabel(IssueLabel issueLabel) {
}

public void updateAssignedUsers(List<AssignedUser> assignedUsers) {
this.assignees = new ArrayList<>();
this.assignees = new HashSet<>();
for (AssignedUser assignedUser : assignedUsers) {
addAssignedUser(assignedUser);
}
Expand Down Expand Up @@ -123,7 +120,7 @@ public void changStatus(IssueStatus status, User statusChangeUser) {
this.status = status;
this.statusChangeUser = statusChangeUser;
this.statusChangedAt = LocalDateTime.now();
Comment comment = Comment.createStatusChangeComment(this, status, statusChangeUser);
Comment comment = Comment.createStatusChangeComment(status, statusChangeUser);
addComment(comment);
}

Expand All @@ -137,7 +134,7 @@ public void updateMilestone(Milestone milestone) {
}

public void updateIssueLabels(List<IssueLabel> issueLabels) {
this.issueLabels = new ArrayList<>();
this.issueLabels = new HashSet<>();
for (IssueLabel issueLabel : issueLabels) {
addIssueLabel(issueLabel);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.team31.codesquad.issuetracker.domain.BaseTimeEntity;
import com.team31.codesquad.issuetracker.domain.label.Label;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
Expand Down Expand Up @@ -32,11 +33,29 @@ public class IssueLabel extends BaseTimeEntity {
@JoinColumn(name = "label_id")
private Label label;

public IssueLabel(Label label) {
public IssueLabel(Label label, Issue issue) {
this.label = label;
this.issue = issue;
}

public void setIssue(Issue issue) {
this.issue = issue;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
IssueLabel that = (IssueLabel) o;
return Objects.equals(getId(), that.getId());
}

@Override
public int hashCode() {
return Objects.hash(getId());
}
}
Loading