Skip to content

Conversation

@jbh010204
Copy link
Member

@jbh010204 jbh010204 commented Aug 10, 2025

✨ 구현한 기능

📢 논의하고 싶은 내용

🎸 기타

Summary by CodeRabbit

  • New Features

    • Inquiry lists now include both the inquiry and its answer, allowing users to view responses directly alongside their inquiries.
  • Bug Fixes

    • Inquiry lists are consistently ordered by creation date in descending order.
  • Documentation

    • Updated API documentation to reflect the new inquiry list response structure.
  • Refactor

    • Inquiry-related APIs and services updated to use a new response format that includes both inquiry and answer details.
    • Removed unused factory method from inquiry response data.

@coderabbitai
Copy link

coderabbitai bot commented Aug 10, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Caution

Review failed

The pull request is closed.

Walkthrough

This change updates the inquiry listing flow to return both inquiries and their associated answers. It introduces new DTOs (InquiryListResponse, InquiryAnswerResponse), modifies method signatures and queries to support the enriched response, and updates controller and documentation layers accordingly. The InquiryResponse.of factory method is also removed.

Changes

Cohort / File(s) Change Summary
Inquiry Listing/Answer DTOs
src/main/java/life/mosu/mosuserver/presentation/inquiry/dto/InquiryListResponse.java, src/main/java/life/mosu/mosuserver/presentation/inquiry/dto/InquiryAnswerResponse.java
Added new record DTOs for wrapping inquiry and answer data, with static factory methods for instantiation.
Inquiry Response DTO
src/main/java/life/mosu/mosuserver/presentation/inquiry/dto/InquiryResponse.java
Removed the static factory method of(InquiryJpaEntity inquiry) and its associated import.
Service & Repository Layer
src/main/java/life/mosu/mosuserver/application/inquiry/InquiryService.java, src/main/java/life/mosu/mosuserver/domain/inquiry/repository/InquiryQueryRepository.java
Changed method signatures from returning Page<InquiryResponse> to Page<InquiryListResponse> for inquiry listing, updating imports accordingly.
JPA Repository Implementation
src/main/java/life/mosu/mosuserver/infra/persistence/jpa/InquiryJpaRepositoryImpl.java
Enhanced the query to join inquiries with their answers, updated mapping logic, changed return type to Page<InquiryListResponse>, and adjusted sorting and pagination.
Controller & Docs
src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryController.java, src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryControllerDocs.java
Updated method signatures and usages to return Page<InquiryListResponse>, adjusted imports, and reformatted code for clarity.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller
    participant Service
    participant Repository
    participant DB

    Client->>Controller: GET /my-inquiries
    Controller->>Service: getMyInquiry(userId, pageable)
    Service->>Repository: searchMyInquiry(userId, pageable)
    Repository->>DB: Query inquiries LEFT JOIN answers
    DB-->>Repository: Inquiry + Answer rows
    Repository->>Service: Page<InquiryListResponse>
    Service->>Controller: Page<InquiryListResponse>
    Controller->>Client: ApiResponseWrapper<Page<InquiryListResponse>>
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Possibly related PRs

Suggested reviewers

  • wlgns12370
  • chominju02

Poem

In the warren of code, a new path appears,
Inquiries and answers, now bundled as peers.
With DTOs fresh and queries anew,
Rabbits rejoice—responses grew!
Hop along, reviewers, and don’t be shy,
For answers and questions now both reply!
🐇✨

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.


📜 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 da43546 and 1e4f080.

📒 Files selected for processing (2)
  • src/main/java/life/mosu/mosuserver/infra/persistence/jpa/InquiryJpaRepositoryImpl.java (6 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/inquiry/dto/InquiryAnswerResponse.java (1 hunks)
✨ 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-287

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.
  • 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.

Support

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

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 @jbh010204, 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!

I've refactored the 'my inquiries' feature to now include the corresponding answers when a user views their questions. This change enhances the user experience by providing a more complete view of their past interactions without needing to fetch answers separately.

Highlights

  • Enhanced Inquiry Listing: The getMyInquiry method across the service, repository, and controller layers now returns a new InquiryListResponse DTO, which encapsulates both the inquiry details and its associated answer.
  • New DTOs Introduced: Two new DTOs, InquiryAnswerResponse and InquiryListResponse, have been added to structure the combined inquiry and answer data.
  • Query Optimization: A new baseQueryWithAnswer method has been implemented in InquiryJpaRepositoryImpl to efficiently fetch inquiry and answer data using a left join, ensuring answers are included when available.
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 refactors the inquiry retrieval functionality to include answers along with the questions, which is a valuable enhancement. The implementation is solid, using a LEFT JOIN to fetch optional answers and introducing new DTOs for a structured response. I particularly appreciate the decoupling of DTOs from JPA entities, which improves the application's architecture. My review includes a few suggestions for improving code consistency and removing redundant code.

.offset(pageable.getOffset())
.limit(pageable.getPageSize());
JPAQuery<Tuple> query = baseQuery()
.where(buildStatusCondition(inquiry, status));

Choose a reason for hiding this comment

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

medium

The baseQuery method was refactored to use the class field inquiry instead of taking it as a parameter, which is a good change. For consistency, the buildStatusCondition method should also be updated to not take the QInquiryJpaEntity inquiry parameter and instead use the class field. This would align it with the implementation of buildOrderByCondition and improve code clarity.

@jbh010204 jbh010204 merged commit 8af2cdb into develop Aug 10, 2025
2 checks passed
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: 3

🧹 Nitpick comments (7)
src/main/java/life/mosu/mosuserver/domain/inquiry/repository/InquiryQueryRepository.java (1)

14-15: Domain repository returning presentation DTOs couples layers; consider decoupling.

The domain repository interface now returns Page<InquiryListResponse> (presentation DTO). This continues the cross-layer dependency that was already present with InquiryResponse.

Consider:

  • Returning a domain/query projection (interface or record) from the repository.
  • Mapping to presentation DTOs in the service/presentation layer.
  • Alternatively, keep projections in infra (JpaRepositoryImpl) and map there.

This reduces coupling and eases DTO evolution without repository interface churn.

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

35-43: Update summary/response docs to reflect answers included in the list.

The endpoint now returns inquiries with answers. Consider clarifying in the summary/description and using a more specific schema example for InquiryListResponse.

Example:

  • Update summary to: “내 문의글 및 답변 조회”
  • Provide an example schema for InquiryListResponse if you maintain example payloads.
src/main/java/life/mosu/mosuserver/presentation/inquiry/dto/InquiryListResponse.java (2)

3-14: Align field naming with DTO type (replyanswer) for consistency.

InquiryAnswerResponse is exposed as reply. Renaming improves clarity and consistency across layers.

 package life.mosu.mosuserver.presentation.inquiry.dto;

-public record InquiryListResponse(
-        InquiryResponse inquiry,
-        InquiryAnswerResponse reply
-) {
+public record InquiryListResponse(
+        InquiryResponse inquiry,
+        InquiryAnswerResponse answer
+) {
 
-    public static InquiryListResponse of(
-            InquiryResponse inquiry,
-            InquiryAnswerResponse reply
-    ) {
-        return new InquiryListResponse(inquiry, reply);
+    public static InquiryListResponse of(
+            InquiryResponse inquiry,
+            InquiryAnswerResponse answer
+    ) {
+        return new InquiryListResponse(inquiry, answer);
     }
 }

1-14: Add Swagger annotations to document the composite response.

Improve API docs by annotating the record and its fields.

+import io.swagger.v3.oas.annotations.media.Schema;
+
- public record InquiryListResponse(
-         InquiryResponse inquiry,
-         InquiryAnswerResponse reply
- ) {
+@Schema(description = "내 문의글 목록 항목 (문의 + 답변)")
+public record InquiryListResponse(
+        @Schema(description = "문의 정보")
+        InquiryResponse inquiry,
+        @Schema(description = "문의 답변 정보 (없을 수 있음)", nullable = true)
+        InquiryAnswerResponse reply
+) {

If you adopt the previous rename to answer, update the field name here as well.

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

3-9: Consider using temporal types instead of Strings for timestamps

Represent createdAt/updatedAt as LocalDateTime/Instant and let Jackson format them (e.g., via @jsonformat or global ObjectMapper). This preserves ordering/timezone semantics and avoids pre-formatting in the repository layer.


11-19: Remove redundant factory method or use it consistently

The of(...) method adds no behavior over the canonical record constructor and isn’t used in mappings. Prefer removing it to keep API minimal, or consistently use it everywhere for symmetry.

Apply this diff if you choose to remove it:

-    public static InquiryAnswerResponse of(
-            String title,
-            String content,
-            String author,
-            String createdAt,
-            String updatedAt
-    ) {
-        return new InquiryAnswerResponse(title, content, author, createdAt, updatedAt);
-    }
src/main/java/life/mosu/mosuserver/infra/persistence/jpa/InquiryJpaRepositoryImpl.java (1)

94-113: Join and projection look correct; ensure uniqueness constraints if 1:1

Projection includes only needed fields. Left join on inquiryAnswer.inquiryId = inquiry.id is fine. If 1:1 is not enforced, consider redesign as noted earlier to prevent duplicates.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 22a2b70 and da43546.

📒 Files selected for processing (8)
  • src/main/java/life/mosu/mosuserver/application/inquiry/InquiryService.java (2 hunks)
  • src/main/java/life/mosu/mosuserver/domain/inquiry/repository/InquiryQueryRepository.java (2 hunks)
  • src/main/java/life/mosu/mosuserver/infra/persistence/jpa/InquiryJpaRepositoryImpl.java (6 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryController.java (3 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryControllerDocs.java (2 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/inquiry/dto/InquiryAnswerResponse.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/inquiry/dto/InquiryListResponse.java (1 hunks)
  • src/main/java/life/mosu/mosuserver/presentation/inquiry/dto/InquiryResponse.java (1 hunks)
🔇 Additional comments (11)
src/main/java/life/mosu/mosuserver/presentation/inquiry/dto/InquiryResponse.java (1)

26-27: No lingering usages of InquiryResponse.of(...) found
A thorough search – including invocation patterns and static imports – returned no references to the removed factory method. The removal is safe.

src/main/java/life/mosu/mosuserver/domain/inquiry/repository/InquiryQueryRepository.java (1)

4-4: Import addition aligns with signature change.

The added import is consistent with the updated return type for searchMyInquiry. Ensure controller and service are aligned (they appear to be).

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

60-63: No N+1 risk in searchMyInquiry – one query with left join

The searchMyInquiry implementation in InquiryJpaRepositoryImpl uses baseQueryWithAnswer(), which performs a single QueryDSL .select(…) over both Inquiry and InquiryAnswer fields with a .leftJoin(inquiryAnswer).on(inquiryAnswer.inquiryId.eq(inquiry.id)). The result tuples are then mapped to InquiryListResponse in one pass, so there is no N+1 query issue here. No further refactor is required.


60-63: Return types are consistent across service, controller, and docs
All call sites use Page<InquiryListResponse>:

  • InquiryService.getMyInquiry(...) returns Page<InquiryListResponse>.
  • InquiryController.getMyInquiries(...) wraps that in ResponseEntity<ApiResponseWrapper<Page<InquiryListResponse>>>.
  • InquiryControllerDocs defines the same return type.

No further changes or versioning are needed.

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

10-10: Import update aligns with new response model

Switch to InquiryListResponse is correct for enriched responses.


72-73: No functional changes here

Line breaks only; logic remains the same.

src/main/java/life/mosu/mosuserver/infra/persistence/jpa/InquiryJpaRepositoryImpl.java (5)

18-21: Imports align with new join and mapping
Looks correct.


35-35: Answer Q-type initialization looks good
Consistent with other Q fields.


45-56: Refactor improves readability and reuse

Using baseQuery() and a dedicated mapper is clean. Status filtering retained; pagination unchanged.


80-93: Base select is minimal and focused
Good separation for reuse and counting.


151-166: No NPE risk: formatDate is already null-safe
BaseTimeEntity.formatDate(LocalDateTime) guards against null and returns null if the input is null, so calling it on tuple.get(inquiryAnswer.updatedAt) cannot throw an NPE. You can safely keep the existing code unchanged.

Likely an incorrect or invalid review comment.

Comment on lines 61 to 77
@Override
public Page<InquiryResponse> searchMyInquiry(Long userId, Pageable pageable) {
JPAQuery<Tuple> query = baseQuery(inquiry)
public Page<InquiryListResponse> searchMyInquiry(Long userId, Pageable pageable) {
JPAQuery<Tuple> query = baseQueryWithAnswer()
.where(inquiry.userId.eq(userId));

long total = getTotalCount(query, inquiry.count());
long total = getTotalCount(query, inquiry.countDistinct());

List<InquiryResponse> content = query
List<InquiryListResponse> content = query
.orderBy(inquiry.createdAt.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch().stream()
.map(this::mapToResponse)
.map(this::mapToInquiryListResponse)
.toList();

return new PageImpl<>(content, pageable, total);
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Use id-based distinct count and validate 1:1 assumption to avoid paging errors

  • Prefer countDistinct on the id expression to avoid dialect-specific issues:
-        long total = getTotalCount(query, inquiry.countDistinct());
+        long total = getTotalCount(query, inquiry.id.countDistinct());
  • If an inquiry can have multiple answers (1:N), the current content query will duplicate inquiries within a page, causing missing unique items and inconsistent paging. If the domain guarantees 1:1 (Inquiry↔Answer), please confirm this is enforced at the JPA mapping and DB level (unique constraint/index). Otherwise, consider a 2-step fetch (page inquiries, then batch-load answers by IN clause) to guarantee uniqueness without relying on joins.

Script to verify relationship and constraints, and confirm service/docs alignment:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect InquiryAnswer entity for 1:1 mapping or uniqueness
fd -a "InquiryAnswerJpaEntity.java" | xargs -r -I{} rg -n --no-heading -A3 -B3 "@OneToOne|@ManyToOne|unique|UniqueConstraint|inquiryId|inquiry" {}

# Check BaseTimeEntity.formatDate implementation for null-safety
fd -a "BaseTimeEntity.java" | xargs -r -I{} rg -n --no-heading -A2 -B2 "static .*formatDate|DateTimeFormatter|null" {}

# Confirm service method return type
rg -n "interface\\s+InquiryQueryRepository|class\\s+InquiryService" -A 50 -S | rg -n "searchMyInquiry\\(|getMyInquiry\\(" -n -S

Length of output: 2736


Use id-based distinct count and prevent duplicate paging issues

In InquiryJpaRepositoryImpl.searchMyInquiry, switch from inquiry.countDistinct() to inquiry.id.countDistinct() so that the total count reflects unique inquiry IDs and avoids dialect-specific quirks:

- long total = getTotalCount(query, inquiry.countDistinct());
+ long total = getTotalCount(query, inquiry.id.countDistinct());

Currently, InquiryAnswerJpaEntity defines inquiryId as a simple @Column (no @OneToOne or unique constraint), so an inquiry with multiple answers will produce duplicate rows in content (and incorrect page sizes). To address this, choose one of the following:

  • Enforce 1:1: Add a unique constraint on inquiry_id in the inquiry_answer table (via JPA @Table(uniqueConstraints=…) or a DB migration) and map it with @OneToOne in the entity.
  • Use a two-step fetch:
    1. Query only distinct inquiry IDs (paged).
    2. Batch-load answers for those IDs and map to InquiryListResponse.

Either approach will ensure unique items per page and consistent paging.

🤖 Prompt for AI Agents
In
src/main/java/life/mosu/mosuserver/infra/persistence/jpa/InquiryJpaRepositoryImpl.java
around lines 61 to 77, the total count query uses inquiry.countDistinct(), which
can cause duplicate counts due to multiple answers per inquiry. Change this to
use inquiry.id.countDistinct() to count unique inquiry IDs. Additionally, to
prevent duplicate rows in the paged content caused by multiple answers per
inquiry, either enforce a one-to-one relationship by adding a unique constraint
on inquiry_id in the inquiry_answer table and mapping it with @OneToOne, or
implement a two-step fetch: first query distinct inquiry IDs with pagination,
then batch-load their answers and map to InquiryListResponse. This will ensure
unique items per page and correct paging behavior.

Comment on lines +57 to 64
public ResponseEntity<ApiResponseWrapper<Page<InquiryListResponse>>> getMyInquiries(
@UserId Long userId,
@PageableDefault(size = 10) Pageable pageable
) {
Page<InquiryResponse> inquiries = inquiryService.getMyInquiry(userId, pageable);
return ResponseEntity.ok(ApiResponseWrapper.success(HttpStatus.OK, "내 질문 목록 조회 성공", inquiries));
Page<InquiryListResponse> inquiries = inquiryService.getMyInquiry(userId, pageable);
return ResponseEntity.ok(
ApiResponseWrapper.success(HttpStatus.OK, "내 질문 목록 조회 성공", inquiries));
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Return type change looks good; ensure upstream/downstream alignment

The switch to Page matches the PR goal. Minor consistency nit: other endpoints use PrincipalDetails.user() while this one uses @userid Long — consider standardizing.

Run to verify signatures/docs are updated:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Service method signature
rg -n "getMyInquiry\\s*\\(" -A 5 -S

# Docs interface return type alignment
fd -a "InquiryControllerDocs.java" | xargs -r rg -n "getMyInquiries|InquiryListResponse|Page<"

# DTO usage across layers
rg -n "InquiryListResponse" -S

Length of output: 4965


Return type change verified across layers

The switch to Page<InquiryListResponse> is applied consistently in:

  • Controller (src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryController.java)
  • Service (src/main/java/life/mosu/mosuserver/application/inquiry/InquiryService.java)
  • Repository (src/main/java/life/mosu/mosuserver/infra/persistence/jpa/InquiryJpaRepositoryImpl.java)
  • API docs (src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryControllerDocs.java)

Minor consistency nit: most controllers inject the current user via PrincipalDetails user, whereas getMyInquiries uses @UserId Long userId. Consider standardizing on one approach for clarity and uniformity.

🤖 Prompt for AI Agents
In
src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryController.java
around lines 57 to 64, the method getMyInquiries currently injects the user
identifier using @UserId Long userId, while most other controllers use
PrincipalDetails user for the current user injection. To maintain consistency
and clarity across the codebase, refactor getMyInquiries to accept
PrincipalDetails user as a parameter instead of @UserId Long userId, then
extract the user ID from PrincipalDetails within the method before calling the
service layer.

Comment on lines +40 to 43
ResponseEntity<ApiResponseWrapper<Page<InquiryListResponse>>> getMyInquiries(
@Parameter(description = "사용자 ID", required = true) Long userId,
@Parameter(description = "페이지 정보") Pageable pageable
);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Security: don’t accept userId from clients for “my” resources; use PrincipalDetails.

“My inquiries” should derive the user id from the authenticated principal, not a request parameter. Accepting userId enables IDOR.

Proposed docs interface update:

-    ResponseEntity<ApiResponseWrapper<Page<InquiryListResponse>>> getMyInquiries(
-            @Parameter(description = "사용자 ID", required = true) Long userId,
-            @Parameter(description = "페이지 정보") Pageable pageable
-    );
+    ResponseEntity<ApiResponseWrapper<Page<InquiryListResponse>>> getMyInquiries(
+            @Parameter(hidden = true) PrincipalDetails principalDetails,
+            @Parameter(description = "페이지 정보") Pageable pageable
+    );

Ensure the controller implementation uses principalDetails.getUser().getId() (or equivalent) and ignores any user id from client input.

📝 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
ResponseEntity<ApiResponseWrapper<Page<InquiryListResponse>>> getMyInquiries(
@Parameter(description = "사용자 ID", required = true) Long userId,
@Parameter(description = "페이지 정보") Pageable pageable
);
ResponseEntity<ApiResponseWrapper<Page<InquiryListResponse>>> getMyInquiries(
@Parameter(hidden = true) PrincipalDetails principalDetails,
@Parameter(description = "페이지 정보") Pageable pageable
);
🤖 Prompt for AI Agents
In
src/main/java/life/mosu/mosuserver/presentation/inquiry/InquiryControllerDocs.java
around lines 40 to 43, the method getMyInquiries currently accepts a userId
parameter from the client, which poses a security risk. Remove the userId
parameter and instead update the method signature to accept the authenticated
user's details via PrincipalDetails or a similar security principal object.
Ensure the controller implementation retrieves the user ID from the
authenticated principal rather than from client input to prevent IDOR
vulnerabilities.

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.

1 participant