Files
Gnuboard7/modules/_bundled/sirsoft-board/docs/api/board.md
T
HeuJung 494e581973 fix(security): KVE-2026 신고 4건 조치 — 관리자 API 권한 게이트 + 금전 처리 경쟁 조건
KISA 신고 4건(KVE-2026-1886/1887/1893/1894)을 검증하고, 미수정 2건과
동종 결함 전수 조사에서 나온 결함을 함께 조치했다.

권한 게이트 (KVE-2026-1893)

- NHN KCP 관리자 주문 연동 7경로가 admin 보유 여부만 보고 세부 권한을 보지 않아,
 업무 권한 없는 관리자가 주문번호·결제정보·수령인 연락처를 조회하고 에스크로
 배송등록까지 할 수 있었다. 조회는 orders.read, 등록은 orders.update, 설정성
 경로는 settings.read 로 게이트해 다른 PG 연동과 강도를 맞췄다.
- 마케팅 채널 저장은 코어 플러그인 설정과 같은 저장소를 덮어쓰는 우회 경로라
 core.plugins.update 를 부착했다.

첨부 해시 노출 (KVE-2026-1894 잔재)

- 비밀글의 썸네일 URL 이 목록·상세 응답에 그대로 실려 첨부 해시가 노출됐다.
 이미지 서빙은 이미 차단돼 있었으나 식별값 자체가 나갔다. 첨부 목록과 같은
 게이트를 써서 값만 가리고 필드는 유지한다.

경쟁 조건 (KVE-2026-1886 + 전수 조사)

- 쿠폰 차감을 조회 후 갱신에서 조건부 UPDATE 로 바꿔 1회 제한 쿠폰의 동시
 사용을 막고, 선점당한 주문은 409 로 되돌린다.
- 라이브 병렬 재현에서 그 롤백이 동작하지 않는 것을 확인했다. Action 훅 기본값이
 큐 래핑 + afterCommit 이라 금전 처리가 호출자 커밋 뒤에 실행되고 있었다.
 쿠폰·적립금 차감/복원 5개 구독에 sync 를 선언했고, 회귀 테스트는 손 등록이
 아니라 실제 등록 경로를 태워 고정했다.
- 동시 부분취소의 취소 누적 컬럼 lost update, 적립 lot 의 read-modify-write,
 주문옵션당 적립 lot 중복 생성을 각각 행 잠금·컬럼 연산·유니크 제약으로 막았다.
 기설치본의 중복 lot 은 인덱스 생성 전에 금액을 합산해 한 줄로 통합한다.

규정·문서

- sync 판정 기준을 hooks.md 에 명문화하고 /AGENTS.md Listener 표와
 coverage manifest 에 반영했다. 같은 증상을 다시 만났을 때의 진단 경로를
 트러블슈팅 사례로 남겼다.
2026-08-22 01:19:36 +09:00

112 KiB

Board API 레퍼런스

소유: module sirsoft-board · 생성: php artisan api:docgen (실측 기반). @generated 블록은 재생성 시 갱신되며, 사람이 작성한 설명은 보존됩니다.


TL;DR (5초 요약)

1. 이 문서는 실제 API 호출로 실측한 Board 엔드포인트 레퍼런스입니다
2. 각 엔드포인트: 메서드/URI/권한 + 요청 파라미터 표 + 요청 예시(raw HTTP) + 실측 응답 필드 표 + 응답 예시(envelope)
3. 응답 필드의 예시값·응답 예시 JSON 은 실제 호출 응답에서 관측된 값입니다
4. 갱신: 코드 변경 후 php artisan api:docgen 재실행
5. 설명(TODO) 칸은 사람이 채웁니다

비밀글 서버측 게이팅 (KVE-2026-1914)

비밀글(is_secret)의 원문은 작성자 본인 또는 게시판 관리 권한(posts.read-secret/manager)을 가진 요청에만 제공됩니다. 판정은 SecretContentGate(SSoT)가 담당하며 게시글 상세 외 다음 경로에도 동일하게 적용됩니다.

  • 댓글 목록(GET .../posts/{postId}/comments): 부모 게시글이 비밀글이고 열람 권한이 없으면 빈 목록(200)을 반환합니다.
  • 첨부 서빙(GET .../attachment/{hash}, .../attachment/{hash}/preview): 부모 게시글이 비밀글이고 열람 권한이 없으면 403. 첨부 요청은 상세와 분리된 요청이라 비밀번호 검증(password_verified)은 적용되지 않으며 작성자/관리 권한만 인정합니다.
  • 상세/목록 응답: 비열람자에게 content·title·reply·attachments가 마스킹됩니다.

목록·검색의 총 건수와 답변·댓글 상한

게시판 목록에 search 를 얹으면 내부 검색이 수행됩니다. 매칭이 아주 많을 수 있으므로 총 건수는 상한까지만 세며, 상한을 넘으면 응답의 pagination 에 정확도가 함께 실립니다 (total_relation / total_is_exact / result_cap). 이때 last_page 는 null 이고 has_more_pages 는 그대로 정확하므로, 마지막 페이지 점프만 감춰지고 다음 페이지 이동은 끝까지 열려 있습니다. 상세 규약은 pagination.md 를 참고하세요.

검색어에 + - * " < > 같은 문자가 들어와도 오류가 나지 않습니다. 코어 정제기가 FULLTEXT 연산자를 제거한 뒤 검색하며, 연산자만 입력한 경우에는 오류 대신 빈 결과를 돌려줍니다.

게시글 상세 응답의 답변 트리와 댓글 목록에도 같은 상한이 적용됩니다. 한 글에 답변·댓글이 극단적으로 많은 경우 그 지점에서 끊기며, 총 건수는 목록 응답의 집계로 확인할 수 있습니다.


POST /api/modules/sirsoft-board/admin/board/{slug}/attachments

  • 라우트명: api.modules.sirsoft-board.admin.board.attachments.upload
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\AttachmentController@upload
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.attachments.upload

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
file body file 예 — 업로드 파일
post_id body integer 아니오 min 1 post 식별자
collection body string 아니오 max 100 첨부 컬렉션 그룹명 (첨부를 용도별로 묶는 키, 미지정 시 default)
temp_key body string 아니오 max 64 게시글 작성 전 임시 업로드 세션 키. post_id가 없을 때 이 키로 첨부를 임시 보관했다가 게시글 저장 시점에 연결합니다 (쿼리스트링으로 보내면 body로 병합).

이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (sirsoft-board.attachment.upload_validation_rules).

요청 예시

POST /api/modules/sirsoft-board/admin/board/{slug}/attachments HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: multipart/form-data; boundary=----G7ExampleBoundary

------G7ExampleBoundary
Content-Disposition: form-data; name="file"; filename="example.pdf"
Content-Type: application/octet-stream

(바이너리 파일 내용)
------G7ExampleBoundary
Content-Disposition: form-data; name="post_id"

1
------G7ExampleBoundary
Content-Disposition: form-data; name="collection"

예시값
------G7ExampleBoundary
Content-Disposition: form-data; name="temp_key"

예시값
------G7ExampleBoundary--

응답 필드 (data 내부)

단건 응답: data 객체의 필드. FileUploader 컴포넌트 호환을 위해 파일 메타는 data.data 로 한 번 더 감싸집니다.

필드 타입 실측 예시값 용도/설명
data object {"id":1,"hash":"apidocsmpl1", ...} 업로드된 첨부파일 메타 객체 (아래 하위 필드)
data.id integer 1 첨부파일 기본 키 (게시판별 첨부 테이블의 내부 식별자)
data.hash string apidocsmpl1 첨부파일 해시 식별자 (다운로드/미리보기 URL 에 사용)
data.original_filename string apidoc-sample.png 사용자가 업로드한 원본 파일명
data.stored_filename string — 스토리지에 실제 저장된 파일명 (충돌 방지용 내부 파일명)
data.mime_type string image/png 업로드 파일의 MIME 타입
data.size integer 2048 파일 크기 (바이트)
data.url string /api/modules/sirsoft-board/boards/apidoc-sample-board/attachment/apidocsmpl1 첨부파일 접근 URL (AttachmentService::getUrl() 산물)
data.order integer 0 첨부파일 표시 순서 (0 부터 오름차순)
data.created_at string 2026-07-08 10:41:34 업로드(생성) 일시

응답 예시

HTTP/1.1 201
{
    "success": true,
    "message": "파일이 업로드되었습니다.",
    "data": {
        "data": {
            "id": 1,
            "hash": "apidocsmpl1",
            "original_filename": "apidoc-sample.png",
            "stored_filename": "apidocsmpl1.png",
            "mime_type": "image/png",
            "size": 2048,
            "url": "/api/modules/sirsoft-board/boards/apidoc-sample-board/attachment/apidocsmpl1",
            "order": 0,
            "created_at": "2026-07-08 10:41:34"
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.attachments.upload)이 없는 경우
404 Not Found path 파라미터에 해당하는 리소스가 없는 경우 (슬러그에 해당하는 게시판 없음 — 게시판을 찾을 수 없습니다.)
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지)
500 Internal Server Error 업로드 처리 실패 (파일 업로드에 실패했습니다.)

설명 게시판 관리자가 게시글 첨부파일 1건을 업로드합니다. auth:sanctum + admin + 게시판별 attachments.upload 권한이 필요하며, AttachmentService::upload()가 게시판별 동적 첨부 테이블에 저장합니다. post_id가 있으면 해당 게시글에 즉시 귀속되고, 없으면 temp_key로 임시 업로드되어 게시글 작성/수정 저장 시점에 연결됩니다. 응답은 FileUploader 컴포넌트 호환을 위해 data.data로 한 번 더 감싸 파일 메타(hash·url·order 등)를 반환합니다.

첨부 개수는 게시판 설정 max_file_count 를 기준으로 직접 업로드 · 미리 올려 둔 파일 연결(attachment_ids) · 임시 업로드 연결(temp_key) · 이미 연결된 첨부 를 모두 합산해 판정합니다. 상한을 넘으면 422(errors.code = attachment_limit_exceeded)를 반환하며, 이 판정은 업로드 엔드포인트뿐 아니라 게시글 생성·수정 저장 시점에도 동일하게 적용됩니다. max_file_count 가 0 이면 개수를 제한하지 않습니다.

GET /api/modules/sirsoft-board/admin/board/{slug}/attachments/download/{hash}

  • 라우트명: api.modules.sirsoft-board.admin.board.attachments.download
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\AttachmentController@download
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.attachments.download

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
hash path string 예 — 대상 리소스의 해시 식별자

요청 예시

GET /api/modules/sirsoft-board/admin/board/{slug}/attachments/download/{hash} HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}

응답 필드 (data 내부)

이 엔드포인트는 JSON 봉투를 반환하지 않습니다. 성공 시 파일 본문을 그대로 내려주는 StreamedResponse(바이너리 스트림)이며, data 구조가 없습니다. 실패 시에만 JSON 에러 봉투가 반환됩니다.

응답 예시

HTTP/1.1 200
Content-Type: image/png
Content-Disposition: attachment; filename="apidoc-sample.png"

(바이너리 파일 내용)

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.attachments.download)이 없는 경우
404 Not Found 슬러그에 해당하는 게시판이 없거나(게시판을 찾을 수 없습니다.), 해시에 해당하는 첨부가 없거나(파일을 찾을 수 없습니다.), 실제 파일이 스토리지에 없는 경우
500 Internal Server Error 다운로드 처리 실패 (파일 다운로드에 실패했습니다.)

설명 게시판 관리자가 첨부파일을 해시로 조회해 다운로드합니다. auth:sanctum + admin + 게시판별 attachments.download 권한이 필요하며, AttachmentService::getByHash()로 대상을 찾은 뒤 download()가 파일 스트림 응답을 생성합니다. 해시에 해당하는 첨부가 없거나 실제 파일이 없으면 404를 반환하고, JSON이 아닌 StreamedResponse로 파일 본문을 직접 전송합니다.

PATCH /api/modules/sirsoft-board/admin/board/{slug}/attachments/reorder

  • 라우트명: api.modules.sirsoft-board.admin.board.attachments.reorder
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\AttachmentController@reorder
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.attachments.upload

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
order body array 예 min 1 첨부파일 순서 배열. FileUploader가 보내는 [{id, order}] 형태로, 각 원소의 id(첨부 ID)와 order(0 이상 정수)를 담아 표시 순서를 지정합니다.

이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (sirsoft-board.attachment.reorder_validation_rules).

요청 예시

PATCH /api/modules/sirsoft-board/admin/board/{slug}/attachments/reorder HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json

{
    "order": [
        "예시값"
    ]
}

응답 필드 (data 내부)

이 엔드포인트는 data 를 반환하지 않습니다 (성공 메시지만 — data 는 null).

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "첨부파일 순서가 변경되었습니다.",
    "data": null
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.attachments.upload)이 없는 경우
404 Not Found 슬러그에 해당하는 게시판이 없는 경우 (게시판을 찾을 수 없습니다.)
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지)
500 Internal Server Error 순서 변경 처리 실패 (첨부파일 순서 변경에 실패했습니다.)

설명 게시판 관리자가 게시글 첨부파일들의 표시 순서를 일괄 변경합니다. auth:sanctum + admin + 게시판별 attachments.upload 권한이 필요하며, FileUploader가 보낸 [{id, order}] 배열을 [ID => order] 매핑으로 변환해 AttachmentService::reorder()가 게시판별 첨부 테이블의 order 값을 갱신합니다.

DELETE /api/modules/sirsoft-board/admin/board/{slug}/attachments/{id}

  • 라우트명: api.modules.sirsoft-board.admin.board.attachments.destroy
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\AttachmentController@destroy
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.attachments.upload

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
id path string 예 — 대상 리소스의 식별자

요청 예시

DELETE /api/modules/sirsoft-board/admin/board/{slug}/attachments/{id} 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.{slug}.admin.attachments.upload)이 없는 경우
404 Not Found path 파라미터에 해당하는 리소스가 없는 경우

설명 게시판 관리자가 첨부파일 1건을 삭제합니다. auth:sanctum + admin + 게시판별 attachments.upload 권한이 필요하며, AttachmentService::getById()로 대상 존재를 확인한 뒤 delete()가 게시판별 첨부 테이블 레코드와 실제 파일을 함께 제거합니다. 첨부가 없으면 404, 삭제 실패 시 500을 반환합니다.

GET /api/modules/sirsoft-board/admin/board/{slug}/posts

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.index
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\PostController@index
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.posts.read

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
page query integer 아니오 min 1 조회할 페이지 번호 (1부터 시작)
per_page query integer 아니오 min 1, max 100 페이지당 항목 수
search query string 아니오 max 255 검색어 (지정한 검색 대상 필드에서 부분 일치)

요청 예시

GET /api/modules/sirsoft-board/admin/board/{slug}/posts?page=1&per_page=1&search=%EC%98%88%EC%8B%9C%EA%B0%92 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}

응답 필드 (data 내부)

목록 응답: data.data[] 배열 항목의 필드 + data.pagination.

필드 타입 실측 예시값 용도/설명
id integer 237 기본 키 (내부 식별자)
category null null 게시글 분류(카테고리) 문자열. 게시판이 카테고리를 쓰지 않거나 미지정 시 null (최대 50자).
author object {"uuid":"a231747f-e82e-4cf2-9ae1-a261849dce40","name":"AP… 작성자 사용자 객체 (uuid/name — author 관계 파생)
is_notice boolean false notice 여부
is_secret boolean false secret 여부
content_mode string html 본문 편집 모드. html(위지윅/HTML) 또는 text(평문)이며, 요약·썸네일 추출과 렌더링 방식을 결정합니다. 미지정 시 text.
is_new boolean true new 여부
status string published 게시글 상태 코드. published(게시됨) / blinded(블라인드) / deleted(삭제됨) 중 하나이며, status_label이 사람이 읽는 라벨입니다.
status_label string 게시됨 상태의 사람이 읽는 라벨 (상태 Enum label() 산물)
view_count integer 43 view 개수 (집계)
comment_count integer 0 comment 개수 (집계)
reply_count integer 0 reply 개수 (집계)
attachment_count integer 0 attachment 개수 (집계)
has_attachment boolean false attachment 여부
thumbnail string /api/modules/sirsoft-board/boards/api… 썸네일 이미지 URL/경로 — /api/modules/sirsoft-board/boards/{slug}/attachment/{hash}/preview 형식 (첫 이미지 첨부의 미리보기 서빙 URL). 비밀글은 열람 권한이 없으면 null 로 내려간다(첨부 해시 노출 차단 — 필드 자체는 유지)
parent_id null null parent 식별자 (연관 리소스 참조)
depth integer 0 계층 트리에서의 깊이 (0 = 최상위, 하위로 갈수록 증가)
is_reply boolean false reply 여부
created_at string 2026-07-07 09:34:50 생성 일시
created_at_formatted string 4시간 전 created_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷)
is_author boolean true author 여부
is_guest_post boolean false guest post 여부
slug string apidoc-sample-board 게시판 슬러그 (URL/테이블명)
title string API 문서 샘플 게시글 제목
deleted_at null null 소프트 삭제 일시 (미삭제 시 null)
content_preview string API 레퍼런스 실측용 완전 샘플 게시글 본문입니다. 목록용 본문 요약(태그 제거 후 앞 150자). 블라인드·비밀글은 원문 유출 방지를 위해 권한과 무관하게 빈 문자열을 반환합니다.
row_type string normal 목록 행 유형. notice(공지) / reply(답변글) / normal(일반) 중 하나로, 목록 렌더링 시 행 스타일과 순번 표시를 분기합니다.
number integer 1 목록에서의 순번 (페이지네이션 반영 행 번호 — HasRowNumber 파생)
show_category boolean false 목록에 카테고리 열을 노출할지 여부. 게시판 설정(show_category)에서 파생되어 각 행에 부여됩니다.

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "게시글 목록을 조회했습니다.",
    "data": {
        "data": [
            {
                "id": 1,
                "category": null,
                "author": {
                    "uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
                    "name": "API 문서 샘플 사용자",
                    "email": "apidoc-sample-user@example.com",
                    "avatar": null,
                    "status": "active",
                    "status_label": "활성",
                    "is_guest": false
                },
                "is_notice": false,
                "is_secret": "{MASKED}",
                "content_mode": "html",
                "is_new": true,
                "status": "published",
                "status_label": "게시됨",
                "view_count": 43,
                "comment_count": 0,
                "reply_count": 0,
                "attachment_count": 0,
                "has_attachment": false,
                "thumbnail": "/api/modules/sirsoft-board/boards/apidoc-sample-board/attachment/apidocsmpl1/preview",
                "parent_id": null,
                "depth": 0,
                "is_reply": false,
                "created_at": "2026-07-08 10:41:34",
                "created_at_formatted": "4시간 전",
                "is_author": true,
                "is_guest_post": false,
                "slug": "apidoc-sample-board",
                "title": "API 문서 샘플 게시글",
                "deleted_at": null,
                "content_preview": "API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.",
                "row_type": "normal",
                "number": 1,
                "show_category": false
            }
        ],
        "pagination": {
            "total": 1,
            "all_total": 1,
            "count": 1,
            "per_page": 25,
            "current_page": 1,
            "last_page": 1,
            "from": 1,
            "to": 1,
            "has_more_pages": false
        },
        "board": {
            "slug": "apidoc-sample-board",
            "name": "API 문서 샘플 게시판",
            "type": "basic",
            "categories": [],
            "show_category": false,
            "settings": {
                "use_file_upload": true,
                "use_comment": true,
                "use_reply": true,
                "use_report": true,
                "secret_mode": "{MASKED}",
                "per_page": 20,
                "per_page_mobile": 15,
                "order_by": "created_at",
                "order_direction": "DESC"
            }
        },
        "abilities": {
            "can_read": true,
            "can_write": true,
            "can_read_secret": "{MASKED}",
            "can_read_comments": true,
            "can_write_comments": true,
            "can_upload": true,
            "can_download": true,
            "can_manage": true
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.posts.read)이 없는 경우
404 Not Found path 파라미터에 해당하는 리소스가 없는 경우
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지)

설명 게시판 관리자가 특정 게시판의 게시글 목록을 조회합니다. auth:sanctum + admin + 게시판별 posts.read 권한이 필요하며, 요청 파라미터로 검색·상태·정렬·페이지네이션이 적용됩니다(PostService::buildListParams). 추가로 admin.manage 권한이 있으면 소프트 삭제된 게시글까지 포함해 조회하며, 응답에는 공지 고정 처리 후의 일반 게시글 총 건수(캐시 기반)와 관리자용 게시판 정보(boardInfo)가 함께 담깁니다.

POST /api/modules/sirsoft-board/admin/board/{slug}/posts

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.store
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\PostController@store
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.posts.write

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)

이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (sirsoft-board.post.store_validation_rules).

요청 예시

POST /api/modules/sirsoft-board/admin/board/{slug}/posts HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}

응답 필드 (data 내부)

단건 응답: data 객체의 필드 (PostResource — 게시글 수정(PUT) 응답과 동일한 구조).

필드 타입 실측 예시값 용도/설명
id integer 1 기본 키 (내부 식별자)
category null null 게시글 분류(카테고리) 문자열. 게시판이 카테고리를 쓰지 않거나 미지정 시 null (최대 50자).
author object {"uuid":"a234c2b1-…","name":"API 문서 샘플 사용자"} 작성자 사용자 객체 (uuid/name — author 관계 파생)
is_notice boolean false 공지 게시글 여부
is_secret boolean false 비밀글 여부
content_mode string html 본문 편집 모드. html(위지윅/HTML) 또는 text(평문).
is_new boolean true 신규(NEW) 표시 대상 여부 (게시판 new_display_hours 기준)
status string published 게시글 상태 코드. published / blinded / deleted 중 하나.
status_label string 게시됨 상태의 사람이 읽는 라벨 (상태 Enum label() 산물)
view_count integer 0 조회수 (집계)
comment_count integer 0 댓글 수 (집계)
reply_count integer 0 답변글 수 (집계)
attachment_count integer 0 첨부파일 수 (집계)
has_attachment boolean false 첨부파일 보유 여부
thumbnail null null 썸네일 이미지 URL/경로 (없으면 null)
parent_id null null 원글 ID (답변글일 때만 값 존재)
depth integer 0 계층 트리에서의 깊이 (0 = 최상위)
is_reply boolean false 답변글 여부
created_at string 2026-07-08 10:41:34 생성 일시
created_at_formatted string 방금 전 created_at 값의 표시용 포맷 문자열
is_author boolean true 현재 사용자가 작성자인지 여부
is_guest_post boolean false 비회원 작성 게시글 여부
title string API 문서 샘플 게시글 제목
content string <p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p> 본문 내용
user_id string a234c2b1-cde8-437f-b28b-23323be2b98d 작성자 사용자 식별자
trigger_type string user 상태 변경을 유발한 주체 (report/admin/system/auto_hide/user/cascade)
updated_at string 2026-07-08 10:41:34 최종 수정 일시
deleted_at null null 소프트 삭제 일시 (미삭제 시 null)
ip_address string 127.0.0.1 작성 요청이 발생한 IP 주소
action_logs array [] 블라인드/복원/삭제 처리 이력 목록. admin.manage 권한 보유자에게만 노출.
board null null 소속 게시판 정보 객체. board 관계 미로드 시 null.
navigation null null 이전/다음 게시글 이동 정보. 쓰기 응답에서는 계산하지 않아 null.
parent null null 원글 객체 (parent 관계 파생)
comments null null 댓글 목록. comments 관계 미로드 시 null.
attachments null null 첨부파일 목록. attachments 관계 미로드 시 null.
replies null null 답변글 목록. replies 관계 미로드 시 null.
is_already_reported boolean false 현재 사용자가 이미 신고한 게시글인지 여부
is_owner boolean true 현재 인증 사용자가 이 리소스의 소유자인지 여부 (BaseApiResource 표준 메타)
abilities object {"can_read":true,"can_write":true,…} 현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵

응답 예시

HTTP/1.1 201
{
    "success": true,
    "message": "게시글이 등록되었습니다.",
    "data": {
        "id": 1,
        "category": null,
        "author": {
            "uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
            "name": "API 문서 샘플 사용자",
            "email": "apidoc-sample-user@example.com",
            "avatar": null,
            "status": "active",
            "status_label": "활성",
            "is_guest": false
        },
        "is_notice": false,
        "is_secret": false,
        "content_mode": "html",
        "is_new": true,
        "status": "published",
        "status_label": "게시됨",
        "view_count": 0,
        "comment_count": 0,
        "reply_count": 0,
        "attachment_count": 0,
        "has_attachment": false,
        "thumbnail": null,
        "parent_id": null,
        "depth": 0,
        "is_reply": false,
        "created_at": "2026-07-08 10:41:34",
        "created_at_formatted": "방금 전",
        "is_author": true,
        "is_guest_post": false,
        "title": "API 문서 샘플 게시글",
        "content": "<p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p>",
        "user_id": "a234c2b1-cde8-437f-b28b-23323be2b98d",
        "trigger_type": "user",
        "updated_at": "2026-07-08 10:41:34",
        "deleted_at": null,
        "ip_address": "127.0.0.1",
        "action_logs": [],
        "board": null,
        "navigation": null,
        "parent": null,
        "comments": null,
        "attachments": null,
        "replies": null,
        "is_already_reported": false,
        "is_owner": true,
        "abilities": {
            "can_read": true,
            "can_write": true,
            "can_read_secret": true,
            "can_read_comments": true,
            "can_write_comments": true,
            "can_upload": true,
            "can_download": true,
            "can_manage": true
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.posts.write)이 없는 경우
404 Not Found path 파라미터에 해당하는 리소스가 없는 경우
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지). 제목/본문 길이, 금지 키워드, 작성 쿨다운, 원글(parent_id) 유효성 위반 포함
500 Internal Server Error 게시글 생성 처리 실패 (게시글 등록에 실패했습니다.)

설명 게시판 관리자가 새 게시글을 작성합니다. auth:sanctum + admin + 게시판별 posts.write 권한이 필요하며, StorePostRequest 검증을 거친 값에 작성자(Auth::id())와 요청 IP가 자동으로 채워집니다. 업로드 파일과 첨부파일 ID 배열은 본문에서 분리되어 PostService::createPost()로 전달되고, 성공 시 생성된 게시글 리소스를 201로 반환합니다.

GET /api/modules/sirsoft-board/admin/board/{slug}/posts/form-data

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.form-data
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\PostController@getFormData
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.posts.write

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
post_id query integer 아니오 min 1 post 식별자
parent_id query integer 아니오 min 1 parent 식별자

요청 예시

GET /api/modules/sirsoft-board/admin/board/{slug}/posts/form-data?post_id=1&parent_id=1 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}

응답 필드 (data 내부)

단건 응답: data 객체의 필드.

필드 타입 실측 예시값 용도/설명
title string `` ���목
content string `` 본문 내용
content_mode string text 본문 편집 모드. html(위지윅/HTML) 또는 text(평문)이며, 폼 초기값은 text입니다.
category null null 게시글 분류(카테고리) 문자열. 게시판이 카테고리를 쓰지 않거나 미지정 시 null (최대 50자).
is_notice boolean false notice 여부
is_secret boolean false secret 여부
parent_id null null parent 식별자 (연관 리소스 참조)

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "게시글 폼 데이터를 조회했습니다.",
    "data": {
        "title": "",
        "content": "",
        "content_mode": "text",
        "category": null,
        "is_notice": false,
        "is_secret": "{MASKED}",
        "parent_id": null
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.posts.write)이 없는 경우
404 Not Found path 파라미터에 해당하는 리소스가 없는 경우
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지). 제목/본문 길이, 금지 키워드, 작성 쿨다운, 원글(parent_id) 유효성 위반 포함

설명 게시글 작성/수정/답변글 폼에 미리 채울 입력 데이터를 반환합니다. auth:sanctum + admin + 게시판별 posts.write 권한이 필요하며, 쿼리 파라미터에 따라 분기합니다. post_id가 있으면 기존 게시글 데이터(수정 모드), parent_id가 있으면 제목에 Re:를 붙이고 원글 카테고리·비밀글 여부를 물려받은 답변글 기본값(답글 허용 게시판만, 아니면 404), 둘 다 없으면 빈 폼(게시판 secret_mode가 always면 비밀글 기본값)을 돌려줍니다.

GET /api/modules/sirsoft-board/admin/board/{slug}/posts/form-meta

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.form-meta
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\PostController@getFormMeta
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.posts.write

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)

요청 예시

GET /api/modules/sirsoft-board/admin/board/{slug}/posts/form-meta HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}

응답 필드 (data 내부)

단건 응답: data 객체의 필드.

필드 타입 실측 예시값 용도/설명
board object {"id":12,"name":"API 문서 샘플 게시판","slug":"apidoc-sample-boa… 폼 화면 표시에 필요한 게시판 정보 객체(이름·슬러그·댓글/답글/비밀글 설정 등). 사용자 권한(abilities)과 함께 항상 포함됩니다.

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "게시글 폼 메타 데이터를 조회했습니다.",
    "data": {
        "board": {
            "id": 1,
            "name": "API 문서 샘플 게시판",
            "slug": "apidoc-sample-board",
            "is_active": true,
            "type": "basic",
            "description": "",
            "per_page": 20,
            "per_page_mobile": 15,
            "order_by": "created_at",
            "order_direction": "DESC",
            "categories": [],
            "show_view_count": true,
            "secret_mode": "{MASKED}",
            "use_comment": true,
            "use_reply": true,
            "max_reply_depth": 5,
            "use_report": true,
            "comment_order": "ASC",
            "max_comment_depth": 10,
            "min_title_length": 2,
            "max_title_length": 200,
            "min_content_length": 10,
            "max_content_length": 10000,
            "min_comment_length": 2,
            "max_comment_length": 1000,
            "blocked_keywords": [],
            "use_file_upload": true,
            "max_file_size": 10,
            "max_file_count": 5,
            "allowed_extensions": [
                "jpg",
                "jpeg",
                "png",
                "gif",
                "pdf",
                "zip"
            ],
            "add_to_menu": null,
            "new_display_hours": 24,
            "board_managers": [],
            "board_steps": [],
            "board_manager_ids": [],
            "board_step_ids": [],
            "notify_author": true,
            "notify_admin_on_post": true,
            "created_at": "2026-07-08 10:41:34",
            "updated_at": "2026-07-08 10:41:34",
            "permissions": null,
            "category_post_counts": null,
            "posts_count": 0,
            "user_abilities": {
                "can_read": true,
                "can_write": true,
                "can_read_secret": "{MASKED}",
                "can_read_comments": true,
                "can_write_comments": true,
                "can_upload": true,
                "can_download": true,
                "can_manage": true
            },
            "abilities": {
                "can_create": true,
                "can_update": true,
                "can_delete": true
            }
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.posts.write)이 없는 경우
404 Not Found path 파라미터에 해당하는 리소스가 없는 경우

설명 게시글 폼 화면 표시용 메타 데이터(읽기 전용)를 반환합니다. auth:sanctum + admin + 게시판별 posts.write 권한이 필요하며, 게시판 정보와 사용자 권한(abilities)을 항상 포함합니다. post_id가 있으면 작성자·작성일·첨부파일과 원글 정보를 덧붙이고(수정 모드), parent_id가 있으면 원글 정보를 포함하되 블라인드/삭제된 원글에는 답글 작성이 차단됩니다(각각 403).

DELETE /api/modules/sirsoft-board/admin/board/{slug}/posts/{id}

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.destroy
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\PostController@destroy
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.posts.write|sirsoft-board.{slug}.admin.manage

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
id path string 예 — 대상 리소스의 식별자

요청 예시

DELETE /api/modules/sirsoft-board/admin/board/{slug}/posts/{id} HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}

응답 필드 (data 내부)

단건 응답: data 객체의 필드.

필드 타입 실측 예시값 용도/설명
id integer 1 기본 키 (내부 식별자)
category null null 게시글 분류(카테고리) 문자열. 게시판이 카테고리를 쓰지 않거나 미지정 시 null (최대 50자).
author object {"uuid":"a234c2b1-cde8-437f-b28b-23323be2b98d","name":"AP… 작성자 사용자 객체 (uuid/name — author 관계 파생)
is_notice boolean false notice 여부
is_secret boolean false secret 여부
content_mode string html 본문 편집 모드. html(위지윅/HTML) 또는 text(평문)이며, 요약·썸네일 추출과 렌더링 방식을 결정합니다. 미지정 시 text.
is_new boolean true new 여부
status string deleted 상태 값 (도메인별 상태 집합 — 사람이 읽는 라벨은 status_label, UI 변형은 status_variant 참조)
status_label string 삭제됨 상태의 사람이 읽는 라벨 (상태 Enum label() 산물)
view_count integer 43 view 개수 (집계)
comment_count integer 0 comment 개수 (집계)
reply_count integer 0 reply 개수 (집계)
attachment_count integer 0 attachment 개수 (집계)
has_attachment boolean false attachment 여부
thumbnail null null 썸네일 이미지 URL/경로
parent_id null null parent 식별자 (연관 리소스 참조)
depth integer 0 계층 트리에서의 깊이 (0 = 최상위, 하위로 갈수록 증가)
is_reply boolean false reply 여부
created_at string 2026-07-08 10:41:34 생성 일시
created_at_formatted string 4시간 전 created_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷)
is_author boolean true author 여부
is_guest_post boolean false guest post 여부
title string API 문서 샘플 게시글 제목
content string <p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p> 본문 내용
user_id string a234c2b1-cde8-437f-b28b-23323be2b98d user 식별자 (연관 리소스 참조)
trigger_type string admin 동작을 유발한 방식/주체 구분 값
updated_at string 2026-07-08 15:01:43 최종 수정 일시
deleted_at string 2026-07-08 15:01:43 소프트 삭제 일시 (미삭제 시 null)
ip_address string 127.0.0.1 요청/행위가 발생한 IP 주소
action_logs array [{"action":"delete","reason":null,"admin_name":"API 문서 샘플… 블라인드/복원/삭제 등 처리 이력 목록(항목별 action·reason·admin_name·created_at). admin.manage 권한 보유자에게만 노출되며, 민감 필드(admin_id·ip_address)는 제외됩니다. 비권한자에게는 null.
board null null 소속 게시판 정보 객체(슬러그·이름·유형·댓글/답글/신고 사용 여부·조회수 표시·최대 답글/댓글 깊이·신고 사유 목록). board 관계가 로드된 경우에만 채워지며, 아니면 null.
navigation null null 이전/다음 게시글 이동 정보(prev·next). 상세 로드 시 계산되며, 쓰기 응답처럼 인접 게시글을 계산하지 않은 경우 null.
parent null null 상위 항목 객체 (parent 관계 파생)
comments null null 게시글에 달린 댓글 목록(CommentResource 컬렉션). comments 관계가 로드된 경우에만 채워지며, 아니면 null.
attachments null null 게시글 첨부파일 목록(AttachmentResource 컬렉션). attachments 관계가 로드된 경우에만 채워지며, 아니면 null(비밀글·삭제글은 권한에 따라 빈 배열 또는 연쇄 삭제분만 노출).
replies null null 이 게시글에 달린 답변글 목록(PostResource 컬렉션, 재귀). replies 관계가 로드된 경우에만 채워지며, 아니면 null.
is_already_reported boolean false already reported 여부
is_owner boolean true 현재 인증 사용자가 이 리소스의 소유자인지 여부 (BaseApiResource 표준 메타)
abilities object {"can_read":true,"can_write":true,"can_read_secret":true,… 현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반)

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "게시글이 삭제되었습니다.",
    "data": {
        "id": 1,
        "category": null,
        "author": {
            "uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
            "name": "API 문서 샘플 사용자",
            "email": "apidoc-sample-user@example.com",
            "avatar": null,
            "status": "active",
            "status_label": "활성",
            "is_guest": false
        },
        "is_notice": false,
        "is_secret": "{MASKED}",
        "content_mode": "html",
        "is_new": true,
        "status": "deleted",
        "status_label": "삭제됨",
        "view_count": 43,
        "comment_count": 0,
        "reply_count": 0,
        "attachment_count": 0,
        "has_attachment": false,
        "thumbnail": null,
        "parent_id": null,
        "depth": 0,
        "is_reply": false,
        "created_at": "2026-07-08 10:41:34",
        "created_at_formatted": "4시간 전",
        "is_author": true,
        "is_guest_post": false,
        "title": "API 문서 샘플 게시글",
        "content": "<p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p>",
        "user_id": "a234c2b1-cde8-437f-b28b-23323be2b98d",
        "trigger_type": "admin",
        "updated_at": "2026-07-08 15:01:43",
        "deleted_at": "2026-07-08 15:01:43",
        "ip_address": "127.0.0.1",
        "action_logs": [
            {
                "action": "delete",
                "reason": null,
                "admin_name": "API 문서 샘플 사용자",
                "created_at": "2026-07-08 06:01:43"
            }
        ],
        "board": null,
        "navigation": null,
        "parent": null,
        "comments": null,
        "attachments": null,
        "replies": null,
        "is_already_reported": false,
        "is_owner": true,
        "abilities": {
            "can_read": true,
            "can_write": true,
            "can_read_secret": "{MASKED}",
            "can_read_comments": true,
            "can_write_comments": true,
            "can_upload": true,
            "can_download": true,
            "can_manage": true
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.posts.write|sirsoft-board.{slug}.admin.manage)이 없는 경우
404 Not Found path 파라미터에 해당하는 리소스가 없는 경우
422 Unprocessable Entity 게시판의 답글 삭제 정책(reply_delete_policy)이 block 이고 대상 글에 살아 있는 답글이 있는 경우 (답글이 달린 글은 삭제할 수 없습니다. 답글을 먼저 삭제해 주세요. — sirsoft-board::validation.post.delete.has_replies)

설명 게시판 관리자가 게시글 1건을 소프트 삭제합니다. auth:sanctum + admin 인증이 필요하며, 라우트 권한은 posts.write 또는 manage입니다. 컨트롤러가 대상 게시글을 조회한 뒤 세분화된 권한 분기를 적용합니다: admin.manage는 모든 글(비회원 글 포함)을, admin.posts.write는 본인 글만 삭제할 수 있으며 이미 삭제된 글의 재처리는 admin.manage가 필요합니다. PostService::deletePost()가 'admin' 컨텍스트로 소프트 삭제를 수행합니다. 삭제 동작은 게시판의 답글 삭제 정책(reply_delete_policy)을 따릅니다 — cascade(기본)에서는 원글 삭제 시 살아 있는 답글 트리(및 그 답글들의 댓글·첨부)가 함께 소프트 삭제되고 이후 원글을 복원하면 연쇄 삭제분(trigger_type='cascade')만 선택 복원되며, block 에서는 살아 있는 직계 답글이 있으면 before_delete 훅 발화 전에 차단되어(부수효과 없음) 422 를 반환합니다.

GET /api/modules/sirsoft-board/admin/board/{slug}/posts/{id}

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.show
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\PostController@show
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.posts.read

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
id path string 예 — 대상 리소스의 식별자

요청 예시

GET /api/modules/sirsoft-board/admin/board/{slug}/posts/{id} HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}

응답 필드 (data 내부)

단건 응답: data 객체의 필드.

필드 타입 실측 예시값 용도/설명
id integer 237 기본 키 (내부 식별자)
category null null 게시글 분류(카테고리) 문자열. 게시판이 카테고리를 쓰지 않거나 미지정 시 null (최대 50자).
author object {"uuid":"a231747f-e82e-4cf2-9ae1-a261849dce40","name":"AP… 작성자 사용자 객체 (uuid/name — author 관계 파생)
is_notice boolean false notice 여부
is_secret boolean false secret 여부
content_mode string html 본문 편집 모드. html(위지윅/HTML) 또는 text(평문)이며, 요약·썸네일 추출과 렌더링 방식을 결정합니다. 미지정 시 text.
is_new boolean true new 여부
status string published 게시글 상태 코드. published(게시됨) / blinded(블라인드) / deleted(삭제됨) 중 하나이며, status_label이 사람이 읽는 라벨입니다.
status_label string 게시됨 상태의 사람이 읽는 라벨 (상태 Enum label() 산물)
view_count integer 43 view 개수 (집계)
comment_count integer 0 comment 개수 (집계)
reply_count integer 0 reply 개수 (집계)
attachment_count integer 0 attachment 개수 (집계)
has_attachment boolean false attachment 여부
thumbnail string /api/modules/sirsoft-board/boards/api… 썸네일 이미지 URL/경로 — /api/modules/sirsoft-board/boards/{slug}/attachment/{hash}/preview 형식 (첫 이미지 첨부의 미리보기 서빙 URL). 비밀글은 열람 권한이 없으면 null 로 내려간다(첨부 해시 노출 차단 — 필드 자체는 유지)
parent_id null null parent 식별자 (연관 리소스 참조)
depth integer 0 계층 트리에서의 깊이 (0 = 최상위, 하위로 갈수록 증가)
is_reply boolean false reply 여부
created_at string 2026-07-07 09:34:50 생성 일시
created_at_formatted string 4시간 전 created_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷)
is_author boolean true author 여부
is_guest_post boolean false guest post 여부
title string API 문서 샘플 게시글 제목
content string <p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p> 본문 내용
user_id string a231747f-e82e-4cf2-9ae1-a261849dce40 user 식별자 (연관 리소스 참조)
trigger_type string user 상태 변경(삭제/블라인드 등)을 유발한 주체. report(신고) / admin(관리자 직권) / system(시스템) / auto_hide(신고 누적 자동 블라인드) / user(사용자 직접) / cascade(상위 삭제 연쇄) 중 하나입니다.
updated_at string 2026-07-07 09:39:03 최종 수정 일시
deleted_at null null 소프트 삭제 일시 (미삭제 시 null)
ip_address string 127.0.0.1 요청/행위가 발생한 IP 주소
action_logs array [] 블라인드/복원/삭제 등 처리 이력 목록(항목별 action·reason·admin_name·created_at). admin.manage 권한 보유자에게만 노출되며, 민감 필드(admin_id·ip_address)는 제외됩니다. 비권한자에게는 null.
board object {"slug":"apidoc-sample-board","name":"API 문서 샘플 게시판","typ… 소속 게시판 정보 객체(슬러그·이름·유형·댓글/답글/신고 사용 여부·조회수 표시·최대 답글/댓글 깊이·신고 사유 목록). board 관계가 로드된 경우에만 채워지며, 아니면 null.
navigation object {"prev":null,"next":null} 이전/다음 게시글 이동 정보. prev·next 키에 인접 게시글 요약(없으면 null)이 담기며, 상세 로드 시 함께 계산됩니다.
parent null null 상위 항목 객체 (parent 관계 파생)
comments array [{"id":760,"post_id":237,"parent_id":null,"content":"API … 게시글에 달린 댓글 목록(CommentResource 컬렉션). comments 관계가 로드된 경우에만 채워지며, 각 항목에 신고 여부가 사전 로드되어 담깁니다.
comments_truncated boolean false 댓글 목록이 상한에서 끊겼는지 여부. true 면 comments 에 실린 것이 전부가 아닙니다
comments_total integer|null 12 댓글 총 건수. 끊기지 않았으면 comments 길이와 같고, 끊겼으면 상한값(그 이상)입니다
comments_total_is_exact boolean true 위 총 건수가 정확한지 여부. false 면 "N건 이상" 으로 표기합니다
attachments array [{"id":155,"hash":"apidocsmpl1","original_filename":"apid… 게시글 첨부파일 목록(AttachmentResource 컬렉션). 비밀글은 열람 권한이 없으면 빈 배열, 삭제된 게시글은 관리 권한이 없으면 연쇄 삭제된 첨부만 노출됩니다.
replies array [] 이 게시글에 달린 답변글 목록(PostResource 컬렉션, 재귀). replies 관계가 로드된 경우에만 채워지며, 아니면 null.
is_already_reported boolean false already reported 여부
is_owner boolean true 현재 인증 사용자가 이 리소스의 소유자인지 여부 (BaseApiResource 표준 메타)
abilities object {"can_read":true,"can_write":true,"can_read_secret":true,… 현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반)

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "게시글 목록을 조회했습니다.",
    "data": {
        "id": 1,
        "category": null,
        "author": {
            "uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
            "name": "API 문서 샘플 사용자",
            "email": "apidoc-sample-user@example.com",
            "avatar": null,
            "status": "active",
            "status_label": "활성",
            "is_guest": false
        },
        "is_notice": false,
        "is_secret": "{MASKED}",
        "content_mode": "html",
        "is_new": true,
        "status": "published",
        "status_label": "게시됨",
        "view_count": 44,
        "comment_count": 0,
        "reply_count": 0,
        "attachment_count": 0,
        "has_attachment": false,
        "thumbnail": "/api/modules/sirsoft-board/boards/apidoc-sample-board/attachment/apidocsmpl1/preview",
        "parent_id": null,
        "depth": 0,
        "is_reply": false,
        "created_at": "2026-07-08 10:41:34",
        "created_at_formatted": "4시간 전",
        "is_author": true,
        "is_guest_post": false,
        "title": "API 문서 샘플 게시글",
        "content": "<p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p>",
        "user_id": "a234c2b1-cde8-437f-b28b-23323be2b98d",
        "trigger_type": "user",
        "updated_at": "2026-07-08 15:01:44",
        "deleted_at": null,
        "ip_address": "127.0.0.1",
        "action_logs": [],
        "board": {
            "slug": "apidoc-sample-board",
            "name": "API 문서 샘플 게시판",
            "type": "basic",
            "use_comment": true,
            "use_reply": true,
            "use_report": true,
            "show_view_count": true,
            "max_reply_depth": 5,
            "max_comment_depth": 10,
            "report_types": [
                {
                    "value": "abuse",
                    "label": "욕설/비방"
                },
                {
                    "value": "hate_speech",
                    "label": "혐오 발언"
                },
                {
                    "value": "spam",
                    "label": "스팸/광고"
                },
                {
                    "value": "copyright",
                    "label": "저작권 침해"
                },
                {
                    "value": "privacy",
                    "label": "개인정보 노출"
                },
                {
                    "value": "misinformation",
                    "label": "허위정보"
                },
                {
                    "value": "sexual",
                    "label": "성적인 콘텐츠"
                },
                {
                    "value": "violence",
                    "label": "폭력적인 콘텐츠"
                },
                {
                    "value": "other",
                    "label": "기타"
                }
            ]
        },
        "navigation": {
            "prev": null,
            "next": null
        },
        "parent": null,
        "comments": [
            {
                "id": 1,
                "post_id": 1,
                "parent_id": null,
                "content": "API 문서 샘플 댓글입니다.",
                "author": {
                    "uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
                    "name": "API 문서 샘플 사용자",
                    "email": "apidoc-sample-user@example.com",
                    "avatar": null,
                    "status": "active",
                    "status_label": "활성",
                    "is_guest": false
                },
                "is_secret": "{MASKED}",
                "status": "published",
                "status_label": "게시됨",
                "depth": 0,
                "replies_count": 0,
                "created_at": "2026-07-08 10:41:34",
                "created_at_formatted": "4시간 전",
                "updated_at": "2026-07-08 10:41:34",
                "deleted_at": null,
                "is_cascade_deleted": false,
                "ip_address": null,
                "action_logs": [],
                "is_author": true,
                "is_guest_comment": false,
                "is_already_reported": false,
                "is_owner": true,
                "abilities": {
                    "can_read": true,
                    "can_write": true,
                    "can_manage": true
                }
            }
        ],
        "attachments": [
            {
                "id": 1,
                "hash": "apidocsmpl1",
                "original_filename": "apidoc-sample.png",
                "mime_type": "image/png",
                "size": 2048,
                "size_formatted": "2 KB",
                "collection": "default",
                "order": 0,
                "download_url": "/api/modules/sirsoft-board/boards/apidoc-sample-board/attachment/apidocsmpl1",
                "preview_url": "/api/modules/sirsoft-board/boards/apidoc-sample-board/attachment/apidocsmpl1/preview",
                "is_image": true,
                "meta": null
            }
        ],
        "replies": [],
        "is_already_reported": false,
        "is_owner": true,
        "abilities": {
            "can_read": true,
            "can_write": true,
            "can_read_secret": "{MASKED}",
            "can_read_comments": true,
            "can_write_comments": true,
            "can_upload": true,
            "can_download": true,
            "can_manage": true
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.posts.read)이 없는 경우
404 Not Found path 파라미터에 해당하는 리소스가 없는 경우

설명 게시판 관리자가 게시글 상세를 조회합니다. auth:sanctum + admin + 게시판별 posts.read 권한이 필요하며, 삭제된 게시글은 admin.manage 권한이 있어야 열람할 수 있습니다(없으면 403). PostService::loadPostDetail()이 조회수 증가·댓글·이전/다음 게시글까지 로드하며, 응답에는 댓글별 신고 여부를 N+1 없이 일괄 사전 로드해 담습니다.

PUT /api/modules/sirsoft-board/admin/board/{slug}/posts/{id}

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.update
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\PostController@update
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.posts.write

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
id path string 예 — 대상 리소스의 식별자

이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (sirsoft-board.post.update_validation_rules).

요청 예시

PUT /api/modules/sirsoft-board/admin/board/{slug}/posts/{id} HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}

응답 필드 (data 내부)

단건 응답: data 객체의 필드.

필드 타입 실측 예시값 용도/설명
id integer 1 기본 키 (내부 식별자)
category null null 게시글 분류(카테고리) 문자열. 게시판이 카테고리를 쓰지 않거나 미지정 시 null (최대 50자).
author object {"uuid":"a234c2b1-cde8-437f-b28b-23323be2b98d","name":"AP… 작성자 사용자 객체 (uuid/name — author 관계 파생)
is_notice boolean false notice 여부
is_secret boolean false secret 여부
content_mode string html 본문 편집 모드. html(위지윅/HTML) 또는 text(평문)이며, 요약·썸네일 추출과 렌더링 방식을 결정합니다. 미지정 시 text.
is_new boolean true new 여부
status string published 상태 값 (도메인별 상태 집합 — 사람이 읽는 라벨은 status_label, UI 변형은 status_variant 참조)
status_label string 게시됨 상태의 사람이 읽는 라벨 (상태 Enum label() 산물)
view_count integer 44 view 개수 (집계)
comment_count integer 0 comment 개수 (집계)
reply_count integer 0 reply 개수 (집계)
attachment_count integer 0 attachment 개수 (집계)
has_attachment boolean false attachment 여부
thumbnail null null 썸네일 이미지 URL/경로
parent_id null null parent 식별자 (연관 리소스 참조)
depth integer 0 계층 트리에서의 깊이 (0 = 최상위, 하위로 갈수록 증가)
is_reply boolean false reply 여부
created_at string 2026-07-08 10:41:34 생성 일시
created_at_formatted string 4시간 전 created_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷)
is_author boolean true author 여부
is_guest_post boolean false guest post 여부
title string API 문서 샘플 게시글 제목
content string <p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p> 본문 내용
user_id string a234c2b1-cde8-437f-b28b-23323be2b98d user 식별자 (연관 리소스 참조)
trigger_type string user 동작을 유발한 방식/주체 구분 값
updated_at string 2026-07-08 15:01:44 최종 수정 일시
deleted_at null null 소프트 삭제 일시 (미삭제 시 null)
ip_address string 127.0.0.1 요청/행위가 발생한 IP 주소
action_logs array [] 블라인드/복원/삭제 등 처리 이력 목록(항목별 action·reason·admin_name·created_at). admin.manage 권한 보유자에게만 노출되며, 민감 필드(admin_id·ip_address)는 제외됩니다. 비권한자에게는 null.
board null null 소속 게시판 정보 객체(슬러그·이름·유형·댓글/답글/신고 사용 여부·조회수 표시·최대 답글/댓글 깊이·신고 사유 목록). board 관계가 로드된 경우에만 채워지며, 아니면 null.
navigation null null 이전/다음 게시글 이동 정보(prev·next). 상세 로드 시 계산되며, 쓰기 응답처럼 인접 게시글을 계산하지 않은 경우 null.
parent null null 상위 항목 객체 (parent 관계 파생)
comments null null 게시글에 달린 댓글 목록(CommentResource 컬렉션). comments 관계가 로드된 경우에만 채워지며, 아니면 null.
attachments null null 게시글 첨부파일 목록(AttachmentResource 컬렉션). attachments 관계가 로드된 경우에만 채워지며, 아니면 null(비밀글·삭제글은 권한에 따라 빈 배열 또는 연쇄 삭제분만 노출).
replies null null 이 게시글에 달린 답변글 목록(PostResource 컬렉션, 재귀). replies 관계가 로드된 경우에만 채워지며, 아니면 null.
is_already_reported boolean false already reported 여부
is_owner boolean true 현재 인증 사용자가 이 리소스의 소유자인지 여부 (BaseApiResource 표준 메타)
abilities object {"can_read":true,"can_write":true,"can_read_secret":true,… 현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반)

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "게시글이 수정되었습니다.",
    "data": {
        "id": 1,
        "category": null,
        "author": {
            "uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
            "name": "API 문서 샘플 사용자",
            "email": "apidoc-sample-user@example.com",
            "avatar": null,
            "status": "active",
            "status_label": "활성",
            "is_guest": false
        },
        "is_notice": false,
        "is_secret": "{MASKED}",
        "content_mode": "html",
        "is_new": true,
        "status": "published",
        "status_label": "게시됨",
        "view_count": 44,
        "comment_count": 0,
        "reply_count": 0,
        "attachment_count": 0,
        "has_attachment": false,
        "thumbnail": null,
        "parent_id": null,
        "depth": 0,
        "is_reply": false,
        "created_at": "2026-07-08 10:41:34",
        "created_at_formatted": "4시간 전",
        "is_author": true,
        "is_guest_post": false,
        "title": "API 문서 샘플 게시글",
        "content": "<p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p>",
        "user_id": "a234c2b1-cde8-437f-b28b-23323be2b98d",
        "trigger_type": "user",
        "updated_at": "2026-07-08 15:01:44",
        "deleted_at": null,
        "ip_address": "127.0.0.1",
        "action_logs": [],
        "board": null,
        "navigation": null,
        "parent": null,
        "comments": null,
        "attachments": null,
        "replies": null,
        "is_already_reported": false,
        "is_owner": true,
        "abilities": {
            "can_read": true,
            "can_write": true,
            "can_read_secret": "{MASKED}",
            "can_read_comments": true,
            "can_write_comments": true,
            "can_upload": true,
            "can_download": true,
            "can_manage": true
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.posts.write)이 없는 경우
404 Not Found path 파라미터에 해당하는 리소스가 없는 경우
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지)

설명 게시판 관리자가 게시글을 수정합니다. auth:sanctum + admin + 게시판별 posts.write 권한이 필요하며, 컨트롤러가 대상 게시글을 조회한 뒤 세분화된 권한을 적용합니다: 일반 글은 admin.manage(타인 글) 또는 admin.write(본인 글), 이미 삭제된 글은 admin.manage가 필요합니다. UpdatePostRequest 검증 값에서 첨부파일 ID 배열을 분리해 PostService::updatePost()로 전달하고, 갱신된 게시글 리소스를 반환합니다.

PATCH /api/modules/sirsoft-board/admin/board/{slug}/posts/{id}/blind

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.blind
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\PostController@blind
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.manage

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
id path string 예 — 대상 리소스의 식별자
reason body string 아니오 max 1000 블라인드 처리 사유(최대 1000자). 처리 이력(action_logs)에 기록되며, 미지정 시 빈 문자열로 저장됩니다.

요청 예시

PATCH /api/modules/sirsoft-board/admin/board/{slug}/posts/{id}/blind HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json

{
    "reason": "예시값"
}

응답 필드 (data 내부)

단건 응답: data 객체의 필드.

필드 타입 실측 예시값 용도/설명
id integer 1 기본 키 (내부 식별자)
category null null 게시글 분류(카테고리) 문자열. 게시판이 카테고리를 쓰지 않거나 미지정 시 null (최대 50자).
author object {"uuid":"a234c2b1-cde8-437f-b28b-23323be2b98d","name":"AP… 작성자 사용자 객체 (uuid/name — author 관계 파생)
is_notice boolean false notice 여부
is_secret boolean false secret 여부
content_mode string html 본문 편집 모드. html(위지윅/HTML) 또는 text(평문)이며, 요약·썸네일 추출과 렌더링 방식을 결정합니다. 미지정 시 text.
is_new boolean true new 여부
status string blinded 상태 값 (도메인별 상태 집합 — 사람이 읽는 라벨은 status_label, UI 변형은 status_variant 참조)
status_label string 블라인드 상태의 사람이 읽는 라벨 (상태 Enum label() 산물)
view_count integer 44 view 개수 (집계)
comment_count integer 0 comment 개수 (집계)
reply_count integer 0 reply 개수 (집계)
attachment_count integer 0 attachment 개수 (집계)
has_attachment boolean false attachment 여부
thumbnail null null 썸네일 이미지 URL/경로
parent_id null null parent 식별자 (연관 리소스 참조)
depth integer 0 계층 트리에서의 깊이 (0 = 최상위, 하위로 갈수록 증가)
is_reply boolean false reply 여부
created_at string 2026-07-08 10:41:34 생성 일시
created_at_formatted string 4시간 전 created_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷)
is_author boolean true author 여부
is_guest_post boolean false guest post 여부
title string API 문서 샘플 게시글 제목
content string <p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p> 본문 내용
user_id string a234c2b1-cde8-437f-b28b-23323be2b98d user 식별자 (연관 리소스 참조)
trigger_type string user 동작을 유발한 방식/주체 구분 값
updated_at string 2026-07-08 15:01:44 최종 수정 일시
deleted_at null null 소프트 삭제 일시 (미삭제 시 null)
ip_address string 127.0.0.1 요청/행위가 발생한 IP 주소
action_logs array [{"action":"blind","reason":"실측 예시값","admin_name":"API 문서… 블라인드/복원/삭제 등 처리 이력 목록(항목별 action·reason·admin_name·created_at). admin.manage 권한 보유자에게만 노출되며, 민감 필드(admin_id·ip_address)는 제외됩니다. 비권한자에게는 null.
board null null 소속 게시판 정보 객체(슬러그·이름·유형·댓글/답글/신고 사용 여부·조회수 표시·최대 답글/댓글 깊이·신고 사유 목록). board 관계가 로드된 경우에만 채워지며, 아니면 null.
navigation null null 이전/다음 게시글 이동 정보(prev·next). 상세 로드 시 계산되며, 쓰기 응답처럼 인접 게시글을 계산하지 않은 경우 null.
parent null null 상위 항목 객체 (parent 관계 파생)
comments null null 게시글에 달린 댓글 목록(CommentResource 컬렉션). comments 관계가 로드된 경우에만 채워지며, 아니면 null.
attachments null null 게시글 첨부파일 목록(AttachmentResource 컬렉션). attachments 관계가 로드된 경우에만 채워지며, 아니면 null(비밀글·삭제글은 권한에 따라 빈 배열 또는 연쇄 삭제분만 노출).
replies null null 이 게시글에 달린 답변글 목록(PostResource 컬렉션, 재귀). replies 관계가 로드된 경우에만 채워지며, 아니면 null.
is_already_reported boolean false already reported 여부
is_owner boolean true 현재 인증 사용자가 이 리소스의 소유자인지 여부 (BaseApiResource 표준 메타)
abilities object {"can_read":true,"can_write":true,"can_read_secret":true,… 현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반)

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "게시글이 블라인드 처리되었습니다.",
    "data": {
        "id": 1,
        "category": null,
        "author": {
            "uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
            "name": "API 문서 샘플 사용자",
            "email": "apidoc-sample-user@example.com",
            "avatar": null,
            "status": "active",
            "status_label": "활성",
            "is_guest": false
        },
        "is_notice": false,
        "is_secret": "{MASKED}",
        "content_mode": "html",
        "is_new": true,
        "status": "blinded",
        "status_label": "블라인드",
        "view_count": 44,
        "comment_count": 0,
        "reply_count": 0,
        "attachment_count": 0,
        "has_attachment": false,
        "thumbnail": null,
        "parent_id": null,
        "depth": 0,
        "is_reply": false,
        "created_at": "2026-07-08 10:41:34",
        "created_at_formatted": "4시간 전",
        "is_author": true,
        "is_guest_post": false,
        "title": "API 문서 샘플 게시글",
        "content": "<p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p>",
        "user_id": "a234c2b1-cde8-437f-b28b-23323be2b98d",
        "trigger_type": "user",
        "updated_at": "2026-07-08 15:01:44",
        "deleted_at": null,
        "ip_address": "127.0.0.1",
        "action_logs": [
            {
                "action": "blind",
                "reason": "실측 예시값",
                "admin_name": "API 문서 샘플 사용자",
                "created_at": "2026-07-08 06:01:44"
            }
        ],
        "board": null,
        "navigation": null,
        "parent": null,
        "comments": null,
        "attachments": null,
        "replies": null,
        "is_already_reported": false,
        "is_owner": true,
        "abilities": {
            "can_read": true,
            "can_write": true,
            "can_read_secret": "{MASKED}",
            "can_read_comments": true,
            "can_write_comments": true,
            "can_upload": true,
            "can_download": true,
            "can_manage": true
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.manage)이 없는 경우
404 Not Found path 파라미터에 해당하는 리소스가 없는 경우
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지)

설명 게시판 관리자가 게시글을 블라인드 처리합니다. auth:sanctum + admin + 게시판별 admin.manage 권한이 필요하며, 선택적 reason(최대 1000자)을 사유로 받아 PostService::blindPost()가 게시글 상태를 블라인드로 전환합니다. 소프트 삭제와 달리 게시글을 숨기되 관리 목적으로 보존하는 처리이며, 복원(restore)으로 되돌릴 수 있습니다.

PATCH /api/modules/sirsoft-board/admin/board/{slug}/posts/{id}/restore

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.restore
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\PostController@restore
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.manage

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
id path string 예 — 대상 리소스의 식별자
reason body string 아니오 max 1000 블라인드 복원 사유(최대 1000자). 처리 이력(action_logs)에 기록되며, 미지정 시 null로 전달됩니다.

요청 예시

PATCH /api/modules/sirsoft-board/admin/board/{slug}/posts/{id}/restore HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json

{
    "reason": "예시값"
}

응답 필드 (data 내부)

단건 응답: data 객체의 필드 (PostResource — 복원된 게시글. 게시글 수정(PUT) 응답과 동일한 구조이며, status 가 published 로 되돌아가고 action_logs 에 restore 이력이 1건 추가됩니다).

필드 타입 실측 예시값 용도/설명
id integer 1 기본 키 (내부 식별자)
category null null 게시글 분류(카테고리) 문자열 (미지정 시 null)
author object {"uuid":"a234c2b1-…","name":"API 문서 샘플 사용자"} 작성자 사용자 객체 (uuid/name — author 관계 파생)
is_notice boolean false 공지 게시글 여부
is_secret boolean false 비밀글 여부
content_mode string html 본문 편집 모드 (html / text)
is_new boolean true 신규(NEW) 표시 대상 여부
status string published 복원 후 게시글 상태 (published 로 되돌아감)
status_label string 게시됨 상태의 사람이 읽는 라벨
view_count integer 44 조회수 (집계)
comment_count integer 0 댓글 수 (집계)
reply_count integer 0 답변글 수 (집계)
attachment_count integer 0 첨부파일 수 (집계)
has_attachment boolean false 첨부파일 보유 여부
thumbnail null null 썸네일 이미지 URL/경로
parent_id null null 원글 ID (답변글일 때만 값 존재)
depth integer 0 계층 트리에서의 깊이
is_reply boolean false 답변글 여부
created_at string 2026-07-08 10:41:34 생성 일시
created_at_formatted string 4시간 전 created_at 값의 표시용 포맷 문자열
is_author boolean true 현재 사용자가 작성자인지 여부
is_guest_post boolean false 비회원 작성 게시글 여부
title string API 문서 샘플 게시글 제목
content string <p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p> 본문 내용
user_id string a234c2b1-cde8-437f-b28b-23323be2b98d 작성자 사용자 식별자
trigger_type string admin 상태 변경을 유발한 주체 (복원은 관리자 직권이므로 admin)
updated_at string 2026-07-08 15:01:45 최종 수정 일시
deleted_at null null 소프트 삭제 일시 (복원 후 null)
ip_address string 127.0.0.1 작성 요청이 발생한 IP 주소
action_logs array [{"action":"restore","reason":null,"admin_name":"API 문서 샘플 사용자","created_at":"2026-07-08 06:01:45"}] 블라인드/복원/삭제 처리 이력 목록. admin.manage 권한 보유자에게만 노출.
board null null 소속 게시판 정보 객체 (관계 미로드 시 null)
navigation null null 이전/다음 게시글 이동 정보 (쓰기 응답은 미계산 → null)
parent null null 원글 객체 (parent 관계 파생)
comments null null 댓글 목록 (관계 미로드 시 null)
attachments null null 첨부파일 목록 (관계 미로드 시 null)
replies null null 답변글 목록 (관계 미로드 시 null)
is_already_reported boolean false 현재 사용자가 이미 신고한 게시글인지 여부
is_owner boolean true 현재 인증 사용자가 이 리소스의 소유자인지 여부
abilities object {"can_read":true,"can_write":true,…} 현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "게시글이 복원되었습니다.",
    "data": {
        "id": 1,
        "category": null,
        "author": {
            "uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
            "name": "API 문서 샘플 사용자",
            "email": "apidoc-sample-user@example.com",
            "avatar": null,
            "status": "active",
            "status_label": "활성",
            "is_guest": false
        },
        "is_notice": false,
        "is_secret": false,
        "content_mode": "html",
        "is_new": true,
        "status": "published",
        "status_label": "게시됨",
        "view_count": 44,
        "comment_count": 0,
        "reply_count": 0,
        "attachment_count": 0,
        "has_attachment": false,
        "thumbnail": null,
        "parent_id": null,
        "depth": 0,
        "is_reply": false,
        "created_at": "2026-07-08 10:41:34",
        "created_at_formatted": "4시간 전",
        "is_author": true,
        "is_guest_post": false,
        "title": "API 문서 샘플 게시글",
        "content": "<p>API 레퍼런스 실측용 완전 샘플 게시글 본문입니다.</p>",
        "user_id": "a234c2b1-cde8-437f-b28b-23323be2b98d",
        "trigger_type": "admin",
        "updated_at": "2026-07-08 15:01:45",
        "deleted_at": null,
        "ip_address": "127.0.0.1",
        "action_logs": [
            {
                "action": "restore",
                "reason": null,
                "admin_name": "API 문서 샘플 사용자",
                "created_at": "2026-07-08 06:01:45"
            }
        ],
        "board": null,
        "navigation": null,
        "parent": null,
        "comments": null,
        "attachments": null,
        "replies": null,
        "is_already_reported": false,
        "is_owner": true,
        "abilities": {
            "can_read": true,
            "can_write": true,
            "can_read_secret": true,
            "can_read_comments": true,
            "can_write_comments": true,
            "can_upload": true,
            "can_download": true,
            "can_manage": true
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.manage)이 없는 경우
404 Not Found 슬러그에 해당하는 게시판 또는 ID 에 해당하는 게시글이 없는 경우 (존재하지 않는 게시글입니다.)
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (reason 이 1000자를 초과하는 등)
500 Internal Server Error 복원 처리 실패 (게시글 복원에 실패했습니다.)

설명 게시판 관리자가 블라인드 처리된 게시글을 복원합니다. auth:sanctum + admin + 게시판별 admin.manage 권한이 필요하며, 선택적 reason(최대 1000자)을 사유로 받아 PostService::restorePost()가 블라인드 상태를 해제해 게시글을 다시 노출합니다.

POST /api/modules/sirsoft-board/admin/board/{slug}/posts/{postId}/comments

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.comments.store
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\CommentController@store
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.comments.write

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
postId path string 예 — 대상 post의 식별자

이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (sirsoft-board.comment.store_validation_rules).

요청 예시

POST /api/modules/sirsoft-board/admin/board/{slug}/posts/{postId}/comments HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}

응답 필드 (data 내부)

단건 응답: data 객체의 필드 (CommentResource).

필드 타입 실측 예시값 용도/설명
id integer 1 댓글 기본 키 (내부 식별자)
post_id integer 1 댓글이 속한 게시글 식별자
parent_id null null 상위 댓글 식별자 (대댓글일 때만 값 존재)
content string API 문서 샘플 댓글입니다. 댓글 본문 내용
author object {"uuid":"a234c2b1-…","name":"API 문서 샘플 사용자"} 작성자 사용자 객체 (author 관계 파생)
is_secret boolean false 비밀 댓글 여부
status string published 댓글 상태 코드 (published / blinded / deleted)
status_label string 게시됨 상태의 사람이 읽는 라벨 (상태 Enum label() 산물)
depth integer 0 댓글 계층 깊이 (0 = 최상위 댓글, 서비스에서 자동 계산)
replies_count integer 0 이 댓글에 달린 대댓글 수 (집계)
created_at string 2026-07-08 10:41:34 생성 일시
created_at_formatted string 방금 전 created_at 값의 표시용 포맷 문자열
updated_at string 2026-07-08 10:41:34 최종 수정 일시
deleted_at null null 소프트 삭제 일시 (미삭제 시 null)
is_cascade_deleted boolean false 상위 게시글/댓글 삭제로 연쇄 삭제된 댓글인지 여부
ip_address string 127.0.0.1 작성 요청이 발생한 IP 주소 (권한자에게만 노출)
action_logs array [] 블라인드/복원/삭제 처리 이력 목록. admin.manage 권한 보유자에게만 노출.
is_author boolean true 현재 사용자가 작성자인지 여부
is_guest_comment boolean false 비회원 작성 댓글 여부
is_already_reported boolean false 현재 사용자가 이미 신고한 댓글인지 여부
is_owner boolean true 현재 인증 사용자가 이 리소스의 소유자인지 여부 (BaseApiResource 표준 메타)
abilities object {"can_read":true,"can_write":true,"can_manage":true} 현재 사용자가 이 댓글에 수행 가능한 작업 불리언 맵

응답 예시

HTTP/1.1 201
{
    "success": true,
    "message": "댓글이 등록되었습니다.",
    "data": {
        "id": 1,
        "post_id": 1,
        "parent_id": null,
        "content": "API 문서 샘플 댓글입니다.",
        "author": {
            "uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
            "name": "API 문서 샘플 사용자",
            "email": "apidoc-sample-user@example.com",
            "avatar": null,
            "status": "active",
            "status_label": "활성",
            "is_guest": false
        },
        "is_secret": false,
        "status": "published",
        "status_label": "게시됨",
        "depth": 0,
        "replies_count": 0,
        "created_at": "2026-07-08 10:41:34",
        "created_at_formatted": "방금 전",
        "updated_at": "2026-07-08 10:41:34",
        "deleted_at": null,
        "is_cascade_deleted": false,
        "ip_address": "127.0.0.1",
        "action_logs": [],
        "is_author": true,
        "is_guest_comment": false,
        "is_already_reported": false,
        "is_owner": true,
        "abilities": {
            "can_read": true,
            "can_write": true,
            "can_manage": true
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.comments.write)이 없거나, 게시판의 댓글 기능이 꺼진 경우 (이 게시판은 댓글 기능이 비활성화되어 있습니다.)
404 Not Found 슬러그에 해당하는 게시판이 없는 경우 (게시판을 찾을 수 없습니다.)
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지). 댓글 길이, 금지 키워드, 작성 쿨다운, 대상 게시글·상위 댓글 유효성 위반 포함
500 Internal Server Error 댓글 생성 처리 실패 (댓글 등록에 실패했습니다.)

설명 게시판 관리자가 특정 게시글에 댓글을 작성합니다. auth:sanctum + admin + 게시판별 comments.write 권한이 필요하며, 게시판의 use_comment가 꺼져 있으면 403으로 차단됩니다. 검증된 값에 게시글 ID·작성자(Auth::id())·요청 IP가 자동으로 채워져 CommentService::createComment()로 전달되고, 성공 시 생성된 댓글 리소스를 201로 반환합니다.

DELETE /api/modules/sirsoft-board/admin/board/{slug}/posts/{postId}/comments/{id}

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.comments.destroy
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\CommentController@destroy
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.comments.write|sirsoft-board.{slug}.admin.manage

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
postId path string 예 — 대상 post의 식별자
id path string 예 — 대상 리소스의 식별자

요청 예시

DELETE /api/modules/sirsoft-board/admin/board/{slug}/posts/{postId}/comments/{id} 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.{slug}.admin.comments.write|sirsoft-board.{slug}.admin.manage)이 없거나, 타인/비회원 댓글을 admin.manage 없이 삭제하려는 경우(접근 권한이 없습니다.), 게시판의 댓글 기능이 꺼진 경우(이 게시판은 댓글 기능이 비활성화되어 있습니다.)
404 Not Found ID 에 해당하는 댓글 또는 슬러그에 해당하는 게시판이 없는 경우 (댓글을 찾을 수 없습니다.)
500 Internal Server Error 삭제 처리 실패 (댓글 삭제에 실패했습니다.)

설명 게시판 관리자가 댓글 1건을 삭제합니다. auth:sanctum + admin 인증이 필요하며, 라우트 권한은 comments.write 또는 manage입니다. 컨트롤러가 댓글을 조회한 뒤 권한을 적용합니다: admin.manage는 모든 댓글(비회원 댓글 포함), admin.write는 본인 댓글만 삭제할 수 있습니다. 게시판의 use_comment가 꺼져 있으면 403이며, CommentService::deleteComment()가 'admin' 컨텍스트로 삭제를 수행합니다. 경로의 {postId}에 속한 댓글만 대상이 됩니다 — 다른 게시글의 댓글 ID를 지정하면 404를 반환하며 해당 댓글은 변경되지 않습니다.

PUT /api/modules/sirsoft-board/admin/board/{slug}/posts/{postId}/comments/{id}

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.comments.update
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\CommentController@update
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.comments.write

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
postId path string 예 — 대상 post의 식별자
id path string 예 — 대상 리소스의 식별자

이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (sirsoft-board.comment.update_validation_rules).

요청 예시

PUT /api/modules/sirsoft-board/admin/board/{slug}/posts/{postId}/comments/{id} HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}

응답 필드 (data 내부)

단건 응답: data 객체의 필드 (CommentResource — 댓글 생성/블라인드 응답과 동일한 구조).

필드 타입 실측 예시값 용도/설명
id integer 1 댓글 기본 키 (내부 식별자)
post_id integer 1 댓글이 속한 게시글 식별자
parent_id null null 상위 댓글 식별자 (대댓글일 때만 값 존재)
content string API 문서 샘플 댓글입니다. (수정) 수정된 댓글 본문 내용
author object {"uuid":"a234c2b1-…","name":"API 문서 샘플 사용자"} 작성자 사용자 객체 (author 관계 파생)
is_secret boolean false 비밀 댓글 여부
status string published 댓글 상태 코드 (published / blinded / deleted)
status_label string 게시됨 상태의 사람이 읽는 라벨
depth integer 0 댓글 계층 깊이 (0 = 최상위 댓글)
replies_count integer 0 이 댓글에 달린 대댓글 수 (집계)
created_at string 2026-07-08 10:41:34 생성 일시
created_at_formatted string 4시간 전 created_at 값의 표시용 포맷 문자열
updated_at string 2026-07-08 15:01:45 최종 수정 일시 (수정 시각으로 갱신)
deleted_at null null 소프트 삭제 일시 (미삭제 시 null)
is_cascade_deleted boolean false 상위 게시글/댓글 삭제로 연쇄 삭제된 댓글인지 여부
ip_address null null 작성 요청이 발생한 IP 주소 (권한자에게만 노출)
action_logs array [] 블라인드/복원/삭제 처리 이력 목록. admin.manage 권한 보유자에게만 노출.
is_author boolean true 현재 사용자가 작성자인지 여부
is_guest_comment boolean false 비회원 작성 댓글 여부
is_already_reported boolean false 현재 사용자가 이미 신고한 댓글인지 여부
is_owner boolean true 현재 인증 사용자가 이 리소스의 소유자인지 여부
abilities object {"can_read":true,"can_write":true,"can_manage":true} 현재 사용자가 이 댓글에 수행 가능한 작업 불리언 맵

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "댓글이 수정되었습니다.",
    "data": {
        "id": 1,
        "post_id": 1,
        "parent_id": null,
        "content": "API 문서 샘플 댓글입니다. (수정)",
        "author": {
            "uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
            "name": "API 문서 샘플 사용자",
            "email": "apidoc-sample-user@example.com",
            "avatar": null,
            "status": "active",
            "status_label": "활성",
            "is_guest": false
        },
        "is_secret": false,
        "status": "published",
        "status_label": "게시됨",
        "depth": 0,
        "replies_count": 0,
        "created_at": "2026-07-08 10:41:34",
        "created_at_formatted": "4시간 전",
        "updated_at": "2026-07-08 15:01:45",
        "deleted_at": null,
        "is_cascade_deleted": false,
        "ip_address": null,
        "action_logs": [],
        "is_author": true,
        "is_guest_comment": false,
        "is_already_reported": false,
        "is_owner": true,
        "abilities": {
            "can_read": true,
            "can_write": true,
            "can_manage": true
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.comments.write)이 없거나, 타인/비회원 댓글을 admin.manage 없이 수정하려는 경우(접근 권한이 없습니다.), 게시판의 댓글 기능이 꺼진 경우(이 게시판은 댓글 기능이 비활성화되어 있습니다.)
404 Not Found ID 에 해당하는 댓글 또는 슬러그에 해당하는 게시판이 없는 경우 (댓글을 찾을 수 없습니다.)
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지)
500 Internal Server Error 수정 처리 실패 (댓글 수정에 실패했습니다.)

설명 게시판 관리자가 댓글 1건을 수정합니다. auth:sanctum + admin + 게시판별 comments.write 권한이 필요하며, 컨트롤러가 댓글을 조회한 뒤 권한을 적용합니다: admin.manage는 모든 댓글, admin.write는 본인 댓글만 수정할 수 있습니다. 게시판의 use_comment가 꺼져 있으면 403이며, UpdateCommentRequest 검증 값으로 CommentService::updateComment()가 갱신을 수행합니다. 경로의 {postId}에 속한 댓글만 대상이 됩니다 — 다른 게시글의 댓글 ID를 지정하면 404를 반환하며 해당 댓글은 변경되지 않습니다.

PATCH /api/modules/sirsoft-board/admin/board/{slug}/posts/{postId}/comments/{id}/blind

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.comments.blind
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\CommentController@blind
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.manage

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
postId path string 예 — 대상 post의 식별자
id path string 예 — 대상 리소스의 식별자
reason body string 아니오 max 1000 댓글 블라인드 처리 사유(최대 1000자). 처리 이력에 기록되며, 미지정 시 빈 문자열로 저장됩니다.

요청 예시

PATCH /api/modules/sirsoft-board/admin/board/{slug}/posts/{postId}/comments/{id}/blind HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json

{
    "reason": "예시값"
}

응답 필드 (data 내부)

단건 응답: data 객체의 필드.

필드 타입 실측 예시값 용도/설명
id integer 1 기본 키 (내부 식별자)
post_id integer 1 post 식별자 (연관 리소스 참조)
parent_id null null parent 식별자 (연관 리소스 참조)
content string API 문서 샘플 댓글입니다. 본문 내용
author object {"uuid":"a234c2b1-cde8-437f-b28b-23323be2b98d","name":"AP… 작성자 사용자 객체 (uuid/name — author 관계 파생)
is_secret boolean false secret 여부
status string blinded 상태 값 (도메인별 상태 집합 — 사람이 읽는 라벨은 status_label, UI 변형은 status_variant 참조)
status_label string 블라인드 상태의 사람이 읽는 라벨 (상태 Enum label() 산물)
depth integer 0 계층 트리에서의 깊이 (0 = 최상위, 하위로 갈수록 증가)
replies_count integer 0 replies 개수 (집계)
created_at string 2026-07-08 10:41:34 생성 일시
created_at_formatted string 4시간 전 created_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷)
updated_at string 2026-07-08 15:01:44 최종 수정 일시
deleted_at null null 소프트 삭제 일시 (미삭제 시 null)
is_cascade_deleted boolean false cascade deleted 여부
ip_address null null 요청/행위가 발생한 IP 주소
action_logs array [{"action":"blind","reason":"실측 예시값","admin_name":"API 문서… 블라인드/복원/삭제 등 처리 이력 목록(항목별 action·reason·admin_name·created_at). admin.manage 권한 보유자에게만 노출되며, 민감 필드(admin_id·ip_address)는 제외됩니다. 비권한자에게는 null.
is_author boolean true author 여부
is_guest_comment boolean false guest comment 여부
is_already_reported boolean false already reported 여부
is_owner boolean true 현재 인증 사용자가 이 리소스의 소유자인지 여부 (BaseApiResource 표준 메타)
abilities object {"can_read":true,"can_write":true,"can_manage":true} 현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반)

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "댓글이 블라인드 처리되었습니다.",
    "data": {
        "id": 1,
        "post_id": 1,
        "parent_id": null,
        "content": "API 문서 샘플 댓글입니다.",
        "author": {
            "uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
            "name": "API 문서 샘플 사용자",
            "email": "apidoc-sample-user@example.com",
            "avatar": null,
            "status": "active",
            "status_label": "활성",
            "is_guest": false
        },
        "is_secret": "{MASKED}",
        "status": "blinded",
        "status_label": "블라인드",
        "depth": 0,
        "replies_count": 0,
        "created_at": "2026-07-08 10:41:34",
        "created_at_formatted": "4시간 전",
        "updated_at": "2026-07-08 15:01:44",
        "deleted_at": null,
        "is_cascade_deleted": false,
        "ip_address": null,
        "action_logs": [
            {
                "action": "blind",
                "reason": "실측 예시값",
                "admin_name": "API 문서 샘플 사용자",
                "created_at": "2026-07-08 06:01:44"
            }
        ],
        "is_author": true,
        "is_guest_comment": false,
        "is_already_reported": false,
        "is_owner": true,
        "abilities": {
            "can_read": true,
            "can_write": true,
            "can_manage": true
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.manage)이 없는 경우
404 Not Found path 파라미터에 해당하는 리소스가 없는 경우
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지)

설명 게시판 관리자가 댓글을 블라인드 처리합니다. auth:sanctum + admin + 게시판별 admin.manage 권한이 필요하며, 게시판의 use_comment가 꺼져 있으면 403으로 차단됩니다. 선택적 reason(최대 1000자)을 사유로 받아 CommentService::blindComment()가 댓글을 숨김 처리하되 관리 목적으로 보존하며, 복원(restore)으로 되돌릴 수 있습니다. 경로의 {postId}에 속한 댓글만 대상이 됩니다 — 다른 게시글의 댓글 ID를 지정하면 404를 반환하며 해당 댓글은 변경되지 않습니다.

PATCH /api/modules/sirsoft-board/admin/board/{slug}/posts/{postId}/comments/{id}/restore

  • 라우트명: api.modules.sirsoft-board.admin.board.posts.comments.restore
  • 컨트롤러: Modules\Sirsoft\Board\Http\Controllers\Admin\CommentController@restore
  • 인증/권한: auth:sanctum + permission:sirsoft-board.{slug}.admin.manage

요청 파라미터

이름 위치 타입 필수 허용값 용도
slug path string 예 — 대상 리소스의 slug (URL 친화 식별자)
postId path string 예 — 대상 post의 식별자
id path string 예 — 대상 리소스의 식별자
reason body string 아니오 max 1000 댓글 블라인드 처리 사유(최대 1000자). 처리 이력에 기록되며, 미지정 시 빈 문자열로 저장됩니다.

요청 예시

PATCH /api/modules/sirsoft-board/admin/board/{slug}/posts/{postId}/comments/{id}/restore HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json

{
    "reason": "예시값"
}

응답 필드 (data 내부)

단건 응답: data 객체의 필드 (CommentResource — 복원된 댓글. 블라인드 응답과 동일한 구조이며, status 가 published 로 되돌아가고 action_logs 에 restore 이력이 1건 추가됩니다).

필드 타입 실측 예시값 용도/설명
id integer 1 댓글 기본 키 (내부 식별자)
post_id integer 1 댓글이 속한 게시글 식별자
parent_id null null 상위 댓글 식별자 (대댓글일 때만 값 존재)
content string API 문서 샘플 댓글입니다. 댓글 본문 내용 (복원되어 원문이 다시 노출됨)
author object {"uuid":"a234c2b1-…","name":"API 문서 샘플 사용자"} 작성자 사용자 객체 (author 관계 파생)
is_secret boolean false 비밀 댓글 여부
status string published 복원 후 댓글 상태 (published 로 되돌아감)
status_label string 게시됨 상태의 사람이 읽는 라벨
depth integer 0 댓글 계층 깊이 (0 = 최상위 댓글)
replies_count integer 0 이 댓글에 달린 대댓글 수 (집계)
created_at string 2026-07-08 10:41:34 생성 일시
created_at_formatted string 4시간 전 created_at 값의 표시용 포맷 문자열
updated_at string 2026-07-08 15:01:45 최종 수정 일시
deleted_at null null 소프트 삭제 일시 (미삭제 시 null)
is_cascade_deleted boolean false 상위 게시글/댓글 삭제로 연쇄 삭제된 댓글인지 여부
ip_address null null 작성 요청이 발생한 IP 주소 (권한자에게만 노출)
action_logs array [{"action":"blind","reason":"실측 예시값",…},{"action":"restore","reason":null,…}] 블라인드/복원/삭제 처리 이력 목록 (복원 이력이 추가됨). admin.manage 권한 보유자에게만 노출.
is_author boolean true 현재 사용자가 작성자인지 여부
is_guest_comment boolean false 비회원 작성 댓글 여부
is_already_reported boolean false 현재 사용자가 이미 신고한 댓글인지 여부
is_owner boolean true 현재 인증 사용자가 이 리소스의 소유자인지 여부
abilities object {"can_read":true,"can_write":true,"can_manage":true} 현재 사용자가 이 댓글에 수행 가능한 작업 불리언 맵

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "댓글이 복원되었습니다.",
    "data": {
        "id": 1,
        "post_id": 1,
        "parent_id": null,
        "content": "API 문서 샘플 댓글입니다.",
        "author": {
            "uuid": "a234c2b1-cde8-437f-b28b-23323be2b98d",
            "name": "API 문서 샘플 사용자",
            "email": "apidoc-sample-user@example.com",
            "avatar": null,
            "status": "active",
            "status_label": "활성",
            "is_guest": false
        },
        "is_secret": false,
        "status": "published",
        "status_label": "게시됨",
        "depth": 0,
        "replies_count": 0,
        "created_at": "2026-07-08 10:41:34",
        "created_at_formatted": "4시간 전",
        "updated_at": "2026-07-08 15:01:45",
        "deleted_at": null,
        "is_cascade_deleted": false,
        "ip_address": null,
        "action_logs": [
            {
                "action": "blind",
                "reason": "실측 예시값",
                "admin_name": "API 문서 샘플 사용자",
                "created_at": "2026-07-08 06:01:44"
            },
            {
                "action": "restore",
                "reason": null,
                "admin_name": "API 문서 샘플 사용자",
                "created_at": "2026-07-08 06:01:45"
            }
        ],
        "is_author": true,
        "is_guest_comment": false,
        "is_already_reported": false,
        "is_owner": true,
        "abilities": {
            "can_read": true,
            "can_write": true,
            "can_manage": true
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
403 Forbidden 요구 권한(sirsoft-board.{slug}.admin.manage)이 없거나, 게시판의 댓글 기능이 꺼진 경우 (이 게시판은 댓글 기능이 비활성화되어 있습니다.)
404 Not Found ID 에 해당하는 댓글 또는 슬러그에 해당하는 게시판이 없는 경우 (댓글을 찾을 수 없습니다.)
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지)
500 Internal Server Error 복원 처리 실패 (댓글 복원에 실패했습니다.)

설명 게시판 관리자가 블라인드 처리된 댓글을 복원합니다. auth:sanctum + admin + 게시판별 admin.manage 권한이 필요하며, 게시판의 use_comment가 꺼져 있으면 403으로 차단됩니다. 요청 본문의 선택적 reason을 사유로 받아 CommentService::restoreComment()가 블라인드 상태를 해제해 댓글을 다시 노출합니다. 경로의 {postId}에 속한 댓글만 대상이 됩니다 — 다른 게시글의 댓글 ID를 지정하면 404를 반환하며 해당 댓글은 변경되지 않습니다.