Merge branch 'be/develop' into be/feat/labeling
This commit is contained in:
commit
6ce71ec4e8
@ -62,7 +62,7 @@ public class ImageController {
|
|||||||
@PutMapping("/{image_id}")
|
@PutMapping("/{image_id}")
|
||||||
@SwaggerApiSuccess(description = "이미지 폴더 이동.")
|
@SwaggerApiSuccess(description = "이미지 폴더 이동.")
|
||||||
@Operation(summary = "이미지 폴더 이동", 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<Void> moveFolderImage(
|
public BaseResponse<Void> moveFolderImage(
|
||||||
@CurrentUser final Integer memberId,
|
@CurrentUser final Integer memberId,
|
||||||
@PathVariable("folder_id") final Integer folderId,
|
@PathVariable("folder_id") final Integer folderId,
|
||||||
@ -78,7 +78,7 @@ public class ImageController {
|
|||||||
@DeleteMapping("/{image_id}")
|
@DeleteMapping("/{image_id}")
|
||||||
@SwaggerApiSuccess(description = "이미지 삭제.")
|
@SwaggerApiSuccess(description = "이미지 삭제.")
|
||||||
@Operation(summary = "이미지 삭제", 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<Void> deleteImage(
|
public BaseResponse<Void> deleteImage(
|
||||||
@CurrentUser final Integer memberId,
|
@CurrentUser final Integer memberId,
|
||||||
@PathVariable("folder_id") final Integer folderId,
|
@PathVariable("folder_id") final Integer folderId,
|
||||||
@ -93,7 +93,7 @@ public class ImageController {
|
|||||||
@PutMapping("/{image_id}/status")
|
@PutMapping("/{image_id}/status")
|
||||||
@SwaggerApiSuccess(description = "이미지 상태 변경.")
|
@SwaggerApiSuccess(description = "이미지 상태 변경.")
|
||||||
@Operation(summary = "이미지 상태 변경", 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<ImageResponse> changeImageStatus(
|
public BaseResponse<ImageResponse> changeImageStatus(
|
||||||
@CurrentUser final Integer memberId,
|
@CurrentUser final Integer memberId,
|
||||||
@PathVariable("folder_id") final Integer folderId,
|
@PathVariable("folder_id") final Integer folderId,
|
||||||
|
@ -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.entity.dto.ImageStatusRequest;
|
||||||
import com.worlabel.domain.image.repository.ImageRepository;
|
import com.worlabel.domain.image.repository.ImageRepository;
|
||||||
import com.worlabel.domain.participant.entity.Participant;
|
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.participant.repository.ParticipantRepository;
|
||||||
import com.worlabel.global.exception.CustomException;
|
import com.worlabel.global.exception.CustomException;
|
||||||
import com.worlabel.global.exception.ErrorCode;
|
import com.worlabel.global.exception.ErrorCode;
|
||||||
@ -121,10 +120,10 @@ public class ImageService {
|
|||||||
// 편집자 이상의 권한을 확인하는 메서드
|
// 편집자 이상의 권한을 확인하는 메서드
|
||||||
private void checkEditorParticipant(final Integer memberId, final Integer projectId) {
|
private void checkEditorParticipant(final Integer memberId, final Integer projectId) {
|
||||||
Participant participant = participantRepository.findByMemberIdAndProjectId(memberId, projectId)
|
Participant participant = participantRepository.findByMemberIdAndProjectId(memberId, projectId)
|
||||||
.orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED));
|
.orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED));
|
||||||
|
|
||||||
if (!participant.getPrivilege().isEditeAuth()) {
|
if (!participant.getPrivilege().isEditeAuth()) {
|
||||||
throw new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED);
|
throw new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ public class LabelService {
|
|||||||
private void checkEditorExistParticipant(final Integer memberId, final Integer projectId) {
|
private void checkEditorExistParticipant(final Integer memberId, final Integer projectId) {
|
||||||
log.debug("권한체크");
|
log.debug("권한체크");
|
||||||
if (participantRepository.doesParticipantUnauthorizedExistByMemberIdAndProjectId(memberId, projectId)) {
|
if (participantRepository.doesParticipantUnauthorizedExistByMemberIdAndProjectId(memberId, projectId)) {
|
||||||
throw new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED);
|
throw new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<LabelCategoryResponse> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
@ -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<LabelCategory, Integer> {
|
||||||
|
|
||||||
|
List<LabelCategory> findAllByProjectId(Integer projectId);
|
||||||
|
|
||||||
|
boolean existsByNameAndProjectId(String categoryName, Integer projectId);
|
||||||
|
}
|
@ -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<LabelCategoryResponse> getCategoryList(final Integer memberId, final Integer projectId) {
|
||||||
|
participantService.checkViewerUnauthorized(memberId, projectId);
|
||||||
|
List<LabelCategory> 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -44,7 +44,7 @@ public class ProjectController {
|
|||||||
|
|
||||||
@Operation(summary = "프로젝트 조회", description = "프로젝트를 조회합니다.")
|
@Operation(summary = "프로젝트 조회", description = "프로젝트를 조회합니다.")
|
||||||
@SwaggerApiSuccess(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}")
|
@GetMapping("/projects/{project_id}")
|
||||||
public BaseResponse<ProjectResponse> getProject(@CurrentUser final Integer memberId, @PathVariable("project_id") final Integer projectId) {
|
public BaseResponse<ProjectResponse> getProject(@CurrentUser final Integer memberId, @PathVariable("project_id") final Integer projectId) {
|
||||||
ProjectResponse project = projectService.getProjectById(memberId, projectId);
|
ProjectResponse project = projectService.getProjectById(memberId, projectId);
|
||||||
@ -66,7 +66,7 @@ public class ProjectController {
|
|||||||
|
|
||||||
@Operation(summary = "프로젝트 수정", description = "프로젝트를 수정합니다.")
|
@Operation(summary = "프로젝트 수정", description = "프로젝트를 수정합니다.")
|
||||||
@SwaggerApiSuccess(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}")
|
@PutMapping("/projects/{project_id}")
|
||||||
public BaseResponse<ProjectResponse> updateProject(
|
public BaseResponse<ProjectResponse> updateProject(
|
||||||
@CurrentUser final Integer memberId,
|
@CurrentUser final Integer memberId,
|
||||||
@ -89,7 +89,7 @@ public class ProjectController {
|
|||||||
|
|
||||||
@Operation(summary = "프로젝트 삭제", description = "프로젝트를 삭제합니다.")
|
@Operation(summary = "프로젝트 삭제", description = "프로젝트를 삭제합니다.")
|
||||||
@SwaggerApiSuccess(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}")
|
@DeleteMapping("/projects/{project_id}")
|
||||||
public BaseResponse<Void> deleteProject(@CurrentUser final Integer memberId,
|
public BaseResponse<Void> deleteProject(@CurrentUser final Integer memberId,
|
||||||
@PathVariable("project_id") final Integer projectId) {
|
@PathVariable("project_id") final Integer projectId) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.worlabel.domain.project.entity;
|
package com.worlabel.domain.project.entity;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.worlabel.domain.labelcategory.entity.LabelCategory;
|
||||||
import com.worlabel.domain.workspace.entity.Workspace;
|
import com.worlabel.domain.workspace.entity.Workspace;
|
||||||
import com.worlabel.global.common.BaseEntity;
|
import com.worlabel.global.common.BaseEntity;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
@ -8,6 +9,9 @@ import lombok.AccessLevel;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "project")
|
@Table(name = "project")
|
||||||
@ -43,6 +47,12 @@ public class Project extends BaseEntity {
|
|||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
private ProjectType projectType;
|
private ProjectType projectType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 프로젝트에 속한 카테고리
|
||||||
|
*/
|
||||||
|
@OneToMany(mappedBy = "project", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
|
private List<LabelCategory> category = new ArrayList<>();
|
||||||
|
|
||||||
private Project(final String title, final Workspace workspace, final ProjectType projectType) {
|
private Project(final String title, final Workspace workspace, final ProjectType projectType) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.workspace = workspace;
|
this.workspace = workspace;
|
||||||
|
@ -108,7 +108,7 @@ public class ProjectService {
|
|||||||
checkNotAdminParticipant(participantRequest.getMemberId(), projectId);
|
checkNotAdminParticipant(participantRequest.getMemberId(), projectId);
|
||||||
|
|
||||||
Participant participant = participantRepository.findByMemberIdAndProjectId(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());
|
participant.updatePrivilege(participantRequest.getPrivilegeType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ public class ProjectService {
|
|||||||
checkNotAdminParticipant(removeMemberId, projectId);
|
checkNotAdminParticipant(removeMemberId, projectId);
|
||||||
|
|
||||||
Participant participant = participantRepository.findByMemberIdAndProjectId(removeMemberId, projectId)
|
Participant participant = participantRepository.findByMemberIdAndProjectId(removeMemberId, projectId)
|
||||||
.orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED));
|
.orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED));
|
||||||
|
|
||||||
participantRepository.delete(participant);
|
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) {
|
private Workspace getWorkspace(final Integer memberId, final Integer workspaceId) {
|
||||||
return workspaceRepository.findByMemberIdAndId(memberId, workspaceId)
|
return workspaceRepository.findByMemberIdAndId(memberId, workspaceId)
|
||||||
.orElseThrow(() -> new CustomException(ErrorCode.WORKSPACE_NOT_FOUND));
|
.orElseThrow(() -> new CustomException(ErrorCode.WORKSPACE_NOT_FOUND));
|
||||||
@ -160,32 +165,27 @@ public class ProjectService {
|
|||||||
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
|
.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) {
|
private void checkEditorParticipant(final Integer memberId, final Integer projectId) {
|
||||||
if(participantRepository.doesParticipantUnauthorizedExistByMemberIdAndProjectId(memberId,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) {
|
private void checkExistParticipant(final Integer memberId, final Integer projectId) {
|
||||||
if (!participantRepository.existsByMemberIdAndProjectId(memberId, 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) {
|
private void checkAdminParticipant(final Integer memberId, final Integer projectId) {
|
||||||
if (!participantRepository.existsByProjectIdAndMemberIdAndPrivilege(projectId, memberId, PrivilegeType.ADMIN)) {
|
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) {
|
private void checkNotAdminParticipant(final Integer memberId, final Integer projectId) {
|
||||||
if (participantRepository.existsByProjectIdAndMemberIdAndPrivilege(projectId, memberId, PrivilegeType.ADMIN)) {
|
if (participantRepository.existsByProjectIdAndMemberIdAndPrivilege(projectId, memberId, PrivilegeType.ADMIN)) {
|
||||||
throw new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED);
|
throw new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +127,6 @@ public class WorkspaceService {
|
|||||||
|
|
||||||
private WorkspaceParticipant getWorkspaceParticipant(final Integer newMemberId, final Workspace workspace) {
|
private WorkspaceParticipant getWorkspaceParticipant(final Integer newMemberId, final Workspace workspace) {
|
||||||
return workspaceParticipantRepository.findByMemberIdAndWorkspace(newMemberId, workspace)
|
return workspaceParticipantRepository.findByMemberIdAndWorkspace(newMemberId, workspace)
|
||||||
.orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_UNAUTHORIZED));
|
.orElseThrow(() -> new CustomException(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +0,0 @@
|
|||||||
package com.worlabel.global.config;
|
|
||||||
|
|
||||||
public class CustomWebSocketConfig1 {
|
|
||||||
}
|
|
@ -37,10 +37,13 @@ public enum ErrorCode {
|
|||||||
// Project - 4000
|
// Project - 4000
|
||||||
PROJECT_NOT_FOUND(HttpStatus.NOT_FOUND, 4000, "프로젝트를 찾을 수 없습니다"),
|
PROJECT_NOT_FOUND(HttpStatus.NOT_FOUND, 4000, "프로젝트를 찾을 수 없습니다"),
|
||||||
PROJECT_IMAGE_MISMATCH(HttpStatus.BAD_REQUEST, 4001, "해당 프로젝트에는 존재하지 않는 이미지입니다."),
|
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 - 5000,
|
||||||
PARTICIPANT_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, 5000, "해당 프로젝트에 접근 권한이 없습니다."),
|
PARTICIPANT_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, 5000, "해당 프로젝트에 참여하고 있지않습니다."),
|
||||||
PARTICIPANT_BAD_REQUEST(HttpStatus.UNAUTHORIZED, 5001, "자기 자신의 권한을 바꿀 수 없습니다."),
|
PARTICIPANT_BAD_REQUEST(HttpStatus.UNAUTHORIZED, 5001, "자기 자신의 권한을 바꿀 수 없습니다."),
|
||||||
|
PARTICIPANT_EDITOR_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, 5002, "해당 프로젝트에 수정 권한이 없습니다."),
|
||||||
|
|
||||||
// Folder - 6000,
|
// Folder - 6000,
|
||||||
FOLDER_NOT_FOUND(HttpStatus.NOT_FOUND, 6000, "해당 폴더를 찾을 수 없습니다."),
|
FOLDER_NOT_FOUND(HttpStatus.NOT_FOUND, 6000, "해당 폴더를 찾을 수 없습니다."),
|
||||||
@ -53,8 +56,9 @@ public enum ErrorCode {
|
|||||||
AI_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 8000, "AI 서버 오류 입니다."),
|
AI_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 8000, "AI 서버 오류 입니다."),
|
||||||
|
|
||||||
// Comment - 9000,
|
// Comment - 9000,
|
||||||
COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, 9000, "해당 댓글을 찾을 수 없습니다.");
|
COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, 9000, "해당 댓글을 찾을 수 없습니다."),
|
||||||
|
|
||||||
|
;
|
||||||
private final HttpStatus status;
|
private final HttpStatus status;
|
||||||
private final int code;
|
private final int code;
|
||||||
private final String message;
|
private final String message;
|
||||||
|
@ -85,7 +85,7 @@ class ImageServiceUnitTest {
|
|||||||
// when & then
|
// when & then
|
||||||
assertThatThrownBy(() -> imageService.uploadImageList(List.of(mock(MultipartFile.class)), 1, 1, 1))
|
assertThatThrownBy(() -> imageService.uploadImageList(List.of(mock(MultipartFile.class)), 1, 1, 1))
|
||||||
.isInstanceOf(CustomException.class)
|
.isInstanceOf(CustomException.class)
|
||||||
.hasMessageContaining(ErrorCode.PARTICIPANT_UNAUTHORIZED.getMessage());
|
.hasMessageContaining(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("이미지 업로드 성공")
|
@DisplayName("이미지 업로드 성공")
|
||||||
|
@ -2,7 +2,6 @@ package com.worlabel.domain.project.service;
|
|||||||
|
|
||||||
import com.worlabel.domain.member.entity.Member;
|
import com.worlabel.domain.member.entity.Member;
|
||||||
import com.worlabel.domain.member.repository.MemberRepository;
|
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.entity.PrivilegeType;
|
||||||
import com.worlabel.domain.participant.repository.ParticipantRepository;
|
import com.worlabel.domain.participant.repository.ParticipantRepository;
|
||||||
import com.worlabel.domain.project.entity.Project;
|
import com.worlabel.domain.project.entity.Project;
|
||||||
@ -142,7 +141,7 @@ class ProjectServiceUnitTest {
|
|||||||
// when & then
|
// when & then
|
||||||
assertThatThrownBy(() -> projectService.updateProject(1, 1, request))
|
assertThatThrownBy(() -> projectService.updateProject(1, 1, request))
|
||||||
.isInstanceOf(CustomException.class)
|
.isInstanceOf(CustomException.class)
|
||||||
.hasMessageContaining(ErrorCode.PARTICIPANT_UNAUTHORIZED.getMessage());
|
.hasMessageContaining(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("프로젝트 수정에 성공하면 수정된 프로젝트가 반환된다.")
|
@DisplayName("프로젝트 수정에 성공하면 수정된 프로젝트가 반환된다.")
|
||||||
@ -172,7 +171,7 @@ class ProjectServiceUnitTest {
|
|||||||
// when & then
|
// when & then
|
||||||
assertThatThrownBy(() -> projectService.deleteProject(1, 1))
|
assertThatThrownBy(() -> projectService.deleteProject(1, 1))
|
||||||
.isInstanceOf(CustomException.class)
|
.isInstanceOf(CustomException.class)
|
||||||
.hasMessageContaining(ErrorCode.PARTICIPANT_UNAUTHORIZED.getMessage());
|
.hasMessageContaining(ErrorCode.PARTICIPANT_EDITOR_UNAUTHORIZED.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("프로젝트 삭제에 성공하면 예외 없이 수행된다.")
|
@DisplayName("프로젝트 삭제에 성공하면 예외 없이 수행된다.")
|
||||||
|
Loading…
Reference in New Issue
Block a user