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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ HELP.md
**/.env.*
*.env
.env
.env.properties
!.env.example
**/.env.example
build/
Expand Down
14 changes: 12 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.4.1'
id 'org.springframework.boot' version '3.3.6'
id 'io.spring.dependency-management' version '1.1.7'
}

Expand Down Expand Up @@ -50,7 +50,7 @@ dependencies {
implementation 'io.jsonwebtoken:jjwt:0.9.1'

// --- AWS (S3) ---
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3'

// --- Flyway (DB Migration) ---
implementation "org.flywaydb:flyway-core:10.21.0"
Expand All @@ -69,6 +69,16 @@ dependencies {
testImplementation 'org.mockito:mockito-junit-jupiter:5.6.0'
testImplementation 'org.assertj:assertj-core:3.24.2'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

// swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0'
}

dependencyManagement {
imports {
mavenBom "io.awspring.cloud:spring-cloud-aws-dependencies:3.1.1"
// ↑ 3.x 대 사용 (프로젝트에 맞는 최신 3.x 가능)
}
}

/* ===== Tasks ===== */
Expand Down
31 changes: 0 additions & 31 deletions src/main/java/inha/gdgoc/config/DotenvLoader.java

This file was deleted.

30 changes: 0 additions & 30 deletions src/main/java/inha/gdgoc/config/S3Config.java

This file was deleted.

67 changes: 35 additions & 32 deletions src/main/java/inha/gdgoc/domain/auth/service/AuthService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package inha.gdgoc.domain.auth.service;

import inha.gdgoc.config.jwt.TokenProvider;
import inha.gdgoc.global.config.jwt.TokenProvider;
import inha.gdgoc.domain.auth.dto.request.UserLoginRequest;
import inha.gdgoc.domain.auth.dto.response.LoginResponse;
import inha.gdgoc.domain.auth.enums.LoginType;
Expand Down Expand Up @@ -28,14 +28,15 @@
import java.util.Map;
import java.util.Optional;

import static inha.gdgoc.util.EncryptUtil.encrypt;
import static inha.gdgoc.global.util.EncryptUtil.encrypt;

@Slf4j
@Service
@RequiredArgsConstructor
public class AuthService {

private final RefreshTokenService refreshTokenService;

@Value("${google.client-id}")
private String clientId;

Expand Down Expand Up @@ -63,9 +64,9 @@ public Map<String, Object> processOAuthLogin(String code, HttpServletResponse re

HttpEntity<MultiValueMap<String, String>> tokenRequest = new HttpEntity<>(params, headers);
ResponseEntity<Map> tokenResponse = restTemplate.postForEntity(
"https://oauth2.googleapis.com/token",
tokenRequest,
Map.class
"https://oauth2.googleapis.com/token",
tokenRequest,
Map.class
);

String googleAccessToken = (String) tokenResponse.getBody().get("access_token");
Expand All @@ -76,10 +77,10 @@ public Map<String, Object> processOAuthLogin(String code, HttpServletResponse re
HttpEntity<Void> userInfoRequest = new HttpEntity<>(userInfoHeaders);

ResponseEntity<Map> userInfoResponse = restTemplate.exchange(
"https://www.googleapis.com/oauth2/v2/userinfo",
HttpMethod.GET,
userInfoRequest,
Map.class
"https://www.googleapis.com/oauth2/v2/userinfo",
HttpMethod.GET,
userInfoRequest,
Map.class
);

// 3. Google에서 가져온 이름, 이메일로 가입된 정보가 없으면 회원가입, 있으면 로그인
Expand All @@ -90,39 +91,40 @@ public Map<String, Object> processOAuthLogin(String code, HttpServletResponse re
Optional<User> foundUser = userRepository.findByEmail(email);
if (foundUser.isEmpty()) {
return Map.of(
"exists", false,
"email", email,
"name", name
"exists", false,
"email", email,
"name", name
);
}

User user = foundUser.get();

String jwtAccessToken = tokenProvider.generateGoogleLoginToken(user, Duration.ofHours(1));
String refreshToken = refreshTokenService.getOrCreateRefreshToken(user, Duration.ofDays(1),
LoginType.GOOGLE_LOGIN);
LoginType.GOOGLE_LOGIN);

ResponseCookie refreshCookie = ResponseCookie.from("refresh_token", refreshToken)
.httpOnly(true)
.secure(true)
.sameSite("None")
.domain(".gdgocinha.com")
.path("/")
.maxAge(Duration.ofDays(1))
.build();
.httpOnly(true)
.secure(true)
.sameSite("None")
.domain(".gdgocinha.com")
.path("/")
.maxAge(Duration.ofDays(1))
.build();

// Set-Cookie 헤더로 추가
log.info("Response Cookie에 저장된 Refresh Token: {}", refreshCookie.toString());
response.addHeader(HttpHeaders.SET_COOKIE, refreshCookie.toString());

return Map.of(
"exists", true,
"access_token", jwtAccessToken
"exists", true,
"access_token", jwtAccessToken
);
}

public LoginResponse loginWithPassword(UserLoginRequest userLoginRequest, HttpServletResponse response)
throws NoSuchAlgorithmException, InvalidKeyException {
public LoginResponse loginWithPassword(UserLoginRequest userLoginRequest,
HttpServletResponse response)
throws NoSuchAlgorithmException, InvalidKeyException {
Optional<User> user = userRepository.findByEmail(userLoginRequest.email());
if (user.isEmpty()) {
return new LoginResponse(false, null);
Expand All @@ -135,16 +137,17 @@ public LoginResponse loginWithPassword(UserLoginRequest userLoginRequest, HttpSe
}

String accessToken = tokenProvider.generateSelfSignupToken(foundUser, Duration.ofHours(1));
String refreshToken = refreshTokenService.getOrCreateRefreshToken(foundUser, Duration.ofDays(1),
LoginType.SELF_SIGNUP);
String refreshToken = refreshTokenService.getOrCreateRefreshToken(foundUser,
Duration.ofDays(1),
LoginType.SELF_SIGNUP);

ResponseCookie refreshCookie = ResponseCookie.from("refresh_token", refreshToken)
.httpOnly(true)
.secure(true)
.sameSite("None")
.path("/")
.maxAge(Duration.ofDays(1))
.build();
.httpOnly(true)
.secure(true)
.sameSite("None")
.path("/")
.maxAge(Duration.ofDays(1))
.build();

log.info("Response Cookie에 저장된 Refresh Token: {}", refreshCookie.toString());
response.addHeader(HttpHeaders.SET_COOKIE, refreshCookie.toString());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package inha.gdgoc.domain.auth.service;

import inha.gdgoc.config.jwt.TokenProvider;
import inha.gdgoc.global.config.jwt.TokenProvider;
import inha.gdgoc.domain.auth.entity.RefreshToken;
import inha.gdgoc.domain.auth.enums.LoginType;
import inha.gdgoc.domain.auth.repository.RefreshTokenRepository;
Expand Down
38 changes: 19 additions & 19 deletions src/main/java/inha/gdgoc/domain/resource/service/S3Service.java
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
package inha.gdgoc.domain.resource.service;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.ObjectMetadata;
import inha.gdgoc.domain.resource.enums.S3KeyType;
import java.io.IOException;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.UUID;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetUrlRequest;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;

@Service
@RequiredArgsConstructor
public class S3Service {

private final AmazonS3 amazonS3;
private final S3Client s3Client;

@Value("${cloud.aws.s3.bucket}")
private String bucketName;

public String upload(
Long userId,
S3KeyType s3key,
MultipartFile file
) throws IOException {
public String upload(Long userId, S3KeyType s3key, MultipartFile file) throws IOException {
String fileName = UUID.randomUUID() + "-" + file.getOriginalFilename();
String prefix = "user/" + userId + "/";
String uploadFilePath = prefix + s3key.getValue() + "/" + fileName;
String key = "user/%d/%s/%s".formatted(userId, s3key.getValue(), fileName);

ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(file.getSize());
metadata.setContentType(file.getContentType());
PutObjectRequest putReq = PutObjectRequest.builder()
.bucket(bucketName)
.key(key)
.contentType(file.getContentType())
.build();

amazonS3.putObject(bucketName, uploadFilePath, file.getInputStream(), metadata);
return uploadFilePath;
s3Client.putObject(putReq, RequestBody.fromInputStream(file.getInputStream(), file.getSize()));
return key;
}

public String getS3FileUrl(String key) {
return amazonS3.getUrl(bucketName, key).toString();
return s3Client.utilities()
.getUrl(GetUrlRequest.builder().bucket(bucketName).key(key).build())
.toExternalForm();
}
}
2 changes: 1 addition & 1 deletion src/main/java/inha/gdgoc/domain/user/entity/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import inha.gdgoc.domain.study.entity.StudyAttendee;
import inha.gdgoc.domain.user.enums.UserRole;
import inha.gdgoc.global.common.BaseEntity;
import inha.gdgoc.util.EncryptUtil;
import inha.gdgoc.global.util.EncryptUtil;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/inha/gdgoc/domain/user/service/UserService.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package inha.gdgoc.domain.user.service;

import static inha.gdgoc.util.EncryptUtil.encrypt;
import static inha.gdgoc.util.EncryptUtil.generateSalt;
import static inha.gdgoc.global.util.EncryptUtil.encrypt;
import static inha.gdgoc.global.util.EncryptUtil.generateSalt;

import inha.gdgoc.domain.auth.dto.request.FindIdRequest;
import inha.gdgoc.domain.user.dto.request.CheckDuplicatedEmailRequest;
Expand All @@ -10,7 +10,7 @@
import inha.gdgoc.domain.user.dto.response.CheckDuplicatedEmailResponse;
import inha.gdgoc.domain.user.entity.User;
import inha.gdgoc.domain.user.repository.UserRepository;
import inha.gdgoc.exception.NotFoundException;
import inha.gdgoc.global.exception.NotFoundException;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
Expand Down
9 changes: 1 addition & 8 deletions src/main/java/inha/gdgoc/global/common/ErrorResponse.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package inha.gdgoc.global.common;

import inha.gdgoc.global.error.ErrorCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
public class ErrorResponse {

private final int status;
Expand All @@ -20,11 +20,4 @@ public ErrorResponse(HttpStatus status, String message) {
this.message = message;
}

public int getStatus() {
return status;
}

public String getMessage() {
return message;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package inha.gdgoc.config.jwt;
package inha.gdgoc.global.config.jwt;

import lombok.Getter;
import lombok.Setter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package inha.gdgoc.config.jwt;
package inha.gdgoc.global.config.jwt;

import inha.gdgoc.domain.auth.enums.LoginType;
import inha.gdgoc.domain.user.entity.User;
Expand Down
Loading
Loading