Skip to content

MOSU-144 feat: Login 후 profile 등록 여부 판단#146

Merged
wlgns12370 merged 7 commits intodevelopfrom
feature/mosu-144
Jul 27, 2025
Merged

MOSU-144 feat: Login 후 profile 등록 여부 판단#146
wlgns12370 merged 7 commits intodevelopfrom
feature/mosu-144

Conversation

@wlgns12370
Copy link
Contributor

@wlgns12370 wlgns12370 commented Jul 27, 2025

✨ 구현한 기능

  • Login 후 profile 등록 여부 판단 로직 추가
  • Auth, OAuth loginResponse 공통화

📢 논의하고 싶은 내용

  • x

🎸 기타

  • x

Summary by CodeRabbit

  • New Features

    • Added validation to prevent applications for exams whose dates have already passed.
    • Login responses now include user details when the profile is not registered.
    • Introduced a new error message for attempts to apply to past exams.
  • Improvements

    • Login and authentication responses are more informative, conditionally providing user information.
    • Cookie handling for authentication tokens is now centralized and streamlined.
    • Enhanced token cookie creation with secure and domain-specific settings.
  • Bug Fixes

    • Ensured accurate feedback during login and application processes regarding profile status and exam eligibility.
  • Tests

    • Added comprehensive tests for login response scenarios, covering both standard and OAuth logins.

@coderabbitai
Copy link

coderabbitai bot commented Jul 27, 2025

Walkthrough

This update introduces a new exam date validation to the application process, modifies authentication and login response structures to include more user details, and refactors cookie handling in the authentication controller. Additional error codes, DTOs, and comprehensive tests for login responses are also included.

Changes

File(s) Change Summary
.../application/ApplicationService.java Added exam date validation in the apply method before other validations.
.../application/vaildator/ApplicationValidator.java Introduced ExamDateNotPassed method to check if exam dates have passed.
.../auth/AuthService.java Modified login to pass the user entity to the login response DTO.
.../domain/user/UserJpaEntity.java Updated constructor to include phoneNumber parameter.
.../global/exception/ErrorCode.java Added new error code: EXAM_DATE_PASSED.
.../global/handler/OAuth2LoginSuccessHandler.java Changed login response creation to use the full OAuthUser object.
.../presentation/auth/AuthController.java Centralized token cookie creation with a helper method and updated login response to include user info.
.../presentation/auth/dto/LoginCommandResponse.java Added UserJpaEntity user field and updated factory method accordingly.
.../presentation/auth/dto/LoginResponse.java Added oauthUser field, replaced single factory method with two overloaded methods, and added conditional logic.
.../presentation/auth/dto/LoginUserResponse.java Introduced new DTO record for user login response details.
.../presentation/auth/dto/LoginResponseTest.java Added comprehensive tests for various login response scenarios.
.../global/util/CookieBuilderUtil.java Added private constructor to prevent instantiation; added methods to create secure temporary cookies.
.../presentation/auth/SignUpController.java Updated cookie creation calls to use secure temporary cookies for token headers.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant AuthController
    participant AuthService
    participant UserRepo
    participant LoginCommandResponse
    participant LoginResponse

    Client->>AuthController: POST /login (LoginRequest)
    AuthController->>AuthService: login(request)
    AuthService->>UserRepo: find user by credentials
    UserRepo-->>AuthService: UserJpaEntity
    AuthService->>LoginCommandResponse: of(token, isProfileRegistered, user)
    AuthService-->>AuthController: LoginCommandResponse
    AuthController->>LoginResponse: from(isProfileRegistered, user)
    AuthController-->>Client: LoginResponse (with oauthUser if not registered)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

우선순위 중

Suggested reviewers

  • jbh010204
  • polyglot-k

Poem

Hopping through the code with glee,
I checked your login carefully—
Now users’ details, clear and bright,
Appear in every login light.
Exam dates guarded, cookies neat,
With tests to make the change complete!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3cd2c20 and 7358961.

📒 Files selected for processing (5)
  • src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/global/util/CookieBuilderUtil.java (2 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/auth/AuthController.java (4 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/auth/SignUpController.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/auth/dto/LoginResponse.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java
  • src/main/java/life/mosu/mosuserver/presentation/auth/AuthController.java
  • src/main/java/life/mosu/mosuserver/presentation/auth/dto/LoginResponse.java
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/java/life/mosu/mosuserver/presentation/auth/SignUpController.java (1)
src/main/java/life/mosu/mosuserver/global/util/CookieBuilderUtil.java (1)
  • CookieBuilderUtil (5-41)
🔇 Additional comments (5)
src/main/java/life/mosu/mosuserver/global/util/CookieBuilderUtil.java (3)

7-9: LGTM! Proper utility class implementation.

The private constructor with UnsupportedOperationException correctly prevents instantiation of this utility class, following best practices for utility class design.


21-28: Good method overloading for flexibility.

The overloaded createCookie method without maxAge parameter provides convenient cookie creation for session cookies. The implementation is consistent with the existing method.


30-40: Review Cookie Security Configuration

Please confirm the following before merging:

  • The domain .mosuedu.com aligns with your deployment (e.g. backend on api.mosuedu.com, front-end on www.mosuedu.com).
  • All clients and environments serve over HTTPS (.secure(true) will block non-HTTPS requests).
  • You intentionally require cross-site cookies (.sameSite("None")) for your authentication flows.
src/main/java/life/mosu/mosuserver/presentation/auth/SignUpController.java (2)

47-51: LGTM! Improved cookie security for access token.

The change from createCookie to temporaryCookie enhances security by using secure cookies with proper domain and sameSite attributes for the access token. This aligns with the security improvements in the CookieBuilderUtil class.


52-56: LGTM! Consistent security improvement for refresh token.

The change to temporaryCookie for the refresh token maintains consistency with the access token handling and applies the same security enhancements (secure flag, domain, and sameSite attributes).

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/mosu-144

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@wlgns12370 wlgns12370 changed the title MOSU-144 feat MOSU-144 feat: Login 후 profile 등록 여부 판단 Jul 27, 2025
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @wlgns12370, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the application's robustness and user experience by refining the exam application process and improving user authentication flows. It adds a crucial validation to prevent applications for past exams and enriches the login response with more detailed user information, particularly for newly registered users. These changes are supported by updates to the core UserJpaEntity and a significant refactoring of cookie handling in the authentication layer, all backed by new DTOs and dedicated unit tests to ensure stability.

Highlights

  • Application Validation Enhancement: Introduced a new validation rule in ApplicationService to prevent users from applying for exams whose dates have already passed, ensuring that only future exams can be applied for.
  • User Information in Login Response: Modified the login process to include detailed user information (UserJpaEntity) within the LoginCommandResponse and LoginResponse DTOs. This allows the frontend to receive more comprehensive user data, especially for users who have not yet completed their profile registration.
  • User Entity Update: The UserJpaEntity constructor has been updated to include a phoneNumber field, enabling the storage of more complete user contact information.
  • Auth Controller Refactoring: Centralized the logic for building and applying HTTP Set-Cookie headers for access and refresh tokens into a new private utility method (applyTokenHeader) within AuthController, significantly improving code readability and maintainability.
  • New Login User DTO and Tests: Introduced a new LoginUserResponse DTO to specifically encapsulate a subset of user details returned during the login process when a profile is not yet fully registered. Comprehensive unit tests have also been added for LoginResponse to ensure its correct behavior across various login scenarios (standard and OAuth).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments or fill out our survey to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces two main features. First, it enhances the login response to include user details if a user profile has not yet been created, which is useful for pre-filling profile forms, especially after an OAuth login. This involves changes to DTOs, services, and controllers. Second, it adds a validation step to prevent users from applying for exams that have already passed.

The changes are generally in the right direction, but there are several points to address:

  • A critical security and functionality regression was introduced in the cookie creation logic, where secure, domain, and sameSite attributes were dropped.
  • There's a potential NullPointerException in the new LoginResponse DTO due to how a Boolean is checked.
  • Several areas could be improved for code quality and maintainability, including adherence to Java naming conventions, simplifying complex Optional usage, and improving test practices.

I've left detailed comments on these points. Addressing them will improve the robustness and security of the application.

Comment on lines 58 to 73
private HttpHeaders applyTokenHeader(Token token) {
HttpHeaders headers = new HttpHeaders(

);
headers.add(HttpHeaders.SET_COOKIE, CookieBuilderUtil.createCookie(
ACCESS_TOKEN_COOKIE_NAME,
token.accessToken(),
token.accessTokenExpireTime()
));
headers.add(HttpHeaders.SET_COOKIE, CookieBuilderUtil.createCookie(
REFRESH_TOKEN_COOKIE_NAME,
token.refreshToken(),
token.refreshTokenExpireTime()
));
return headers;
}

Choose a reason for hiding this comment

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

critical

The new helper method relies on CookieBuilderUtil, which creates cookies without the secure, domain, and sameSite attributes that were present in the original implementation. This is a critical regression.

  • The secure attribute is essential for security, ensuring cookies are only sent over HTTPS.
  • The domain and sameSite attributes are crucial for the cookie to work correctly across subdomains (e.g., api.mosuedu.com and www.mosuedu.com).

The CookieBuilderUtil needs to be updated to correctly configure these attributes.

Comment on lines 13 to 26
public static LoginResponse from(final OAuthUser user) {
if (user.getIsProfileRegistered().equals(true)) {
return new LoginResponse(true, null);
}
return new LoginResponse(false, LoginUserResponse.from(user.getUser()));
}

public static LoginResponse from(Boolean isProfileRegistered, final UserJpaEntity user) {
if (isProfileRegistered.equals(true)) {
return new LoginResponse(true, null);
}
return new LoginResponse(false, LoginUserResponse.from(user));
}
}

Choose a reason for hiding this comment

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

high

There are a couple of improvements that can be made here:

  1. The logic in the two from methods is duplicated. You can refactor this by having one method call the other to reduce code duplication.
  2. Using isProfileRegistered.equals(true) can lead to a NullPointerException if isProfileRegistered is null. It's safer to use Boolean.TRUE.equals(isProfileRegistered), which is null-safe.
    public static LoginResponse from(final OAuthUser user) {
        return from(user.getIsProfileRegistered(), user.getUser());
    }

    public static LoginResponse from(Boolean isProfileRegistered, final UserJpaEntity user) {
        if (Boolean.TRUE.equals(isProfileRegistered)) {
            return new LoginResponse(true, null);
        }
        return new LoginResponse(false, LoginUserResponse.from(user));
    }


Set<Subject> subjects = request.getSubjects();

validator.ExamDateNotPassed(examIds);

Choose a reason for hiding this comment

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

medium

Consider calling the validator method with a lowercase starting letter to adhere to Java naming conventions.

Suggested change
validator.ExamDateNotPassed(examIds);
validator.examDateNotPassed(examIds);

Comment on lines +71 to +79
public void ExamDateNotPassed(List<Long> examIds) {
List<ExamJpaEntity> exams = examJpaRepository.findAllById(examIds);
boolean hasPassedExam = exams.stream()
.anyMatch(exam -> exam.getExamDate().isBefore(LocalDate.now()));

if (hasPassedExam) {
throw new CustomRuntimeException(ErrorCode.EXAM_DATE_PASSED);
}
}

Choose a reason for hiding this comment

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

medium

According to Java naming conventions, method names should start with a lowercase letter and be in camelCase. Please rename ExamDateNotPassed to examDateNotPassed to follow this convention.

Suggested change
public void ExamDateNotPassed(List<Long> examIds) {
List<ExamJpaEntity> exams = examJpaRepository.findAllById(examIds);
boolean hasPassedExam = exams.stream()
.anyMatch(exam -> exam.getExamDate().isBefore(LocalDate.now()));
if (hasPassedExam) {
throw new CustomRuntimeException(ErrorCode.EXAM_DATE_PASSED);
}
}
public void examDateNotPassed(List<Long> examIds) {
List<ExamJpaEntity> exams = examJpaRepository.findAllById(examIds);
boolean hasPassedExam = exams.stream()
.anyMatch(exam -> exam.getExamDate().isBefore(LocalDate.now()));
if (hasPassedExam) {
throw new CustomRuntimeException(ErrorCode.EXAM_DATE_PASSED);
}
}

Comment on lines 26 to 27
private final static String ACCESS_TOKEN_COOKIE_NAME = "accessToken";
private final static String REFRESH_TOKEN_COOKIE_NAME = "refreshToken";

Choose a reason for hiding this comment

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

medium

According to standard Java conventions, the static modifier should come before final for constants.

Suggested change
private final static String ACCESS_TOKEN_COOKIE_NAME = "accessToken";
private final static String REFRESH_TOKEN_COOKIE_NAME = "refreshToken";
private static final String ACCESS_TOKEN_COOKIE_NAME = "accessToken";
private static final String REFRESH_TOKEN_COOKIE_NAME = "refreshToken";

Comment on lines 59 to 61
HttpHeaders headers = new HttpHeaders(

);

Choose a reason for hiding this comment

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

medium

The HttpHeaders instantiation can be simplified. The empty lines are unnecessary.

        HttpHeaders headers = new HttpHeaders();

Comment on lines +14 to +29
public static LoginUserResponse from(UserJpaEntity user) {
return Optional.ofNullable(user)
.map(userEntity -> {
String gender = Optional.ofNullable(userEntity.getGender())
.map(Enum::name)
.orElse(null);

return new LoginUserResponse(
gender,
userEntity.getName(),
userEntity.getBirth(),
userEntity.getPhoneNumber()
);
})
.orElse(null);
}

Choose a reason for hiding this comment

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

medium

The use of nested Optional makes this factory method more complex than necessary and can be difficult to read. A simple null check would be more straightforward and achieve the same result with better readability.

    public static LoginUserResponse from(UserJpaEntity user) {
        if (user == null) {
            return null;
        }

        String gender = (user.getGender() != null) ? user.getGender().name() : null;

        return new LoginUserResponse(
                gender,
                user.getName(),
                user.getBirth(),
                user.getPhoneNumber()
        );
    }

Comment on lines +3 to +6
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

Choose a reason for hiding this comment

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

medium

These tests are using JUnit 5 (@org.junit.jupiter.api.Test), but the assertions are from JUnit 4 (org.junit.Assert). For consistency and to leverage JUnit 5 features, it's recommended to use assertions from org.junit.jupiter.api.Assertions.

Suggested change
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

Comment on lines +82 to +83
String jsonResponse = objectMapper.writeValueAsString(response);
log.info("카카오_로그인_사용자가_기존의_회원인_경우_응답 JSON : {}", jsonResponse);

Choose a reason for hiding this comment

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

medium

Logging the JSON response in a test can be useful for debugging, but it adds noise to the test execution logs. Tests should ideally be silent on success. Consider removing these log statements from the tests to keep the logs clean, which helps in identifying real issues faster.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/main/java/life/mosu/mosuserver/application/application/vaildator/ApplicationValidator.java (1)

71-79: Consider improving robustness and method naming consistency.

The validation logic is correct, but there are two areas for improvement:

  1. Method naming inconsistency: This method uses ExamDateNotPassed while others use RequestNoDuplicateExams, ExamIdsAndLunchSelection. Consider renaming to validateExamDateNotPassed for consistency.

  2. Handling non-existent exam IDs: If some examIds don't exist in the database, they won't be included in the stream check, potentially allowing the validation to pass incorrectly. Consider adding an existence check similar to ExamIdsAndLunchSelection.

public void ExamDateNotPassed(List<Long> examIds) {
    List<ExamJpaEntity> exams = examJpaRepository.findAllById(examIds);
+   
+   if (exams.size() != examIds.size()) {
+       throw new CustomRuntimeException(ErrorCode.EXAM_NOT_FOUND);
+   }
+   
    boolean hasPassedExam = exams.stream()
            .anyMatch(exam -> exam.getExamDate().isBefore(LocalDate.now()));

    if (hasPassedExam) {
        throw new CustomRuntimeException(ErrorCode.EXAM_DATE_PASSED);
    }
}
src/main/java/life/mosu/mosuserver/presentation/auth/dto/LoginResponse.java (2)

13-18: Consider using direct boolean comparison for better performance.

The logic is correct, but using user.getIsProfileRegistered().equals(true) is less efficient than a direct boolean comparison.

Apply this diff for better performance:

-        if (user.getIsProfileRegistered().equals(true)) {
+        if (user.getIsProfileRegistered()) {

20-25: Consider using direct boolean comparison for consistency.

Same optimization opportunity as the previous method - direct boolean comparison would be more efficient and cleaner.

Apply this diff for consistency:

-        if (isProfileRegistered.equals(true)) {
+        if (isProfileRegistered) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd75aca and 3cd2c20.

📒 Files selected for processing (11)
  • src/main/java/life/mosu/mosuserver/application/application/ApplicationService.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/application/application/vaildator/ApplicationValidator.java (2 hunks)
  • src/main/java/life/mosu/mosuserver/application/auth/AuthService.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/domain/user/UserJpaEntity.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/global/handler/OAuth2LoginSuccessHandler.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/auth/AuthController.java (4 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/auth/dto/LoginCommandResponse.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/auth/dto/LoginResponse.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/auth/dto/LoginUserResponse.java (1 hunks)
  • src/test/java/life/mosu/mosuserver/presentation/auth/dto/LoginResponseTest.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-deploy
🔇 Additional comments (23)
src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java (1)

104-104: LGTM! New error code follows established patterns.

The addition of EXAM_DATE_PASSED error code is well-placed among exam-related errors and uses appropriate HTTP status and descriptive Korean message consistent with the codebase style.

src/main/java/life/mosu/mosuserver/application/application/ApplicationService.java (1)

44-44: LGTM! Validation placed appropriately in the chain.

The exam date validation is correctly positioned before other business rule validations, ensuring expired exams are caught early in the process.

src/main/java/life/mosu/mosuserver/application/application/vaildator/ApplicationValidator.java (1)

3-3: LGTM! Import addition is necessary.

The LocalDate import is correctly added to support the new date validation functionality.

src/main/java/life/mosu/mosuserver/application/auth/AuthService.java (1)

40-40: LGTM! Clean enhancement to include user entity in response.

The change correctly passes the already-extracted user entity to the LoginCommandResponse.of method, enabling richer response data without affecting the method's core authentication logic.

src/main/java/life/mosu/mosuserver/global/handler/OAuth2LoginSuccessHandler.java (1)

56-56: LGTM! Enhanced OAuth2 response with richer user context.

Passing the complete OAuthUser object instead of just a boolean flag allows the LoginResponse to access more detailed user information for response construction.

src/main/java/life/mosu/mosuserver/presentation/auth/dto/LoginCommandResponse.java (3)

3-3: LGTM! Proper import for the new field.

Clean addition of the necessary import for UserJpaEntity.


7-9: LGTM! Well-structured record enhancement.

The addition of the UserJpaEntity user field extends the response capabilities while maintaining the existing structure.


11-14: LGTM! Factory method properly updated.

The of method signature correctly reflects the new parameter, maintaining consistency with the calling code in AuthService.

src/main/java/life/mosu/mosuserver/domain/user/UserJpaEntity.java (2)

72-75: LGTM! Constructor parameter addition is well-structured.

The phoneNumber parameter is cleanly added to the @Builder constructor, maintaining the existing parameter organization.


80-80: LGTM! Proper field assignment.

The phoneNumber field is correctly assigned from the constructor parameter, completing the enhancement to include phone number during entity construction.

src/main/java/life/mosu/mosuserver/presentation/auth/dto/LoginUserResponse.java (2)

7-12: LGTM! Well-designed DTO record structure.

The record fields are appropriately typed and organized, providing a clean interface for user response data.


14-29: LGTM! Excellent factory method with robust null safety.

The from method demonstrates good defensive programming practices:

  • Uses Optional.ofNullable to handle null user entities
  • Safely converts enum to string using Enum::name
  • Provides graceful fallback with orElse(null) for both the gender field and the entire response

This implementation ensures the DTO creation won't fail even with incomplete user data.

src/main/java/life/mosu/mosuserver/presentation/auth/dto/LoginResponse.java (2)

3-6: LGTM! Clean import additions.

The new imports are well-organized and necessary for the enhanced LoginResponse functionality.


8-11: Good use of Jackson annotation for conditional serialization.

The @JsonInclude(Include.NON_NULL) annotation on the oauthUser field properly excludes null values from JSON serialization, which aligns with the business logic where this field should only be present when the profile is not registered.

src/test/java/life/mosu/mosuserver/presentation/auth/dto/LoginResponseTest.java (5)

1-58: Excellent test setup with comprehensive configuration.

The test class is well-structured with proper ObjectMapper configuration for Java time serialization and realistic test data setup. The use of Korean naming conventions aligns well with the domain context.


64-84: Good test coverage for OAuth registered user scenario.

The test properly verifies that when an OAuth user has a registered profile, the response contains isProfileRegistered: true and oauthUser: null. The JSON logging is helpful for debugging.


86-106: Good test coverage for OAuth unregistered user scenario.

The test correctly verifies that when an OAuth user doesn't have a registered profile, the response contains isProfileRegistered: false and oauthUser with user details.


113-125: Thorough testing of MOSU login registered scenario.

The test properly validates the factory method that accepts explicit parameters, ensuring correct behavior when the profile is registered.


127-139: Complete test coverage for MOSU login unregistered scenario.

The test validates the scenario where a MOSU user's profile is not registered, ensuring the oauthUser field is populated correctly.

src/main/java/life/mosu/mosuserver/presentation/auth/AuthController.java (4)

6-6: Good addition of utility import.

The import of CookieBuilderUtil supports the refactored cookie handling approach.


26-27: Well-defined constants for cookie names.

The static final constants follow Java naming conventions and improve maintainability by centralizing cookie name definitions.


42-45: Clean integration of refactored cookie handling and enhanced response.

The login method now properly uses the extracted helper method for cookie handling and passes the user entity to create a richer login response. This aligns well with the LoginResponse changes.


58-73: Excellent refactoring of cookie creation logic.

The applyTokenHeader method effectively centralizes cookie creation logic, making the code more maintainable and reusable. The use of CookieBuilderUtil promotes consistency across the application.

@wlgns12370 wlgns12370 merged commit bef3036 into develop Jul 27, 2025
2 checks passed
@wlgns12370 wlgns12370 linked an issue Jul 27, 2025 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[🛠 기능 구현] Login 후 profile 등록 여부 판단

1 participant