diff --git a/backend/api/src/main/java/com/studyclub/api/application/StudyApplicationFormController.java b/backend/api/src/main/java/com/studyclub/api/application/StudyApplicationFormController.java index c738a35d0..d8c573cc2 100644 --- a/backend/api/src/main/java/com/studyclub/api/application/StudyApplicationFormController.java +++ b/backend/api/src/main/java/com/studyclub/api/application/StudyApplicationFormController.java @@ -1,31 +1,22 @@ package com.studyclub.api.application; -import com.studyclub.api.application.StudyApplicationFormRequests.StudyApplicationFormRequest; import com.studyclub.api.application.StudyApplicationFormResponses.StudyApplicationFormResponse; -import com.studyclub.api.auth.security.RequireCaptainOrNavigator; -import com.studyclub.api.auth.security.RequireOnboarding; -import com.studyclub.common.error.BusinessException; -import com.studyclub.common.error.ErrorCode; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** - * 사용자 사이트의 신청 폼 — 크루가 조회하고, 캡틴·네비게이터가 저장한다. + * 사용자 사이트의 신청 폼 — 크루가 조회한다. * - *
백오피스 화면은 {@link AdminApplicationFormController}({@code /api/admin})를 쓰고 캡틴만 통과한다. 같은 - * 기능이지만 관객이 달라 경로와 권한을 나눴다 — POL-0001 · api/endpoint-convention.md + *
저장(PUT)은 백오피스 {@link AdminApplicationFormController}({@code /api/admin})에서만 가능하고 캡틴만 통과한다.
+ * specs/authz-guards/spec.md B절 후속 — 네비게이터는 신청 폼을 고치지 않는다.
*/
-@Tag(name = "스터디 신청 폼", description = "크루가 조회하고, 캡틴·네비게이터가 저장한다")
+@Tag(name = "스터디 신청 폼", description = "크루가 조회한다")
@RestController
@RequestMapping("/api/studies/{studyId}/application-form")
public class StudyApplicationFormController {
@@ -50,34 +41,6 @@ public StudyApplicationFormResponse getForm(
return studyApplicationFormService.getForm(studyId, optionalAccountId(authentication));
}
- @Operation(
- summary = "스터디 신청 폼 저장 (사용자 사이트)",
- description =
- """
- 캡틴 또는 그 스터디의 네비게이터가 추가 질문을 통째로 교체합니다.
- 백오피스에서 저장하는 경로는 PUT /api/admin/studies/{studyId}/application-form 이고,
- 그쪽은 캡틴만 통과합니다 (POL-0001).
- 이미 신청서가 있거나 모집이 시작됐으면 CONFLICT입니다.""")
- @SecurityRequirement(name = "bearerAuth")
- @RequireOnboarding
- @RequireCaptainOrNavigator
- @PutMapping
- public StudyApplicationFormResponse replaceForm(
- @Parameter(description = "신청 폼을 저장할 스터디 ID", example = "1") @PathVariable Long studyId,
- @Valid @RequestBody StudyApplicationFormRequest request,
- Authentication authentication) {
- return studyApplicationFormService.replaceFormFromSite(
- studyId, authenticatedAccountId(authentication), request);
- }
-
- private Long authenticatedAccountId(Authentication authentication) {
- Long accountId = optionalAccountId(authentication);
- if (accountId == null) {
- throw new BusinessException(ErrorCode.UNAUTHORIZED);
- }
- return accountId;
- }
-
private Long optionalAccountId(Authentication authentication) {
if (authentication == null || !(authentication.getPrincipal() instanceof Long accountId)) {
return null;
diff --git a/backend/api/src/main/java/com/studyclub/api/application/StudyApplicationFormService.java b/backend/api/src/main/java/com/studyclub/api/application/StudyApplicationFormService.java
index d84b0de45..4bf4bd26d 100644
--- a/backend/api/src/main/java/com/studyclub/api/application/StudyApplicationFormService.java
+++ b/backend/api/src/main/java/com/studyclub/api/application/StudyApplicationFormService.java
@@ -75,13 +75,6 @@ public StudyApplicationFormResponse getForm(Long studyId, Long accountId) {
return toResponse(study);
}
- /** 사용자 사이트 저장 — 권한은 {@code @RequireCaptainOrNavigator}. */
- @Transactional
- public StudyApplicationFormResponse replaceFormFromSite(
- Long studyId, Long accountId, StudyApplicationFormRequest request) {
- return replace(studyId, request);
- }
-
/** 백오피스 저장 — 권한은 {@code @RequireAdmin}. */
@Transactional
public StudyApplicationFormResponse replaceFormFromBackOffice(
diff --git a/backend/api/src/test/java/com/studyclub/api/application/StudyApplicationFormIntegrationTest.java b/backend/api/src/test/java/com/studyclub/api/application/StudyApplicationFormIntegrationTest.java
index 7a2d5a78d..b6d67dbfc 100644
--- a/backend/api/src/test/java/com/studyclub/api/application/StudyApplicationFormIntegrationTest.java
+++ b/backend/api/src/test/java/com/studyclub/api/application/StudyApplicationFormIntegrationTest.java
@@ -106,8 +106,8 @@ void publicFormIsReadableWithoutToken() {
}
@Test
- @DisplayName("성공 - 네비게이터는 사용자 사이트에서 신청 폼을 저장하고 정규화된 폼을 다시 받는다")
- void navigatorReplacesFormFromSite() {
+ @DisplayName("실패 - 사용자 사이트 PUT은 삭제되어 존재하지 않는다 (4xx — 메서드 불일치)")
+ void sitePutIsRemoved() {
var response =
rest.exchange(
"/api/studies/" + EDITABLE_STUDY_ID + "/application-form",
@@ -115,20 +115,7 @@ void navigatorReplacesFormFromSite() {
authenticatedJsonRequest(LEADER_ID, validRequest()),
Map.class);
- assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
- assertThat(response.getBody()).containsEntry("title", "새 신청 폼");
- assertThat(response.getBody()).containsEntry("description", "마크다운 **원문**");
- List> questions = (List>) response.getBody().get("questions");
- assertThat(questions).hasSize(1);
- @SuppressWarnings("unchecked")
- Map