Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 10 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ on:

permissions:
contents: read
pull-requests: write

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down Expand Up @@ -36,4 +37,12 @@ jobs:
run: chmod +x gradlew

- name: gradlew test
run: ./gradlew test
run: ./gradlew test

- name : add coverage to PR
id: jacoco
uses: madrapps/[email protected]
with:
paths: |
${{ github.workspace }}/**/build/reports/jacoco/test/jacocoTestReport.xml
token: ${{ secrets.GITHUB_TOKEN }}
52 changes: 52 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
id 'java'
id 'org.springframework.boot' version '3.4.6-SNAPSHOT'
id 'io.spring.dependency-management' version '1.1.7'
id 'jacoco'
}

group = 'com.specialwarriors'
Expand Down Expand Up @@ -92,4 +93,55 @@ dependencies {

tasks.named('test') {
useJUnitPlatform()
finalizedBy jacocoTestReport
}

jacoco {
toolVersion = "0.8.11"
}

def jacocoExcludePatterns = [
'com/specialwarriors/conal/ConalApplication.class',
'**/common/**',
'**/exception/**',
'**/dto/**',
'**/config/**',
'**/enums/**',
'**/converter/**',
'**/test/**'
]

for (qPattern in '**/QA'..'**/QZ') {
jacocoExcludePatterns.add(qPattern + '*')
}

jacocoTestReport {
reports {
xml.required = true
csv.required = true
html.required = true
}

afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, excludes: jacocoExcludePatterns)
}))
}
}

jacocoTestCoverageVerification {
violationRules {

rule {
enabled = true
element = 'CLASS'

// 커버리지 제외 범위
excludes = jacocoExcludePatterns
}
}
}

clean {
delete file('src/main/generated')
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
import java.util.ArrayList;
import java.util.List;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Table(name = "github_repos")
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EqualsAndHashCode(of = "id")
public class GithubRepo {

@Id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
@RequiredArgsConstructor
public enum GithubRepoException implements BaseException {

UNAUTHORIZED_GITHUBREPO_ACCESS(HttpStatus.FORBIDDEN, "리포지토리 접근 권한이 없습니다"),
NOT_FOUND_GITHUBREPO(HttpStatus.NOT_FOUND, "깃허브 리포지토리를 찾을 수 없습니다"),
NOT_FOUND_GITHUBEMAIL(HttpStatus.NOT_FOUND, "기여자 이메일이 없습니다"),
UNAUTHORIZED_GITHUB_REPO_ACCESS(HttpStatus.FORBIDDEN, "리포지토리 접근 권한이 없습니다"),
GITHUB_REPO_NOT_FOUND(HttpStatus.NOT_FOUND, "깃허브 리포지토리를 찾을 수 없습니다"),
CONTRIBUTOR_EMAIL_NOT_FOUND(HttpStatus.NOT_FOUND, "기여자 이메일이 없습니다"),
INVALID_URL(HttpStatus.BAD_REQUEST, "잘못된 URL 입니다.");

private final HttpStatus status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.specialwarriors.conal.github_repo.domain.GithubRepo;
import com.specialwarriors.conal.github_repo.exception.GithubRepoException;
import com.specialwarriors.conal.github_repo.repository.GithubRepoRepository;
import com.specialwarriors.conal.user.domain.User;
import com.specialwarriors.conal.user.service.UserQuery;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

Expand All @@ -12,29 +14,25 @@
public class GithubRepoQuery {

private final GithubRepoRepository githubRepoRepository;
private final UserQuery userQuery;

public GithubRepo findByRepositoryId(Long repositoryId) {
return githubRepoRepository.findById(repositoryId).orElseThrow(() ->
new GeneralException(GithubRepoException.NOT_FOUND_GITHUBREPO)
);
}
public GithubRepo findByUserIdAndRepositoryId(long userId, long repositoryId) {

public GithubRepo findByUserIdAndRepositoryId(Long userId, Long repositoryId) {
GithubRepo githubRepo = githubRepoRepository.findById(repositoryId)
.orElseThrow(() -> new GeneralException(GithubRepoException.GITHUB_REPO_NOT_FOUND));

GithubRepo githubRepo = githubRepoRepository.findById(repositoryId).orElseThrow(() ->
new GeneralException(GithubRepoException.NOT_FOUND_GITHUBREPO)
);
User user = userQuery.findById(userId);

if (!userId.equals(githubRepo.getUser().getId())) {
throw new GeneralException(GithubRepoException.UNAUTHORIZED_GITHUBREPO_ACCESS);
if (user.notHasGithubRepo(githubRepo)) {
throw new GeneralException(GithubRepoException.UNAUTHORIZED_GITHUB_REPO_ACCESS);
}

return githubRepo;
}

public GithubRepo findByRepositoryId(long repositoryId) {
public GithubRepo findById(long repositoryId) {

return githubRepoRepository.findById(repositoryId)
.orElseThrow(() -> new GeneralException(GithubRepoException.NOT_FOUND_GITHUBREPO));
.orElseThrow(() -> new GeneralException(GithubRepoException.GITHUB_REPO_NOT_FOUND));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public GithubRepoCreateResponse createGithubRepo(Long userId, GithubRepoCreateRe
private void validateCreateRequest(GithubRepoCreateRequest request) {
UrlUtil.validateGitHubUrl(request.url());
if (request.emails().isEmpty()) {
throw new GeneralException(GithubRepoException.NOT_FOUND_GITHUBEMAIL);
throw new GeneralException(GithubRepoException.CONTRIBUTOR_EMAIL_NOT_FOUND);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,17 @@ public class NotificationService {
public void updateNotificationAgreement(long userId, long repositoryId,
NotificationAgreementUpdateRequest request) {

GithubRepo githubRepo = githubRepoQuery.findByRepositoryId(repositoryId);
GithubRepo githubRepo = githubRepoQuery.findById(repositoryId);

NotificationType notificationType = NotificationType.valueOf(request.type());
NotificationAgreement notificationAgreement = notificationAgreementQuery
.findByGithubRepoAndType(githubRepo, notificationType);

// 사용자가 자신의 github repo에 접근한 것이 맞는 지 검증
User user = userQuery.findById(userId);
if (!user.hasGithubRepo(repositoryId)) {
throw new GeneralException(GithubRepoException.UNAUTHORIZED_GITHUBREPO_ACCESS);

if (user.notHasGithubRepo(githubRepo)) {
throw new GeneralException(GithubRepoException.UNAUTHORIZED_GITHUB_REPO_ACCESS);
}

if (request.isAgree()) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/specialwarriors/conal/user/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ public User(int githubId, String username, String avatarUrl) {
this.avatarUrl = avatarUrl;
}

public boolean hasGithubRepo(long repositoryId) {
public boolean notHasGithubRepo(GithubRepo githubRepo) {

return githubRepos.stream().anyMatch(repo -> repo.getId() == repositoryId);
return !githubRepos.contains(githubRepo);
}

public void addGithubRepo(GithubRepo githubRepo) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void openVote(long repoId) {
final Date issuedAt = new Date();
final long expirationMillis = 604800000;

GithubRepo githubRepo = githubRepoQuery.findByRepositoryId(repoId);
GithubRepo githubRepo = githubRepoQuery.findById(repoId);
List<Contributor> contributors = githubRepo.getContributors();

String[] userTokens = contributors.stream().map(Contributor::getEmail)
Expand All @@ -62,7 +62,7 @@ public List<String> findVoteTargetEmails(long repoId, String userToken) {
throw new GeneralException(VoteException.UNAUTHORIZED_VOTE_ACCESS);
}

GithubRepo githubRepo = githubRepoQuery.findByRepositoryId(repoId);
GithubRepo githubRepo = githubRepoQuery.findById(repoId);

return githubRepo.getContributors().stream()
.map(Contributor::getEmail)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.specialwarriors.conal.github_repo.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import com.specialwarriors.conal.common.config.QuerydslConfig;
import com.specialwarriors.conal.common.exception.GeneralException;
import com.specialwarriors.conal.github_repo.domain.GithubRepo;
import com.specialwarriors.conal.github_repo.exception.GithubRepoException;
import com.specialwarriors.conal.github_repo.repository.GithubRepoRepository;
import com.specialwarriors.conal.user.repository.UserRepository;
import com.specialwarriors.conal.user.service.UserQuery;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;

@ActiveProfiles("test")
@DataJpaTest
@Import(QuerydslConfig.class)
class GithubRepoQueryTest {

@Autowired
private UserRepository userRepository;

@Autowired
private GithubRepoRepository githubRepoRepository;

private GithubRepoQuery githubRepoQuery;

@BeforeEach
void init() {
UserQuery userQuery = new UserQuery(userRepository);
githubRepoQuery = new GithubRepoQuery(githubRepoRepository, userQuery);
}

@Nested
@DisplayName("ID로 Github Repository를 조회할 때 ")
@Sql(scripts = "/sql/github_repo/service/find_by_repository_id_test_setup.sql",
executionPhase = ExecutionPhase.BEFORE_TEST_CLASS)
class FindByIdTest {

@DisplayName("성공한다.")
@Test
public void success() {
// given
long repositoryId = 1L;

// when
GithubRepo githubRepo = githubRepoQuery.findById(repositoryId);

// then
assertThat(githubRepo.getId()).isEqualTo(repositoryId);
}

@DisplayName("존재하지 않는 Repository일 경우 예외가 발생한다.")
@Test
public void githubRepoNotFound() {
// given
long repositoryId = 2L;

// when

// then
assertThatThrownBy(() -> githubRepoQuery.findById(repositoryId))
.isInstanceOf(GeneralException.class)
.extracting("exception")
.isEqualTo(GithubRepoException.GITHUB_REPO_NOT_FOUND);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
insert into users(id, github_id, username, avatar_url)
values (1, 1, 'username', 'avatar_url');

insert into github_repos(id, name, url, end_date, user_id)
values (1, 'repo', 'repo_url', now(), 1);