이슈 본연: API 레퍼런스의 미채움 마커 5종(실측 제외/TODO/필드 없음/대표 에러 없음)
1,194건을 코드에서 읽어 전수 채우고(0건), api:docgen 재생성이 사람이 채운 내용을
손실·열화시키던 멱등성 결함 4종(CRLF, 표 파이프 이스케이프, 에러 서술 보존, 중복
라우트명 키)을 근본 수정. --check 를 실측 제외와 드리프트가 구분되도록 재정의.
ParameterDescriber/ResourceFieldDescriber 에 leaf 폴백·SEO 스코프·공통 사전 확장.
파생 결함(문서 실측 중 발견): ResponseHelper 기본 메시지 키 6종이 존재하지 않는
messages.* 를 가리켜 응답 message 가 번역문 대신 키 문자열로 노출되던 문제를 common.*
으로 정정하고, 코어 7 + gdpr/marketing/pay_kginicis/verification/ecommerce 확장의
호출부와 누락 lang 키(게시판 10키 + 이커머스 category_images 4키 포함)를 ko/en/ja
전수 정정. 중복 그룹 키 2건은 기존 키로 호출부 통합.
보안: GET /api/identity/challenges/{id} 는 권한 가드 없는 공개 폴링 엔드포인트인데
Service::getStatus 가 attempts/max_attempts 를 응답에 담아 남은 시도 횟수를 추론할 수
있었다. 두 필드를 제거하고, 챌린지 화면(admin_basic/basic)의 서버 attempts 참조를
제거(남은 횟수 UI 는 query fallback + verify 실패 시 로컬 증가로 유지).
부수 정리(변경셋에 들어온 board 컨트롤러의 audit 사전 결함): FormRequest 4개 신설로
base Request 주입 제거, CommentController 의 Board 직접 호출을 BoardService 위임으로
전환, PHPDoc @return 보강. board 스위트에서 발견한 stale test 3건(seed SSoT 불일치,
admin 계정 user 역할 누락)도 같은 세션에서 정정.
버전 정렬(공개 release 기준): 코어 7.0.3→7.0.4, sirsoft-board 1.0.1→1.0.2,
verification_kginicis 1.0.0→1.0.1, admin_basic 1.0.1→1.0.4.
38 KiB
Reports API 레퍼런스
소유: module
sirsoft-board· 생성:php artisan api:docgen(실측 기반). @generated 블록은 재생성 시 갱신되며, 사람이 작성한 설명은 보존됩니다.
TL;DR (5초 요약)
1. 이 문서는 실제 API 호출로 실측한 Reports 엔드포인트 레퍼런스입니다
2. 각 엔드포인트: 메서드/URI/권한 + 요청 파라미터 표 + 요청 예시(raw HTTP) + 실측 응답 필드 표 + 응답 예시(envelope)
3. 응답 필드의 예시값·응답 예시 JSON 은 실제 호출 응답에서 관측된 값입니다
4. 갱신: 코드 변경 후 php artisan api:docgen 재실행
5. 설명(TODO) 칸은 사람이 채웁니다
GET /api/modules/sirsoft-board/admin/reports
- 라우트명:
api.modules.sirsoft-board.admin.reports.index - 컨트롤러:
Modules\Sirsoft\Board\Http\Controllers\Admin\ReportController@index - 인증/권한:
auth:sanctum+permission:sirsoft-board.reports.view
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| filters | query | array | 아니오 | — | 추가 필터 조건 맵 (필드별 조건) |
| status | query | string | 아니오 | — | 상태 필터 (해당 상태의 항목만 조회) |
| target_type | query | string | 아니오 | — | 신고 대상 타입 필터 (post/comment). 단일 문자열 또는 배열로 여러 타입을 전달할 수 있습니다. |
| target_status | query | string | 아니오 | — | 신고 대상 콘텐츠의 현재 상태 필터 (게시글/댓글의 status 기준). 단일 문자열 또는 배열로 전달하며 all은 무시됩니다. |
| board_id | query | integer | 아니오 | — | board 식별자 |
| reported_at_from | query | string | 아니오 | — | 신고 접수 기간 시작일 (YYYY-MM-DD). 마지막 신고일시(last_reported_at) 기준으로 이 날짜 00:00:00 이후 건만 조회합니다. |
| reported_at_to | query | string | 아니오 | — | 신고 접수 기간 종료일 (YYYY-MM-DD). 마지막 신고일시(last_reported_at) 기준으로 이 날짜 23:59:59 이전 건만 조회합니다. |
| sort_by | query | string | 아니오 | — | 정렬 기준 필드명 |
| sort_order | query | string | 아니오 | asc, desc |
정렬 방향 (asc 오름차순 / desc 내림차순) |
| per_page | query | integer | 아니오 | — | 페이지당 항목 수 |
요청 예시
GET /api/modules/sirsoft-board/admin/reports?filters=%EC%98%88%EC%8B%9C%EA%B0%92&status=%EC%98%88%EC%8B%9C%EA%B0%92&target_type=%EC%98%88%EC%8B%9C%EA%B0%92&target_status=%EC%98%88%EC%8B%9C%EA%B0%92&board_id=1&reported_at_from=%EC%98%88%EC%8B%9C%EA%B0%92&reported_at_to=%EC%98%88%EC%8B%9C%EA%B0%92&sort_by=%EC%98%88%EC%8B%9C%EA%B0%92&sort_order=asc&per_page=1 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
목록 응답: data.data[] 배열 항목의 필드 + data.pagination.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 7 |
기본 키 (내부 식별자) |
| board_id | integer | 6 |
게시판 ID (게시판 삭제 시 NULL) |
| board | object | {"id":6,"name":"Q&A","slug":"qna","title":"파일 업로드 오류","cu… |
신고 대상이 속한 게시판 정보 (id/name/slug/대상 제목/현재 상태). 게시판 삭제 시 관계 대신 첫 신고 로그의 스냅샷 값으로 폴백합니다. |
| target_type | string | comment |
신고 대상 타입 (post, comment) |
| target_type_label | string | 댓글 |
target_type 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| target_id | integer | 282 |
신고 대상 ID (동적 테이블의 ID) |
| post_id | integer | 99 |
post 식별자 (연관 리소스 참조) |
| content | null | null |
본문 내용 |
| content_mode | string | text |
대상 본문의 형식 모드 (text/html 등). 목록에서는 미리보기 표시 방식을 결정하며 스냅샷이 없으면 text로 기본 설정됩니다. |
| content_preview | string | 저도 비슷한 경험이 있어요. |
대상 본문의 미리보기 (앞 100자로 잘린 발췌). 목록 응답에서만 채워지고 상세 응답에서는 null 입니다. |
| author | object | {"uuid":"a1e0a91a-fba6-491c-a53e-7285a5686857","name":"관리… |
작성자 사용자 객체 (uuid/name — author 관계 파생) |
| reporter | object | {"uuid":"a1e0a91a-fba6-491c-a53e-7285a5686857","name":"관리… |
대표 신고자 정보 (uuid/name/email/is_guest). 첫 번째 신고 로그에서 추출하며, 비회원 신고 시 게스트로 표시됩니다. |
| reason_type | string | abuse |
대표 신고 사유 코드 (첫 번째 신고 로그의 사유 Enum 값 — 예: abuse, spam). |
| reason_type_label | string | 욕설/비방 |
reason_type 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| status | string | review |
신고 상태 (pending, review, rejected, suspended) |
| status_label | string | 검토 |
상태의 사람이 읽는 라벨 (상태 Enum label() 산물) |
| status_variant | string | info |
상태 표시 색상/스타일 변형 키 (상태 Enum variant() 산물 — UI 배지용) |
| processor | object | {"uuid":"a1e0a91a-fba6-491c-a53e-7285a5686857","name":"관리자"} |
신고를 처리한 관리자 정보 (uuid/name). 처리자가 지정되지 않은 경우 null 입니다. |
| processed_at | string | 2026-06-01 09:35:42 |
processed 일시 |
| metadata | null | null |
메타데이터 (IP, User Agent 등) |
| report_count | integer | 1 |
report 개수 (집계) |
| last_reported_at | string | 2026-06-02 09:35:42 |
last reported 일시 |
| is_reactivated | boolean | false |
reactivated 여부 |
| target_status | string | published |
신고 대상 콘텐츠(게시글/댓글)의 현재 상태. 대상 테이블의 status 컬럼을 서브쿼리로 조인한 값입니다 (예: published, blinded). |
| target_trigger_type | string | admin |
신고 대상의 현재 상태를 유발한 트리거 유형. 대상 테이블의 trigger_type 값으로, 블라인드 처리가 자동(auto_hide)/관리자 수동(admin) 중 무엇에 의한 것인지 구분합니다. |
| target_status_label | string | 게시중 |
target_status 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| created_at | string | 2026-06-04 09:35:42 |
생성 일시 |
| updated_at | string | 2026-06-04 09:35:42 |
최종 수정 일시 |
| is_owner | boolean | false |
현재 인증 사용자가 이 리소스의 소유자인지 여부 (BaseApiResource 표준 메타) |
| abilities | object | {"can_view":true,"can_manage":true} |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반) |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "신고 목록을 조회했습니다.",
"data": {
"data": [
{
"id": 1,
"board_id": 1,
"board": {
"id": 1,
"name": "API 문서 샘플 게시판",
"slug": "apidoc-sample-board",
"title": null,
"current_status": null,
"deleted_at": null
},
"target_type": "post",
"target_type_label": "게시글",
"target_id": 1,
"post_id": 1,
"content": null,
"content_mode": "text",
"content_preview": "",
"author": {
"uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
"name": "API 문서 샘플 사용자",
"email": "apidoc-sample-user@example.com",
"is_guest": false
},
"reporter": null,
"reason_type": null,
"reason_type_label": null,
"status": "pending",
"status_label": "접수",
"status_variant": "warning",
"processor": null,
"processed_at": null,
"metadata": null,
"report_count": 0,
"last_reported_at": "2026-07-08 10:41:34",
"is_reactivated": false,
"target_status": "published",
"target_trigger_type": "user",
"target_status_label": "게시중",
"created_at": "2026-07-08 10:41:34",
"updated_at": "2026-07-08 10:41:34",
"is_owner": false,
"abilities": {
"can_view": true,
"can_manage": true
}
}
],
"statistics": {
"by_status": {
"pending": 1
},
"by_type": {
"post": 1
},
"total": 1
},
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 1,
"from": 1,
"to": 1,
"has_more_pages": false
},
"abilities": {
"can_view": true,
"can_manage": true
}
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-board.reports.view)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 신고 관리 화면의 목록을 조회합니다. auth:sanctum 인증과 sirsoft-board.reports.view 권한이 필요합니다. 동일 대상(게시글/댓글)에 대한 여러 신고는 그룹화되어 최초 신고 1건만 목록에 노출되며, filters/status/target_type/target_status/board_id/기간(reported_at_from20 범위로 강제 제한되며, 응답에는 상태별 통계와 사용자 권한 정보가 함께 포함됩니다.reported_at_to)으로 필터링하고 sort_by/sort_order로 정렬합니다. per_page는 10
PATCH /api/modules/sirsoft-board/admin/reports/bulk-status
- 라우트명:
api.modules.sirsoft-board.admin.reports.bulk-status - 컨트롤러:
Modules\Sirsoft\Board\Http\Controllers\Admin\ReportController@bulkUpdateStatus - 인증/권한:
auth:sanctum+permission:sirsoft-board.reports.manage
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| ids | body | array | 예 | min 1 | 대상 리소스 식별자 배열 (대량 작업 대상) |
| status | body | string | 예 | — | 일괄 전환할 신고 상태 (ReportStatus 허용값: pending/review/rejected/suspended 등). 지정한 모든 신고를 이 상태로 변경합니다. |
| process_note | body | string | 아니오 | max 1000 | 처리 메모 (최대 1000자). 상태 변경 사유나 조치 내용을 처리 이력에 함께 기록합니다. |
요청 예시
PATCH /api/modules/sirsoft-board/admin/reports/bulk-status HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"ids": [
"예시값"
],
"status": "예시값",
"process_note": "예시값"
}
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| affected_count | integer | 3 |
실제로 상태가 변경된 신고 건수 (영구삭제·동일 상태 등 전환 불가 건은 제외) |
| restored_count | integer | 1 |
상태 변경(반려 등)에 따라 공개 상태로 복구된 대상 콘텐츠 건수 |
| manual_blind_restored | integer | 1 |
그중 관리자 수동 블라인드(admin 트리거)였다가 함께 복구된 건수 |
| status_label | string | 반려 |
전환된 신고 상태의 사람이 읽는 라벨 (ReportStatus::label() 산물) |
| message | string | 3개 신고를 반려(으)로 변경했습니다. |
화면에 그대로 노출 가능한 안내 문구 (봉투 최상위 message 와 동일 값) |
응답 예시
{
"success": true,
"message": "3개 신고를 반려(으)로 변경했습니다. 수동 블라인드 처리된 1건이 함께 복구되었습니다.",
"data": {
"affected_count": 3,
"restored_count": 1,
"manual_blind_restored": 1,
"status_label": "반려",
"message": "3개 신고를 반려(으)로 변경했습니다. 수동 블라인드 처리된 1건이 함께 복구되었습니다."
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-board.reports.manage)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 500 | Internal Server Error | 일괄 상태 변경 처리 중 오류가 발생한 경우 (sirsoft-board::messages.reports.bulk_status_update_failed) |
설명 여러 신고의 상태를 한 번에 변경합니다. auth:sanctum 인증과 sirsoft-board.reports.manage 권한이 필요합니다. ids로 지정한 신고들만 대상으로 하며(그룹 확장 없음) status로 지정한 상태로 일괄 전환하고, 선택적으로 process_note(최대 1000자)를 처리 메모로 남깁니다. 응답은 실제 변경된 건수(affected_count), 대상 콘텐츠 복구 건수(restored_count), 수동 블라인드 복구 건수(manual_blind_restored)와 안내 메시지를 반환합니다.
POST /api/modules/sirsoft-board/admin/reports/status-counts
- 라우트명:
api.modules.sirsoft-board.admin.reports.status-counts - 컨트롤러:
Modules\Sirsoft\Board\Http\Controllers\Admin\ReportController@getStatusCounts - 인증/권한:
auth:sanctum+permission:sirsoft-board.reports.view
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| ids | body | array | 예 | min 1 | 대상 리소스 식별자 배열 (대량 작업 대상) |
| target_status | body | string | 아니오 | — | 집계 기준이 되는 전환 대상 상태 (ReportStatus 허용값). 지정 시 해당 상태로의 일괄 전환을 가정한 상태별 건수 요약을 계산합니다. |
요청 예시
POST /api/modules/sirsoft-board/admin/reports/status-counts HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"ids": [
"예시값"
],
"target_status": "예시값"
}
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| status_counts | object | {"pending":{"count":2,"label":"접수"},"deleted":{"count":1,"label":"영구삭제"}} |
선택된 신고들의 현재 상태별 집계 맵. 키는 상태 코드(pending/review/rejected/suspended/deleted), 값은 {count, label} |
| changeable_status_counts | object | {"pending":{"count":2,"label":"접수"}} |
status_counts 에서 영구삭제(deleted)와 전환 대상 상태(target_status)를 제외한 집계 (실제로 변경될 항목만) |
| total_count | integer | 3 |
요청한 ids 의 총 개수 |
| changeable_count | integer | 2 |
실제로 상태 변경이 가능한 건수 (total_count − unchangeable_count) |
| deleted_count | integer | 1 |
선택 항목 중 영구삭제(deleted) 상태로 변경 불가한 건수 |
| same_status_count | integer | 0 |
선택 항목 중 이미 target_status 와 동일해 변경이 무의미한 건수 (target_status 가 deleted 이면 0) |
| unchangeable_count | integer | 1 |
변경 불가 총 건수 (deleted_count + same_status_count) |
| all_deleted | boolean | false |
선택 항목이 모두 영구삭제 상태인지 여부 |
| all_unchangeable | boolean | false |
선택 항목 전부가 변경 불가인지 여부 (changeable_count === 0) |
| target_status_label | string | null | 반려 |
target_status 의 사람이 읽는 라벨. target_status 미지정 시 null |
| restorable_blind_count | integer | 1 |
target_status 가 rejected 일 때, 반려 처리로 공개 상태로 복구될 블라인드 대상 건수 (그 외 상태에서는 0) |
응답 예시
{
"success": true,
"message": "상태별 건수를 조회했습니다.",
"data": {
"status_counts": {
"pending": {
"count": 2,
"label": "접수"
},
"deleted": {
"count": 1,
"label": "영구삭제"
}
},
"changeable_status_counts": {
"pending": {
"count": 2,
"label": "접수"
}
},
"total_count": 3,
"changeable_count": 2,
"deleted_count": 1,
"same_status_count": 0,
"unchangeable_count": 1,
"all_deleted": false,
"all_unchangeable": false,
"target_status_label": "반려",
"restorable_blind_count": 1
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-board.reports.view)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 500 | Internal Server Error | 상태별 건수 집계 중 오류가 발생한 경우 (sirsoft-board::messages.reports.status_counts_failed) |
설명 선택된 신고들의 상태별 건수를 집계하여 반환합니다. auth:sanctum 인증과 sirsoft-board.reports.view 권한이 필요합니다. 대량 상태 변경을 실행하기 전에 사용자에게 선택한 신고들의 상태 분포를 미리 보여주기 위한 조회용 API로, ids 배열(최소 1개)과 선택적 target_status를 받아 상태별 건수와 요약 정보를 계산합니다.
DELETE /api/modules/sirsoft-board/admin/reports/{report}
- 라우트명:
api.modules.sirsoft-board.admin.reports.destroy - 컨트롤러:
Modules\Sirsoft\Board\Http\Controllers\Admin\ReportController@destroy - 인증/권한:
auth:sanctum+permission:sirsoft-board.reports.manage
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| report | path | string | 예 | — | 대상 report의 식별자 |
요청 예시
DELETE /api/modules/sirsoft-board/admin/reports/{report} HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
이 엔드포인트는 data 를 반환하지 않습니다 (성공 메시지만 — data 는 null).
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "신고가 삭제되었습니다.",
"data": null
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-board.reports.manage)이 없는 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 신고를 삭제합니다(소프트 삭제). auth:sanctum 인증과 sirsoft-board.reports.manage 권한이 필요합니다. 경로의 report(신고 ID)에 해당하는 신고 케이스를 소프트 삭제하며, 존재하지 않으면 404, 스코프 권한 위반 시 403을 반환합니다.
GET /api/modules/sirsoft-board/admin/reports/{report}
- 라우트명:
api.modules.sirsoft-board.admin.reports.show - 컨트롤러:
Modules\Sirsoft\Board\Http\Controllers\Admin\ReportController@show - 인증/권한:
auth:sanctum+permission:sirsoft-board.reports.view
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| report | path | string | 예 | — | 대상 report의 식별자 |
요청 예시
GET /api/modules/sirsoft-board/admin/reports/{report} HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 1 |
기본 키 (내부 식별자) |
| board_id | integer | 4 |
게시판 ID (게시판 삭제 시 NULL) |
| board | object | {"id":4,"name":"갤러리","slug":"gallery"} |
신고 대상이 속한 게시판 정보 (id/name/slug). 게시판이 삭제된 경우 관계 대신 첫 신고 로그 스냅샷의 게시판명으로 폴백합니다. |
| target_type | string | post |
신고 대상 타입 (post, comment) |
| target_id | integer | 55 |
신고 대상 ID (동적 테이블의 ID) |
| post | object | {"id":55,"title":"작업물 공유합니다","content":"최근에 작업한 결과물입니다.피드… |
신고 대상 게시글 상세 (id/title/content/작성일시/작성자). 대상이 댓글이면 해당 댓글의 상위 게시글 정보가 담기며, 조회 불가 시 null 입니다. |
| comment | null | null |
신고 대상 댓글 상세 (id/content/작성일시/작성자). 대상 타입이 comment 일 때만 채워지고 게시글 신고에서는 null 입니다. |
| target_status | string | published |
신고 대상 콘텐츠의 현재 상태 (reportable의 current_status — 예: published, blinded). |
| target_status_label | string | 게시중 |
target_status 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| blind_trigger_type | string | admin |
대상 콘텐츠의 블라인드/상태 변경을 유발한 트리거 유형 (reportable의 trigger_type — 예: 자동/관리자 수동). |
| blind_trigger_type_label | string | 관리자 수동 |
blind_trigger_type 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| status | string | pending |
신고 상태 (pending, review, rejected, suspended) |
| available_actions | array | ["review","rejected","suspended","deleted"] |
현재 상태에서 전환 가능한 다음 신고 상태 목록 (상태 Enum의 getAvailableTransitions() 산물). 상태 변경 UI의 선택지로 사용됩니다. |
| abilities | object | {"can_view":true,"can_manage":true} |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반) |
| reporters | array | [{"id":1,"reporter":{"uuid":"a1e0a91a-fba6-491c-a53e-7285… |
이 케이스에 접수된 개별 신고 로그 목록. 각 항목은 신고자(reporter)·사유(reason_type/reason_detail)·신고 시점 스냅샷(snapshot)·신고 일시를 포함합니다. |
| report_count | integer | 1 |
report 개수 (집계) |
| reason_summary | string | 욕설/비방 1건 |
신고 사유 요약 문자열. 상위 2개 사유를 "사유 N건" 형식으로 나열하고 나머지는 "외 N건"으로 합산해 표시합니다. |
| first_reported_at | string | 2026-06-04 09:35:42 |
first reported 일시 |
| last_reported_at | string | 2026-05-13 09:35:42 |
last reported 일시 |
| histories | array | [{"id":1,"type":"reported","action_label":"신고 접수","proces… |
신고 처리 이력 타임라인 (process_histories JSON 기반, 최신순). 각 항목은 이벤트 유형·라벨·처리자·사유·신고자 수·발생 일시를 포함하며, 접수 이벤트에는 처리자가 없습니다. |
| metadata | object | {"ip":"127.0.0.1","user_agent":"Mozilla\/5.0 (Windows NT … |
메타데이터 (IP, User Agent 등) |
| created_at | string | 2026-06-04 09:35:42 |
생성 일시 |
| updated_at | string | 2026-06-04 09:35:42 |
최종 수정 일시 |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "신고 목록을 조회했습니다.",
"data": {
"id": 1,
"board_id": 1,
"board": {
"id": 1,
"name": "API 문서 샘플 게시판",
"slug": "apidoc-sample-board"
},
"target_type": "post",
"target_id": 1,
"post": {
"id": 1,
"title": "API 문서 샘플 게시글",
"content": "<p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p>",
"content_mode": "html",
"created_at": "2026-07-08 10:41:34",
"author": {
"uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
"name": "API 문서 샘플 사용자",
"email": "apidoc-sample-user@example.com",
"is_guest": false
}
},
"comment": null,
"target_status": "published",
"target_status_label": "게시중",
"blind_trigger_type": "user",
"blind_trigger_type_label": "사용자 직접 삭제",
"status": "pending",
"available_actions": [
"review",
"rejected",
"suspended",
"deleted"
],
"abilities": {
"can_view": true,
"can_manage": true
},
"reporters": [],
"report_count": 0,
"reason_summary": "-",
"first_reported_at": "2026-07-08 10:41:34",
"last_reported_at": "2026-07-08 10:41:34",
"histories": [],
"metadata": {
"reason": "spam"
},
"created_at": "2026-07-08 10:41:34",
"updated_at": "2026-07-08 10:41:34"
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-board.reports.view)이 없는 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 신고 케이스 1건의 상세 정보를 조회합니다. auth:sanctum 인증과 sirsoft-board.reports.view 권한이 필요합니다. 경로의 report(신고 ID)를 기준으로 동일 대상에 대한 모든 신고를 그룹화한 상세 정보와 신고 대상 콘텐츠(reportable) 데이터를 함께 반환하며, 처리 이력(histories), 신고자 목록(reporters), 사유 요약(reason_summary), 전환 가능한 상태(available_actions) 등을 포함합니다. 대상이 없으면 404, 스코프 권한 위반 시 403을 반환합니다.
GET /api/modules/sirsoft-board/admin/reports/{report}/reporters
- 라우트명:
api.modules.sirsoft-board.admin.reports.reporters - 컨트롤러:
Modules\Sirsoft\Board\Http\Controllers\Admin\ReportController@reporters - 인증/권한:
auth:sanctum+permission:sirsoft-board.reports.view
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| report | path | string | 예 | — | 대상 report의 식별자 |
| per_page | query | integer | 아니오 | min 1 | 페이지당 항목 수 |
| page | query | integer | 아니오 | min 1 | 조회할 페이지 번호 (1부터 시작) |
요청 예시
GET /api/modules/sirsoft-board/admin/reports/{report}/reporters?per_page=1&page=1 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
목록 응답: data.data[] 배열 항목의 필드 + data.pagination.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 1 |
기본 키 (내부 식별자) |
| reporter | object | {"uuid":"a1e0a91a-fba6-491c-a53e-7285a5686857","name":"관리… |
개별 신고자 정보 (uuid/name/email). 비회원(게스트) 신고 로그인 경우 null 입니다. |
| reason_type | string | abuse |
신고 사유 코드 (사유 Enum 값 — 예: abuse, spam). |
| reason_type_label | string | 욕설/비방 |
reason_type 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| reason_detail | string | 욕설과 비방이 포함된 게시글입니다. 다른 사용자를 모욕하는 내용이 … |
신고자가 직접 입력한 상세 사유 텍스트. 입력하지 않은 경우 null 입니다. |
| snapshot | object | {"board_name":"갤러리","title":"작업물 공유합니다","content":"최근에 작업… |
신고 접수 시점의 대상 콘텐츠 스냅샷 (게시판명/제목/본문/작성자 등). 이후 대상이 수정·삭제되어도 신고 당시 내용을 보존합니다. |
| reported_at | string | 2026-06-04 09:35:42 |
reported 일시 |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "신고 목록을 조회했습니다.",
"data": {
"data": [],
"pagination": {
"total": 0,
"from": 0,
"to": 0,
"per_page": 25,
"current_page": 1,
"last_page": 1
}
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-board.reports.view)이 없는 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 신고 케이스에 접수된 개별 신고자 목록을 페이지네이션으로 반환합니다. auth:sanctum 인증과 sirsoft-board.reports.view 권한이 필요합니다. 경로의 report(신고 케이스 ID)에 대해 각 신고자의 신고 사유(reason_type/reason_detail)와 신고 시점 스냅샷(snapshot)을 포함한 항목을 반환하며, per_page(최대 50)와 page로 페이지를 제어합니다. 대상이 없으면 404를 반환합니다.
PATCH /api/modules/sirsoft-board/admin/reports/{report}/status
- 라우트명:
api.modules.sirsoft-board.admin.reports.update-status - 컨트롤러:
Modules\Sirsoft\Board\Http\Controllers\Admin\ReportController@updateStatus - 인증/권한:
auth:sanctum+permission:sirsoft-board.reports.manage
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| report | path | string | 예 | — | 대상 report의 식별자 |
| status | body | string | 예 | — | 전환할 신고 상태 (ReportStatus 허용값). 현재 상태에서 전환 불가한 값(영구삭제 등)은 검증에서 422로 차단됩니다. |
| process_note | body | string | 아니오 | max 1000 | 처리 메모 (최대 1000자). 상태 변경 사유나 조치 내용을 처리 이력에 함께 기록합니다. |
요청 예시
PATCH /api/modules/sirsoft-board/admin/reports/{report}/status HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"status": "예시값",
"process_note": "예시값"
}
응답 필드 (data 내부)
단건 응답: data 객체의 필드 (ReportResource — 상태 변경 후 재조회한 신고 케이스).
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 1 |
기본 키 (내부 식별자) |
| board_id | integer | null | 1 |
게시판 ID (게시판 삭제 시 null) |
| board | object | {"id":1,"name":"공지사항","slug":"notice","title":"...","current_status":"blinded","deleted_at":null} |
신고 대상이 속한 게시판 정보 + 대상 제목/현재 상태. 게시판 삭제 시 첫 신고 로그의 스냅샷 값으로 폴백합니다. |
| target_type | string | post |
신고 대상 타입 (post, comment) |
| target_type_label | string | 게시글 |
target_type 값의 사람이 읽는 라벨 |
| target_id | integer | 1 |
신고 대상 ID (동적 테이블의 ID) |
| post_id | integer | null | 1 |
대상 게시글 ID. 대상이 댓글이면 상위 게시글 ID |
| content | null | null |
본문 내용 (상세(show) 요청에서만 채워지며, 상태 변경 응답에서는 null) |
| content_mode | string | html |
대상 본문의 형식 모드 (text/html). 스냅샷이 없으면 text |
| content_preview | string | API 레퍼런스 실측용 완전 샘플 게시글 본문입니다. |
대상 본문의 미리보기 (앞 100자 발췌) |
| author | object | {"uuid":"...","name":"홍길동","email":"user@example.com","is_guest":false} |
신고 대상 콘텐츠의 작성자. 회원 정보가 없으면 스냅샷 이름 + is_guest: true |
| reporter | object | null | {"uuid":"...","name":"신고자","email":"reporter@example.com","is_guest":false} |
대표 신고자(첫 번째 신고 로그) 정보. 신고 로그가 없으면 null |
| reason_type | string | null | abuse |
대표 신고 사유 코드 (첫 신고 로그의 사유 Enum 값) |
| reason_type_label | string | null | 욕설/비방 |
reason_type 의 사람이 읽는 라벨 |
| status | string | rejected |
변경된 신고 상태 (pending, review, rejected, suspended, deleted) |
| status_label | string | 반려 |
상태의 사람이 읽는 라벨 (ReportStatus::label()) |
| status_variant | string | info |
상태 배지 색상/스타일 변형 키 (ReportStatus::variant()) |
| processor | object | null | {"uuid":"...","name":"관리자"} |
상태를 변경한 처리 관리자 (uuid/name). 미지정 시 null |
| processed_at | string | null | 2026-07-08 10:41:34 |
처리 일시 |
| metadata | null | null |
메타데이터 (상세(show) 요청에서만 채워지며, 상태 변경 응답에서는 null) |
| report_count | integer | null | null |
케이스 신고 건수 집계. 목록(paginateGrouped) 응답에서만 채워지며 단건 재조회에서는 null |
| last_reported_at | string | null | 2026-07-08 10:41:34 |
마지막 신고 일시 (재접수 시 갱신) |
| is_reactivated | boolean | false |
반려/중단 후 재접수된 케이스인지 여부 (last_activated_at 존재 여부) |
| target_status | null | null |
대상 콘텐츠의 현재 상태. 목록 조회의 서브쿼리로만 주입되며 단건 재조회에서는 null |
| target_trigger_type | null | null |
대상 상태를 유발한 트리거 유형. 목록 조회에서만 채워지며 단건 재조회에서는 null |
| target_status_label | null | null |
target_status 의 라벨. target_status 가 없으면 null |
| created_at | string | 2026-07-08 10:41:34 |
생성 일시 |
| updated_at | string | 2026-07-08 10:42:10 |
최종 수정 일시 |
| is_owner | boolean | false |
현재 인증 사용자가 이 리소스의 소유자(reporter_id)인지 여부 |
| abilities | object | {"can_view":true,"can_manage":true} |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 |
응답 예시
{
"success": true,
"message": "신고 상태가 변경되었습니다.",
"data": {
"id": 1,
"board_id": 1,
"board": {
"id": 1,
"name": "API 문서 샘플 게시판",
"slug": "apidoc-sample-board",
"title": "API 문서 샘플 게시글",
"current_status": "published",
"deleted_at": null
},
"target_type": "post",
"target_type_label": "게시글",
"target_id": 1,
"post_id": 1,
"content": null,
"content_mode": "html",
"content_preview": "<p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p>",
"author": {
"uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
"name": "API 문서 샘플 사용자",
"email": "apidoc-sample-user@example.com",
"is_guest": false
},
"reporter": null,
"reason_type": null,
"reason_type_label": null,
"status": "rejected",
"status_label": "반려",
"status_variant": "info",
"processor": {
"uuid": "a1e0a91a-fba6-491c-a53e-7285a5686857",
"name": "관리자"
},
"processed_at": "2026-07-08 10:42:10",
"metadata": null,
"report_count": null,
"last_reported_at": "2026-07-08 10:41:34",
"is_reactivated": false,
"target_status": null,
"target_trigger_type": null,
"target_status_label": null,
"created_at": "2026-07-08 10:41:34",
"updated_at": "2026-07-08 10:42:10",
"is_owner": false,
"abilities": {
"can_view": true,
"can_manage": true
}
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-board.reports.manage)이 없거나, 권한 스코프(본인만/역할 범위)를 벗어난 신고에 접근한 경우 (auth.scope_denied) |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지). 영구삭제(deleted) 상태 신고의 상태를 변경하려 한 경우에도 422 (sirsoft-board::messages.reports.cannot_change_deleted_status) |
| 500 | Internal Server Error | 상태 변경 처리 중 오류가 발생한 경우 (sirsoft-board::messages.reports.status_update_failed) |
설명 단건 신고의 상태를 변경합니다. auth:sanctum 인증과 sirsoft-board.reports.manage 권한이 필요합니다. 경로의 report(신고 ID)에 대해 status로 지정한 상태로 전환하고 선택적으로 process_note(최대 1000자)를 처리 메모로 남깁니다. 영구삭제(deleted) 등 전환 불가 상태는 FormRequest 검증에서 422로 선차단되고 서비스의 deleted 가드가 2차 방어선으로 동작하며, 대상이 없으면 404를 반환합니다.