Skip to content
Merged
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
26 changes: 25 additions & 1 deletion .deploy/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,28 @@
FROM openjdk:17

# 빌드 시 전달받을 ARG 변수 설정
ARG DATASOURCE_URL_LOCAL
ARG DATASOURCE_USERNAME
ARG DATASOURCE_PASSWORD
ARG JWT_SECRET_KEY
ARG JWT_EXPIRED_IN
ARG REFRESH_TOKEN_EXPIRED_IN
ARG KAKAO_CLIENT_KEY
ARG KAKAO_REDIRECT_URL

# ARG 값을 ENV로 설정하여 런타임에서도 사용 가능하도록 설정
ENV DATASOURCE_URL_LOCAL=$DATASOURCE_URL_LOCAL
ENV DATASOURCE_USERNAME=$DATASOURCE_USERNAME
ENV DATASOURCE_PASSWORD=$DATASOURCE_PASSWORD
ENV JWT_SECRET_KEY=$JWT_SECRET_KEY
ENV JWT_EXPIRED_IN=$JWT_EXPIRED_IN
ENV REFRESH_TOKEN_EXPIRED_IN=$REFRESH_TOKEN_EXPIRED_IN
ENV KAKAO_CLIENT_KEY=$KAKAO_CLIENT_KEY
ENV KAKAO_REDIRECT_URL=$KAKAO_REDIRECT_URL

# JAR 파일 복사
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

# 실행 명령어
ENTRYPOINT ["java", "-jar", "/app.jar"]
11 changes: 8 additions & 3 deletions .deploy/neighbors-blue-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ services:
- app-network
environment:
- TZ=Asia/Seoul
- DB_URL=${DATASOURCE_URL_LOCAL}
- DB_USERNAME=${DATASOURCE_USERNAME}
- DB_PASSWORD=${DATASOURCE_PASSWORD}
- DATASOURCE_URL_LOCAL=${DATASOURCE_URL_LOCAL}
- DATASOURCE_USERNAME=${DATASOURCE_USERNAME}
- DATASOURCE_PASSWORD=${DATASOURCE_PASSWORD}
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
- JWT_EXPIRED_IN=${JWT_EXPIRED_IN}
- REFRESH_TOKEN_EXPIRED_IN=${REFRESH_TOKEN_EXPIRED_IN}
- KAKAO_CLIENT_KEY=${KAKAO_CLIENT_KEY}
- KAKAO_REDIRECT_URL=${KAKAO_REDIRECT_URL}

networks:
app-network:
Expand Down
11 changes: 8 additions & 3 deletions .deploy/neighbors-green-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ services:
- app-network
environment:
- TZ=Asia/Seoul
- DB_URL=${DATASOURCE_URL_LOCAL}
- DB_USERNAME=${DATASOURCE_USERNAME}
- DB_PASSWORD=${DATASOURCE_PASSWORD}
- DATASOURCE_URL_LOCAL=${DATASOURCE_URL_LOCAL}
- DATASOURCE_USERNAME=${DATASOURCE_USERNAME}
- DATASOURCE_PASSWORD=${DATASOURCE_PASSWORD}
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
- JWT_EXPIRED_IN=${JWT_EXPIRED_IN}
- REFRESH_TOKEN_EXPIRED_IN=${REFRESH_TOKEN_EXPIRED_IN}
- KAKAO_CLIENT_KEY=${KAKAO_CLIENT_KEY}
- KAKAO_REDIRECT_URL=${KAKAO_REDIRECT_URL}

networks:
app-network:
Expand Down
29 changes: 28 additions & 1 deletion .github/workflows/CD.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ jobs:
build:
runs-on: ubuntu-latest

env:
DATASOURCE_URL_LOCAL: ${{ secrets.DATASOURCE_URL_LOCAL }}
DATASOURCE_USERNAME: ${{ secrets.DATASOURCE_USERNAME }}
DATASOURCE_PASSWORD: ${{ secrets.DATASOURCE_PASSWORD }}
JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY }}
JWT_EXPIRED_IN: ${{ secrets.JWT_EXPIRED_IN }}
REFRESH_TOKEN_EXPIRED_IN: ${{ secrets.REFRESH_TOKEN_EXPIRED_IN }}
KAKAO_CLIENT_KEY: ${{ secrets.KAKAO_CLIENT_KEY }}
KAKAO_REDIRECT_URL: ${{ secrets.KAKAO_REDIRECT_URL }}

steps:

# 레포지토리의 특정 브랜치, 커밋을 가져오는 설정
Expand Down Expand Up @@ -43,11 +53,23 @@ jobs:
- name: Build with Gradle Wrapper
run: ./gradlew build

# docker image를 build 하고 docker hub에 push
# docker image를 build 하고 docker hub에 push
- name: Docker Build and Push
run: |
sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
sudo docker build -f ./.deploy/Dockerfile -t ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }} .
sudo docker build \
--build-arg DATASOURCE_URL_LOCAL=${{ secrets.DATASOURCE_URL_LOCAL }} \
--build-arg DATASOURCE_USERNAME=${{ secrets.DATASOURCE_USERNAME }} \
--build-arg DATASOURCE_PASSWORD=${{ secrets.DATASOURCE_PASSWORD }} \
--build-arg JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }} \
--build-arg JWT_EXPIRED_IN=${{ secrets.JWT_EXPIRED_IN }} \
--build-arg REFRESH_TOKEN_EXPIRED_IN=${{ secrets.REFRESH_TOKEN_EXPIRED_IN }} \
--build-arg KAKAO_CLIENT_KEY=${{ secrets.KAKAO_CLIENT_KEY }} \
--build-arg KAKAO_REDIRECT_URL=${{ secrets.KAKAO_REDIRECT_URL }} \
--platform linux/amd64 \
-f ./.deploy/Dockerfile \
-t ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }} .
sudo docker push ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}

deploy:
Expand Down Expand Up @@ -80,6 +102,11 @@ jobs:
echo "DATASOURCE_URL_LOCAL=${{ secrets.DATASOURCE_URL_LOCAL }}" >> ./.env
echo "DATASOURCE_USERNAME=${{ secrets.DATASOURCE_USERNAME }}" >> ./.env
echo "DATASOURCE_PASSWORD=${{ secrets.DATASOURCE_PASSWORD }}" >> ./.env
echo "JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }}" >> ./.env
echo "JWT_EXPIRED_IN=${{ secrets.JWT_EXPIRED_IN }}" >> ./.env
echo "REFRESH_TOKEN_EXPIRED_IN=${{ secrets.REFRESH_TOKEN_EXPIRED_IN }}" >> ./.env
echo "KAKAO_CLIENT_KEY=${{ secrets.KAKAO_CLIENT_KEY }}" >> ./.env
echo "KAKAO_REDIRECT_URL=${{ secrets.KAKAO_REDIRECT_URL }}" >> ./.env
chmod +x deploy.sh
source deploy.sh

Expand Down
24 changes: 24 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FROM openjdk:17

# 빌드 시 전달받을 ARG 변수 설정
ARG DATASOURCE_URL_LOCAL
ARG DATASOURCE_USERNAME
ARG DATASOURCE_PASSWORD
ARG JWT_SECRET_KEY
ARG JWT_EXPIRED_IN
ARG REFRESH_TOKEN_EXPIRED_IN

# ARG 값을 ENV로 설정하여 런타임에서도 사용 가능하도록 설정
ENV DATASOURCE_URL_LOCAL=$DATASOURCE_URL_LOCAL
ENV DATASOURCE_USERNAME=$DATASOURCE_USERNAME
ENV DATASOURCE_PASSWORD=$DATASOURCE_PASSWORD
ENV JWT_SECRET_KEY=$JWT_SECRET_KEY
ENV JWT_EXPIRED_IN=$JWT_EXPIRED_IN
ENV REFRESH_TOKEN_EXPIRED_IN=$REFRESH_TOKEN_EXPIRED_IN

# JAR 파일 복사
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar

# 실행 명령어
ENTRYPOINT ["java", "-jar", "/app.jar"]
5 changes: 5 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'

//Jwt
implementation 'io.jsonwebtoken:jjwt-api:0.11.2'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.2', 'io.jsonwebtoken:jjwt-jackson:0.11.2'

compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.mysql:mysql-connector-j'
Expand Down
14 changes: 0 additions & 14 deletions src/main/java/com/neighbors/santa/TestController.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.neighbors.santa.application.baseResponse;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Data;

@Data
@JsonPropertyOrder({"code", "message", "data"})
public class BaseResponse<T> {
private final BaseResponseStatus status;
private final String message;

@JsonInclude(JsonInclude.Include.NON_NULL)
private final T data;

public BaseResponse(BaseResponseStatus status, String message, T data) {
this.status = status;
this.message = message;
this.data = data;
}

public BaseResponse(BaseResponseStatus status, String message) {
this(status, message, null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.neighbors.santa.application.baseResponse;

import lombok.Getter;

@Getter
public enum BaseResponseMessage {

//oauth success
로그인_성공했습니다("로그인 성공했습니다"),

//jwt error message
JWT_토큰_오류입니다("JWT 토큰 오류입니다"),
지원하지_않는_토큰_입니다("지원하지 않는 토큰 입니다"),
토큰이_올바르지_못한_형식입니다("토큰이 올바르지 못한 형식입니다"),
유효하지_않은_토큰_입니다("유효하지 않은 토큰입니다");

private final String message;

private BaseResponseMessage(String message) {
this.message = message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.neighbors.santa.application.baseResponse;

public enum BaseResponseStatus {
OK, BAD_REQUEST, JWT_ERROR;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.neighbors.santa.application.oauth.dto;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.neighbors.santa.common.jwt.AuthTokens;
import lombok.Builder;
import lombok.Data;

@Builder
@Data
public class OAuthLoginResponse {
private boolean isMember;

@JsonInclude(JsonInclude.Include.NON_NULL)
private AuthTokens authTokens;

@JsonInclude(JsonInclude.Include.NON_NULL)
private String email;

public static OAuthLoginResponse createSuccessObjFrom(AuthTokens authTokens, String email) {
return OAuthLoginResponse.builder()
.authTokens(authTokens)
.email(email)
.isMember(true)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.neighbors.santa.application.oauth.dto.kakao;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;

@Getter
@JsonIgnoreProperties(ignoreUnknown = true)
public class KakaoInfoResponse{

@JsonProperty("kakao_account")
private KakaoAccount kakaoAccount;

@Getter
@JsonIgnoreProperties(ignoreUnknown = true)
static class KakaoAccount {
private KakaoProfile profile;
private String email;
}

@Getter
@JsonIgnoreProperties(ignoreUnknown = true)
static class KakaoProfile {
private String nickname;
}

public String getEmail() {
return kakaoAccount.getEmail();
}

public String getNickname() {
return kakaoAccount.profile.getNickname();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.neighbors.santa.application.oauth.dto.kakao;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class KakaoTokens {

@JsonProperty("access_token")
private String accessToken;

@JsonProperty("token_type")
private String tokenType;

@JsonProperty("refresh_token")
private String refreshToken;

@JsonProperty("expires_in")
private String expiresIn;

@JsonProperty("refresh_token_expires_in")
private String refreshTokenExpiresIn;

@JsonProperty("scope")
private String scope;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.neighbors.santa.application.oauth.service;

import com.neighbors.santa.application.oauth.dto.kakao.KakaoInfoResponse;
import com.neighbors.santa.application.oauth.dto.kakao.KakaoTokens;
import com.neighbors.santa.application.oauth.dto.OAuthLoginResponse;
import com.neighbors.santa.application.baseResponse.BaseResponse;
import com.neighbors.santa.application.baseResponse.BaseResponseMessage;
import com.neighbors.santa.application.baseResponse.BaseResponseStatus;
import com.neighbors.santa.common.jwt.AuthTokens;
import com.neighbors.santa.common.jwt.JwtProvider;
import com.neighbors.santa.common.jwt.JwtUserDetails;
import com.neighbors.santa.domain.model.User;
import com.neighbors.santa.domain.service.CreateUser;
import com.neighbors.santa.domain.service.oauth.kakao.RequestKakaoInfo;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

@Service
@RequiredArgsConstructor
public class OAuthService {

private final RequestKakaoInfo requestUserInfo;
private final CreateUser createUser;
private final JwtProvider jwtProvider;

public BaseResponse<OAuthLoginResponse> oAuthKaKaoLoin(String code){
KakaoInfoResponse kakaoInfoResponse = requestUserInfo.requestKakaoInfo(code);

User user = User.builder()
.email(kakaoInfoResponse.getEmail())
.userName(kakaoInfoResponse.getNickname())
.build();

createUser.createUser(user);

AuthTokens authTokens = jwtProvider.createToken(JwtUserDetails.from(user));

return new BaseResponse<>(
BaseResponseStatus.OK,
BaseResponseMessage.로그인_성공했습니다.getMessage(),
OAuthLoginResponse.createSuccessObjFrom(authTokens, kakaoInfoResponse.getEmail())
);
}
}
23 changes: 23 additions & 0 deletions src/main/java/com/neighbors/santa/common/ErrorResponseUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.neighbors.santa.common;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.neighbors.santa.application.baseResponse.BaseResponse;
import com.neighbors.santa.application.baseResponse.BaseResponseStatus;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class ErrorResponseUtil {

private static final ObjectMapper objectMapper = new ObjectMapper();

public static void setResponse(HttpServletResponse response, BaseResponseStatus responseStatus) throws IOException {

BaseResponse errorResponse = new BaseResponse(responseStatus, "");

response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.setContentType("application/json");
response.getWriter().write(objectMapper.writeValueAsString(errorResponse));
}

}
Loading
Loading