Skip to content

Commit 027f83d

Browse files
committed
Merge branch 'dev' of https://github.com/Team-WSS/WSS-Server into dev
2 parents c878a1c + a100187 commit 027f83d

File tree

75 files changed

+896
-437
lines changed

Some content is hidden

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

75 files changed

+896
-437
lines changed

.github/workflows/AutoAssignAndReview.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ jobs:
99
- uses: hkusu/review-assign-action@v1
1010
with:
1111
assignees: ${{ github.actor }}
12-
reviewers: sansan20535, GiJungPark, EunjeongHeo
12+
reviewers: sansan20535, GiJungPark, ljy1348

.github/workflows/CD-develop.yml

Lines changed: 47 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -8,71 +8,56 @@ jobs:
88
deploy-ci-develop:
99
runs-on: ubuntu-22.04
1010

11-
steps:
12-
- name: Checkout
13-
uses: actions/checkout@v3
14-
15-
- name: Set up JDK 17
16-
uses: actions/setup-java@v3
17-
with:
18-
distribution: 'corretto'
19-
java-version: '17'
20-
21-
- name: Create application.yml and application-prod.yml
22-
run: |
23-
mkdir src/main/resources
24-
cd src/main/resources
25-
echo "${{ secrets.APPLICATION }}" > ./application.yml
26-
echo "${{ secrets.APPLICATION_PROD_DEVELOP }}" > ./application-prod.yml
27-
28-
- name: create-json
29-
id: create-json
30-
uses: jsdaniell/create-json@1.1.2
31-
with:
32-
name: "websoso-fcm.json"
33-
json: ${{ secrets.WEBSOSOFCM_JSON }}
34-
dir: 'src/main/resources/'
35-
36-
- name: Create apple login key file
37-
env:
38-
API_KEY: ${{ secrets.APPSTORE_API_KEY_ID_DEV }}
39-
run: |
40-
mkdir -p src/main/resources/static/apple
41-
echo "${{ secrets.APPLE_AUTH_KEY_DEV }}" > src/main/resources/static/apple/AuthKey_$API_KEY.p8
42-
43-
- name: Grant execute permission for gradlew
44-
run: chmod +x gradlew
45-
shell: bash
46-
47-
- name: Build with Gradle
48-
run: ./gradlew build -x test
49-
shell: bash
50-
51-
- name: Docker build Setting
52-
uses: docker/setup-buildx-action@v2.9.1
53-
54-
- name: Docker hub Login
55-
uses: docker/login-action@v2.2.0
56-
with:
57-
username: ${{ secrets.DOCKERHUB_USERNAME }}
58-
password: ${{ secrets.DOCKERHUB_ACCESSTOKEN }}
59-
60-
- name: Docker image Build and Push
61-
run: |
62-
docker build --platform linux/amd64 -t websoso/websoso-image .
63-
docker push websoso/websoso-image
11+
steps:
12+
- name: Checkout
13+
uses: actions/checkout@v3
14+
with:
15+
token: ${{ secrets.ACTION_TOKEN }}
16+
submodules: true
17+
fetch-depth: 0
18+
19+
- name: Update Submodule
20+
run: git submodule update --init --recursive --remote
21+
22+
- name: Set up JDK 17
23+
uses: actions/setup-java@v3
24+
with:
25+
distribution: 'corretto'
26+
java-version: '17'
27+
28+
- name: Grant execute permission for gradlew
29+
run: chmod +x gradlew
30+
shell: bash
31+
32+
- name: Build with Gradle
33+
run: ./gradlew build -x test -Dspring.profiles.active=dev
34+
shell: bash
35+
36+
- name: Docker build Setting
37+
uses: docker/setup-buildx-action@v2.9.1
38+
39+
- name: Docker hub Login
40+
uses: docker/login-action@v2.2.0
41+
with:
42+
username: ${{ secrets.DOCKERHUB_USERNAME }}
43+
password: ${{ secrets.DOCKERHUB_ACCESSTOKEN }}
44+
45+
- name: Docker image Build and Push
46+
run: |
47+
docker build --platform linux/amd64 -t websoso/websoso-image .
48+
docker push websoso/websoso-image
6449
6550
deploy-cd-develop:
6651
needs: deploy-ci-develop
6752
runs-on: ubuntu-22.04
6853

6954
steps:
70-
- name: Run Docker container
71-
uses: appleboy/ssh-action@master
72-
with:
73-
host: ${{ secrets.DEVELOP_SERVER_IP }}
74-
username: ${{ secrets.DEVELOP_SERVER_USER }}
75-
key: ${{ secrets.DEVELOP_SERVER_KEY }}
76-
script: |
77-
cd ~
78-
./deploy.sh
55+
- name: Run Docker container
56+
uses: appleboy/ssh-action@master
57+
with:
58+
host: ${{ secrets.DEVELOP_SERVER_IP }}
59+
username: ${{ secrets.DEVELOP_SERVER_USER }}
60+
key: ${{ secrets.DEVELOP_SERVER_KEY }}
61+
script: |
62+
cd ~
63+
./deploy.sh

.github/workflows/CI-develop.yml

Lines changed: 23 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# workflow 이름: CI-develop
2-
name: CI-devleop
2+
name: CI-develop
33

44
# trigger: dev 브랜치에 PR 발생할 때
55
on:
@@ -8,45 +8,27 @@ on:
88

99
# workflow의 세부 작업 단위 job 정의
1010
jobs:
11-
build-develop: # job 이름: build-develop
12-
runs-on: ubuntu-22.04 # VM의 OS 지정 (EC2와 동일 버전)
11+
build-develop:
12+
runs-on: ubuntu-22.04
1313

1414
steps:
15-
- name: Checkout
16-
uses: actions/checkout@v3
17-
18-
- name: Set up JDK 17
19-
uses: actions/setup-java@v3
20-
with:
21-
distribution: 'corretto'
22-
java-version: '17'
23-
24-
- name: Create application.yml and application-prod.yml and websoso-fcm.json
25-
run: |
26-
mkdir src/main/resources
27-
cd src/main/resources
28-
echo "${{ secrets.APPLICATION }}" > ./application.yml
29-
echo "${{ secrets.APPLICATION_PROD_DEVELOP }}" > ./application-prod.yml
30-
31-
- name: create-json
32-
id: create-json
33-
uses: jsdaniell/create-json@1.1.2
34-
with:
35-
name: "websoso-fcm.json"
36-
json: ${{ secrets.WEBSOSOFCM_JSON }}
37-
dir: 'src/main/resources/'
38-
39-
- name: Create apple login key file
40-
env:
41-
API_KEY: ${{ secrets.APPSTORE_API_KEY_ID_DEV }}
42-
run: |
43-
mkdir -p src/main/resources/static/apple
44-
echo "${{ secrets.APPLE_AUTH_KEY_DEV }}" > src/main/resources/static/apple/AuthKey_$API_KEY.p8
45-
46-
- name: Grant execute permission for gradlew
47-
run: chmod +x gradlew
48-
shell: bash
49-
50-
- name: Build with Gradle
51-
run: ./gradlew build -x test
52-
shell: bash
15+
- name: Checkout
16+
uses: actions/checkout@v3
17+
with:
18+
token: ${{ secrets.ACTION_TOKEN }}
19+
submodules: true
20+
fetch-depth: 0
21+
22+
- name: Set up JDK 17
23+
uses: actions/setup-java@v3
24+
with:
25+
distribution: 'corretto'
26+
java-version: '17'
27+
28+
- name: Grant execute permission for gradlew
29+
run: chmod +x gradlew
30+
shell: bash
31+
32+
- name: Build with Gradle
33+
run: ./gradlew build -x test
34+
shell: bash

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ out/
3838

3939
## application.yml ##
4040
*.yml
41+
!application.yml
4142

4243
## QClass ##
4344
**/generated/

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[submodule "config-repo"]
2+
path = config-repo
3+
url = https://github.com/Team-WSS/WSS-Server-Submodule.git
4+
branch = main

Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ FROM amd64/amazoncorretto:17
22

33
WORKDIR /app
44

5+
COPY config-repo/ /app/config-repo/
6+
57
COPY ./build/libs/WSS-Server-0.0.1-SNAPSHOT.jar /app/websoso.jar
68

7-
CMD ["java", "-Duser.timezone=Asia/Seoul", "-jar", "-Dspring.profiles.active=prod", "websoso.jar"]
9+
ENTRYPOINT ["java", "-Duser.timezone=Asia/Seoul", "-Dspring.profiles.active=${SPRING_PROFILES_ACTIVE}", "-jar", "websoso.jar"]

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ dependencies {
9090
implementation "com.google.firebase:firebase-admin:${firebaseAdminVersion}"
9191

9292
// S3 Mapping Library
93-
implementation "com.github.Team-WSS:WSS-Server-S3:${wssS3Version}"
93+
api "com.github.Team-WSS:WSS-Server-S3:${wssS3Version}"
9494

9595
// ============== Project Modules ==============
9696
implementation project(':wss-service-support')

config-repo

Submodule config-repo added at 28333fa

src/main/java/org/websoso/WSSServer/application/AccountApplication.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
import org.websoso.WSSServer.feed.repository.FeedRepository;
1212
import org.websoso.WSSServer.oauth2.service.AppleService;
1313
import org.websoso.WSSServer.oauth2.service.KakaoService;
14-
import org.websoso.WSSServer.repository.RefreshTokenRepository;
15-
import org.websoso.WSSServer.service.DiscordMessageClient;
14+
import org.websoso.WSSServer.oauth2.repository.RefreshTokenRepository;
15+
import org.websoso.WSSServer.notification.service.DiscordMessageClient;
1616
import org.websoso.WSSServer.service.MessageFormatter;
1717
import org.websoso.WSSServer.user.domain.User;
1818
import org.websoso.WSSServer.user.domain.WithdrawalReason;

src/main/java/org/websoso/WSSServer/application/AuthApplication.java

Lines changed: 88 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,135 @@
22

33
import static org.websoso.WSSServer.exception.error.CustomAuthError.INVALID_TOKEN;
44

5+
import io.jsonwebtoken.Claims;
6+
import java.security.PublicKey;
7+
import java.util.Map;
58
import lombok.RequiredArgsConstructor;
69
import org.springframework.stereotype.Service;
710
import org.springframework.transaction.annotation.Transactional;
811
import org.websoso.WSSServer.config.jwt.CustomAuthenticationToken;
912
import org.websoso.WSSServer.config.jwt.JWTUtil;
1013
import org.websoso.WSSServer.config.jwt.JwtProvider;
1114
import org.websoso.WSSServer.config.jwt.JwtValidationType;
15+
import org.websoso.WSSServer.dto.auth.ApplePublicKeys;
16+
import org.websoso.WSSServer.dto.auth.AppleTokenResponse;
17+
import org.websoso.WSSServer.dto.auth.AuthResponse;
1218
import org.websoso.WSSServer.dto.auth.LogoutRequest;
1319
import org.websoso.WSSServer.dto.auth.ReissueResponse;
1420
import org.websoso.WSSServer.dto.user.LoginResponse;
1521
import org.websoso.WSSServer.exception.exception.CustomAuthException;
22+
import org.websoso.WSSServer.oauth2.domain.UserAppleToken;
23+
import org.websoso.WSSServer.oauth2.dto.KakaoUserInfo;
24+
import org.websoso.WSSServer.oauth2.service.AppleClient;
25+
import org.websoso.WSSServer.oauth2.service.AppleKeyGenerator;
26+
import org.websoso.WSSServer.oauth2.service.AppleService;
1627
import org.websoso.WSSServer.oauth2.service.KakaoService;
17-
import org.websoso.WSSServer.repository.RefreshTokenRepository;
18-
import org.websoso.WSSServer.user.domain.RefreshToken;
28+
import org.websoso.WSSServer.oauth2.repository.RefreshTokenRepository;
29+
import org.websoso.WSSServer.oauth2.domain.RefreshToken;
30+
import org.websoso.WSSServer.oauth2.service.TokenService;
1931
import org.websoso.WSSServer.user.domain.User;
20-
import org.websoso.WSSServer.user.repository.UserDeviceRepository;
32+
import org.websoso.WSSServer.notification.repository.UserDeviceRepository;
2133
import org.websoso.WSSServer.user.service.UserService;
2234

2335
@Service
2436
@RequiredArgsConstructor
2537
public class AuthApplication {
38+
39+
private final TokenService tokenService;
2640
private final JwtProvider jwtProvider;
2741
private final JWTUtil jwtUtil;
2842
private final RefreshTokenRepository refreshTokenRepository;
2943
private final UserDeviceRepository userDeviceRepository;
3044
private final UserService userService;
3145
private final KakaoService kakaoService;
46+
private final AppleService appleService;
47+
private final AppleClient appleClient;
3248
private static final String KAKAO_PREFIX = "kakao";
3349
private static final String APPLE_PREFIX = "apple";
50+
private final AppleKeyGenerator appleKeyGenerator;
3451

52+
@Transactional
3553
public ReissueResponse reissue(String refreshToken) {
36-
RefreshToken storedRefreshToken = refreshTokenRepository.findByRefreshToken(refreshToken)
37-
.orElseThrow(() -> new CustomAuthException(INVALID_TOKEN, "given token is invalid token for reissue"));
38-
54+
// 1. 토큰 유효성 검증
3955
if (jwtUtil.validateJWT(refreshToken) != JwtValidationType.VALID_REFRESH) {
4056
throw new CustomAuthException(INVALID_TOKEN, "given token is invalid token for reissue");
4157
}
4258

59+
// 2. 저장된 토큰 조회
60+
RefreshToken storedRefreshToken = tokenService.findRefreshTokenOrThrow(refreshToken);
61+
62+
// 3. 새로운 토큰 생성
4363
Long userId = jwtUtil.getUserIdFromJwt(refreshToken);
4464
CustomAuthenticationToken customAuthenticationToken = new CustomAuthenticationToken(userId, null, null);
65+
4566
String newAccessToken = jwtProvider.generateAccessToken(customAuthenticationToken);
4667
String newRefreshToken = jwtProvider.generateRefreshToken(customAuthenticationToken);
4768

48-
refreshTokenRepository.delete(storedRefreshToken);
49-
refreshTokenRepository.save(new RefreshToken(newRefreshToken, userId));
69+
// 4. 리프레시 토큰 교체
70+
tokenService.rotateRefreshToken(storedRefreshToken, newRefreshToken, userId);
5071

5172
return ReissueResponse.of(newAccessToken, newRefreshToken);
5273
}
5374

75+
@Transactional
76+
public AuthResponse loginKakao(String kakaoAccessToken) {
77+
// 1. 카카오 로그인 인증
78+
KakaoUserInfo kakaoUserInfo = kakaoService.getUserInfo(kakaoAccessToken);
79+
80+
// 2. 사용자 정보 불러오기 / 생성
81+
User user = userService.getOrCreateKakaoUser(kakaoUserInfo);
82+
83+
// 3. Access / Refresh Token 생성
84+
CustomAuthenticationToken customAuthenticationToken = CustomAuthenticationToken.create(user.getUserId());
85+
String accessToken = jwtProvider.generateAccessToken(customAuthenticationToken);
86+
String refreshToken = jwtProvider.generateRefreshToken(customAuthenticationToken);
87+
88+
// 4. Refresh Token 저장
89+
tokenService.saveRefreshToken(user, refreshToken);
90+
91+
boolean isRegister = !user.isTemporaryNickname();
92+
return AuthResponse.of(accessToken, refreshToken, isRegister);
93+
}
94+
95+
@Transactional
96+
public AuthResponse loginApple(String authorizationCode, String appleToken) {
97+
// 1. 공개키 가져오기 & 헤더 파싱
98+
ApplePublicKeys applePublicKeys = appleClient.getApplePublicKeys();
99+
Map<String, String> headers = jwtProvider.parseAppleTokenHeader(appleToken);
100+
101+
// 2. 공개키 생성 및 검증 (서명 확인)
102+
PublicKey publicKey = appleKeyGenerator.generatePublicKey(headers, applePublicKeys);
103+
Claims claims = jwtProvider.extractClaims(appleToken, publicKey);
104+
105+
// 3. 애플 서버에서 Refresh Token 받아오기
106+
String clientSecret = appleKeyGenerator.createClientSecret();
107+
AppleTokenResponse appleTokenResponse = appleClient.requestAppleToken(authorizationCode, clientSecret);
108+
109+
// 4. 유저 정보 추출
110+
String email = claims.get("email", String.class);
111+
String userIdentifier = claims.get("sub", String.class);
112+
String customSocialId = APPLE_PREFIX + "_" + userIdentifier;
113+
String defaultNickname = APPLE_PREFIX.charAt(0) + "*" + userIdentifier.substring(7, 15);
114+
115+
// 5. 유저 처리
116+
User user = userService.getOrCreateAppleUser(customSocialId, email, defaultNickname);
117+
118+
// 6. 애플 Refresh Token 저장
119+
appleService.upsertRefreshToken(user, appleTokenResponse.getRefreshToken());
120+
121+
// 7. Access / Refresh Token 생성
122+
CustomAuthenticationToken customAuthenticationToken = CustomAuthenticationToken.create(user.getUserId());
123+
String accessToken = jwtProvider.generateAccessToken(customAuthenticationToken);
124+
String refreshToken = jwtProvider.generateRefreshToken(customAuthenticationToken);
125+
126+
// 8. Refresh Token 저장
127+
tokenService.saveRefreshToken(user, refreshToken);
128+
129+
boolean isRegister = !user.isTemporaryNickname();
130+
131+
return AuthResponse.of(accessToken, refreshToken, isRegister);
132+
}
133+
54134
// TODO: getUserOrException -> existUserOrException 변경
55135
@Transactional(readOnly = true)
56136
public LoginResponse login(Long userId) {

0 commit comments

Comments
 (0)