Skip to content

T-15 활동 CRUD + 본문 정제 - #69

Open
ff1451 wants to merge 1 commit into
feat/t14-activity-categoryfrom
feat/t15-activity-crud
Open

T-15 활동 CRUD + 본문 정제#69
ff1451 wants to merge 1 commit into
feat/t14-activity-categoryfrom
feat/t15-activity-crud

Conversation

@ff1451

@ff1451 ff1451 commented Aug 19, 2026

Copy link
Copy Markdown

요약

  • 관리자 활동 CRUD(생성/조회/수정/공개-숨김/삭제), 페이징+선택 필터(categoryId/year/published), 같은 (카테고리, 연, 월) 버킷 안에서의 순서 변경, 사진 전체 교체 API.
  • 본문(HTML)은 생성/수정 저장 시점에만 jsoup Safelist로 정제한다(ADR-008). img는 safelist만으로 호스트 제한이 안 돼, 정제 후 별도로 허용 호스트(image.bcsdlab.com, static.koreatech.in)가 아닌 <img>를 제거한다(INV-10).
  • AC-3.8: activity_category는 soft delete라 activity FK(RESTRICT)가 삭제를 막아주지 않는다(행이 물리적으로 남아 있어서 위반이 안 남) — 애플리케이션에서 existsByCategory_Id로 직접 검사해 409로 막는다.

05-api-spec.md 대비 의도적 차이

  • ActivityCreateRequest/ActivityUpdateRequestisPublished, imageUrls를 넣지 않았다. 공개 여부는 PATCH .../publish, 사진은 PUT .../images 전체 교체로만 다루는 기존 규약(트랙 페이지/커리큘럼과 동일)을 그대로 따른 것이다.

다른 PR(T-14, #68)에 대한 수정

AdminActivityCategoryIntegrationTestIntegrationTestSupport의 공유 컨테이너를 쓰는데, activity_category.deleteAll()이 soft-delete된(@SQLRestriction으로 걸러진) activity 행을 못 지우고 물리적으로 남겨서, 그 행이 FK로 카테고리를 계속 참조해 다음 테스트의 정리(deleteAll)를 막는 문제가 있었다. T-15에서 Activity가 같은 컨테이너에 처음 등장하면서 이 잠재 버그가 드러나 이 PR에서 함께 고쳤다(jdbcTemplate 물리 삭제로 대체). T-14 자체 코드는 건드리지 않았다.

검증

  • ./gradlew test 전체 통과, 3회 연속 재실행으로 공유 컨테이너 순서 의존성 없음 확인.
  • AC-3.3(월 범위 400), AC-3.4(사진 순서/썸네일), AC-3.5(script 태그 제거), AC-3.8(활동 남은 카테고리 삭제 차단), 공개/숨김·soft delete, 같은 (카테고리,연,월) 순서 변경 — 통합 테스트로 커버.
  • jsoup 새니타이저는 단위 테스트 7종으로 별도 검증(스크립트 제거, 이벤트 핸들러 제거, 미허용 태그 제거, 호스트 제한 이미지 제거, 콘텐츠 보존, null-safety).

남은 항목

  • T-16(활동 공개 API)에서 이 도메인의 공개 조회 엔드포인트를 다룬다.

Refs #58 (프로젝트), 브랜치는 feat/t14-activity-category(#68) 위에 스택.

머지하지 않습니다. 부원 리뷰 후 직접 머지 예정입니다.

- Activity/ActivityImage 엔티티, 관리자 CRUD·페이징·필터(Specification), 순서 변경(월 단위
  버킷), 사진 전체 교체 API 구현.
- ActivityContentSanitizer: jsoup Safelist로 태그/속성 제한 + img 태그는 별도로 호스트
  화이트리스트(image.bcsdlab.com, static.koreatech.in) 검사 후 제거(safelist만으로는 호스트
  단위 제한이 안 됨). 저장 시점에만 정제한다(ADR-008).
- ActivityImage는 BaseTimeEntity를 상속하지 않는다 — activity_image 테이블에는 updated_at이
  없다(사진은 항상 전체 교체로만 다뤄 수정 시각이 필요 없음).
- AdminActivityService.getActivities: Specification.where(null)이 새 Spring Data JPA
  버전에서 PredicateSpecification 오버로드와 겹쳐 모호해서, null이 아닌 조건만 모아
  Specification.allOf(List)로 대체.
- AC-3.8: activity_category는 soft delete라 activity FK(RESTRICT)가 행을 막아주지
  않는다(행이 물리적으로 남아 있어 위반이 안 남) — AdminActivityCategoryService에서
  activityRepository.existsByCategory_Id로 직접 검사.
- 같은 IntegrationTestSupport 컨테이너를 공유하는 테스트 정리 순서 버그 수정: activity가
  soft delete(@SQLRestriction)라 deleteAll()이 삭제된 행을 못 찾아 물리적으로 남기고, 그
  남은 행이 activity_category FK를 계속 참조해 다음 deleteAll()을 막는다. 이미 열려 있는
  T-14 PR(#68)의 AdminActivityCategoryIntegrationTest도 T-15부터 같은 컨테이너에
  activity 행이 생기면서 새로 취약해져 함께 수정(jdbcTemplate 물리 삭제로 대체).

검증: ./gradlew test 전체 통과 3회 연속.
@ff1451

ff1451 commented Aug 19, 2026

Copy link
Copy Markdown
Author

Refs #27

@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bc63c59b-5c2f-491a-be79-bff84e033888

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ff1451 ff1451 mentioned this pull request Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant