Skip to content

MOSU-152 refactor: 인가 고도화#157

Merged
wlgns12370 merged 7 commits intodevelopfrom
refactor/mosu-152
Jul 28, 2025
Merged

MOSU-152 refactor: 인가 고도화#157
wlgns12370 merged 7 commits intodevelopfrom
refactor/mosu-152

Conversation

@wlgns12370
Copy link
Contributor

@wlgns12370 wlgns12370 commented Jul 28, 2025

✨ 구현한 기능

📢 논의하고 싶은 내용

  • x

🎸 기타

  • x

Summary by CodeRabbit

  • New Features

    • Added a new error message for invalid sign-up authentication tokens.
  • Refactor

    • Updated inquiry creation and deletion to use authenticated user details instead of user IDs.
    • Centralized and enforced permission checks for inquiry actions.
    • Simplified and unified token validation skip logic for specific endpoints.
    • Changed sign-up token validation to throw specific errors and no longer return a token object.
    • Revised profile registration and existence checks to rely on user roles instead of database queries.
    • Enhanced user information synchronization to include phone numbers across OAuth and profile updates.
    • Updated OAuth user handling with improved null checks and default values.
    • Removed profile registration steps from sign-up service and related processor component.
    • Modified API controllers and documentation to use Spring Security principal details for authentication.
  • Chores

    • Removed obsolete endpoint configurations and related code for token reissue.
    • Cleaned up unused imports and improved parameter formatting in several controllers.
    • Deleted deprecated profile request DTO and replaced with updated sign-up profile request DTO.
    • Added logging support for OAuth user info processing.
  • Documentation

    • Updated API documentation to reflect changes in authentication parameter handling.

@coderabbitai
Copy link

coderabbitai bot commented Jul 28, 2025

Walkthrough

This set of changes refactors authentication and permission handling in inquiry-related services and controllers, removes the access token reissue endpoint and its documentation, and centralizes endpoint skipping logic in the access token filter. It also introduces a new error code for invalid sign-up tokens and updates the sign-up token validation flow to throw custom exceptions. Additionally, profile registration logic and related classes were removed or simplified, and user entity update methods were extended to include phone number handling. Minor DTO and import adjustments were made accordingly.

Changes

Cohort / File(s) Change Summary
Inquiry Service Refactor
src/main/java/life/mosu/mosuserver/application/inquiry/InquiryService.java
Refactored to accept UserJpaEntity instead of user ID, centralized permission checks with a new private method, updated method signatures, and added logging annotation.
Inquiry Controller & Docs Update
src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryController.java,
src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryControllerDocs.java
Updated to use @AuthenticationPrincipal PrincipalDetails for user context instead of custom annotation or user ID, modified method signatures, and adjusted imports and formatting.
Error Code Update
src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java
Added new enum constant INVALID_SIGN_UP_TOKEN and fixed minor syntax.
Sign-Up Token Validation Refactor
src/main/java/life/mosu/mosuserver/presentation/oauth/SignUpTokenService.java
Changed validateSignUpToken to return void, throw custom exceptions for missing/invalid tokens, and removed return value.
Access Token Filter Simplification
src/main/java/life/mosu/mosuserver/presentation/oauth/AccessTokenFilter.java
Unified skipped endpoint logic into a list, removed reissue endpoint handling, and simplified control flow for skipping token validation.
Auth Controller & Docs Cleanup
src/main/java/life/mosu/mosuserver/presentation/auth/AuthController.java,
src/main/java/life/mosu/mosuserver/presentation/auth/AuthControllerDocs.java
Removed reissueAccessToken method and related imports from controller and API documentation interface.
Security Config Cleanup
src/main/resources/security-config.yml
Removed the endpoints.reissue path from configuration.
AuthService Refactor
src/main/java/life/mosu/mosuserver/application/auth/AuthService.java
Removed reissueAccessToken method, changed profile registration check to rely on user role instead of repository query.
SignUpService & Processor Removal
src/main/java/life/mosu/mosuserver/application/auth/SignUpService.java,
src/main/java/life/mosu/mosuserver/application/auth/processor/SignUpProfileStepProcessor.java
Removed profile registration method and related processor class, deleted associated imports and fields.
ProfileService Refactor
src/main/java/life/mosu/mosuserver/application/profile/ProfileService.java
Changed profile registration to use SignUpProfileRequest, replaced profile existence check with role-based check, removed redundant save method, and extended user info synchronization to include phone number.
UserService Update
src/main/java/life/mosu/mosuserver/application/user/UserService.java
Extended syncUserInfoFromProfile to include phone number when updating user info.
UserJpaEntity Update
src/main/java/life/mosu/mosuserver/domain/user/UserJpaEntity.java
Added phoneNumber parameter to updateOAuthUser and updateUserInfo methods, updating the field accordingly.
OAuthUserInfo Extension
src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserInfo.java
Added phoneNumber field to OAuthUserInfo record, added logging annotation and debug log in ofKakao method, with placeholder phone number and TODO comment.
OAuthUserService Null Handling & Role Update
src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserService.java
Improved null checks and default values for email, gender, and name when creating new OAuth users; changed default birth date and user role; added phone number handling in user update method.
Profile DTO Changes
src/main/java/life/mosu/mosuserver/presentation/profile/ProfileController.java,
src/main/java/life/mosu/mosuserver/presentation/profile/ProfileControllerDocs.java,
src/main/java/life/mosu/mosuserver/presentation/profile/dto/ProfileRequest.java,
src/main/java/life/mosu/mosuserver/presentation/profile/dto/SignUpProfileRequest.java
Replaced usage of deprecated ProfileRequest DTO with SignUpProfileRequest in controller, docs, and DTO package; deleted ProfileRequest record; adjusted import statements and package declarations accordingly.
Auth DTO Import Update
src/main/java/life/mosu/mosuserver/presentation/auth/dto/SignUpRequest.java
Added import for SignUpProfileRequest to support updated profile request DTO usage.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant InquiryController
    participant InquiryService

    Client->>InquiryController: create(request, PrincipalDetails)
    InquiryController->>InquiryService: createInquiry(user, request)
    InquiryService->>InquiryService: hasPermission(user, inquiry)
    InquiryService-->>InquiryController: (success or error)
    InquiryController-->>Client: Response
Loading
sequenceDiagram
    participant Client
    participant AccessTokenFilter

    Client->>AccessTokenFilter: HTTP Request
    AccessTokenFilter->>AccessTokenFilter: Check skippedUrlPrefixes
    alt Skipped
        AccessTokenFilter-->>Client: Proceed without token validation
    else Not Skipped
        AccessTokenFilter->>AccessTokenFilter: Validate token
        AccessTokenFilter-->>Client: Proceed or error
    end
Loading
sequenceDiagram
    participant Client
    participant SignUpTokenService

    Client->>SignUpTokenService: validateSignUpToken(token)
    alt Token is null
        SignUpTokenService-->>Client: Throw NOT_FOUND_SIGN_UP_TOKEN
    else Token not found
        SignUpTokenService-->>Client: Throw INVALID_SIGN_UP_TOKEN
    else Token valid
        SignUpTokenService->>SignUpTokenService: Delete token
        SignUpTokenService-->>Client: (void)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15–20 minutes

Suggested reviewers

  • jbh010204
  • polyglot-k

Poem

A hop, a skip, a check for rights,
Now tokens guard the server nights.
Controllers learn to trust the spring,
While docs and configs lose a string.
With errors clear and code concise,
This bunny says: "Reviewing's nice!"
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

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

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

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.

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 primarily focuses on enhancing the authorization mechanisms within the application, particularly for inquiry management. It refactors how user permissions are checked by passing UserJpaEntity directly to service methods and introducing a centralized permission check. Additionally, the token filtering logic has been streamlined to improve clarity and maintainability, and error handling for sign-up tokens has been made more granular.

Highlights

  • Authorization Enhancement: Implemented a new hasPermission utility in InquiryService to centralize access control for inquiry creation and deletion, ensuring only the post owner or an ADMIN can perform these actions. This refactors how user permissions are checked by passing UserJpaEntity directly to service methods.
  • API Contract Update: Modified InquiryController and its documentation to pass PrincipalDetails (containing UserJpaEntity) directly to service methods for authorization, replacing the previous userId parameter and removing the custom @UserId annotation.
  • Token Filter Refinement: The AccessTokenFilter now uses a predefined list of skippedUrlPrefixes to bypass token validation for specific public or authentication-related endpoints (e.g., login, logout, OAuth, Swagger/API docs), simplifying the filter logic and removing hardcoded endpoint checks and the reissueEndpoint configuration.
  • Sign-Up Token Validation Improvement: The SignUpTokenService now uses more specific CustomRuntimeException and ErrorCode for token validation failures, providing clearer error messages and improving robustness, and no longer returns the SignUpToken object after validation.
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

The pull request enhances authorization by integrating Spring Security's PrincipalDetails and refactoring the AccessTokenFilter. The changes improve code clarity and security. The review suggests improvements such as reordering the permission check in InquiryService, hiding PrincipalDetails from Swagger documentation, correcting a syntax issue in ErrorCode, updating the Javadoc in SignUpTokenService, and extracting the signup URL to a constant in AccessTokenFilter.

Comment on lines +137 to +138
REFUND_CALCULATION_FAILED(HttpStatus.CONFLICT, "환불 금액 계산에 실패하였습니다."),
;

Choose a reason for hiding this comment

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

high

The last enum value REFUND_CALCULATION_FAILED should not have a comma after it. This is a syntax issue that could cause problems.

Suggested change
REFUND_CALCULATION_FAILED(HttpStatus.CONFLICT, "환불 금액 계산에 실패하였습니다."),
;
REFUND_CALCULATION_FAILED(HttpStatus.CONFLICT, "환불 금액 계산에 실패하였습니다.")
;

public void createInquiry(UserJpaEntity user, InquiryCreateRequest request) {
InquiryJpaEntity inquiryEntity = inquiryJpaRepository.save(request.toEntity(user));

hasPermission(inquiryEntity.getUserId(), user);

Choose a reason for hiding this comment

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

medium

The hasPermission check is performed after saving the inquiry. It's more appropriate to perform this check before saving to prevent unnecessary database operations if the user lacks permission. This can improve efficiency and prevent potential data inconsistencies.

Comment on lines +69 to 72
PrincipalDetails principalDetails,
@Parameter(name = "postId", description = "삭제할 문의의 ID", in = ParameterIn.PATH)
@PathVariable Long postId
);

Choose a reason for hiding this comment

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

medium

The principalDetails parameter in the deleteInquiry method should be hidden from the API documentation because it's resolved by Spring Security and not provided directly by the client. Hiding it will prevent confusion for API consumers.

Suggested change
PrincipalDetails principalDetails,
@Parameter(name = "postId", description = "삭제할 문의의 ID", in = ParameterIn.PATH)
@PathVariable Long postId
);
@Parameter(hidden = true) PrincipalDetails principalDetails,
@Parameter(name = "postId", description = "삭제할 문의의 ID", in = ParameterIn.PATH)
@PathVariable Long postId

*
* @param token 검증할 토큰
* @return 유효한 SignUpToken 객체
* @throws AuthenticationException 토큰이 유효하지 않을 경우

Choose a reason for hiding this comment

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

medium

The @throws tag should refer to CustomRuntimeException instead of AuthenticationException to accurately reflect the exceptions thrown by this method.

Suggested change
* @throws AuthenticationException 토큰이 유효하지 않을 경우
* @throws CustomRuntimeException 토큰이 유효하지 않을 경우

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: 2

🧹 Nitpick comments (2)
src/main/java/life/mosu/mosuserver/presentation/oauth/SignUpTokenService.java (1)

19-25: Update JavaDoc to match the new method signature.

The method signature correctly changed to void for a validation method, but the JavaDoc still mentions returning a SignUpToken object, which is now inconsistent.

     /**
-     * 회원가입 토큰을 검증하고, 유효하면 SignUpToken 객체를 반환합니다.
+     * 회원가입 토큰을 검증합니다. 유효하지 않으면 예외를 발생시킵니다.
      *
      * @param token 검증할 토큰
-     * @throws AuthenticationException 토큰이 유효하지 않을 경우
+     * @throws CustomRuntimeException 토큰이 유효하지 않거나 찾을 수 없을 경우
      */
src/main/java/life/mosu/mosuserver/application/inquiry/InquiryService.java (1)

9-9: Consider adding logging statements or remove unused @slf4j.

The @Slf4j annotation and UserRole import were added, but no logging statements are visible in the provided code. If logging isn't being used, consider removing the annotation to avoid unused dependencies.

Also applies to: 17-17, 24-24

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between aa0bf3b and 4f07bf4.

📒 Files selected for processing (8)
  • src/main/java/life/mosu/mosuserver/application/inquiry/InquiryService.java (4 hunks)
  • src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java (2 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/auth/AuthControllerDocs.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryController.java (5 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryControllerDocs.java (4 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/oauth/AccessTokenFilter.java (4 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/oauth/SignUpTokenService.java (1 hunks)
  • src/main/resources/security-config.yml (0 hunks)
💤 Files with no reviewable changes (2)
  • src/main/resources/security-config.yml
  • src/main/java/life/mosu/mosuserver/presentation/auth/AuthControllerDocs.java
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/java/life/mosu/mosuserver/presentation/oauth/SignUpTokenService.java (1)
src/main/java/life/mosu/mosuserver/application/auth/provider/OneTimeTokenProvider.java (1)
  • Service (16-66)
🔇 Additional comments (16)
src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java (2)

30-31: LGTM! Well-structured error code addition.

The new INVALID_SIGN_UP_TOKEN error code follows existing conventions with appropriate HTTP status and clear Korean error message. It's properly placed in the sign-up token error section.


137-137: Good syntax cleanup.

Removing the trailing comma before the semicolon improves code consistency and follows proper Java enum syntax conventions.

src/main/java/life/mosu/mosuserver/presentation/oauth/SignUpTokenService.java (3)

7-8: LGTM! Proper imports for enhanced exception handling.

The added imports support the transition to using CustomRuntimeException with specific error codes, improving error handling consistency across the application.


26-28: Excellent defensive programming with proper error handling.

The explicit null check prevents potential NullPointerException and provides clear error messaging using the appropriate NOT_FOUND_SIGN_UP_TOKEN error code.


32-34: LGTM! Improved exception handling with specific error codes.

The change from AuthenticationException to CustomRuntimeException with the specific INVALID_SIGN_UP_TOKEN error code provides better error specificity and aligns with the application's centralized exception handling approach.

src/main/java/life/mosu/mosuserver/presentation/oauth/AccessTokenFilter.java (4)

10-10: LGTM! Required import for the refactored URL handling.

The List import is necessary to support the new consolidated approach for handling skipped URL prefixes.


24-33: Excellent refactoring! Centralized and maintainable URL configuration.

Consolidating all skipped URL prefixes into a single immutable list significantly improves maintainability and makes it easier to manage which endpoints bypass token validation. The use of List.of() is appropriate for static configuration.


47-56: Excellent code simplification with improved readability.

The replacement of multiple conditional checks with a single stream-based approach using anyMatch and startsWith maintains the same functionality while significantly improving code readability and maintainability. The added logging is also helpful for debugging.


104-104: Minor formatting improvement.

The added blank line improves code readability by providing visual separation between the conditional logic and the return statement.

src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryControllerDocs.java (2)

12-12: LGTM: Import updates align with authorization enhancement.

The addition of PrincipalDetails and @AuthenticationPrincipal imports properly supports the shift from custom user ID extraction to Spring Security's standard authentication principal approach.

Also applies to: 23-23


36-36: LGTM: Consistent use of @AuthenticationPrincipal annotation.

The create method properly uses @AuthenticationPrincipal PrincipalDetails which aligns with Spring Security best practices for accessing authenticated user information.

src/main/java/life/mosu/mosuserver/application/inquiry/InquiryService.java (2)

61-63: LGTM: Proper permission check placement for deletion.

The permission validation is correctly placed before the deletion operation, preventing unauthorized access and avoiding unnecessary processing.


88-92: LGTM: Well-implemented centralized permission check.

The hasPermission method properly implements role-based and ownership-based authorization logic, checking both admin privileges and resource ownership. The use of appropriate error codes enhances the user experience.

src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryController.java (3)

4-4: LGTM: Proper imports for Spring Security integration.

The addition of PrincipalDetails and @AuthenticationPrincipal imports correctly supports the authorization enhancement by integrating with Spring Security's authentication context.

Also applies to: 21-21


43-45: LGTM: Consistent authentication principal usage.

The controller properly extracts the user entity from PrincipalDetails and passes it to the service layer, maintaining the authentication context throughout the call chain.


74-80: LGTM: Well-structured method with proper authorization flow.

The deleteInquiry method correctly:

  • Uses @AuthenticationPrincipal for consistent authentication handling
  • Extracts the user entity from PrincipalDetails
  • Maintains the @PreAuthorize annotation for layered security
  • Passes the full user context to the service layer

Comment on lines +36 to 41
public void createInquiry(UserJpaEntity user, InquiryCreateRequest request) {
InquiryJpaEntity inquiryEntity = inquiryJpaRepository.save(request.toEntity(user));

hasPermission(inquiryEntity.getUserId(), user);
inquiryAttachmentService.createAttachment(request.attachments(), inquiryEntity);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Move permission check before inquiry creation for efficiency.

The permission check occurs after saving the inquiry entity, which could result in unnecessary database writes if the user lacks permission. Consider restructuring to validate permissions before persistence.

Apply this diff to move the permission check:

 public void createInquiry(UserJpaEntity user, InquiryCreateRequest request) {
+    // Pre-validate user has permission to create inquiries for themselves
+    // (This assumes the request contains user context or we validate current user can create)
     InquiryJpaEntity inquiryEntity = inquiryJpaRepository.save(request.toEntity(user));
-
-    hasPermission(inquiryEntity.getUserId(), user);
     inquiryAttachmentService.createAttachment(request.attachments(), inquiryEntity);
 }

Note: Since the user is creating their own inquiry, the permission check may be redundant here unless there are specific business rules about inquiry creation.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main/java/life/mosu/mosuserver/application/inquiry/InquiryService.java
between lines 36 and 41, the permission check is currently performed after
saving the inquiry entity, which can cause unnecessary database writes if the
user lacks permission. To fix this, move the hasPermission call to before the
inquiryJpaRepository.save invocation to validate permissions prior to
persistence. This ensures that the inquiry is only saved if the user has the
appropriate permissions.

@ApiResponse(responseCode = "200", description = "질문 삭제 성공")
})
ResponseEntity<ApiResponseWrapper<Void>> deleteInquiry(
PrincipalDetails principalDetails,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add missing @AuthenticationPrincipal annotation for consistency.

The deleteInquiry method signature uses PrincipalDetails but is missing the @AuthenticationPrincipal annotation, unlike the create method. This inconsistency could cause confusion and potential runtime issues.

Apply this diff to fix the inconsistency:

-    ResponseEntity<ApiResponseWrapper<Void>> deleteInquiry(
-            PrincipalDetails principalDetails,
+    ResponseEntity<ApiResponseWrapper<Void>> deleteInquiry(
+            @AuthenticationPrincipal PrincipalDetails principalDetails,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
PrincipalDetails principalDetails,
ResponseEntity<ApiResponseWrapper<Void>> deleteInquiry(
@AuthenticationPrincipal PrincipalDetails principalDetails,
🤖 Prompt for AI Agents
In
src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryControllerDocs.java
at line 69, the method parameter PrincipalDetails is missing the
@AuthenticationPrincipal annotation. Add the @AuthenticationPrincipal annotation
before PrincipalDetails to maintain consistency with the create method and avoid
potential runtime issues.

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: 2

🧹 Nitpick comments (2)
src/main/java/life/mosu/mosuserver/application/auth/AuthService.java (1)

46-53: Refactor for improved readability and conciseness.

The current if-else-if structure can be simplified. The final return Boolean.FALSE is redundant since the else-if already handles the ROLE_PENDING case.

Consider this more concise implementation:

 private Boolean isProfileRegistered(UserJpaEntity user) {
-    if (user.getUserRole() == UserRole.ROLE_USER) {
-        return Boolean.TRUE;
-    } else if (user.getUserRole() == UserRole.ROLE_PENDING) {
-        return Boolean.FALSE;
-    }
-    return Boolean.FALSE;
+    return user.getUserRole() == UserRole.ROLE_USER;
 }

This simplification assumes that only ROLE_USER indicates a registered profile, while all other roles (including ROLE_PENDING) indicate an unregistered profile.

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

61-61: TODO comment indicates incomplete implementation.

The TODO comment suggests that handling of null Kakao information and service term approval needs further implementation. This could lead to issues in production.

Would you like me to help implement the null value handling logic or create an issue to track this task?

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4f07bf4 and bd49672.

📒 Files selected for processing (16)
  • src/main/java/life/mosu/mosuserver/application/auth/AuthService.java (3 hunks)
  • src/main/java/life/mosu/mosuserver/application/auth/SignUpService.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/application/auth/processor/SignUpProfileStepProcessor.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserInfo.java (2 hunks)
  • src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserService.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/application/profile/ProfileService.java (3 hunks)
  • src/main/java/life/mosu/mosuserver/application/user/UserService.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/domain/user/UserJpaEntity.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/auth/AuthController.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/auth/AuthControllerDocs.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/auth/dto/SignUpRequest.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/oauth/AccessTokenFilter.java (4 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/profile/ProfileController.java (2 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/profile/ProfileControllerDocs.java (2 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/profile/dto/ProfileRequest.java (0 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/profile/dto/SignUpProfileRequest.java (1 hunks)
💤 Files with no reviewable changes (5)
  • src/main/java/life/mosu/mosuserver/presentation/auth/AuthController.java
  • src/main/java/life/mosu/mosuserver/presentation/auth/AuthControllerDocs.java
  • src/main/java/life/mosu/mosuserver/application/auth/SignUpService.java
  • src/main/java/life/mosu/mosuserver/application/auth/processor/SignUpProfileStepProcessor.java
  • src/main/java/life/mosu/mosuserver/presentation/profile/dto/ProfileRequest.java
✅ Files skipped from review due to trivial changes (2)
  • src/main/java/life/mosu/mosuserver/presentation/auth/dto/SignUpRequest.java
  • src/main/java/life/mosu/mosuserver/presentation/profile/dto/SignUpProfileRequest.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/life/mosu/mosuserver/presentation/oauth/AccessTokenFilter.java
🔇 Additional comments (17)
src/main/java/life/mosu/mosuserver/application/user/UserService.java (1)

34-35: Confirmed signature match in UserJpaEntity – LGTM

Verified that UserJpaEntity.updateUserInfo(Gender, String, String, LocalDate) exactly matches the call in UserService (gender, userName, phoneNumber, birth). The new phone number parameter is correctly placed and typed.

src/main/java/life/mosu/mosuserver/presentation/profile/ProfileController.java (2)

9-9: LGTM! Import updated for DTO refactoring.

Clean import change from ProfileRequest to SignUpProfileRequest as part of the profile registration flow simplification.


34-34: LGTM! Parameter type updated consistently.

The method parameter type is correctly updated to match the new import. The change maintains consistency with the DTO refactoring.

src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserInfo.java (2)

9-11: LGTM! Logging capability added.

The @Slf4j annotation is properly added to enable logging functionality for OAuth user info processing.


17-17: LGTM! Phone number field added to record.

The phoneNumber field is correctly added to the record structure to support enhanced user information.

src/main/java/life/mosu/mosuserver/presentation/profile/ProfileControllerDocs.java (2)

16-16: LGTM! Documentation import updated consistently.

The import change from ProfileRequest to SignUpProfileRequest correctly aligns with the controller refactoring.


29-29: LGTM! API documentation parameter updated.

The method signature in the documentation interface is correctly updated to match the controller implementation.

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

90-100: LGTM! OAuth user update method enhanced with phone number support.

The updateOAuthUser method signature and implementation are correctly updated to include phone number handling. The parameter order is consistent and the field assignment is proper.


102-112: LGTM! User info update method enhanced with phone number support.

The updateUserInfo method signature and implementation are correctly updated to include phone number handling. The parameter order matches the OAuth update method, maintaining consistency across the codebase.

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

6-6: LGTM - UserRole import added for role-based profile checks.

The import addition supports the new role-based profile registration determination logic.


37-37: Verify role-based profile registration logic coverage

All instances of profileJpaRepository.existsByUserId(...) have been removed—only the role-based check remains:

• src/main/java/life/mosu/mosuserver/application/auth/AuthService.java:37
Boolean isProfileRegistered = isProfileRegistered(user);

Please confirm that:

  • Every existing user in your data has the correct role indicating a registered profile.
  • No other parts of the application still rely on repository-based existence checks.
src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserService.java (2)

52-56: LGTM - Phone number support added to OAuth user updates.

The addition of phoneNumber parameter to the updateOAuthUser method call enhances user data synchronization for existing OAuth users. This change is consistent with the broader user profile data handling improvements.


62-67: No unique constraints on email/loginId
Verified that the User JPA entity does not declare any @Column(unique = true) or @Table(uniqueConstraints…) for the email or loginId fields. Defaulting to "NA" will not violate database uniqueness constraints.

src/main/java/life/mosu/mosuserver/application/profile/ProfileService.java (4)

7-7: LGTM - Import and DTO changes support refactored profile registration.

The addition of UserRole import and change from ProfileRequest to SignUpProfileRequest align with the broader refactoring of profile registration logic.

Also applies to: 12-12


26-26: Profile registration method simplified and consistent with refactoring.

The changes improve the method by:

  • Using the consolidated SignUpProfileRequest DTO
  • Encapsulating profile existence check in a private method
  • Simplifying profile saving with direct repository call

Also applies to: 30-30, 33-33


56-60: Role-based profile existence check aligns with architectural changes.

The method correctly implements the new role-based approach where ROLE_PENDING indicates no profile exists yet, while other roles indicate an existing profile. This is consistent with the changes in AuthService.


62-65: Enhanced user info synchronization with phone number support.

The method now synchronizes phone number data along with gender, username, and birth date. This enhancement is consistent with the broader phone number support added across the user management system.

Comment on lines +32 to +33
//TODO: 카카오 승인 시 파씽 로직 고도화
log.info("Kakao attributes: {}", attributes);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Security concern: Potential PII exposure in logs.

Logging OAuth attributes at INFO level may expose sensitive user information including email, phone numbers, and other personal data.

Consider using DEBUG level and sanitizing sensitive data:

-        log.info("Kakao attributes: {}", attributes);
+        log.debug("Kakao attributes received for user: {}", 
+            attributes.containsKey("kakao_account") ? "present" : "missing");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
//TODO: 카카오 승인 시 파씽 로직 고도화
log.info("Kakao attributes: {}", attributes);
//TODO: 카카오 승인 시 파씅 로직 고도화
log.debug("Kakao attributes received for user: {}",
attributes.containsKey("kakao_account") ? "present" : "missing");
🤖 Prompt for AI Agents
In src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserInfo.java
around lines 32 to 33, the code logs OAuth attributes at INFO level, which risks
exposing sensitive personal information. Change the log level from INFO to DEBUG
and sanitize or mask any personally identifiable information before logging to
prevent PII exposure.

String gender = null;
String birthDay = null;
String birthYear = null;
String phoneNumber = "010-1234-5678";
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Critical issue: Hardcoded phone number and incomplete builder.

Two issues found:

  1. Hardcoded placeholder phone number "010-1234-5678"
  2. The phoneNumber field is not included in the builder call (lines 52-55)

Apply this fix to include phoneNumber in the builder and use the actual value:

             return OAuthUserInfo.builder()
                     .name(name)
                     .email("test123@gmali.com")
+                    .phoneNumber(phoneNumber)
                     .build();

Also consider extracting phone number from Kakao attributes instead of using hardcoded value when the TODO is addressed.

🤖 Prompt for AI Agents
In src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserInfo.java at
line 40, replace the hardcoded phone number string with a variable that will
hold the actual phone number value. Then, in the builder call between lines 52
and 55, add the phoneNumber field to ensure it is properly set when creating the
object. Later, update the code to extract the phone number dynamically from
Kakao attributes instead of using a hardcoded value once the related TODO is
implemented.

@wlgns12370 wlgns12370 merged commit edb214c into develop Jul 28, 2025
2 checks passed
@wlgns12370 wlgns12370 deleted the refactor/mosu-152 branch July 28, 2025 14:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[🛠 리팩토링] 인가 고도화

2 participants