diff --git a/backend/src/main/java/com/worlabel/domain/image/controller/ImageController.java b/backend/src/main/java/com/worlabel/domain/image/controller/ImageController.java index a668802..a0e1d64 100644 --- a/backend/src/main/java/com/worlabel/domain/image/controller/ImageController.java +++ b/backend/src/main/java/com/worlabel/domain/image/controller/ImageController.java @@ -62,7 +62,7 @@ public class ImageController { @PutMapping("/{image_id}") @SwaggerApiSuccess(description = "이미지 폴더 이동.") @Operation(summary = "이미지 폴더 이동", description = "이미지가 위치한 폴더를 변경합니다.") - @SwaggerApiError({ErrorCode.BAD_REQUEST, ErrorCode.NOT_AUTHOR, ErrorCode.SERVER_ERROR, ErrorCode.PARTICIPANT_UNAUTHORIZED, ErrorCode.FOLDER_NOT_FOUND, ErrorCode.IMAGE_NOT_FOUND}) + @SwaggerApiError({ErrorCode.BAD_REQUEST, ErrorCode.NOT_AUTHOR, ErrorCode.SERVER_ERROR, ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED, ErrorCode.FOLDER_NOT_FOUND, ErrorCode.IMAGE_NOT_FOUND}) public BaseResponse moveFolderImage( @CurrentUser final Integer memberId, @PathVariable("folder_id") final Integer folderId, @@ -78,7 +78,7 @@ public class ImageController { @DeleteMapping("/{image_id}") @SwaggerApiSuccess(description = "이미지 삭제.") @Operation(summary = "이미지 삭제", description = "폴더에서 해당 이미지를 제거합니다.") - @SwaggerApiError({ErrorCode.BAD_REQUEST, ErrorCode.NOT_AUTHOR, ErrorCode.SERVER_ERROR, ErrorCode.PARTICIPANT_UNAUTHORIZED, ErrorCode.FOLDER_NOT_FOUND, ErrorCode.IMAGE_NOT_FOUND}) + @SwaggerApiError({ErrorCode.BAD_REQUEST, ErrorCode.NOT_AUTHOR, ErrorCode.SERVER_ERROR, ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED, ErrorCode.FOLDER_NOT_FOUND, ErrorCode.IMAGE_NOT_FOUND}) public BaseResponse deleteImage( @CurrentUser final Integer memberId, @PathVariable("folder_id") final Integer folderId, @@ -93,7 +93,7 @@ public class ImageController { @PutMapping("/{image_id}/status") @SwaggerApiSuccess(description = "이미지 상태 변경.") @Operation(summary = "이미지 상태 변경", description = "특정 이미지의 상태를 변경합니다.") - @SwaggerApiError({ErrorCode.BAD_REQUEST, ErrorCode.NOT_AUTHOR, ErrorCode.SERVER_ERROR, ErrorCode.PARTICIPANT_UNAUTHORIZED, ErrorCode.FOLDER_NOT_FOUND, ErrorCode.IMAGE_NOT_FOUND}) + @SwaggerApiError({ErrorCode.BAD_REQUEST, ErrorCode.NOT_AUTHOR, ErrorCode.SERVER_ERROR, ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED, ErrorCode.FOLDER_NOT_FOUND, ErrorCode.IMAGE_NOT_FOUND}) public BaseResponse changeImageStatus( @CurrentUser final Integer memberId, @PathVariable("folder_id") final Integer folderId, diff --git a/backend/src/main/java/com/worlabel/domain/image/service/ImageService.java b/backend/src/main/java/com/worlabel/domain/image/service/ImageService.java index 4d30233..a6bfd31 100644 --- a/backend/src/main/java/com/worlabel/domain/image/service/ImageService.java +++ b/backend/src/main/java/com/worlabel/domain/image/service/ImageService.java @@ -7,7 +7,6 @@ import com.worlabel.domain.image.entity.dto.ImageResponse; import com.worlabel.domain.image.entity.dto.ImageStatusRequest; import com.worlabel.domain.image.repository.ImageRepository; import com.worlabel.domain.participant.entity.Participant; -import com.worlabel.domain.participant.entity.PrivilegeType; import com.worlabel.domain.participant.repository.ParticipantRepository; import com.worlabel.global.exception.CustomException; import com.worlabel.global.exception.ErrorCode; @@ -121,10 +120,10 @@ public class ImageService { // 편집자 이상의 권한을 확인하는 메서드 private void checkEditorParticipant(final Integer memberId, final Integer projectId) { Participant participant = participantRepository.findByMemberIdAndProjectId(memberId, projectId) - .orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED)); + .orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED)); if (!participant.getPrivilege().isEditeAuth()) { - throw new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED); + throw new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED); } } diff --git a/backend/src/main/java/com/worlabel/domain/label/service/LabelService.java b/backend/src/main/java/com/worlabel/domain/label/service/LabelService.java index b7bfb67..01a2b41 100644 --- a/backend/src/main/java/com/worlabel/domain/label/service/LabelService.java +++ b/backend/src/main/java/com/worlabel/domain/label/service/LabelService.java @@ -174,7 +174,7 @@ public class LabelService { private void checkEditorExistParticipant(final Integer memberId, final Integer projectId) { log.debug("권한체크"); if (participantRepository.doesParticipantUnauthorizedExistByMemberIdAndProjectId(memberId, projectId)) { - throw new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED); + throw new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED); } } } diff --git a/backend/src/main/java/com/worlabel/domain/labelcategory/controller/LabelCategoryController.java b/backend/src/main/java/com/worlabel/domain/labelcategory/controller/LabelCategoryController.java new file mode 100644 index 0000000..17a12c5 --- /dev/null +++ b/backend/src/main/java/com/worlabel/domain/labelcategory/controller/LabelCategoryController.java @@ -0,0 +1,66 @@ +package com.worlabel.domain.labelcategory.controller; + +import com.worlabel.domain.labelcategory.entity.dto.LabelCategoryRequest; +import com.worlabel.domain.labelcategory.entity.dto.LabelCategoryResponse; +import com.worlabel.domain.labelcategory.service.LabelCategoryService; +import com.worlabel.global.annotation.CurrentUser; +import com.worlabel.global.config.swagger.SwaggerApiError; +import com.worlabel.global.config.swagger.SwaggerApiSuccess; +import com.worlabel.global.exception.ErrorCode; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.data.repository.query.Param; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Tag(name = "레이블 카테고리 관련 API") +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/projects/{project_id}/categories") +public class LabelCategoryController { + + private final LabelCategoryService categoryService; + + @Operation(summary = "레이블 카테고리 생성", description = "프로젝트에 카테고리를 생성합니다.") + @SwaggerApiSuccess(description = "카테고리 성공적으로 생성합니다.") + @SwaggerApiError({ErrorCode.EMPTY_REQUEST_PARAMETER, ErrorCode.SERVER_ERROR}) + @PostMapping + public LabelCategoryResponse createFolder(@CurrentUser final Integer memberId, @PathVariable("project_id") final Integer projectId, @RequestBody final LabelCategoryRequest categoryRequest) { + return categoryService.createCategory(memberId, projectId, categoryRequest); + } + + @Operation(summary = "레이블 카테고리 단일 조회", description = "레이블 카테고리를 조회합니다.") + @SwaggerApiSuccess(description = "카테고리 성공적으로 조회합니다.") + @SwaggerApiError({ErrorCode.EMPTY_REQUEST_PARAMETER, ErrorCode.SERVER_ERROR}) + @GetMapping("/{category_id}") + public LabelCategoryResponse getCategoryById(@CurrentUser final Integer memberId, @PathVariable("project_id") final Integer projectId, @PathVariable("category_id") final Integer categoryId) { + return categoryService.getCategoryById(memberId, projectId, categoryId); + } + + @Operation(summary = "레이블 카테고리 존재 여부 조회", description = "해당 프로젝트에 같은 레이블 카테고리 이름이 있는지 조회합니다.") + @SwaggerApiSuccess(description = "카테고리 존재 여부를 조회합니다.") + @SwaggerApiError({ErrorCode.EMPTY_REQUEST_PARAMETER, ErrorCode.SERVER_ERROR}) + @GetMapping("/exist") + public boolean existByCategoryName(@CurrentUser final Integer memberId, @PathVariable("project_id") final Integer projectId, @Param("categoryName") final String categoryName) { + return categoryService.existByCategoryName(memberId, projectId, categoryName); + } + + @Operation(summary = "레이블 카테고리 리스트 조회", description = "레이블 카테고리 리스트를 조회합니다..") + @SwaggerApiSuccess(description = "카테고리 리스트를 성공적으로 조회합니다.") + @SwaggerApiError({ErrorCode.EMPTY_REQUEST_PARAMETER, ErrorCode.SERVER_ERROR}) + @GetMapping + public List getCategoryList(@CurrentUser final Integer memberId, @PathVariable("project_id") final Integer projectId) { + return categoryService.getCategoryList(memberId, projectId); + } + + + @Operation(summary = "카테고리 삭제", description = "카테고리를 삭제합니다.") + @SwaggerApiError({ErrorCode.EMPTY_REQUEST_PARAMETER, ErrorCode.SERVER_ERROR}) + @SwaggerApiSuccess(description = "카테고리를 성공적으로 삭제합니다.") + @DeleteMapping("/{category_id}") + public void deleteCategoryById(@CurrentUser final Integer memberId, @PathVariable("project_id") final Integer projectId, @PathVariable("category_id") final Integer categoryId) { + categoryService.deleteCategory(memberId, projectId, categoryId); + } +} diff --git a/backend/src/main/java/com/worlabel/domain/labelcategory/entity/LabelCategory.java b/backend/src/main/java/com/worlabel/domain/labelcategory/entity/LabelCategory.java new file mode 100644 index 0000000..ec2cd67 --- /dev/null +++ b/backend/src/main/java/com/worlabel/domain/labelcategory/entity/LabelCategory.java @@ -0,0 +1,45 @@ +package com.worlabel.domain.labelcategory.entity; + + +import com.worlabel.domain.project.entity.Project; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@Table(name = "label_category") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class LabelCategory { + + /** + * 레이블 카테고리 PK + */ + @Id + @Column(name = "label_category_id", nullable = false) + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + /** + * 레이블 카테고리 이름 + */ + @Column(name = "name", nullable = false) + private String name; + + /** + * 속한 프로젝트 + */ + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "project_id", nullable = false) + private Project project; + + private LabelCategory(final String name,final Project project) { + this.name = name; + this.project = project; + } + + public static LabelCategory of(final String title, final Project project) { + return new LabelCategory(title, project); + } +} diff --git a/backend/src/main/java/com/worlabel/domain/labelcategory/entity/dto/LabelCategoryRequest.java b/backend/src/main/java/com/worlabel/domain/labelcategory/entity/dto/LabelCategoryRequest.java new file mode 100644 index 0000000..851da52 --- /dev/null +++ b/backend/src/main/java/com/worlabel/domain/labelcategory/entity/dto/LabelCategoryRequest.java @@ -0,0 +1,16 @@ +package com.worlabel.domain.labelcategory.entity.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Schema(name = "카테고리 요청 DTO", description = "카테고리 생성 및 수정을 위한 요청 DTO") +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class LabelCategoryRequest { + + @Schema(description = "카테고리 이름", example = "Car") + private String categoryName; +} diff --git a/backend/src/main/java/com/worlabel/domain/labelcategory/entity/dto/LabelCategoryResponse.java b/backend/src/main/java/com/worlabel/domain/labelcategory/entity/dto/LabelCategoryResponse.java new file mode 100644 index 0000000..ab5507b --- /dev/null +++ b/backend/src/main/java/com/worlabel/domain/labelcategory/entity/dto/LabelCategoryResponse.java @@ -0,0 +1,22 @@ +package com.worlabel.domain.labelcategory.entity.dto; + +import com.worlabel.domain.labelcategory.entity.LabelCategory; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@Schema(name = "카테고리 응답 DTO", description = "카테고리 조회 응답 DTO") +public class LabelCategoryResponse { + + @Schema(description = "카테고리 ID", example = "1") + private Integer id; + + @Schema(description = "카테고리 이름", example = "Car") + private String name; + + public static LabelCategoryResponse from(LabelCategory labelCategory) { + return new LabelCategoryResponse(labelCategory.getId(), labelCategory.getName()); + } +} diff --git a/backend/src/main/java/com/worlabel/domain/labelcategory/repository/LabelCategoryRepository.java b/backend/src/main/java/com/worlabel/domain/labelcategory/repository/LabelCategoryRepository.java new file mode 100644 index 0000000..1d69d49 --- /dev/null +++ b/backend/src/main/java/com/worlabel/domain/labelcategory/repository/LabelCategoryRepository.java @@ -0,0 +1,13 @@ +package com.worlabel.domain.labelcategory.repository; + +import com.worlabel.domain.labelcategory.entity.LabelCategory; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface LabelCategoryRepository extends JpaRepository { + + List findAllByProjectId(Integer projectId); + + boolean existsByNameAndProjectId(String categoryName, Integer projectId); +} diff --git a/backend/src/main/java/com/worlabel/domain/labelcategory/service/LabelCategoryService.java b/backend/src/main/java/com/worlabel/domain/labelcategory/service/LabelCategoryService.java new file mode 100644 index 0000000..a4c836c --- /dev/null +++ b/backend/src/main/java/com/worlabel/domain/labelcategory/service/LabelCategoryService.java @@ -0,0 +1,69 @@ +package com.worlabel.domain.labelcategory.service; + +import com.worlabel.domain.labelcategory.entity.LabelCategory; +import com.worlabel.domain.labelcategory.entity.dto.LabelCategoryRequest; +import com.worlabel.domain.labelcategory.entity.dto.LabelCategoryResponse; +import com.worlabel.domain.labelcategory.repository.LabelCategoryRepository; +import com.worlabel.domain.participant.service.ParticipantService; +import com.worlabel.domain.project.entity.Project; +import com.worlabel.domain.project.service.ProjectService; +import com.worlabel.global.exception.CustomException; +import com.worlabel.global.exception.ErrorCode; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional +@RequiredArgsConstructor +public class LabelCategoryService { + + private final LabelCategoryRepository labelCategoryRepository; + private final ParticipantService participantService; + private final ProjectService projectService; + + public LabelCategoryResponse createCategory(final Integer memberId, final Integer projectId, final LabelCategoryRequest categoryRequest) { + participantService.checkEditorUnauthorized(memberId, projectId); + + // 이미 존재하는지 확인 있다면 예외 + if (labelCategoryRepository.existsByNameAndProjectId(categoryRequest.getCategoryName(), projectId)) { + throw new CustomException(ErrorCode.PROJECT_CATEGORY_EXIST); + } + + Project project = projectService.getProject(projectId); + + LabelCategory labelCategory = LabelCategory.of(categoryRequest.getCategoryName(), project); + labelCategoryRepository.save(labelCategory); + + return LabelCategoryResponse.from(labelCategory); + } + + public void deleteCategory(final int memberId, final int projectId, final int categoryId) { + participantService.checkEditorUnauthorized(memberId, projectId); + LabelCategory category = getCategory(categoryId); + labelCategoryRepository.delete(category); + } + + public LabelCategoryResponse getCategoryById(final int memberId, final int projectId, final int categoryId) { + participantService.checkViewerUnauthorized(memberId, projectId); + return LabelCategoryResponse.from(getCategory(categoryId)); + } + + public boolean existByCategoryName(final int memberId, final int projectId, final String categoryName) { + participantService.checkViewerUnauthorized(memberId, projectId); + return labelCategoryRepository.existsByNameAndProjectId(categoryName, projectId); + } + + public List getCategoryList(final Integer memberId, final Integer projectId) { + participantService.checkViewerUnauthorized(memberId, projectId); + List labelCategoryList = labelCategoryRepository.findAllByProjectId(projectId); + return labelCategoryList.stream().map(LabelCategoryResponse::from).toList(); + } + + private LabelCategory getCategory(final Integer categoryId) { + return labelCategoryRepository.findById(categoryId).orElseThrow(() -> new CustomException(ErrorCode.PROJECT_CATEGORY_NOT_FOUND)); + } + +} diff --git a/backend/src/main/java/com/worlabel/domain/participant/service/ParticipantService.java b/backend/src/main/java/com/worlabel/domain/participant/service/ParticipantService.java new file mode 100644 index 0000000..632658d --- /dev/null +++ b/backend/src/main/java/com/worlabel/domain/participant/service/ParticipantService.java @@ -0,0 +1,36 @@ +package com.worlabel.domain.participant.service; + +import com.worlabel.domain.participant.repository.ParticipantRepository; +import com.worlabel.global.exception.CustomException; +import com.worlabel.global.exception.ErrorCode; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ParticipantService { + + private final ParticipantRepository participantRepository; + + /** + * 프로젝트 수정 권한이 없으면 예외 + * @param memberId 사용자 ID + * @param projectId 프로젝트 ID + */ + public void checkEditorUnauthorized(final Integer memberId, final Integer projectId){ + if (participantRepository.doesParticipantUnauthorizedExistByMemberIdAndProjectId(memberId, projectId)) { + throw new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED); + } + } + + /** + * 프로젝트 View 권한이 없으면 예외 + */ + public void checkViewerUnauthorized(final Integer memberId, final Integer projectId){ + if (participantRepository.doesParticipantUnauthorizedExistByMemberIdAndProjectId(memberId, projectId)) { + throw new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED); + } + } +} diff --git a/backend/src/main/java/com/worlabel/domain/project/controller/ProjectController.java b/backend/src/main/java/com/worlabel/domain/project/controller/ProjectController.java index 5affa25..bef2493 100644 --- a/backend/src/main/java/com/worlabel/domain/project/controller/ProjectController.java +++ b/backend/src/main/java/com/worlabel/domain/project/controller/ProjectController.java @@ -44,7 +44,7 @@ public class ProjectController { @Operation(summary = "프로젝트 조회", description = "프로젝트를 조회합니다.") @SwaggerApiSuccess(description = "프로젝트를 성공적으로 조회합니다.") - @SwaggerApiError({ErrorCode.PROJECT_NOT_FOUND, ErrorCode.PARTICIPANT_UNAUTHORIZED, ErrorCode.SERVER_ERROR}) + @SwaggerApiError({ErrorCode.PROJECT_NOT_FOUND, ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED, ErrorCode.SERVER_ERROR}) @GetMapping("/projects/{project_id}") public BaseResponse getProject(@CurrentUser final Integer memberId, @PathVariable("project_id") final Integer projectId) { ProjectResponse project = projectService.getProjectById(memberId, projectId); @@ -66,7 +66,7 @@ public class ProjectController { @Operation(summary = "프로젝트 수정", description = "프로젝트를 수정합니다.") @SwaggerApiSuccess(description = "프로젝트를 성공적으로 수정합니다.") - @SwaggerApiError({ErrorCode.PROJECT_NOT_FOUND, ErrorCode.PARTICIPANT_UNAUTHORIZED, ErrorCode.SERVER_ERROR}) + @SwaggerApiError({ErrorCode.PROJECT_NOT_FOUND, ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED, ErrorCode.SERVER_ERROR}) @PutMapping("/projects/{project_id}") public BaseResponse updateProject( @CurrentUser final Integer memberId, @@ -89,7 +89,7 @@ public class ProjectController { @Operation(summary = "프로젝트 삭제", description = "프로젝트를 삭제합니다.") @SwaggerApiSuccess(description = "프로젝트를 성공적으로 삭제합니다.") - @SwaggerApiError({ErrorCode.PROJECT_NOT_FOUND, ErrorCode.PARTICIPANT_UNAUTHORIZED, ErrorCode.SERVER_ERROR}) + @SwaggerApiError({ErrorCode.PROJECT_NOT_FOUND, ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED, ErrorCode.SERVER_ERROR}) @DeleteMapping("/projects/{project_id}") public BaseResponse deleteProject(@CurrentUser final Integer memberId, @PathVariable("project_id") final Integer projectId) { diff --git a/backend/src/main/java/com/worlabel/domain/project/entity/Project.java b/backend/src/main/java/com/worlabel/domain/project/entity/Project.java index e9d6d6d..a7c315b 100644 --- a/backend/src/main/java/com/worlabel/domain/project/entity/Project.java +++ b/backend/src/main/java/com/worlabel/domain/project/entity/Project.java @@ -1,6 +1,7 @@ package com.worlabel.domain.project.entity; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.worlabel.domain.labelcategory.entity.LabelCategory; import com.worlabel.domain.workspace.entity.Workspace; import com.worlabel.global.common.BaseEntity; import jakarta.persistence.*; @@ -8,6 +9,9 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import java.util.ArrayList; +import java.util.List; + @Getter @Entity @Table(name = "project") @@ -43,6 +47,12 @@ public class Project extends BaseEntity { @Enumerated(EnumType.STRING) private ProjectType projectType; + /** + * 프로젝트에 속한 카테고리 + */ + @OneToMany(mappedBy = "project", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) + private List category = new ArrayList<>(); + private Project(final String title, final Workspace workspace, final ProjectType projectType) { this.title = title; this.workspace = workspace; diff --git a/backend/src/main/java/com/worlabel/domain/project/service/ProjectService.java b/backend/src/main/java/com/worlabel/domain/project/service/ProjectService.java index 3cb564e..2ad79c3 100644 --- a/backend/src/main/java/com/worlabel/domain/project/service/ProjectService.java +++ b/backend/src/main/java/com/worlabel/domain/project/service/ProjectService.java @@ -108,7 +108,7 @@ public class ProjectService { checkNotAdminParticipant(participantRequest.getMemberId(), projectId); Participant participant = participantRepository.findByMemberIdAndProjectId(participantRequest.getMemberId(), projectId) - .orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED)); + .orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED)); participant.updatePrivilege(participantRequest.getPrivilegeType()); } @@ -118,7 +118,7 @@ public class ProjectService { checkNotAdminParticipant(removeMemberId, projectId); Participant participant = participantRepository.findByMemberIdAndProjectId(removeMemberId, projectId) - .orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED)); + .orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED)); participantRepository.delete(participant); } @@ -150,6 +150,11 @@ public class ProjectService { } } + public Project getProject(final Integer projectId) { + return projectRepository.findById(projectId) + .orElseThrow(() -> new CustomException(ErrorCode.PROJECT_NOT_FOUND)); + } + private Workspace getWorkspace(final Integer memberId, final Integer workspaceId) { return workspaceRepository.findByMemberIdAndId(memberId, workspaceId) .orElseThrow(() -> new CustomException(ErrorCode.WORKSPACE_NOT_FOUND)); @@ -160,32 +165,27 @@ public class ProjectService { .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND)); } - private Project getProject(final Integer projectId) { - return projectRepository.findById(projectId) - .orElseThrow(() -> new CustomException(ErrorCode.PROJECT_NOT_FOUND)); - } - private void checkEditorParticipant(final Integer memberId, final Integer projectId) { if(participantRepository.doesParticipantUnauthorizedExistByMemberIdAndProjectId(memberId,projectId)){ - throw new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED); + throw new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED); } } private void checkExistParticipant(final Integer memberId, final Integer projectId) { if (!participantRepository.existsByMemberIdAndProjectId(memberId, projectId)) { - throw new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED); + throw new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED); } } private void checkAdminParticipant(final Integer memberId, final Integer projectId) { if (!participantRepository.existsByProjectIdAndMemberIdAndPrivilege(projectId, memberId, PrivilegeType.ADMIN)) { - throw new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED); + throw new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED); } } private void checkNotAdminParticipant(final Integer memberId, final Integer projectId) { if (participantRepository.existsByProjectIdAndMemberIdAndPrivilege(projectId, memberId, PrivilegeType.ADMIN)) { - throw new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED); + throw new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED); } } diff --git a/backend/src/main/java/com/worlabel/domain/workspace/service/WorkspaceService.java b/backend/src/main/java/com/worlabel/domain/workspace/service/WorkspaceService.java index 99cdc87..e667150 100644 --- a/backend/src/main/java/com/worlabel/domain/workspace/service/WorkspaceService.java +++ b/backend/src/main/java/com/worlabel/domain/workspace/service/WorkspaceService.java @@ -127,6 +127,6 @@ public class WorkspaceService { private WorkspaceParticipant getWorkspaceParticipant(final Integer newMemberId, final Workspace workspace) { return workspaceParticipantRepository.findByMemberIdAndWorkspace(newMemberId, workspace) - .orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED)); + .orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED)); } } \ No newline at end of file diff --git a/backend/src/main/java/com/worlabel/global/config/CustomWebSocketConfig1.java b/backend/src/main/java/com/worlabel/global/config/CustomWebSocketConfig1.java deleted file mode 100644 index 456d455..0000000 --- a/backend/src/main/java/com/worlabel/global/config/CustomWebSocketConfig1.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.worlabel.global.config; - -public class CustomWebSocketConfig1 { -} diff --git a/backend/src/main/java/com/worlabel/global/exception/ErrorCode.java b/backend/src/main/java/com/worlabel/global/exception/ErrorCode.java index 5e473cf..afa7f9a 100644 --- a/backend/src/main/java/com/worlabel/global/exception/ErrorCode.java +++ b/backend/src/main/java/com/worlabel/global/exception/ErrorCode.java @@ -37,10 +37,13 @@ public enum ErrorCode { // Project - 4000 PROJECT_NOT_FOUND(HttpStatus.NOT_FOUND, 4000, "프로젝트를 찾을 수 없습니다"), PROJECT_IMAGE_MISMATCH(HttpStatus.BAD_REQUEST, 4001, "해당 프로젝트에는 존재하지 않는 이미지입니다."), + PROJECT_CATEGORY_EXIST(HttpStatus.BAD_REQUEST,4002, "이미 존재하는 카테고리입니다."), + PROJECT_CATEGORY_NOT_FOUND(HttpStatus.NOT_FOUND, 4003, "해당 카테고리를 찾을 수 없습니다."), // Participant - 5000, - PARTICIPANT_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, 5000, "해당 프로젝트에 접근 권한이 없습니다."), + PARTICIPANT_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, 5000, "해당 프로젝트에 참여하고 있지않습니다."), PARTICIPANT_BAD_REQUEST(HttpStatus.UNAUTHORIZED, 5001, "자기 자신의 권한을 바꿀 수 없습니다."), + PARTICIPANT_EDITOR_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, 5002, "해당 프로젝트에 수정 권한이 없습니다."), // Folder - 6000, FOLDER_NOT_FOUND(HttpStatus.NOT_FOUND, 6000, "해당 폴더를 찾을 수 없습니다."), @@ -53,8 +56,9 @@ public enum ErrorCode { AI_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 8000, "AI 서버 오류 입니다."), // Comment - 9000, - COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, 9000, "해당 댓글을 찾을 수 없습니다."); + COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, 9000, "해당 댓글을 찾을 수 없습니다."), + ; private final HttpStatus status; private final int code; private final String message; diff --git a/backend/src/test/java/com/worlabel/domain/image/service/ImageServiceUnitTest.java b/backend/src/test/java/com/worlabel/domain/image/service/ImageServiceUnitTest.java index 6bafa02..aaa6a3c 100644 --- a/backend/src/test/java/com/worlabel/domain/image/service/ImageServiceUnitTest.java +++ b/backend/src/test/java/com/worlabel/domain/image/service/ImageServiceUnitTest.java @@ -85,7 +85,7 @@ class ImageServiceUnitTest { // when & then assertThatThrownBy(() -> imageService.uploadImageList(List.of(mock(MultipartFile.class)), 1, 1, 1)) .isInstanceOf(CustomException.class) - .hasMessageContaining(ErrorCode.PARTICIPANT_UNAUTHORIZED.getMessage()); + .hasMessageContaining(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED.getMessage()); } @DisplayName("이미지 업로드 성공") diff --git a/backend/src/test/java/com/worlabel/domain/project/service/ProjectServiceUnitTest.java b/backend/src/test/java/com/worlabel/domain/project/service/ProjectServiceUnitTest.java index 71313c2..b535d0b 100644 --- a/backend/src/test/java/com/worlabel/domain/project/service/ProjectServiceUnitTest.java +++ b/backend/src/test/java/com/worlabel/domain/project/service/ProjectServiceUnitTest.java @@ -2,7 +2,6 @@ package com.worlabel.domain.project.service; import com.worlabel.domain.member.entity.Member; import com.worlabel.domain.member.repository.MemberRepository; -import com.worlabel.domain.participant.entity.Participant; import com.worlabel.domain.participant.entity.PrivilegeType; import com.worlabel.domain.participant.repository.ParticipantRepository; import com.worlabel.domain.project.entity.Project; @@ -142,7 +141,7 @@ class ProjectServiceUnitTest { // when & then assertThatThrownBy(() -> projectService.updateProject(1, 1, request)) .isInstanceOf(CustomException.class) - .hasMessageContaining(ErrorCode.PARTICIPANT_UNAUTHORIZED.getMessage()); + .hasMessageContaining(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED.getMessage()); } @DisplayName("프로젝트 수정에 성공하면 수정된 프로젝트가 반환된다.") @@ -172,7 +171,7 @@ class ProjectServiceUnitTest { // when & then assertThatThrownBy(() -> projectService.deleteProject(1, 1)) .isInstanceOf(CustomException.class) - .hasMessageContaining(ErrorCode.PARTICIPANT_UNAUTHORIZED.getMessage()); + .hasMessageContaining(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED.getMessage()); } @DisplayName("프로젝트 삭제에 성공하면 예외 없이 수행된다.")