Skip to content

Commit 9bd3e15

Browse files
authored
Google, Apple 인증 구현 ~ 게시물 업로드 (#69)
* Server Https 설정 및 도메인 연결 (#18) * Google Auth 구현 로그인 성공 후 Query String으로 accessToken, refreshToken return (#15) * config Jpa, Spring Security Oauth Client Dependencry 추가 * modify Spring Security Config 수정 * feat Google Oauth 기본적인 기능 구현, 로그인 성공시 쿼리 스트링으로 accessToken refreshToken 전송 * refactor 폴더 구조 Oauth 부분을 infrastructure -> config으로 변경 및 DB 저장하는 기능 구현 * feat Keystore 생성 프로젝트 최상단에서 keytool -genkey -alias spring -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 4000 명령 사용 * feat application-dev.yaml 생성 * Front에서 인증받은 identityToken으로 Jwt 토큰 검증 (#21) * feat Apple Token 인증로직 구현 * feat Member Repository에 저장 및 Token 발급 로직 추가 * remove ApiTest 삭제 * modify AppleTokenStatus 값 수정 * GlobalExceptionHandler를 통한 Security Redirect 로직 우회 (#23) * feat Request Response 출력을 위한 Filter 추가 * feat Apple SignUp Service 개발 Token을 받아와서 검증하고 User 있는지 체크 후 Repository에 저장 * modify Status 이름이 전송되지 않은 경우 발생시킬 메시지 작성 * feat 알 수 없는 에러 발생시에 Redirect를 방지하기 위해서 GlobalExceptionHandler 전송 * feat Apple Service에서 MemberRepository로 바로 접근하지 않게 수정 * refactor Test 코드 작성 용이를 위해 Request Validation과 로그인 로직을 분리 * config 테스트를 위한 H2database Dependency 추가 * refactor Test를 위해서 AppleUserInfo 및 MemberRepository 리팩터링 * test AppleService 테스트 추가 * Https 설정 gitignore 추가 (#24) * 파이썬으로 전적 검색 사이트 스크랩핑하는 코드 작성 및 Spring에서 실행 후 결과 리턴 받기 (#26) * config Dependency 추가, ProcessExecutor java에서 python 사용하기 위해서 추가 * feat Search Controller, Service, Status, vo (model) 개발 * test Search Service 검색어 정상 동작/실패 테스트 코드 작성 * modify Search Controller -> 인증 후 사용가능하게 변경 * 전적 검색 Redis Caching 구현 (#27) * config Spring Data Jpa Dependency 추가 * feat Redis Config 추가 * feat RedisCachedGame Entity, Repository, Converter 생성 * refactor Searched Model VO -> DTO 변경 * feat Redis Caching Logic 추가 * test Redis Caching 잘 되는지 테스트 * Controller 단에서 발생하는 에러가 있을 경우, 리다이렉트 대신 해당하는 에러 메시지 정확히 출력 (#28) * feat CustomEntryPoint 설정해서 Redirect 방지 * fix PathVariable로 받아야할 데이터 RequestParam으로 받고 잇던 것 수정 * Youtube 업로드 구현 (#30) * config youtube upload를 위한 dependency 추가 * feat Youtube Upload 기능 구현 * feat Video 업로드 기능 구현 * feat Video 업로드시 로컬에 저장 후 Youtube로 재업로드 하는 방식으로 수정 feat YoutubeStatus 개발 * modify 전적검색 게임 id검색해서 오는 정보에서 그냥 날짜 승패 소환사명 챔피언명 보여주고 선택 (#32) * feat 게임 아이디로 게임 검색 & 유저 riot id로 유저 검색 개발 * refactor Lolsearch Service -> Infrastructure의 Adapter로 변경 * refactor Entity Package 추가 (Riot Entity Package 따로 분리 필요할 것 같아서) * modify 기존에 검색하던 방식 삭제 * modify 게임아이디 이상할 경우 Adapter에서 Not Found 발생 test 해당 사항에 대해서 TestCode 추가 * feat VO 객체 Test를 위한 Dummy Class 작성 * feat MatchGame, MatchUser Entity 작성, Converter 작성 및 Test 코드 작성 * feat MatchGame/UserRepository 작성, MatchGameService, Test 작성 * feat MatchGameResponse DTO, Test 작성 Entity -> Dto 변환 * fix MatchUser add시 NullPointException 방지 * feat MatchUserRepository, Service, TestCode 작성 * feat MatchGameService 개발 및 Test 코드 작성 * modify MatchResponse에 GameId 추가 * feat BoardService, Test 개발 * modify Game Creation Date -> UTC 형식으로 변경 * feat BoardApiController SearchMatch API 작성 * refactor Dummy 데이터 Test 쪽으로 변경 및 VO 전부 Record로 수정 * S3 동영상 업로드 구현 (#34) * config S3 Upload를 위한 Dependency 추가 * modify Local에 영상 업로드하는 방식 삭제 * feat S3 업로드 개발 * S3 파일 추가, 삭제, 확인 구현 및 Test 코드 작성 (#36) * config S3 Upload를 위한 Dependency 추가 * modify Local에 영상 업로드하는 방식 삭제 * feat S3 업로드 개발 * feat 파일 존재하는지 확인하는 코드 작성 및 Test 코드 작성 * test S3Service 파일 업로드 테스트 * feat S3 파일 삭제 * test MethodOrder를 활용해서 S3 업로드, 삭제, 조회 테스트 코드 수정 * Apple Oauth nonce 추가 (#38) * 유저 로그인시 issuer, identity 저장 (#39) * modify Member, MatchGame, MatchUser 변경 Member Issuer nullable false MatchGame MatchMember Dummy Test로 이동 MatchGame MySQL ID 생성 MatchGame, MatchUser 연관관계 설정 방식 Riot에서 발급받은 ID로 고정 * modify MemberConverter에서 AppleUser sub값 받아오게 변경 * modify MemberConverter Google Identifier, Provider 입력 * modify signIn 또는 unlink하는 방식 identifier까지 입력해야 하는 방식으로 변경 * fix search match api uri 변경 #42 * fix 전적 검색 KR_ 안붙여줘서 발생할 수 있는 버그 수정 #25 * 닉네임 변경 기능 추가 및 Issuer, Identifier 검증 로직 추가 * modify Apple Oauth User Info 공통화, Token에 Identifier, Provider 추가 * feat MemberSession 접근해서 Member 닉네임 변경하는 로직개발(MemberSession은 SessionResolver가 넣는 방식) * fix Random으로 생성된 Nickname이 varchar(30) 넘어가던 버그 수정 * modify Apple Oauth Provider, Identifier, Email 검증 및 회원가입으로 Test 코드 수정 * test nickname 변경 및 signInOrUp 메서드 Test 코드 작성 * fix 전적검색시 제대로 검색 안되는 Bug Fix #25 Adapter에 "KR_" 삭제 Controller에 붙여서 관련된 테스트 코드 전체 수정 * modify 챔피이름 한국어로 나가도록 수정 #46 * Jwt 토큰 Renew 로직 개발 tokenClaims에 accessToken인지 refreshToken인지 구분하는 로직 추가 test 코드 작성 * Github Actions를 이용한 CI/CD 도입 (#50) * deploy Project Build가 되는지 까지만 테스트 * deploy S3 upload 테스트 * deploy CodeDeploy를 활용해서 CICD 테스트 * fix Region, Secrets 수정 * fix AWS_CODE_DEPLOY_APPLICATION 수정 * fix appspec.yml was not found 에러 수정 * fix cp: cannot stat 'cp': No such file or directory 에러 수정 * fix /home/runner/work/gamemuncheol-api/gamemuncheol-api/springboot-intro-build.zip/appspec.yml was not found Error: Process completed with exit code 255. * fix /home/runner/work/gamemuncheol-api/gamemuncheol-api/springboot-intro-build.zip/appspec.yml was not found Error: Process completed with exit code 255. * Code Deploy Error Fix (#51) * fix CodeDeploy Error Msg Detail : The overall deployment failed because too many individual instances failed deployment, too few healthy instances are available for deployment, or some instances in your deployment group are experiencing problems. * fix Typo * fix Unable to access jarfile /home/ubuntu/spring-github-action/application.jar 에러 수정 * fix Error: Unable to access jarfile /home/ubuntu/spring-github-action/home/ubuntu/spring-github-action/gamemoonchul-0.0.1-SNAPSHOT.jar Error Fix * fix stop.log > Service Not Found Fix * fix java.lang.IllegalStateException: Could not load store from 'classpath:keystore-aws.p12' Error Fix * fix GlobalExceptionHandler 삭제하고 RuntimeException.class 처리하는 로직 ApiExceptionHandler로 이동 (#53) * feat member/me API 개발 #54 * test Member Api Controller 통합 테스트 작성 (#55) * Member Entity 변경 (개인정보 처리방침 동의 컬럼 추가) (#58) * modify Privacy Agreed Column 추가, Converter, Dto 수정 * feat Member Privacy Not Agreed Role 추가 /privacy/agree API 추가 Spring Security Config, TokenProvider 등 수정 * fix Test 코드 Filter에서 에러 발생해서 403 발생하는 것 확인 * modify Privacy API User 권한도 접근 가능하게 변경 * modify --warning-mode all 옵션 추가 (#60) * feat Privacy API Controller 작성 (#59) * modify Privacy Agreed Column 추가, Converter, Dto 수정 * feat Member Privacy Not Agreed Role 추가 /privacy/agree API 추가 Spring Security Config, TokenProvider 등 수정 * fix Test 코드 Filter에서 에러 발생해서 403 발생하는 것 확인 * modify Privacy API User 권한도 접근 가능하게 변경 * feat Privacy API Controller 작성, BaseIntegrationTest에서 Transactional 옵션 제거 * modify workflow --warning-mode all 추가 #51 * config Test Junit Dependency 추가 참조 이슈 : spring-io/initializr#1476 * modify Test -i 옵션으로 Test 실패 원인 파악 시도 #51 * modify Privacy Controller 삭제 및 MatchUserService 이동 * fix 업로드 된 URL이 정확한 S3 URL에 매칭되지 않는 문제 수정 (#63) * 사진 업로드 기능 구현 (#67) * feat Image Upload 개발 * test ImageFile Upload 테스트 * refactor LolSearchAdapter 이름 변경 및 BoardService간 의존관계 역전 (#65) * refactor LolSearchAdapter 이름 변경 및 BoardService간 의존관계 역전 * modify RiotApiPort 구현체 Adapter로 네이밍 수정 * 게시판 업로드 추가/삭제 구현 (#68) * feat PostEntity, Converter, Dto, Service, Repository modify CamelCase로 되어있던 Column 필드들 수정 * test PostService Test 작성 * refactor BoardService -> RiotService 변경 및 Board, Riot Service 분리 * feat Post Delete 개발 및 Test * fix MemberSession Parameter로 넘어가지 않게 수정 * feat Post 업로드, 삭제 API 구현 * Actuator, Prometheus Dependency 추가 및 SecurityConfig 수정 (#72) * config Actuator, Prometeus Dependency 추가 * feat SecurityConfig 수정 * 이미지, 비디오 업로드 API Riot -> Post로 이동 (#74)
1 parent 85707d9 commit 9bd3e15

File tree

121 files changed

+4448
-263
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+4448
-263
lines changed

.DS_Store

-6 KB
Binary file not shown.

.github/workflows/cd-wordflow.yml

+34-28
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ name: CD with Gradle
44
# main 브랜치로 push되거나 pull request가 발생했을 때 워크플로우를 실행
55
on:
66
push:
7-
branches: [ "main" ]
7+
branches: [ "develop" ]
88
pull_request:
9-
branches: [ "main" ]
9+
branches: [ "develop" ]
1010

1111
# 워크플로우에서는 저장소 내용을 읽을 수 있는 권한만 설정
1212
permissions:
@@ -30,37 +30,43 @@ jobs:
3030
distribution: "adopt"
3131

3232
# 세 번째 단계: GitHub secrets에서 데이터를 가져와 application.properties 파일 생성
33-
# - name: Make application.properties
34-
# run: |
35-
# cd ./src/main/resources
36-
# touch ./application.properties
37-
# echo "${{ secrets.PROPERTIES }}" > ./application.properties
38-
# shell: bash
33+
- name: Make application.yaml
34+
run: |
35+
cd ./src/main/resources
36+
touch ./application.yaml
37+
echo "${{ secrets.APPLICATION_YAML }}" > ./application.yaml
38+
echo "${{ secrets.AWS_KEYSTORE }}" | base64 --decode > ./keystore-aws.p12
39+
cd ../../test/resources
40+
touch ./application.yaml
41+
echo "${{ secrets.APPLICATION_TEST_YAML }}" > ./application.yaml
42+
shell: bash
3943

40-
# 네 번째 단계: Gradle을 사용해 프로젝트 빌드, 테스트는 제외
44+
# 네 번째 단계: Gradle을 사용해 프로젝트
4145
- name: Build with Gradle
4246
run: |
4347
chmod +x ./gradlew
44-
./gradlew clean build -x test
48+
./gradlew test -i
49+
./gradlew clean build --warning-mode all
50+
51+
52+
# 전송할 파일을 담을 디렉토리 생성
53+
- name: Make Directory for deliver
54+
run: mkdir deploy
4555

46-
# 다섯 번째 단계: Docker 이미지를 빌드하고 Docker 저장소에 푸시
47-
- name: Docker build & push to docker repo
56+
# Jar 파일 Copy
57+
- name: Copy Jar
4858
run: |
49-
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
50-
docker build -f Dockerfile -t ${{ secrets.DOCKER_REPO }}/directors-dev .
51-
docker push ${{ secrets.DOCKER_REPO }}/directors-dev
52-
# 실행주체: GitHub Actions > GitHub Infra // End
59+
cp ./build/libs/*.jar ./deploy/
60+
cp ./appspec.yml ./deploy/
61+
cp -r ./scripts ./deploy/
5362
54-
# 여섯 번째 단계: SSH를 사용하여 서버에 배포
55-
- name: Deploy to server
56-
uses: appleboy/ssh-action@master
63+
- name: Deliver to AWS S3
64+
uses: aws-actions/configure-aws-credentials@v1
5765
with:
58-
host: ${{ secrets.HOST }}
59-
username: ubuntu
60-
key: ${{ secrets.KEY }}
61-
envs: GITHUB_SHA
62-
script: |
63-
sudo docker rm -f $(docker ps -qa)
64-
sudo docker pull ${{ secrets.DOCKER_REPO }}/directors-dev
65-
docker-compose up -d
66-
docker image prune -f
66+
aws-region: ap-southeast-2
67+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
68+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
69+
- name: S3에 업로드
70+
run: aws deploy push --application-name ${{ secrets.AWS_CODE_DEPLOY_APPLICATION }} --ignore-hidden-files --s3-location s3://gamemuncheol-s3/deploy.zip --source ./deploy
71+
- name: EC2에 배포
72+
run: aws deploy create-deployment --application-name ${{ secrets.AWS_CODE_DEPLOY_APPLICATION }} --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name ${{ secrets.AWS_CODE_DEPLOY_APPLICATION }} --s3-location bucket=gamemuncheol-s3,key=deploy.zip,bundleType=zip

.gitignore

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ build/
44
!gradle/wrapper/gradle-wrapper.jar
55
!**/src/main/**/build/
66
!**/src/test/**/build/
7+
**.DS_Store
78

89
### STS ###
910
.apt_generated
@@ -38,3 +39,13 @@ out/
3839

3940
### Security ###
4041
/src/main/resources/application.yaml
42+
AuthKey_P2J7JVJRGF.p8
43+
/src/main/resources/keystore.p12
44+
/src/test/resources/application.yaml
45+
src/main/resources/lol_scrapers.py
46+
src/main/resources/client_secrets.json
47+
48+
### Video ###
49+
src/main/resources/static/video/**
50+
51+

appspec.yml

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
version: 0.0
2+
os: linux
3+
4+
files:
5+
- source: /
6+
destination: /home/ubuntu/spring-github-action
7+
overwrite: yes
8+
9+
permissions:
10+
- object: /
11+
owner: ubuntu
12+
group: ubuntu
13+
14+
hooks:
15+
AfterInstall:
16+
- location: scripts/stop.sh
17+
timeout: 60
18+
ApplicationStart:
19+
- location: scripts/start.sh
20+
timeout: 60

build.gradle

+34-2
Original file line numberDiff line numberDiff line change
@@ -27,28 +27,60 @@ dependencies {
2727
implementation 'javax.xml.bind:jaxb-api:2.3.1' // xml 에러 방지
2828
// Swagger end
2929

30+
// aws s3를 위한 설정 - start
31+
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
32+
// aws s3를 위한 설정 - end
33+
34+
3035
// spring security start
3136
implementation 'org.springframework.boot:spring-boot-starter-security'
32-
testImplementation 'org.springframework.security:spring-security-test'
37+
implementation 'org.projectlombok:lombok:1.18.30'
38+
testImplementation 'org.springframework.security:spring-security-test'
3339
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' // oauth2
3440
implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5'
3541
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5'
3642
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5'
43+
implementation 'com.auth0:jwks-rsa:0.22.1' // apple oauth
44+
implementation 'com.auth0:java-jwt:4.4.0' // apple oauth
3745
// spring security end
3846

47+
48+
// Process Executor
49+
implementation 'org.zeroturnaround:zt-exec:1.12'
50+
// Process Executor
51+
52+
// prometheus + grafana
53+
implementation 'org.springframework.boot:spring-boot-starter-actuator'
54+
implementation 'io.micrometer:micrometer-registry-prometheus'
55+
3956
// JPA start
4057
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
4158
runtimeOnly 'com.mysql:mysql-connector-j'
59+
implementation 'org.springframework.boot:spring-boot-starter-data-redis' // redis
4260
// JPA end
4361

62+
// Test를 위한 H2database
63+
runtimeOnly 'com.h2database:h2'
64+
// Test를 위한 H2database
65+
66+
// youtube
67+
implementation 'com.google.apis:google-api-services-youtube:v3-rev222-1.25.0'
68+
implementation 'com.google.oauth-client:google-oauth-client-jetty:1.35.0'
69+
// youtube
70+
71+
// Apple Oauth 관련 라이브러리 Start
72+
implementation 'com.google.code.gson:gson:2.10.1'
73+
// Apple Oauth 관련 라이브러리 End
74+
4475
implementation 'org.springframework.boot:spring-boot-starter-web'
4576
compileOnly 'org.projectlombok:lombok'
4677
developmentOnly 'org.springframework.boot:spring-boot-devtools'
4778
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
4879
annotationProcessor 'org.projectlombok:lombok'
4980
testImplementation 'org.springframework.boot:spring-boot-starter-test'
81+
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
5082
}
5183

5284
tasks.named('test') {
5385
useJUnitPlatform()
54-
}
86+
}

scripts/start.sh

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/bash
2+
3+
ROOT_PATH="/home/ubuntu/spring-github-action"
4+
JAR="$ROOT_PATH/gamemoonchul-0.0.1-SNAPSHOT.jar"
5+
6+
APP_LOG="$ROOT_PATH/application.log"
7+
ERROR_LOG="$ROOT_PATH/error.log"
8+
START_LOG="$ROOT_PATH/start.log"
9+
10+
NOW=$(date +%c)
11+
12+
13+
echo "[$NOW] > $JAR 실행" >> $START_LOG
14+
nohup java -jar $JAR > $APP_LOG 2> $ERROR_LOG &
15+
16+
SERVICE_PID=$(pgrep -f $JAR)
17+
echo "[$NOW] > 서비스 PID: $SERVICE_PID" >> $START_LOG

scripts/stop.sh

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
3+
ROOT_PATH="/home/ubuntu/spring-github-action"
4+
JAR="$ROOT_PATH/gamemoonchul-0.0.1-SNAPSHOT.jar"
5+
STOP_LOG="$ROOT_PATH/stop.log"
6+
SERVICE_PID=$(pgrep -f $JAR) # 실행중인 Spring 서버의 PID
7+
8+
if [ -z "$SERVICE_PID" ]; then
9+
echo "서비스 NotFound" >> $STOP_LOG
10+
else
11+
echo "서비스 종료 " >> $STOP_LOG
12+
kill "$SERVICE_PID"
13+
# kill -9 $SERVICE_PID # 강제 종료를 하고 싶다면 이 명령어 사용
14+
fi
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.gamemoonchul.application;
2+
3+
import com.gamemoonchul.common.exception.ApiException;
4+
import com.gamemoonchul.config.apple.AppleIDTokenValidator;
5+
import com.gamemoonchul.config.apple.entities.AppleCredential;
6+
import com.gamemoonchul.config.apple.enums.AppleTokenStatus;
7+
import com.gamemoonchul.config.jwt.TokenDto;
8+
import com.gamemoonchul.config.jwt.TokenHelper;
9+
import com.gamemoonchul.config.oauth.user.AppleOAuth2UserInfo;
10+
import com.gamemoonchul.domain.entity.Member;
11+
import com.gamemoonchul.domain.converter.MemberConverter;
12+
import com.gamemoonchul.infrastructure.web.dto.AppleSignUpRequestDto;
13+
import lombok.RequiredArgsConstructor;
14+
import org.springframework.stereotype.Service;
15+
16+
17+
@Service
18+
@RequiredArgsConstructor
19+
public class AppleService {
20+
private final AppleIDTokenValidator appleIDTokenValidator;
21+
private final MemberService memberService;
22+
private final TokenHelper tokenHelper;
23+
24+
public AppleCredential validateRequest(AppleSignUpRequestDto signUpRequest) {
25+
AppleCredential appleUserInfo = appleIDTokenValidator.extractAppleUserinfoFromIDToken(signUpRequest.getIdentityToken());
26+
if(signUpRequest.getName() == null || signUpRequest.getName().isEmpty()) {
27+
throw new ApiException(AppleTokenStatus.INVALID_SIGNUP_FORM);
28+
}
29+
appleUserInfo.setName(signUpRequest.getName());
30+
return appleUserInfo;
31+
}
32+
33+
public TokenDto signInOrUp(AppleCredential credential) {
34+
Member member = MemberConverter.toEntity(credential);
35+
AppleOAuth2UserInfo userInfo = new AppleOAuth2UserInfo(credential);
36+
memberService.signInOrUp(member);
37+
TokenDto token = tokenHelper.generateToken(userInfo);
38+
return token;
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.gamemoonchul.application;
2+
3+
import com.gamemoonchul.domain.converter.riot.MatchGameConverter;
4+
import com.gamemoonchul.domain.entity.riot.MatchGame;
5+
import com.gamemoonchul.domain.model.vo.riot.MatchRecord;
6+
import com.gamemoonchul.infrastructure.repository.MatchGameRepository;
7+
import lombok.RequiredArgsConstructor;
8+
import lombok.extern.slf4j.Slf4j;
9+
import org.springframework.stereotype.Service;
10+
11+
import java.util.Optional;
12+
13+
@Service
14+
@Slf4j
15+
@RequiredArgsConstructor
16+
public class MatchGameService {
17+
private final MatchGameRepository matchGameRepository;
18+
private final MatchGameConverter matchConverter;
19+
20+
public Optional<MatchGame> findByGameId(String gameId) {
21+
return matchGameRepository.findByGameId(gameId);
22+
}
23+
24+
public MatchGame save(MatchRecord vo) {
25+
MatchGame matchGame = matchConverter.toMatchGame(vo);
26+
return matchGameRepository.save(matchGame);
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.gamemoonchul.application;
2+
3+
import com.gamemoonchul.domain.converter.riot.MatchUserConverter;
4+
import com.gamemoonchul.domain.entity.riot.MatchGame;
5+
import com.gamemoonchul.domain.entity.riot.MatchUser;
6+
import com.gamemoonchul.domain.model.vo.riot.ParticipantRecord;
7+
import com.gamemoonchul.infrastructure.repository.MatchUserRepository;
8+
import jakarta.transaction.Transactional;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.stereotype.Service;
11+
12+
import java.util.ArrayList;
13+
import java.util.List;
14+
15+
@Service
16+
@Transactional
17+
@RequiredArgsConstructor
18+
public class MatchUserService {
19+
private final MatchUserRepository matchUserRepository;
20+
private final MatchUserConverter matchUserConverter;
21+
22+
public List<MatchUser> saveAll(List<ParticipantRecord> participants, MatchGame matchGame) {
23+
List<MatchUser> matchUsers = new ArrayList<>();
24+
participants.stream().map(
25+
participant -> matchUserConverter.toEntities(participant, matchGame)
26+
).forEach(matchUser -> {
27+
matchUsers.add(matchUserRepository.save(matchUser));
28+
});
29+
return matchUsers;
30+
}
31+
32+
public List<MatchUser> findByMatchGameId(MatchGame matchGame) {
33+
return matchUserRepository.findByMatchGame(matchGame);
34+
}
35+
}

0 commit comments

Comments
 (0)