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
787 changes: 787 additions & 0 deletions hs_err_pid59708.log

Large diffs are not rendered by default.

4,897 changes: 4,897 additions & 0 deletions replay_pid59708.log

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void logout(
CookieUtils.deleteRefreshTokenCookie(cookieSecure)
);

// 2. 레거시 쿠키(Path=/api/auth)도 삭제 (과거 잔재 청소)
// 2. 레거시 쿠키(Path=/api/auth)도 삭제
response.addCookie(CookieUtils.deleteRefreshTokenCookie(cookieSecure, "/api/auth", "Lax"));
response.addCookie(CookieUtils.deleteRefreshTokenCookie(cookieSecure, "/api/auth", "Strict"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public OAuthLoginResponse login(
) {
OAuthLoginResult result = oAuthService.login(OAuthProvider.from(provider), code);

// 1. 레거시(/api/auth) 쿠키 제거 (예전 SameSite가 Strict였다면 Strict로 한 번 더)
// 1. 레거시(/api/auth) 쿠키 제거
response.addCookie(CookieUtils.deleteRefreshTokenCookie(cookieSecure, "/api/auth", "Strict"));
response.addCookie(CookieUtils.deleteRefreshTokenCookie(cookieSecure, "/api/auth", "Lax"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public class LogoutServiceImpl implements LogoutService {
@Override
public void logout(String refreshToken) {

// refreshToken 없어도 로그아웃은 성공
if (refreshToken == null || refreshToken.isBlank()) {
log.info("Logout: no refreshToken provided");
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,15 @@ public void saveRefreshToken(Long userId, String refreshToken) {
public TokenResponse refreshAccessToken(HttpServletRequest request,
HttpServletResponse response) {

// 1. Cookie에서 refreshToken 추출
String refreshToken = extractRefreshToken(request);

// 1-1. JWT 서명 검증 (DB 조회 전)
Long jwtUserId;
try {
jwtUserId = jwtProvider.getUserId(refreshToken, "refresh");
} catch (JwtException | IllegalArgumentException | CustomException e) {
throw new CustomException(ErrorCode.REFRESH_TOKEN_INVALID);
}

// 2. DB 조회
RefreshToken savedToken = refreshTokenMapper.findByToken(refreshToken)
.orElseThrow(() ->
new CustomException(ErrorCode.REFRESH_TOKEN_INVALID)
Expand All @@ -75,10 +72,8 @@ public TokenResponse refreshAccessToken(HttpServletRequest request,
throw new CustomException(ErrorCode.REFRESH_TOKEN_INVALID);
}

// 3. 만료 체크
if (savedToken.getExpiresAt().isBefore(Instant.now())) {
// 만료된 토큰은 즉시 삭제 후 예외 반환 (rotation 로직 미진입)
refreshTokenMapper.deleteByToken(refreshToken); // 만료 토큰 정리
refreshTokenMapper.deleteByToken(refreshToken);
throw new CustomException(ErrorCode.REFRESH_TOKEN_EXPIRED);
}
Comment thread
joonhyong marked this conversation as resolved.

Expand All @@ -88,30 +83,24 @@ public TokenResponse refreshAccessToken(HttpServletRequest request,
throw new CustomException(ErrorCode.REFRESH_TOKEN_INVALID);
}

// 4. 기존 refreshToken 폐기 (Rotation 로직 진입)
int deletedCount = refreshTokenMapper.deleteByToken(refreshToken);
if (deletedCount == 0) {
throw new CustomException(ErrorCode.REFRESH_TOKEN_INVALID);
}

// 5. 새 Access + Refresh 발급
TokenResponse accessToken = jwtIssuer.issueAccessToken(userId);

// 6. 새 refreshToken 발급
String newRefreshToken = jwtIssuer.issueRefreshToken(userId);

// 7. DB 저장
saveRefreshToken(userId, newRefreshToken);

// 8. 새 refreshToken 쿠키 설정
response.addCookie(CookieUtils.createRefreshTokenCookie(
newRefreshToken,
jwtProperties.refreshExpirationSeconds(),
cookieSecure
)
);

// 9. accessToken만 반환
return accessToken;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.ureca.unity.domain.call.service.CallService;
import com.ureca.unity.global.exception.CustomException;
import com.ureca.unity.global.exception.ErrorCode;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
Expand All @@ -12,6 +13,10 @@
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Tag(
name = "3. Call",
description = "전화 연결"
)
@RestController
@RequestMapping("/api/agora")
@RequiredArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@
import com.ureca.unity.domain.call.service.RecordingServiceImpl;
import com.ureca.unity.global.exception.CustomException;
import com.ureca.unity.global.exception.ErrorCode;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.ErrorResponse;
import org.springframework.web.bind.annotation.*;

@Tag(
name = "3. Call",
description = "전화 연결"
)
@RestController
@RequestMapping("/api/recording")
@RequiredArgsConstructor
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

10 changes: 0 additions & 10 deletions src/main/java/com/ureca/unity/domain/example/model/Example.java

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public void agree(Long userId) {
User user = userMapper.findById(userId)
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));

// 이미 동의했으면 아무 것도 안 함 (멱등성)
if (user.getTermsAgreedAt() != null) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.ureca.unity.domain.recommend.service.RecommendService;
import com.ureca.unity.global.exception.CustomException;
import com.ureca.unity.global.exception.ErrorCode;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -13,6 +14,10 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Tag(
name = "5. Recommend",
description = "추천 로직"
)
@RestController
@RequestMapping("/api/v1/recommend")
@RequiredArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
@Getter @Setter
public class RecommendRequest {
private long summaryId;
private int k = 5; //기본값
private int k = 5;
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,30 +107,4 @@ public RecommendResponse getRandomByCategory() {
response.setItems(results);
return response;
}


// public List<RecommendItem> getRecommendationsWithFallback(long summaryId) {
// List<RecommendItem> items = recommendMapper.selectBySummaryId(summaryId);
//
// // 추천 없으면 빈 리스트 처리
// if (items == null) {
// items = new ArrayList<>();
// }
//
// // 카테고리별로 그룹화
// Map<Integer, List<RecommendItem>> byCategory = items.stream()
// .collect(Collectors.groupingBy(RecommendItem::getCategoryId));
//
// List<Category> categories = categoryMapper.selectAll();
// for (Category c : categories) {
// if (!byCategory.containsKey(c.getCategoryId()) || byCategory.get(c.getCategoryId()).isEmpty()) {
// // 추천 없으면 fallback
// List<RecommendItem> fallback = recommendMapper.selectRandomByCategory(c.getCategoryId());
// items.addAll(fallback);
// }
// }
//
// // score=0, rankNo=0인 fallback도 이미 Mapper에서 설정됨
// return items;
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@ public class OAuthTokenCrypto {

private static final String ALG = "AES";
private static final String TRANSFORM = "AES/GCM/NoPadding";
private static final int IV_LEN = 12; // GCM 권장 12 bytes
private static final int IV_LEN = 12;
private static final int TAG_BITS = 128;

private final byte[] keyBytes;
private final SecureRandom random = new SecureRandom();

public OAuthTokenCrypto(@Value("${security.oauth-token.secret}") String secret) {
// 최소 수정 버전: secret을 16/24/32 bytes로 맞춰 쓰는 걸 권장
// 여기서는 "UTF-8 바이트" 기준으로 32바이트로 잘라/패딩 처리
byte[] raw = secret.getBytes(StandardCharsets.UTF_8);
this.keyBytes = new byte[32];
for (int i = 0; i < this.keyBytes.length; i++) {
Expand All @@ -43,7 +41,6 @@ public String encrypt(String plain) {

byte[] ct = cipher.doFinal(plain.getBytes(StandardCharsets.UTF_8));

// 저장 포맷: base64( iv + ciphertext )
byte[] out = new byte[iv.length + ct.length];
System.arraycopy(iv, 0, out, 0, iv.length);
System.arraycopy(ct, 0, out, iv.length, ct.length);
Expand All @@ -58,7 +55,7 @@ public String decrypt(String enc) {
if (enc == null) return null;
try {
byte[] in = Base64.getDecoder().decode(enc);
if (in.length < IV_LEN + 1) return enc; // 방어: 평문이 들어온 경우 그냥 반환
if (in.length < IV_LEN + 1) return enc;
Comment thread
joonhyong marked this conversation as resolved.

byte[] iv = new byte[IV_LEN];
byte[] ct = new byte[in.length - IV_LEN];
Expand All @@ -73,7 +70,6 @@ public String decrypt(String enc) {
byte[] pt = cipher.doFinal(ct);
return new String(pt, StandardCharsets.UTF_8);
} catch (Exception e) {
// 방어: 기존 데이터가 평문/다른 포맷이면 그냥 원문 반환(마이그레이션 단계에서 유용)
return enc;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.setConnectTimeout(Duration.ofSeconds(3)) // 연결 시도 제한
.setReadTimeout(Duration.ofSeconds(5)) // 응답 읽기 제한
.setConnectTimeout(Duration.ofSeconds(3))
.setReadTimeout(Duration.ofSeconds(5))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public OpenAPI openAPI() {
return new OpenAPI()
.tags(List.of(
new io.swagger.v3.oas.models.tags.Tag().name("1. Auth"),
new io.swagger.v3.oas.models.tags.Tag().name("2. Exam"),
new io.swagger.v3.oas.models.tags.Tag().name("3. STT"),
new io.swagger.v3.oas.models.tags.Tag().name("2. Policy"),
new io.swagger.v3.oas.models.tags.Tag().name("3. Call"),
new io.swagger.v3.oas.models.tags.Tag().name("4. Summary")
))
.components(new Components()
Expand Down
16 changes: 0 additions & 16 deletions src/main/resources/mapper/example/ExampleMapper.xml

This file was deleted.