Skip to content

Commit

Permalink
Merge pull request #12 from WE-ARE-RACCOONS/develop
Browse files Browse the repository at this point in the history
RAC-82
  • Loading branch information
ywj9811 authored Oct 29, 2023
2 parents 909b665 + 463946c commit be28fb7
Show file tree
Hide file tree
Showing 28 changed files with 650 additions and 15 deletions.
78 changes: 78 additions & 0 deletions .github/workflows/CD-develop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Java CD with Gradle

on:
push:
branches: [ "develop" ]

permissions:
contents: read

jobs:
build:

runs-on: ubuntu-latest
env :
working-directory: ./
APPLICATION: ${{ secrets.APPLICATION }}

steps:
- uses: actions/checkout@v2
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'adopt'

- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Create application.yml
run: |
mkdir ./src/main/resources
echo "${{env.APPLICATION}}" > ./src/main/resources/application.yml
- name: Grant execute permission for gradlew
run: chmod +x gradlew
working-directory: ${{ env.working-directory }}

- name: Build with Gradle
run: ./gradlew build
working-directory: ${{ env.working-directory }}

- name: Cleanup Gradle Cache
if: ${{ always() }}
run: |
rm -f ~/.gradle/caches/modules-2/modules-2.lock
rm -f ~/.gradle/caches/modules-2/gc.properties
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build and Push Docker image
run: |
docker build -t ywj9811/postgraduate_develop:latest .
docker push ywj9811/postgraduate_develop:latest
- name: Deploy
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_SERVER_HOST }}
username: ${{ secrets.EC2_SERVER_USERNAME }}
key: ${{ secrets.PRIVATE_KEY }}
envs: GITHUB_SHA
script: |
docker-compose -f /home/ec2-user/config/docker-compose.yml down
docker-compose -f /home/ec2-user/config/docker-compose.yml pull
docker-compose -f /home/ec2-user/config/docker-compose.yml up -d --force-recreate --build
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM openjdk:17-jdk
ARG JAR_FILE=./build/libs/postgraduate-0.0.1-SNAPSHOT.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.postgraduate.domain.auth.application.dto;

import com.postgraduate.domain.user.domain.entity.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class AuthUserResponse {
private User user;
private boolean isNew;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.postgraduate.domain.auth.application.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class JwtTokenResponse {
private String accessToken;
private String refreshToken;
private boolean isNew;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.postgraduate.domain.auth.application.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Builder
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class KakaoAccessTokenResponse {
Integer app_id;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.postgraduate.domain.auth.application.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class KakaoLoginRequest {
private String accessToken;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.postgraduate.domain.auth.application.dto;

import lombok.*;

@Builder
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class KakaoUserInfoResponse {
private Long id;
private KakaoAccount kakaoAccount;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class KakaoAccount {
private String email;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.postgraduate.domain.auth.application.mapper;

import com.postgraduate.domain.auth.application.dto.AuthUserResponse;
import com.postgraduate.domain.user.domain.entity.User;

public class AuthMapper {
public static AuthUserResponse mapToAuthUser(User user, boolean isNew) {
return AuthUserResponse.builder()
.user(user)
.isNew(isNew).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.postgraduate.domain.auth.application.usecase.jwt;

import com.postgraduate.domain.auth.application.dto.JwtTokenResponse;
import com.postgraduate.domain.user.domain.entity.User;
import com.postgraduate.domain.user.domain.entity.constant.Role;
import com.postgraduate.global.jwt.JwtProvider;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class JwtUseCase {
private final JwtProvider jwtProvider;

public JwtTokenResponse signIn(User user, boolean isNew) {
String accessToken = jwtProvider.generateToken(user.getUserId(), user.getRole(), false);
String refreshToken = jwtProvider.generateToken(user.getUserId(), user.getRole(), true);
return new JwtTokenResponse(accessToken, refreshToken, isNew);
}

public JwtTokenResponse regenerateToken(String refreshToken) {
jwtProvider.validateToken(refreshToken);
Claims claims = jwtProvider.parseClaims(refreshToken);
String role = claims.get("role", String.class);
String id = claims.getSubject();
String newAccessToken = jwtProvider.generateToken(Long.valueOf(id), Role.valueOf(role), false);
return new JwtTokenResponse(newAccessToken, null, false);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.postgraduate.domain.auth.application.usecase.kakao;

import com.postgraduate.domain.auth.application.dto.KakaoAccessTokenResponse;
import com.postgraduate.domain.auth.application.dto.KakaoUserInfoResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

@RequiredArgsConstructor
@Service
public class KakaoAccessTokenUseCase {

@Value("${app-id.kakao}")
private String APP_ID;
private final WebClient webClient;
private static final String USER_INFO_URI = "https://kapi.kakao.com/v2/user/me";
private static final String VALIDATE_TOKEN_URI = "https://kapi.kakao.com/v1/user/access_token_info";


public KakaoUserInfoResponse getUserInfo(String accessToken) {

verifyAccessToken(accessToken);

return webClient.get()
.uri(USER_INFO_URI)
.headers(h -> h.setBearerAuth(accessToken))
.retrieve()
.bodyToMono(KakaoUserInfoResponse.class)
.block();
}

private void verifyAccessToken(String accessToken) {
KakaoAccessTokenResponse kakaoAccessTokenResponse = webClient.get()
.uri(VALIDATE_TOKEN_URI)
.headers(h -> h.setBearerAuth(accessToken))
.retrieve()
.bodyToMono(KakaoAccessTokenResponse.class)
.block();

if (kakaoAccessTokenResponse == null ||
!kakaoAccessTokenResponse.getApp_id().toString().equals(APP_ID)) {
//TODO: 예외 처리
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.postgraduate.domain.auth.application.usecase.kakao;

import com.postgraduate.domain.auth.application.dto.AuthUserResponse;
import com.postgraduate.domain.auth.application.dto.KakaoUserInfoResponse;
import com.postgraduate.domain.auth.application.mapper.AuthMapper;
import com.postgraduate.domain.user.domain.entity.User;
import com.postgraduate.domain.user.domain.service.UserGetService;
import com.postgraduate.domain.user.domain.service.UserSaveService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@Service
@RequiredArgsConstructor
public class KakaoSignInUseCase {
private final KakaoAccessTokenUseCase kakaoTokenUseCase;
private final UserSaveService userSaveService;
private final UserGetService userGetService;

@Transactional
public AuthUserResponse getUser(String token) {
KakaoUserInfoResponse userInfo = kakaoTokenUseCase.getUserInfo(token);
Long socialId = userInfo.getId();
Optional<User> user = userGetService.bySocialId(socialId);
if (user.isPresent()) {
return AuthMapper.mapToAuthUser(user.get(), false);
}

User newUser = userSaveService.saveUser(socialId);
return AuthMapper.mapToAuthUser(newUser, true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.postgraduate.domain.auth.presentation;

import com.postgraduate.domain.auth.application.dto.AuthUserResponse;
import com.postgraduate.domain.auth.application.usecase.jwt.JwtUseCase;
import com.postgraduate.domain.auth.application.usecase.kakao.KakaoSignInUseCase;
import com.postgraduate.domain.auth.application.dto.JwtTokenResponse;
import com.postgraduate.domain.auth.application.dto.KakaoLoginRequest;
import com.postgraduate.global.auth.AuthDetails;
import com.postgraduate.global.dto.ResponseDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import static com.postgraduate.domain.auth.presentation.contant.AuthResponseMessage.*;
import static org.springframework.http.HttpStatus.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/user")
@Tag(name = "AUTH Controller")
public class AuthController {
private final KakaoSignInUseCase kakaoSignInUseCase;
private final JwtUseCase jwtUseCase;

@PostMapping("/login")
@Operation(description = "카카오 로그인")
public ResponseDto<JwtTokenResponse> getUserDetails(@RequestBody KakaoLoginRequest request) {
AuthUserResponse authUser = kakaoSignInUseCase.getUser(request.getAccessToken());
JwtTokenResponse jwtToken = jwtUseCase.signIn(authUser.getUser(), authUser.isNew());
return ResponseDto.create(OK.value(), SUCCESS_AUTH_MESSAGE.getMessage(), jwtToken);
}

@PostMapping("/refresh")
@Operation(description = "refreshToken 으로 accessToken 재발급")
public ResponseDto<JwtTokenResponse> refresh(@AuthenticationPrincipal AuthDetails authDetails) {
Long userId = authDetails.getUserId();
String refreshToken = "";/*Redis에서 userId로 refreshToken 확인*/
JwtTokenResponse jwtToken = jwtUseCase.regenerateToken(refreshToken);
return ResponseDto.create(OK.value(), SUCCESS_REGENERATE_TOKEN_MESSAGE.getMessage(), jwtToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.postgraduate.domain.auth.presentation.contant;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum AuthResponseMessage {
SUCCESS_AUTH_MESSAGE("사용자 인증에 성공하였습니다."),
SUCCESS_REGENERATE_TOKEN_MESSAGE("토큰 재발급에 성공하였습니다.");
private final String message;
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ public class Payment {
private LocalDate deletedAt;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
@ColumnDefault("'IMPOSSIBLE'")
private Status status;
@Builder.Default
private Status status = Status.IMPOSSIBLE;
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ public class Review {
@Column(nullable = false)
private String content;
@Column(nullable = false)
@ColumnDefault("'REJECT'")
@Enumerated(EnumType.STRING)
private Status status;
@Builder.Default
private Status status = Status.REJECT;
@CreationTimestamp
private LocalDate createdAt;
@UpdateTimestamp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ public static UserInfoResponse mapToInfo(User user) {
.point(user.getPoint())
.build();
}

public static User mapToUser(Long socialId) {
return User.builder()
.socialId(socialId)
.build();
}
}
Loading

0 comments on commit be28fb7

Please sign in to comment.