Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package org.ezcode.codetest.presentation.usermanagement;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.ezcode.codetest.application.usermanagement.auth.dto.request.FindPasswordRequest;
import org.ezcode.codetest.application.usermanagement.user.dto.request.ResetPasswordRequest;
import org.ezcode.codetest.application.usermanagement.auth.dto.request.SendEmailRequest;
import org.ezcode.codetest.application.usermanagement.auth.dto.response.FindPasswordResponse;
import org.ezcode.codetest.application.usermanagement.auth.dto.response.SendEmailResponse;
import org.ezcode.codetest.application.usermanagement.auth.dto.response.VerifyEmailCodeResponse;
import org.ezcode.codetest.application.usermanagement.auth.service.AuthService;
import org.ezcode.codetest.application.usermanagement.user.dto.response.ChangeUserPasswordResponse;
import org.ezcode.codetest.application.usermanagement.user.dto.response.VerifyFindPasswordResponse;
import org.ezcode.codetest.domain.user.model.entity.AuthUser;
import org.ezcode.codetest.domain.user.exception.UserException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
Expand All @@ -21,13 +19,19 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

@Slf4j
@RestController
@RequiredArgsConstructor
Expand All @@ -48,11 +52,34 @@ public ResponseEntity<SendEmailResponse> sendMailCode(
//이메일에서 버튼 클릭하면 자동으로 연결
@Operation(summary = "이메일 코드 입력 및 인증", description = "이메일로 받은 코드를 입력하여 이메일 인증된 회원으로 전환합니다")
@GetMapping("/auth/verify")
public ResponseEntity<VerifyEmailCodeResponse> verifyEmailCode(
public void verifyEmailCode(
@RequestParam String email,
@RequestParam String key
){
return ResponseEntity.status(HttpStatus.OK).body(authService.verifyEmailCode(email, key));
@RequestParam String key,
HttpServletResponse response
) throws IOException {
try {
authService.verifyEmailCode(email, key);

// 성공 시 프론트엔드로 리디렉션
String redirectUrl = UriComponentsBuilder
.fromUriString("https://ezcode.my/email-verify-success")
.queryParam("status", "success")
.build()
.toUriString();
Comment on lines +64 to +68
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

하드코딩된 리디렉션 URL을 설정으로 분리하세요.

https://ezcode.my/... URL이 하드코딩되어 있습니다. 개발/스테이징/프로덕션 환경에 따라 다른 URL을 사용해야 할 가능성이 높으므로, application.yml 또는 @Value를 통해 외부 설정으로 분리하는 것이 좋습니다.

♻️ 설정 분리 예시
// Controller에 추가
@Value("${app.email-verify.success-url}")
private String successRedirectUrl;

@Value("${app.email-verify.failure-url}")
private String failureRedirectUrl;
# application.yml
app:
  email-verify:
    success-url: https://ezcode.my/email-verify-success
    failure-url: https://ezcode.my/email-verify-failure
🤖 Prompt for AI Agents
In
@src/main/java/org/ezcode/codetest/presentation/usermanagement/UserVerifyController.java
around lines 64 - 68, The redirect URL in UserVerifyController is hardcoded into
the redirectUrl assignment; inject configurable properties instead (e.g. add
@Value("${app.email-verify.success-url}") private String successRedirectUrl and
@Value("${app.email-verify.failure-url}") private String failureRedirectUrl to
the controller) and replace the
UriComponentsBuilder.fromUriString("https://ezcode.my/...") call with
UriComponentsBuilder.fromUriString(successRedirectUrl) (and similarly use
failureRedirectUrl for the failure path), and add the corresponding keys
(app.email-verify.success-url and app.email-verify.failure-url) to
application.yml for environment-specific values.


response.sendRedirect(redirectUrl);
} catch (UserException e) {
// 실패 시 프론트엔드로 리디렉션 (에러 메시지 포함)
String errorMessage = URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8);
String redirectUrl = UriComponentsBuilder
.fromUriString("https://ezcode.my/email-verify-failure")
.queryParam("status", "failure")
.queryParam("message", errorMessage)
.build()
.toUriString();
Comment on lines +73 to +79
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

URL 이중 인코딩 문제가 발생할 수 있습니다.

URLEncoder.encode()로 인코딩한 후 UriComponentsBuilder.queryParam()에 전달하면, queryParam()이 다시 인코딩을 수행하여 이중 인코딩 문제가 발생합니다.

🐛 수정 제안
-            String errorMessage = URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8);
             String redirectUrl = UriComponentsBuilder
                 .fromUriString("https://ezcode.my/email-verify-failure")
                 .queryParam("status", "failure")
-                .queryParam("message", errorMessage)
-                .build()
+                .queryParam("message", e.getMessage())
+                .encode()
+                .build()
                 .toUriString();

UriComponentsBuilder.encode()를 사용하면 쿼리 파라미터가 적절히 인코딩됩니다. URLEncoder.encode()는 제거하세요.

🤖 Prompt for AI Agents
In
@src/main/java/org/ezcode/codetest/presentation/usermanagement/UserVerifyController.java
around lines 73 - 79, Remove the manual URLEncoder.encode usage: don't set
errorMessage = URLEncoder.encode(...); instead pass the raw e.getMessage() (or a
sanitized message variable) into UriComponentsBuilder.queryParam("message", ...)
and call .encode() on the UriComponentsBuilder chain to let it perform proper
encoding; update the redirectUrl construction that uses UriComponentsBuilder to
call .encode() before .toUriString() and remove the now-unneeded
URLEncoder/StandardCharsets usage.


response.sendRedirect(redirectUrl);
}
Comment on lines +71 to +82
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

UserException 외의 예외 처리가 누락되었습니다.

UserException만 catch하고 있어, 다른 런타임 예외(DB 오류, 네트워크 오류 등)가 발생하면 사용자에게 적절한 리디렉션 없이 500 에러가 노출될 수 있습니다. 일반 예외에 대한 fallback 처리를 추가하거나, @ControllerAdvice에서 이 엔드포인트에 대한 예외 처리를 별도로 구현하는 것을 권장합니다.

🐛 예외 처리 보완 예시
         } catch (UserException e) {
             // 실패 시 프론트엔드로 리디렉션 (에러 메시지 포함)
-            String errorMessage = URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8);
             String redirectUrl = UriComponentsBuilder
                 .fromUriString("https://ezcode.my/email-verify-failure")
                 .queryParam("status", "failure")
-                .queryParam("message", errorMessage)
-                .build()
+                .queryParam("message", e.getMessage())
+                .encode()
+                .build()
                 .toUriString();
             
             response.sendRedirect(redirectUrl);
+        } catch (Exception e) {
+            log.error("이메일 인증 중 예외 발생: email={}", email, e);
+            String redirectUrl = UriComponentsBuilder
+                .fromUriString("https://ezcode.my/email-verify-failure")
+                .queryParam("status", "failure")
+                .queryParam("message", "인증 처리 중 오류가 발생했습니다.")
+                .encode()
+                .build()
+                .toUriString();
+            
+            response.sendRedirect(redirectUrl);
         }
🤖 Prompt for AI Agents
In
@src/main/java/org/ezcode/codetest/presentation/usermanagement/UserVerifyController.java
around lines 71 - 82, The current try/catch in UserVerifyController only handles
UserException, so add a fallback catch for Exception to ensure
DB/network/runtime errors also redirect to the failure page; inside the new
catch(Exception e) log the error and build the same redirect URL (use
URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8) or a generic message
if null) and call response.sendRedirect(redirectUrl), or alternatively implement
a @ControllerAdvice global handler for this endpoint that performs the same
redirect behavior for uncaught exceptions.

}


Expand Down