Skip to content

Commit

Permalink
Google, Apple 인증 구현 ~ 게시물 업로드 (#69)
Browse files Browse the repository at this point in the history
* 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)
  • Loading branch information
rookedsysc authored May 3, 2024
1 parent 85707d9 commit 9bd3e15
Show file tree
Hide file tree
Showing 121 changed files with 4,448 additions and 263 deletions.
Binary file removed .DS_Store
Binary file not shown.
62 changes: 34 additions & 28 deletions .github/workflows/cd-wordflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ name: CD with Gradle
# main 브랜치로 push되거나 pull request가 발생했을 때 워크플로우를 실행
on:
push:
branches: [ "main" ]
branches: [ "develop" ]
pull_request:
branches: [ "main" ]
branches: [ "develop" ]

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

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

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

# 다섯 번째 단계: Docker 이미지를 빌드하고 Docker 저장소에 푸시
- name: Docker build & push to docker repo
# Jar 파일 Copy
- name: Copy Jar
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -f Dockerfile -t ${{ secrets.DOCKER_REPO }}/directors-dev .
docker push ${{ secrets.DOCKER_REPO }}/directors-dev
# 실행주체: GitHub Actions > GitHub Infra // End
cp ./build/libs/*.jar ./deploy/
cp ./appspec.yml ./deploy/
cp -r ./scripts ./deploy/
# 여섯 번째 단계: SSH를 사용하여 서버에 배포
- name: Deploy to server
uses: appleboy/ssh-action@master
- name: Deliver to AWS S3
uses: aws-actions/configure-aws-credentials@v1
with:
host: ${{ secrets.HOST }}
username: ubuntu
key: ${{ secrets.KEY }}
envs: GITHUB_SHA
script: |
sudo docker rm -f $(docker ps -qa)
sudo docker pull ${{ secrets.DOCKER_REPO }}/directors-dev
docker-compose up -d
docker image prune -f
aws-region: ap-southeast-2
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: S3에 업로드
run: aws deploy push --application-name ${{ secrets.AWS_CODE_DEPLOY_APPLICATION }} --ignore-hidden-files --s3-location s3://gamemuncheol-s3/deploy.zip --source ./deploy
- name: EC2에 배포
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
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
**.DS_Store

### STS ###
.apt_generated
Expand Down Expand Up @@ -38,3 +39,13 @@ out/

### Security ###
/src/main/resources/application.yaml
AuthKey_P2J7JVJRGF.p8
/src/main/resources/keystore.p12
/src/test/resources/application.yaml
src/main/resources/lol_scrapers.py
src/main/resources/client_secrets.json

### Video ###
src/main/resources/static/video/**


20 changes: 20 additions & 0 deletions appspec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
version: 0.0
os: linux

files:
- source: /
destination: /home/ubuntu/spring-github-action
overwrite: yes

permissions:
- object: /
owner: ubuntu
group: ubuntu

hooks:
AfterInstall:
- location: scripts/stop.sh
timeout: 60
ApplicationStart:
- location: scripts/start.sh
timeout: 60
36 changes: 34 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,60 @@ dependencies {
implementation 'javax.xml.bind:jaxb-api:2.3.1' // xml 에러 방지
// Swagger end

// aws s3를 위한 설정 - start
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
// aws s3를 위한 설정 - end


// spring security start
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.projectlombok:lombok:1.18.30'
testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' // oauth2
implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5'
implementation 'com.auth0:jwks-rsa:0.22.1' // apple oauth
implementation 'com.auth0:java-jwt:4.4.0' // apple oauth
// spring security end


// Process Executor
implementation 'org.zeroturnaround:zt-exec:1.12'
// Process Executor

// prometheus + grafana
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus'

// JPA start
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.mysql:mysql-connector-j'
implementation 'org.springframework.boot:spring-boot-starter-data-redis' // redis
// JPA end

// Test를 위한 H2database
runtimeOnly 'com.h2database:h2'
// Test를 위한 H2database

// youtube
implementation 'com.google.apis:google-api-services-youtube:v3-rev222-1.25.0'
implementation 'com.google.oauth-client:google-oauth-client-jetty:1.35.0'
// youtube

// Apple Oauth 관련 라이브러리 Start
implementation 'com.google.code.gson:gson:2.10.1'
// Apple Oauth 관련 라이브러리 End

implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
useJUnitPlatform()
}
}
17 changes: 17 additions & 0 deletions scripts/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

ROOT_PATH="/home/ubuntu/spring-github-action"
JAR="$ROOT_PATH/gamemoonchul-0.0.1-SNAPSHOT.jar"

APP_LOG="$ROOT_PATH/application.log"
ERROR_LOG="$ROOT_PATH/error.log"
START_LOG="$ROOT_PATH/start.log"

NOW=$(date +%c)


echo "[$NOW] > $JAR 실행" >> $START_LOG
nohup java -jar $JAR > $APP_LOG 2> $ERROR_LOG &

SERVICE_PID=$(pgrep -f $JAR)
echo "[$NOW] > 서비스 PID: $SERVICE_PID" >> $START_LOG
14 changes: 14 additions & 0 deletions scripts/stop.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

ROOT_PATH="/home/ubuntu/spring-github-action"
JAR="$ROOT_PATH/gamemoonchul-0.0.1-SNAPSHOT.jar"
STOP_LOG="$ROOT_PATH/stop.log"
SERVICE_PID=$(pgrep -f $JAR) # 실행중인 Spring 서버의 PID

if [ -z "$SERVICE_PID" ]; then
echo "서비스 NotFound" >> $STOP_LOG
else
echo "서비스 종료 " >> $STOP_LOG
kill "$SERVICE_PID"
# kill -9 $SERVICE_PID # 강제 종료를 하고 싶다면 이 명령어 사용
fi
40 changes: 40 additions & 0 deletions src/main/java/com/gamemoonchul/application/AppleService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.gamemoonchul.application;

import com.gamemoonchul.common.exception.ApiException;
import com.gamemoonchul.config.apple.AppleIDTokenValidator;
import com.gamemoonchul.config.apple.entities.AppleCredential;
import com.gamemoonchul.config.apple.enums.AppleTokenStatus;
import com.gamemoonchul.config.jwt.TokenDto;
import com.gamemoonchul.config.jwt.TokenHelper;
import com.gamemoonchul.config.oauth.user.AppleOAuth2UserInfo;
import com.gamemoonchul.domain.entity.Member;
import com.gamemoonchul.domain.converter.MemberConverter;
import com.gamemoonchul.infrastructure.web.dto.AppleSignUpRequestDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;


@Service
@RequiredArgsConstructor
public class AppleService {
private final AppleIDTokenValidator appleIDTokenValidator;
private final MemberService memberService;
private final TokenHelper tokenHelper;

public AppleCredential validateRequest(AppleSignUpRequestDto signUpRequest) {
AppleCredential appleUserInfo = appleIDTokenValidator.extractAppleUserinfoFromIDToken(signUpRequest.getIdentityToken());
if(signUpRequest.getName() == null || signUpRequest.getName().isEmpty()) {
throw new ApiException(AppleTokenStatus.INVALID_SIGNUP_FORM);
}
appleUserInfo.setName(signUpRequest.getName());
return appleUserInfo;
}

public TokenDto signInOrUp(AppleCredential credential) {
Member member = MemberConverter.toEntity(credential);
AppleOAuth2UserInfo userInfo = new AppleOAuth2UserInfo(credential);
memberService.signInOrUp(member);
TokenDto token = tokenHelper.generateToken(userInfo);
return token;
}
}
28 changes: 28 additions & 0 deletions src/main/java/com/gamemoonchul/application/MatchGameService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.gamemoonchul.application;

import com.gamemoonchul.domain.converter.riot.MatchGameConverter;
import com.gamemoonchul.domain.entity.riot.MatchGame;
import com.gamemoonchul.domain.model.vo.riot.MatchRecord;
import com.gamemoonchul.infrastructure.repository.MatchGameRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
@Slf4j
@RequiredArgsConstructor
public class MatchGameService {
private final MatchGameRepository matchGameRepository;
private final MatchGameConverter matchConverter;

public Optional<MatchGame> findByGameId(String gameId) {
return matchGameRepository.findByGameId(gameId);
}

public MatchGame save(MatchRecord vo) {
MatchGame matchGame = matchConverter.toMatchGame(vo);
return matchGameRepository.save(matchGame);
}
}
35 changes: 35 additions & 0 deletions src/main/java/com/gamemoonchul/application/MatchUserService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.gamemoonchul.application;

import com.gamemoonchul.domain.converter.riot.MatchUserConverter;
import com.gamemoonchul.domain.entity.riot.MatchGame;
import com.gamemoonchul.domain.entity.riot.MatchUser;
import com.gamemoonchul.domain.model.vo.riot.ParticipantRecord;
import com.gamemoonchul.infrastructure.repository.MatchUserRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
@Transactional
@RequiredArgsConstructor
public class MatchUserService {
private final MatchUserRepository matchUserRepository;
private final MatchUserConverter matchUserConverter;

public List<MatchUser> saveAll(List<ParticipantRecord> participants, MatchGame matchGame) {
List<MatchUser> matchUsers = new ArrayList<>();
participants.stream().map(
participant -> matchUserConverter.toEntities(participant, matchGame)
).forEach(matchUser -> {
matchUsers.add(matchUserRepository.save(matchUser));
});
return matchUsers;
}

public List<MatchUser> findByMatchGameId(MatchGame matchGame) {
return matchUserRepository.findByMatchGame(matchGame);
}
}
Loading

0 comments on commit 9bd3e15

Please sign in to comment.