Skip to content

feat: 아티클 상세조회 구현#18

Merged
rootTiket merged 9 commits intodevfrom
feat/#17
Jul 7, 2025
Merged

feat: 아티클 상세조회 구현#18
rootTiket merged 9 commits intodevfrom
feat/#17

Conversation

@rootTiket
Copy link
Contributor

@rootTiket rootTiket commented Jul 7, 2025

🚀 PR 요약

아티클 상세조회 API 를 구현했습니다.

✨ PR 상세 내용

  1. 아티클 상세조회 API를 구현했습니다.
  2. 아티클 api 주소를 복수형으로 변경했습니다.

🚨 주의 사항

없습니다

✅ 체크 리스트

  • 리뷰어 설정했나요?
  • Label 설정했나요?
  • 제목 양식 맞췄나요? (ex. feat: 기능 추가)
  • 변경 사항에 대한 테스트를 진행했나요?

close #17

Summary by CodeRabbit

  • New Features

    • Added an endpoint to retrieve detailed information for a specific article, including URL, memo, reminder time, and category details.
    • Introduced a new response format for article details.
    • Added support for an optional reminder time when creating articles.
  • Bug Fixes

    • Improved error handling with a specific message when an article is not found.
  • Tests

    • Enhanced and added tests to verify article detail retrieval and reminder time functionality.

@rootTiket rootTiket requested a review from ose0221 July 7, 2025 15:22
@rootTiket rootTiket self-assigned this Jul 7, 2025
@rootTiket rootTiket added the FEAT label Jul 7, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jul 7, 2025

Walkthrough

This change adds support for retrieving detailed information about an article by its ID, including a new reminder time field. It introduces new DTOs for detailed responses, a new exception for not-found cases, and extends both the domain entity and service layers. Tests and fixtures are updated accordingly.

Changes

File(s) Change Summary
.../domain/article/application/ArticleManagementUsecase.java Added getArticleDetail method; updated createArticle to use remindTime.
.../domain/article/domain/entity/Article.java Added remindAt field; updated create method to accept and set remindAt.
.../domain/article/domain/service/ArticleGetService.java Added findById method with exception handling.
.../domain/article/exception/ArticleNotFoundException.java Introduced new exception class for article not found.
.../domain/article/presentation/ArticleController.java Changed base mapping to /articles; added GET /details/{articleId} endpoint.
.../domain/article/presentation/dto/request/ArticleCreateRequest.java Removed @NotNull from remindTime field.
.../domain/article/presentation/dto/response/ArticleDetailResponse.java Added new response DTO for article details.
.../domain/category/presentation/dto/response/CategoryDetail.java Added new response DTO for category details.
.../global/exception/constant/ExceptionCode.java Added ARTICLE_NOT_FOUND enum constant.
.../domain/article/application/ArticleManagementUsecaseTest.java Added/updated tests for reminder time and article detail retrieval.
.../domain/fixture/TestFixture.java Updated article fixture methods to include remindAt.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ArticleController
    participant ArticleManagementUsecase
    participant ArticleGetService
    participant ArticleRepository

    Client->>ArticleController: GET /articles/details/{articleId}
    ArticleController->>ArticleManagementUsecase: getArticleDetail(articleId)
    ArticleManagementUsecase->>ArticleGetService: findById(articleId)
    ArticleGetService->>ArticleRepository: findById(articleId)
    ArticleRepository-->>ArticleGetService: Article or not found
    ArticleGetService-->>ArticleManagementUsecase: Article or throw ArticleNotFoundException
    ArticleManagementUsecase-->>ArticleController: ArticleDetailResponse
    ArticleController-->>Client: ResponseDto<ArticleDetailResponse>
Loading

Assessment against linked issues

Objective (Issue #) Addressed Explanation
Implement article detail retrieval (#17)

Possibly related PRs

Suggested reviewers

  • ose0221

Poem

A bunny hops through fields of code,
With articles detailed, a brand new load.
Remind me, it says, with a gentle nudge,
If an article’s missing, exceptions won’t budge!
Now queries return, both rich and refined—
This rabbit’s delighted with features combined! 🐇✨


📜 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 bb1a38c and 61abc5b.

📒 Files selected for processing (1)
  • src/test/java/com/pinback/pinback_server/domain/article/application/ArticleManagementUsecaseTest.java (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/test/java/com/pinback/pinback_server/domain/article/application/ArticleManagementUsecaseTest.java
⏰ 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
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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 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

@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/com/pinback/pinback_server/domain/article/presentation/ArticleController.java (1)

32-37: Consider using primitive long for consistency.

The implementation looks good and follows the established controller pattern. However, consider using long instead of Long for the path variable to maintain consistency with the service layer and avoid unnecessary autoboxing.

-	public ResponseDto<ArticleDetailResponse> getArticleDetails(@PathVariable Long articleId) {
+	public ResponseDto<ArticleDetailResponse> getArticleDetails(@PathVariable long articleId) {
src/test/java/com/pinback/pinback_server/domain/fixture/TestFixture.java (1)

26-26: Consider using relative dates for better test maintainability.

The fixture updates properly support the new remindAt field in article creation. However, using a hardcoded future date (2025-07-07) might cause issues in tests that depend on relative time comparisons or when run in different years.

Consider using a relative date approach:

-		return Article.create("test", "testmemo", user, category, LocalDateTime.of(2025, 7, 7, 12, 0, 0));
+		return Article.create("test", "testmemo", user, category, LocalDateTime.now().plusDays(1));

This would make the test data more maintainable and prevent potential issues with time-based assertions.

Also applies to: 30-30

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 52d14ed and bb1a38c.

📒 Files selected for processing (11)
  • src/main/java/com/pinback/pinback_server/domain/article/application/ArticleManagementUsecase.java (2 hunks)
  • src/main/java/com/pinback/pinback_server/domain/article/domain/entity/Article.java (2 hunks)
  • src/main/java/com/pinback/pinback_server/domain/article/domain/service/ArticleGetService.java (2 hunks)
  • src/main/java/com/pinback/pinback_server/domain/article/exception/ArticleNotFoundException.java (1 hunks)
  • src/main/java/com/pinback/pinback_server/domain/article/presentation/ArticleController.java (3 hunks)
  • src/main/java/com/pinback/pinback_server/domain/article/presentation/dto/request/ArticleCreateRequest.java (1 hunks)
  • src/main/java/com/pinback/pinback_server/domain/article/presentation/dto/response/ArticleDetailResponse.java (1 hunks)
  • src/main/java/com/pinback/pinback_server/domain/category/presentation/dto/response/CategoryDetail.java (1 hunks)
  • src/main/java/com/pinback/pinback_server/global/exception/constant/ExceptionCode.java (1 hunks)
  • src/test/java/com/pinback/pinback_server/domain/article/application/ArticleManagementUsecaseTest.java (3 hunks)
  • src/test/java/com/pinback/pinback_server/domain/fixture/TestFixture.java (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/java/com/pinback/pinback_server/domain/article/domain/service/ArticleGetService.java (1)
src/main/java/com/pinback/pinback_server/domain/article/exception/ArticleNotFoundException.java (1)
  • ArticleNotFoundException (6-10)
⏰ 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
🔇 Additional comments (14)
src/main/java/com/pinback/pinback_server/domain/article/presentation/dto/request/ArticleCreateRequest.java (1)

16-16: Good change: Making remindTime optional aligns with business logic.

Removing the @NotNull validation annotation makes the reminder functionality optional, which is a logical design decision since not all articles need reminders.

src/main/java/com/pinback/pinback_server/global/exception/constant/ExceptionCode.java (1)

22-22: LGTM: Exception code follows established patterns.

The new ARTICLE_NOT_FOUND exception code correctly uses HTTP 404 status and follows the consistent error code naming convention.

src/main/java/com/pinback/pinback_server/domain/article/domain/service/ArticleGetService.java (1)

23-25: Clean implementation of article retrieval with proper exception handling.

The findById method correctly uses Optional.orElseThrow with a method reference to handle the case when an article is not found, providing clear error handling.

src/main/java/com/pinback/pinback_server/domain/article/domain/entity/Article.java (2)

54-55: Proper JPA mapping for the new remindAt field.

The remindAt field is correctly mapped to the database column remind_at and allows null values, which is consistent with the optional nature of reminders.


60-60: Factory method properly updated to handle the new field.

The create method signature and builder pattern are correctly updated to include the remindAt parameter, maintaining consistency in the entity creation process.

Also applies to: 67-67

src/main/java/com/pinback/pinback_server/domain/article/application/ArticleManagementUsecase.java (1)

34-34: Correctly integrated remindTime parameter.

The createArticle method properly passes the remindTime from the command to the Article.create method, completing the integration of the reminder functionality.

src/main/java/com/pinback/pinback_server/domain/article/exception/ArticleNotFoundException.java (1)

1-10: LGTM! Clean exception implementation.

The exception class follows the established pattern in the codebase, properly extending ApplicationException and using the predefined error code. The implementation is concise and appropriate for its purpose.

src/main/java/com/pinback/pinback_server/domain/category/presentation/dto/response/CategoryDetail.java (1)

5-15: LGTM! Well-structured DTO record.

The record class properly encapsulates category information with appropriate field types. The static factory method of() follows the established pattern for creating DTOs from entities and correctly maps the entity fields.

src/main/java/com/pinback/pinback_server/domain/article/presentation/ArticleController.java (1)

21-21: LGTM! Improved RESTful endpoint naming.

Changing from /article to /articles follows RESTful conventions using plural form for resource endpoints.

src/main/java/com/pinback/pinback_server/domain/article/presentation/dto/response/ArticleDetailResponse.java (1)

8-23: LGTM! Well-designed response DTO.

The record structure appropriately captures all necessary article details. The static factory method from() correctly maps entity fields to DTO fields and properly handles the category conversion using CategoryDetail.of(). The use of LocalDateTime for remindAt is appropriate for timestamp representation.

src/test/java/com/pinback/pinback_server/domain/fixture/TestFixture.java (1)

3-3: LGTM! Proper import addition.

The LocalDateTime import is correctly added to support the new timestamp field in article creation.

src/test/java/com/pinback/pinback_server/domain/article/application/ArticleManagementUsecaseTest.java (3)

20-20: LGTM!

The import addition for ArticleDetailResponse is necessary for the new test method.


56-56: LGTM!

The assertion correctly validates that the remindAt field is properly set from the command's remindTime parameter, ensuring the new reminder functionality works as expected.


74-93: Comprehensive test coverage for article detail retrieval.

The test effectively validates all aspects of the article detail retrieval functionality:

  • Tests the complete flow from setup to response validation
  • Verifies all response fields (url, memo, category details, remindAt)
  • Follows the AAA (Arrange-Act-Assert) pattern correctly
  • Properly integrates with the existing test fixture methods

The test logic and assertions are well-structured and comprehensive.

Comment on lines +38 to +41
public ArticleDetailResponse getArticleDetail(long articleId) {
Article article = articleGetService.findById(articleId);
return ArticleDetailResponse.from(article);
}
Copy link

@coderabbitai coderabbitai bot Jul 7, 2025

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider adding authorization checks for article access.

The getArticleDetail method correctly retrieves and transforms article data. However, there's no authorization check to ensure users can only access their own articles.

Consider adding a user parameter and verifying article ownership:

-public ArticleDetailResponse getArticleDetail(long articleId) {
+public ArticleDetailResponse getArticleDetail(long articleId, User user) {
     Article article = articleGetService.findById(articleId);
+    if (!article.getUser().equals(user)) {
+        throw new UnauthorizedAccessException();
+    }
     return ArticleDetailResponse.from(article);
}

Run the following script to check if similar authorization patterns exist in the codebase:


🏁 Script executed:

#!/bin/bash
# Check for authorization patterns in other usecase methods
rg -A 5 -B 5 "getUser\(\)\.equals|\.getUser\(\)" --type java

Length of output: 62


I couldn’t find any existing ownership checks or security annotations with the initial pattern search. Let’s broaden the search to see if the codebase uses any custom exception, Spring Security hooks, or user‐fetching utilities:


🏁 Script executed:

#!/bin/bash
# 1. Check for custom unauthorized exception usage
rg -n "UnauthorizedAccessException" --type java

# 2. Search for Spring Security context usage
rg -n "SecurityContextHolder" --type java

# 3. Look for method‐level security annotations
rg -n "@PreAuthorize" --type java

# 4. Find utilities or services fetching the current user
rg -n "getCurrentUser" --type java
rg -n "Principal" --type java

Length of output: 1218


We still need to see how getArticleDetail is being called in your controllers so we can update both layers. Let’s locate all usages:


🏁 Script executed:

#!/bin/bash
# List every occurrence of getArticleDetail in the repo
rg -n "getArticleDetail" --type java

Length of output: 774


Let’s inspect how @CurrentUser is set up and how the controller method is defined so we can align our changes:


🏁 Script executed:

#!/bin/bash
# 1. Show the resolver implementation and annotation it looks for
sed -n '1,200p' src/main/java/com/pinback/pinback_server/global/config/resolver/CurrentUserArgumentResolver.java

# 2. View the controller method signature
sed -n '1,200p' src/main/java/com/pinback/pinback_server/domain/article/presentation/ArticleController.java

# 3. Locate the CurrentUser annotation definition
rg -n "interface CurrentUser" --type java

Length of output: 3820


Enforce article‐ownership check in detail endpoint

The controller and use-case need to accept the authenticated user and verify ownership before returning article details:

• Update ArticleController#getArticleDetails to inject the current user:

@GetMapping("/details/{articleId}")
public ResponseDto<ArticleDetailResponse> getArticleDetails(
    @PathVariable Long articleId,
    @CurrentUser User user
) {
    ArticleDetailResponse response = articleManagementUsecase.getArticleDetail(articleId, user);
    return ResponseDto.ok(response);
}

• Change ArticleManagementUsecase#getArticleDetail to accept User and throw an access‐denied exception if the user doesn’t own the article:

-public ArticleDetailResponse getArticleDetail(long articleId) {
-    Article article = articleGetService.findById(articleId);
-    return ArticleDetailResponse.from(article);
-}
+public ArticleDetailResponse getArticleDetail(long articleId, User user) {
+    Article article = articleGetService.findById(articleId);
+    if (!article.getUser().equals(user)) {
+        throw new org.springframework.security.access.AccessDeniedException(
+            "You do not have permission to view this article"
+        );
+    }
+    return ArticleDetailResponse.from(article);
+}

• Add import in ArticleManagementUsecase:

import org.springframework.security.access.AccessDeniedException;

These changes ensure only the owning user can retrieve article details.

🤖 Prompt for AI Agents
In
src/main/java/com/pinback/pinback_server/domain/article/application/ArticleManagementUsecase.java
around lines 38 to 41, modify the getArticleDetail method to accept a User
parameter representing the authenticated user. After retrieving the article by
ID, check if the article's owner matches the provided user; if not, throw an
AccessDeniedException. Also, add the import statement for
org.springframework.security.access.AccessDeniedException. This enforces
ownership verification before returning article details.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

아니 어차피 유저정보 안써서 손해야

Copy link

Choose a reason for hiding this comment

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

@rootTiket 네, 이해했습니다. 해당 프로젝트에서는 아티클 상세 조회에 유저 권한 확인이 필요하지 않다는 점 알겠습니다. 현재 구현이 요구사항에 맞다면 그대로 진행하시면 됩니다.


✏️ Learnings added
Learnt from: rootTiket
PR: Pinback-Team/pinback-server#18
File: src/main/java/com/pinback/pinback_server/domain/article/application/ArticleManagementUsecase.java:38-41
Timestamp: 2025-07-07T15:33:02.697Z
Learning: In the Pinback server project, article detail retrieval (getArticleDetail method) does not require user authorization checks. Articles can be accessed by ID without ownership verification as per the project's design decision.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

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 (2)
src/test/java/com/pinback/pinback_server/domain/article/application/ArticleManagementUsecaseTest.java (1)

77-77: Improve test method naming.

The test method name test() is not descriptive and doesn't follow naming conventions. Consider a more descriptive name that explains what the test is verifying.

-	void test() {
+	void getArticleDetail() {
src/test/java/com/pinback/pinback_server/domain/fixture/TestFixture.java (1)

26-26: Consider using a more flexible approach for reminder dates.

The hard-coded date LocalDateTime.of(2025, 7, 7, 12, 0, 0) works functionally but may impact test maintainability. Consider these improvements:

  1. Extract to a constant for better maintainability
  2. Use relative dates to avoid future date obsolescence
  3. Add parameterization for different test scenarios

Here's a suggested refactor to improve maintainability:

+import java.time.LocalDateTime;
+
 public class TestFixture {
+    private static final LocalDateTime DEFAULT_REMIND_AT = LocalDateTime.of(2025, 7, 7, 12, 0, 0);
+
     public static Article article(User user) {
         Category category = category(user);
-        return Article.create("test", "testmemo", user, category, LocalDateTime.of(2025, 7, 7, 12, 0, 0));
+        return Article.create("test", "testmemo", user, category, DEFAULT_REMIND_AT);
     }
 
     public static Article articleWithCategory(User user, Category category) {
-        return Article.create("test", "testmemo", user, category, LocalDateTime.of(2025, 7, 7, 12, 0, 0));
+        return Article.create("test", "testmemo", user, category, DEFAULT_REMIND_AT);
     }
+
+    public static Article articleWithRemindAt(User user, Category category, LocalDateTime remindAt) {
+        return Article.create("test", "testmemo", user, category, remindAt);
+    }
 }

This approach provides better maintainability while maintaining backward compatibility for existing tests.

Also applies to: 30-30

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 52d14ed and bb1a38c.

📒 Files selected for processing (11)
  • src/main/java/com/pinback/pinback_server/domain/article/application/ArticleManagementUsecase.java (2 hunks)
  • src/main/java/com/pinback/pinback_server/domain/article/domain/entity/Article.java (2 hunks)
  • src/main/java/com/pinback/pinback_server/domain/article/domain/service/ArticleGetService.java (2 hunks)
  • src/main/java/com/pinback/pinback_server/domain/article/exception/ArticleNotFoundException.java (1 hunks)
  • src/main/java/com/pinback/pinback_server/domain/article/presentation/ArticleController.java (3 hunks)
  • src/main/java/com/pinback/pinback_server/domain/article/presentation/dto/request/ArticleCreateRequest.java (1 hunks)
  • src/main/java/com/pinback/pinback_server/domain/article/presentation/dto/response/ArticleDetailResponse.java (1 hunks)
  • src/main/java/com/pinback/pinback_server/domain/category/presentation/dto/response/CategoryDetail.java (1 hunks)
  • src/main/java/com/pinback/pinback_server/global/exception/constant/ExceptionCode.java (1 hunks)
  • src/test/java/com/pinback/pinback_server/domain/article/application/ArticleManagementUsecaseTest.java (3 hunks)
  • src/test/java/com/pinback/pinback_server/domain/fixture/TestFixture.java (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/java/com/pinback/pinback_server/domain/article/domain/service/ArticleGetService.java (1)
src/main/java/com/pinback/pinback_server/domain/article/exception/ArticleNotFoundException.java (1)
  • ArticleNotFoundException (6-10)
🔇 Additional comments (19)
src/main/java/com/pinback/pinback_server/domain/category/presentation/dto/response/CategoryDetail.java (1)

5-15: LGTM! Clean DTO implementation with good factory pattern.

The record class implementation is well-structured with appropriate field types and follows the static factory method pattern, which is a good practice for DTO creation from domain entities.

src/main/java/com/pinback/pinback_server/domain/article/presentation/dto/request/ArticleCreateRequest.java (1)

16-19: LGTM! Making remindTime optional is appropriate.

Removing the @NotNull annotation makes the reminder time field optional during validation, which aligns with the feature implementation where users may not always want to set a reminder.

src/main/java/com/pinback/pinback_server/global/exception/constant/ExceptionCode.java (1)

22-22: LGTM! Exception code follows established patterns.

The new ARTICLE_NOT_FOUND exception code is properly implemented with appropriate HTTP status (404), follows the sequential error code pattern (c40403), and has a clear Korean message consistent with other exception codes.

src/main/java/com/pinback/pinback_server/domain/article/exception/ArticleNotFoundException.java (1)

6-10: LGTM! Standard exception implementation following application patterns.

The exception class correctly extends ApplicationException and uses the appropriate exception code. The implementation follows the established pattern used throughout the application.

src/main/java/com/pinback/pinback_server/domain/article/domain/service/ArticleGetService.java (1)

23-25: LGTM! Proper implementation of repository pattern with exception handling.

The findById method correctly uses the Optional.orElseThrow() pattern and throws the appropriate domain-specific exception when an article is not found. The implementation follows established patterns in the codebase.

src/main/java/com/pinback/pinback_server/domain/article/application/ArticleManagementUsecase.java (3)

11-11: LGTM!

Proper import addition for the new response DTO.


34-34: LGTM!

Correct integration of the new remindTime parameter into the article creation flow.


38-41: LGTM!

Clean implementation of the article detail retrieval method. The method properly delegates to the service layer and converts the entity to a response DTO.

src/main/java/com/pinback/pinback_server/domain/article/domain/entity/Article.java (3)

3-3: LGTM!

Proper import addition for the new LocalDateTime field.


54-55: LGTM!

Well-structured field addition with appropriate JPA mapping. The nullable nature allows for optional reminders.


60-60: LGTM!

Proper integration of the new remindAt parameter into the factory method and builder pattern.

Also applies to: 67-67

src/test/java/com/pinback/pinback_server/domain/article/application/ArticleManagementUsecaseTest.java (3)

20-20: LGTM!

Proper import addition for the new response DTO.


56-56: LGTM!

Good addition to verify the new remindAt field is properly saved.


75-92: LGTM!

Comprehensive test coverage for the new getArticleDetail functionality. The test properly verifies all fields of the response DTO.

src/main/java/com/pinback/pinback_server/domain/article/presentation/ArticleController.java (3)

3-4: LGTM!

Proper import additions for the new endpoint functionality.

Also applies to: 12-12


21-21: LGTM!

Good practice to use plural form for REST API endpoints.


32-36: Confirm SecurityConfig Secures /articles/details
Authentication is enforced globally by SecurityConfig (anyRequest().authenticated()), so /articles/details/{articleId} already requires a valid JWT. No @CurrentUser parameter is needed for authentication.

If your business requirements differ:

  • To make details public (no auth): add
    .requestMatchers("/articles/details/**").permitAll()
    in SecurityConfig.filterChain(...).
  • To restrict access to article owners: inject the current user and enforce ownership, e.g.:
    @GetMapping("/details/{articleId}")
    public ResponseDto<ArticleDetailResponse> getArticleDetails(@CurrentUser User user,
                                                                @PathVariable Long articleId) {
        // verify user owns articleId before returning details
    }

Key locations:

  • src/main/java/com/pinback/pinback_server/global/config/security/SecurityConfig.java
  • src/main/java/com/pinback/pinback_server/domain/article/presentation/ArticleController.java

Likely an incorrect or invalid review comment.

src/main/java/com/pinback/pinback_server/domain/article/presentation/dto/response/ArticleDetailResponse.java (1)

1-23: LGTM!

Well-structured DTO record with clean field definitions and proper entity mapping. The factory method correctly converts all Article fields and maintains consistency with the CategoryDetail pattern.

src/test/java/com/pinback/pinback_server/domain/fixture/TestFixture.java (1)

3-3: LGTM: Required import for LocalDateTime.

The import is correctly added to support the new LocalDateTime parameter in the Article.create method calls.

@rootTiket rootTiket merged commit 7d4223e into dev Jul 7, 2025
5 checks passed
@rootTiket rootTiket deleted the feat/#17 branch July 7, 2025 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 아티클 상세 조회 구현

1 participant