Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
8dfec94
feat: implement user block functionality with API endpoints and caching
hgkim-openerd Jun 26, 2025
9d7508d
feat: implement block filtering functionality with @BlockFilter annot…
hgkim-openerd Jun 26, 2025
c0a73f9
feat: implement user blocking functionality with BlockWord annotation…
hgkim-openerd Jun 27, 2025
e86d8af
docs: remove md doc
hgkim-openerd Jun 27, 2025
62aae17
docs: add block readme make by claude
hgkim-openerd Jun 27, 2025
ad992f7
feat: enhance block functionality with validation and service integra…
hgkim-openerd Jun 27, 2025
4641a86
feat: add BlockCreateRequest DTO for block request handling
hgkim-openerd Jun 27, 2025
dc2aa76
feat: add no arg construct
hgkim-openerd Jun 27, 2025
e24d6e7
feat: refactor BlockWord configuration and serializer for improved de…
hgkim-openerd Jun 29, 2025
0d84170
feat: enhance block management with new endpoints and response structure
hgkim-openerd Jun 30, 2025
31ea611
feat: implement in-memory user block repository and associated servic…
hgkim-openerd Jun 30, 2025
2daaf7e
feat: add user block management API documentation and tests
hgkim-openerd Jun 30, 2025
58c8f70
feat: update JpaUserBlockRepository with new query for blocked user i…
hgkim-openerd Jun 30, 2025
9dfa2e0
feat: refactor JPQL queries in JpaUserBlockRepository for improved re…
hgkim-openerd Jun 30, 2025
c13aadb
feat: standardize CI pipeline step names and improve test execution o…
hgkim-openerd Jun 30, 2025
c1f8132
feat: exclude asciidoctor from build step in CI configuration
hgkim-openerd Jul 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 17 additions & 16 deletions .github/workflows/dev_continuous_integration.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Dev CI Pipeline
name: dev ci pipeline

on:
workflow_dispatch:
Expand Down Expand Up @@ -32,48 +32,49 @@ jobs:
run: |
echo "Branch: ${{ github.event.pull_request.base.ref || github.ref_name }}"

- name: Checkout Code (코드 체크아웃)
- name: checkout code
uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.GIT_ACCESS_TOKEN }}

- name: Setup JDK (자바 설정)
- name: setup jdk
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'

- name: Setup Gradle Cache (그래들 캐시 설정)
- name: setup gradle cache
uses: actions/cache@v3
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Install Dependencies (종속성 설치)
- name: install dependencies
run: ./gradlew dependencies

- name: Run Integration Tests (통합 테스트 실행)
run: ./gradlew clean integrationTest
- name: run unit tests
run: ./gradlew unit_test

- name: Run Unit Tests (단위 테스트 실행)
run: ./gradlew unitTest
- name: run rules tests
run: ./gradlew check_rule_test

- name: Build Project (프로젝트 빌드)
run: ./gradlew build
- name: run integration tests
run: ./gradlew integration_test

- name: Store Test Results (테스트 결과 저장)
- name: build project
run: ./gradlew build -x test -x asciidoctor --build-cache --parallel

- name: store test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: |
build/reports/tests/
build/reports/integration-tests/
path: build/reports/

- name: Publish Test Report (테스트 보고서 발행)
- name: publish test report
uses: mikepenz/action-junit-report@v3
if: always()
with:
Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -206,17 +206,17 @@ tasks.named('test') {
excludeTags 'data-jpa-test', 'integration'
}
}
tasks.register('integrationTest', Test) {
tasks.register('integration_test', Test) {
useJUnitPlatform {
includeTags 'integration'
}
}
tasks.register('unitTest', Test) {
tasks.register('unit_test', Test) {
useJUnitPlatform {
includeTags 'unit'
}
}
tasks.register('check_rule', Test) {
tasks.register('check_rule_test', Test) {
useJUnitPlatform {
includeTags 'rule'
}
Expand Down
2 changes: 1 addition & 1 deletion git.environment-variables
38 changes: 38 additions & 0 deletions http/block/차단_필터링_테스트.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
### @BlockWord 시리얼라이저 테스트

### 토큰 발급 (일반)
# @no-cookie-jar
POST {{host}}/api/v1/oauth/login
Content-Type: application/json

{
"email": "rkdtkfma@naver.com",
"socialType": "KAKAO"
}

> {%
//토큰을 전역변수로 저장
client.global.set("accessToken", response.body.data.accessToken);
%}


### 1. 차단 관계 생성
POST {{host}}/api/v1/blocks/create
Content-Type: application/json
Authorization: Bearer {{accessToken}}

{
"blockedUserId": 3
}

### 1-1. 차단 목록 조회 (차단이 제대로 되었는지 확인)
GET {{host}}/api/v1/blocks
Authorization: Bearer {{accessToken}}

### 2. 리뷰 조회 - 차단된 사용자 컨텐츠 필터링 확인
GET {{host}}/api/v1/reviews/274
Authorization: Bearer {{accessToken}}

### 3. 리뷰 상세 조회 - 차단된 사용자 컨텐츠 필터링 확인
GET {{host}}/api/v1/reviews/detail/1
Authorization: Bearer {{accessToken}}
202 changes: 202 additions & 0 deletions src/docs/asciidoc/api/support/block/user-block.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
=== 사용자 차단 관리 ===

사용자 간의 차단 관계를 관리하는 기능입니다.
차단된 사용자와의 상호작용을 제한하여 사용자 경험을 보호합니다.

==== 차단 기능 개요 ====

* 특정 사용자를 차단하여 해당 사용자의 콘텐츠나 상호작용을 차단할 수 있습니다
* 차단된 사용자는 차단한 사용자의 콘텐츠에 접근하거나 상호작용할 수 없습니다
* 차단 관계는 일방향성이며, 상호 차단도 가능합니다

'''

==== 사용자 차단 ====

특정 사용자를 차단합니다.

[source]
----
POST /api/v1/blocks
----

[discrete]
===== 요청 파라미터 =====

include::{snippets}/block-create/request-fields.adoc[]

[discrete]
===== 응답 파라미터 =====

include::{snippets}/block-create/response-fields.adoc[]

차단 완료 후 현재 사용자가 차단한 모든 사용자 목록을 반환합니다.

'''

==== 차단 해제 ====

차단한 사용자를 해제합니다.

[source]
----
DELETE /api/v1/blocks/{blockedUserId}
----

[discrete]
===== 경로 파라미터 =====

include::{snippets}/block-delete/path-parameters.adoc[]

[discrete]
===== 응답 파라미터 =====

include::{snippets}/block-delete/response-fields.adoc[]

차단 해제 후 현재 사용자가 차단한 모든 사용자 목록을 반환합니다.

'''

==== 차단 목록 조회 ====

현재 사용자가 차단한 사용자들의 상세 정보를 조회합니다.

[source]
----
GET /api/v1/blocks
----

[discrete]
===== 응답 파라미터 =====

include::{snippets}/block-list/response-fields.adoc[]

각 차단된 사용자의 ID, 이름, 차단 시각 정보를 포함합니다.

'''

==== 차단 사용자 ID 목록 조회 ====

빠른 차단 여부 확인을 위해 차단된 사용자 ID만 조회합니다.

[source]
----
GET /api/v1/blocks/ids
----

[discrete]
===== 응답 파라미터 =====

include::{snippets}/block-ids/response-fields.adoc[]

클라이언트에서 빠른 필터링이나 권한 체크에 사용할 수 있습니다.

'''

==== 차단 여부 확인 ====

특정 사용자가 차단되었는지 확인합니다.

[source]
----
GET /api/v1/blocks/check/{targetUserId}
----

[discrete]
===== 경로 파라미터 =====

include::{snippets}/block-check/path-parameters.adoc[]

[discrete]
===== 응답 파라미터 =====

include::{snippets}/block-check/response-fields.adoc[]

'''

==== 상호 차단 여부 확인 ====

두 사용자가 서로 차단했는지 확인합니다.

[source]
----
GET /api/v1/blocks/mutual-check/{targetUserId}
----

[discrete]
===== 경로 파라미터 =====

include::{snippets}/block-mutual-check/path-parameters.adoc[]

[discrete]
===== 응답 파라미터 =====

include::{snippets}/block-mutual-check/response-fields.adoc[]

상호 차단 상태에서는 양쪽 모두 상대방의 콘텐츠에 접근할 수 없습니다.

'''

==== 차단 통계 조회 ====

===== 나를 차단한 사용자 수 =====

현재 사용자를 차단한 다른 사용자들의 수를 조회합니다.

[source]
----
GET /api/v1/blocks/stats/blocked-by-count
----

[discrete]
====== 응답 파라미터 ======

include::{snippets}/block-blocked-by-count/response-fields.adoc[]

===== 내가 차단한 사용자 수 =====

현재 사용자가 차단한 사용자들의 수를 조회합니다.

[source]
----
GET /api/v1/blocks/stats/blocking-count
----

[discrete]
====== 응답 파라미터 ======

include::{snippets}/block-blocking-count/response-fields.adoc[]

'''

==== 에러 코드 ====

차단 API 요청 시 발생할 수 있는 예외 상황입니다.

[cols="1,2,3",options="header"]
|===
| 코드 | 상황 | 설명

| 400
| 자기 자신을 차단하려는 경우
| 자기 자신은 차단할 수 없습니다.

| 400
| 이미 차단된 사용자를 다시 차단하려는 경우
| 이미 차단된 사용자입니다.

| 404
| 존재하지 않는 사용자를 차단하려는 경우
| 해당 사용자를 찾을 수 없습니다.

| 404
| 차단하지 않은 사용자를 해제하려는 경우
| 차단 관계가 존재하지 않습니다.

| 401
| 인증되지 않은 사용자
| 로그인이 필요합니다.
|===

** 추가되지 않은 에러 코드는 요청 바랍니다.
** Request validation에 대한 내용은 공통 예외를 통해 처리됩니다.
2 changes: 2 additions & 0 deletions src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ include::api/review/reply/sub-review-reply-list.adoc[]

== 지원 (support) 관련 API

include::api/support/block/user-block.adoc[]

include::api/support/report/user-report.adoc[]

include::api/support/help/help-register.adoc[]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package app.bottlenote.common.block.annotation;

import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* 차단된 사용자의 컨텐츠를 대체 메시지로 변경하는 어노테이션
* JSON 직렬화 시점에서 동작합니다.
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = app.bottlenote.common.block.serializer.BlockWordSerializer.class)
public @interface BlockWord {

/**
* 차단된 사용자 컨텐츠 대체 메시지
* 기본값: "차단된 사용자의 글입니다"
*/
String value() default "차단된 사용자의 글입니다";

/**
* 차단 판단 기준이 되는 사용자 ID 경로
* 기본값: "userId"
* 중첩 객체 예시: "userInfo.userId"
*/
String userIdPath() default "userId";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package app.bottlenote.common.block.config;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;

@Slf4j
@Configuration
@RequiredArgsConstructor
public class BlockWordConfig {
}
Loading
Loading