From 68ea4405e92b5ffdc3225fe81923abcb4ff57d6c Mon Sep 17 00:00:00 2001 From: dangnak2 <80161984+dangnak2@users.noreply.github.com> Date: Thu, 19 Oct 2023 15:47:55 +0900 Subject: [PATCH 1/3] =?UTF-8?q?[PDS-36]=20fix:=20=EC=95=84=EC=B9=B4?= =?UTF-8?q?=EC=9D=B4=EB=B9=99=20=EC=9E=90=EB=A3=8C=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?hard=20delete=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PLADIALMArchiving/archiving/service/ArchivingService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/example/PLADIALMArchiving/archiving/service/ArchivingService.java b/src/main/java/com/example/PLADIALMArchiving/archiving/service/ArchivingService.java index 670cc89..d8ca6cd 100644 --- a/src/main/java/com/example/PLADIALMArchiving/archiving/service/ArchivingService.java +++ b/src/main/java/com/example/PLADIALMArchiving/archiving/service/ArchivingService.java @@ -55,7 +55,7 @@ public void deleteMaterial(Long materialId, User user) { if(user.getRole() != Role.ADMIN || !user.getUserId().equals(material.getUser().getUserId())) throw new BaseException(BaseResponseCode.UNAUTHORIZED_USER); - material.delete(); + materialRepository.delete(material); } public Page searchMaterial(Long projectId, SearchMaterialReq searchMaterialReq, Pageable pageable) { From 81cc29403ec17b155b092fceb160968f38c468ca Mon Sep 17 00:00:00 2001 From: dangnak2 <80161984+dangnak2@users.noreply.github.com> Date: Thu, 19 Oct 2023 15:48:33 +0900 Subject: [PATCH 2/3] =?UTF-8?q?[PDS-36]=20fix:=20=EC=95=84=EC=B9=B4?= =?UTF-8?q?=EC=9D=B4=EB=B9=99=20=EC=9E=90=EB=A3=8C=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?soft=20delete=20=EB=A1=9C=EC=A7=81=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/PLADIALMArchiving/archiving/entity/Material.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/example/PLADIALMArchiving/archiving/entity/Material.java b/src/main/java/com/example/PLADIALMArchiving/archiving/entity/Material.java index 49cd874..14d4ef0 100644 --- a/src/main/java/com/example/PLADIALMArchiving/archiving/entity/Material.java +++ b/src/main/java/com/example/PLADIALMArchiving/archiving/entity/Material.java @@ -61,8 +61,4 @@ public static Material toEntity(UploadMaterialReq uploadMaterialReq, Project pro .user(user) .build(); } - - public void delete() { - this.setIsEnable(false); - } } From 9c8c182d6c6688cae1936a6b3b4aebcc772394d9 Mon Sep 17 00:00:00 2001 From: dangnak2 <80161984+dangnak2@users.noreply.github.com> Date: Thu, 19 Oct 2023 18:36:50 +0900 Subject: [PATCH 3/3] =?UTF-8?q?[PDS-36]=20feat:=20=EC=95=84=EC=B9=B4?= =?UTF-8?q?=EC=9D=B4=EB=B9=99=20API=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EB=B0=8F=20=EC=9D=BC=EB=B6=80=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ArchivingController.java | 73 ++++++++++++++++--- .../dto/request/RegisterProjectReq.java | 8 ++ .../dto/request/SearchMaterialReq.java | 7 ++ .../dto/request/UploadMaterialReq.java | 16 ++++ .../archiving/service/ArchivingService.java | 6 ++ .../global/config/SwaggerConfig.java | 4 +- .../global/exception/BaseResponseCode.java | 4 +- 7 files changed, 104 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/example/PLADIALMArchiving/archiving/controller/ArchivingController.java b/src/main/java/com/example/PLADIALMArchiving/archiving/controller/ArchivingController.java index 9e33fe6..b82f0e9 100644 --- a/src/main/java/com/example/PLADIALMArchiving/archiving/controller/ArchivingController.java +++ b/src/main/java/com/example/PLADIALMArchiving/archiving/controller/ArchivingController.java @@ -5,15 +5,26 @@ import com.example.PLADIALMArchiving.archiving.dto.request.UploadMaterialReq; import com.example.PLADIALMArchiving.archiving.dto.response.SearchMaterialRes; import com.example.PLADIALMArchiving.archiving.service.ArchivingService; +import com.example.PLADIALMArchiving.global.exception.BaseException; +import com.example.PLADIALMArchiving.global.exception.BaseResponseCode; import com.example.PLADIALMArchiving.global.resolver.Account; import com.example.PLADIALMArchiving.global.response.ResponseCustom; import com.example.PLADIALMArchiving.user.entity.User; import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; +import javax.validation.Valid; + @Api(tags = "아카이빙 API") @RestController @RequiredArgsConstructor @@ -25,8 +36,15 @@ public class ArchivingController { /** * 프로젝트를 추가한다. */ + @Operation(summary = "프로젝트 추가 (김민기)", description = "자료 아카이빙을 위한 프로젝트를 추가한다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "(S0001)요청에 성공했습니다."), + @ApiResponse(responseCode = "409", description = "(P0001)이미 등록된 프로젝트입니다.", content = @Content(schema = @Schema(implementation = ResponseCustom.class))), + @ApiResponse(responseCode = "400", description = "(P0006)올바르지 않은 프로젝트 이름입니다. 다시 입력해주세요. (공백, 특수문자 제외 20자 이내)", content = @Content(schema = @Schema(implementation = ResponseCustom.class))), + }) @PostMapping("/projects/register") - public ResponseCustom registerProject(@RequestBody RegisterProjectReq registerProjectReq) { + public ResponseCustom registerProject(@RequestBody @Valid RegisterProjectReq registerProjectReq) + { archivingService.registerProject(registerProjectReq); return ResponseCustom.OK(); } @@ -34,13 +52,25 @@ public ResponseCustom registerProject(@RequestBody RegisterProjectReq registe /** * 자료를 업로드한다. */ + @Operation(summary = "자료 업로드 (김민기)", description = "아카이빙할 자료를 업로드한다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "(S0001)요청에 성공했습니다."), + @ApiResponse(responseCode = "400", description = "(G0001)잘못된 요청입니다.", content = @Content(schema = @Schema(implementation = ResponseCustom.class))), + @ApiResponse(responseCode = "403", description = "(G0002)접근권한이 없습니다.", content = @Content(schema = @Schema(implementation = ResponseCustom.class))), + @ApiResponse(responseCode = "404", description = "(P0002)존재하지 않는 프로젝트입니다.", content = @Content(schema = @Schema(implementation = ResponseCustom.class))), + }) @PostMapping("/projects/{projectId}/upload") - public ResponseCustom uploadMaterial( - @RequestBody UploadMaterialReq uploadMaterialReq, - @PathVariable Long projectId, + public ResponseCustom uploadMaterial + ( + @RequestBody @Valid UploadMaterialReq uploadMaterialReq, + @Parameter(description = "(Long) 프로젝트 Id", example = "1") @PathVariable(name = "projectId") Long projectId, @Account User user ) { + if(!StringUtils.hasText(uploadMaterialReq.getFileKey()) || !StringUtils.hasText(uploadMaterialReq.getName()) || + !StringUtils.hasText(uploadMaterialReq.getExtension()) || uploadMaterialReq.getSize() == null) + throw new BaseException(BaseResponseCode.INVALID_UPLOAD_MATERIAL_REQUEST); + archivingService.uploadMaterial(uploadMaterialReq, projectId, user); return ResponseCustom.OK(); } @@ -48,10 +78,17 @@ public ResponseCustom uploadMaterial( /** * 자료목록을 조회 및 검색한다. */ + @Operation(summary = "자료목록 조회 및 검색 (김민기)", description = "아카이빙 자료목록을 조회 및 검색한다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "(S0001)요청에 성공했습니다."), + @ApiResponse(responseCode = "404", description = "(P0002)존재하지 않는 프로젝트입니다.", content = @Content(schema = @Schema(implementation = ResponseCustom.class))), + @ApiResponse(responseCode = "404", description = "(P0003)존재하지 않는 카테고리입니다.", content = @Content(schema = @Schema(implementation = ResponseCustom.class))), + }) @PostMapping("/projects/{projectId}") - public ResponseCustom> searchMaterial( - @PathVariable Long projectId, - @RequestBody SearchMaterialReq searchMaterialReq, + public ResponseCustom> searchMaterial + ( + @Parameter(description = "(Long) 프로젝트 Id", example = "1") @PathVariable(name = "projectId") Long projectId, + @RequestBody @Valid SearchMaterialReq searchMaterialReq, Pageable pageable ) { @@ -60,9 +97,17 @@ public ResponseCustom> searchMaterial( /** * 자료를 삭제한다. */ + @Operation(summary = "자료 삭제 (김민기)", description = "아카이빙 자료를 삭제한다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "(S0001)요청에 성공했습니다."), + @ApiResponse(responseCode = "400", description = "(G0001)잘못된 요청입니다.", content = @Content(schema = @Schema(implementation = ResponseCustom.class))), + @ApiResponse(responseCode = "403", description = "(G0002)접근권한이 없습니다.", content = @Content(schema = @Schema(implementation = ResponseCustom.class))), + @ApiResponse(responseCode = "404", description = "(P0004)존재하지 않는 자료입니다.", content = @Content(schema = @Schema(implementation = ResponseCustom.class))), + @ApiResponse(responseCode = "401", description = "(P0005)관리자 계정 또는 자료를 업로드한 유저가 아니므로 자료를 삭제할 수 없습니다.", content = @Content(schema = @Schema(implementation = ResponseCustom.class))), + }) @DeleteMapping("/materials/{materialId}") public ResponseCustom deleteMaterial( - @PathVariable Long materialId, + @Parameter(description = "(Long) 자원 Id", example = "15") @PathVariable(name = "materialId") Long materialId, @Account User user ) { @@ -73,10 +118,16 @@ public ResponseCustom deleteMaterial( /** * 자료를 다운로드한다. */ - @GetMapping("/materials/{materialsId}") + @Operation(summary = "자료 다운로드 (김민기)", description = "아카이빙 자료를 다운로드한다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "(S0001)요청에 성공했습니다."), + @ApiResponse(responseCode = "400", description = "(G0001)잘못된 요청입니다.", content = @Content(schema = @Schema(implementation = ResponseCustom.class))), + @ApiResponse(responseCode = "404", description = "(P0004)존재하지 않는 자료입니다.", content = @Content(schema = @Schema(implementation = ResponseCustom.class))), + }) + @GetMapping("/materials/{materialId}") public ResponseCustom downloadMaterial( - @PathVariable Long materialsId + @Parameter(description = "(Long) 자원 Id", example = "15") @PathVariable(name = "materialId") Long materialId ) { - return ResponseCustom.OK(archivingService.downloadMaterial(materialsId)); + return ResponseCustom.OK(archivingService.downloadMaterial(materialId)); } } diff --git a/src/main/java/com/example/PLADIALMArchiving/archiving/dto/request/RegisterProjectReq.java b/src/main/java/com/example/PLADIALMArchiving/archiving/dto/request/RegisterProjectReq.java index 7819e21..7edcdd7 100644 --- a/src/main/java/com/example/PLADIALMArchiving/archiving/dto/request/RegisterProjectReq.java +++ b/src/main/java/com/example/PLADIALMArchiving/archiving/dto/request/RegisterProjectReq.java @@ -1,8 +1,16 @@ package com.example.PLADIALMArchiving.archiving.dto.request; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Size; @Getter +@NoArgsConstructor public class RegisterProjectReq { + + @Schema(type = "String", description = "프로젝트 이름 (공백, 특수문자 제외)", minLength = 1, maxLength = 20) + @Size(max = 20, message = "P0006") private String name; } diff --git a/src/main/java/com/example/PLADIALMArchiving/archiving/dto/request/SearchMaterialReq.java b/src/main/java/com/example/PLADIALMArchiving/archiving/dto/request/SearchMaterialReq.java index 3c26868..500fe1f 100644 --- a/src/main/java/com/example/PLADIALMArchiving/archiving/dto/request/SearchMaterialReq.java +++ b/src/main/java/com/example/PLADIALMArchiving/archiving/dto/request/SearchMaterialReq.java @@ -1,9 +1,16 @@ package com.example.PLADIALMArchiving.archiving.dto.request; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; +import javax.validation.constraints.Size; + @Getter public class SearchMaterialReq { + private String cond; + + @Schema(type = "String", description = "검색 카테고리 (전체, 이미지, 비디오, 문서)", maxLength = 10) + @Size(max = 10, message = "P0003") private String category; } diff --git a/src/main/java/com/example/PLADIALMArchiving/archiving/dto/request/UploadMaterialReq.java b/src/main/java/com/example/PLADIALMArchiving/archiving/dto/request/UploadMaterialReq.java index 0d7027c..dc03997 100644 --- a/src/main/java/com/example/PLADIALMArchiving/archiving/dto/request/UploadMaterialReq.java +++ b/src/main/java/com/example/PLADIALMArchiving/archiving/dto/request/UploadMaterialReq.java @@ -1,11 +1,27 @@ package com.example.PLADIALMArchiving.archiving.dto.request; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + @Getter public class UploadMaterialReq { + + @Schema(type = "String", description = "aws s3 file key") + @NotNull(message = "P0007") private String fileKey; + + @Schema(type = "String", description = "자료 이름 (공백, 특수문자 제외)", minLength = 1, maxLength = 20) + @Size(max = 20, message = "P0007") private String name; + + @Schema(type = "String", description = "자료 사이즈") + @NotNull(message = "P0007") private Long size; + + @Schema(type = "String", description = "확장자 ex) png, jpeg, mp4 ...") + @NotNull(message = "P0007") private String extension; } diff --git a/src/main/java/com/example/PLADIALMArchiving/archiving/service/ArchivingService.java b/src/main/java/com/example/PLADIALMArchiving/archiving/service/ArchivingService.java index d8ca6cd..6bd00cd 100644 --- a/src/main/java/com/example/PLADIALMArchiving/archiving/service/ArchivingService.java +++ b/src/main/java/com/example/PLADIALMArchiving/archiving/service/ArchivingService.java @@ -21,6 +21,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; + import java.util.ArrayList; import java.util.List; @@ -36,11 +37,16 @@ public class ArchivingService { @Transactional public void registerProject(RegisterProjectReq registerProjectReq) { + if(!validatePrjNameInput(registerProjectReq.getName())) throw new BaseException(BaseResponseCode.INVALID_NAME); boolean present = projectRepository.findByName(registerProjectReq.getName()).isPresent(); if(present) throw new BaseException(BaseResponseCode.ALREADY_REGISTERED_PROJECT); projectRepository.save(Project.toEntity(registerProjectReq.getName())); } + private boolean validatePrjNameInput(String name) { + return name.matches("^[a-zA-Z0-9가-핳]{1,20}$"); + } + @Transactional public void uploadMaterial(UploadMaterialReq uploadMaterialReq, Long projectId, User user) { Project project = projectRepository.findById(projectId).orElseThrow(() -> new BaseException(BaseResponseCode.PROJECT_NOT_FOUND)); diff --git a/src/main/java/com/example/PLADIALMArchiving/global/config/SwaggerConfig.java b/src/main/java/com/example/PLADIALMArchiving/global/config/SwaggerConfig.java index 2629cc7..eccc903 100644 --- a/src/main/java/com/example/PLADIALMArchiving/global/config/SwaggerConfig.java +++ b/src/main/java/com/example/PLADIALMArchiving/global/config/SwaggerConfig.java @@ -28,9 +28,9 @@ @Configuration public class SwaggerConfig { - private static final String API_NAME = "PLADI_SERVER_API"; + private static final String API_NAME = "PLADI_ARCHIVING_API"; private static final String API_VERSION = "0.0.1"; - private static final String API_DESCRIPTION = "PLADI_SERVER_API_명세서"; + private static final String API_DESCRIPTION = "PLADI_ARCHIVING_명세서"; @Bean diff --git a/src/main/java/com/example/PLADIALMArchiving/global/exception/BaseResponseCode.java b/src/main/java/com/example/PLADIALMArchiving/global/exception/BaseResponseCode.java index e334432..10639eb 100644 --- a/src/main/java/com/example/PLADIALMArchiving/global/exception/BaseResponseCode.java +++ b/src/main/java/com/example/PLADIALMArchiving/global/exception/BaseResponseCode.java @@ -29,11 +29,13 @@ public enum BaseResponseCode { BLACKLIST_TOKEN("T0007", HttpStatus.FORBIDDEN, "로그아웃 혹은 회원 탈퇴된 토큰입니다."), // Archiving - ALREADY_REGISTERED_PROJECT("P0001", HttpStatus.BAD_REQUEST, "이미 등록된 프로젝트입니다."), + ALREADY_REGISTERED_PROJECT("P0001", HttpStatus.CONFLICT, "이미 등록된 프로젝트입니다."), PROJECT_NOT_FOUND("P0002", HttpStatus.NOT_FOUND, "존재하지 않는 프로젝트입니다."), CATEGORY_NOT_FOUND("P0003", HttpStatus.NOT_FOUND, "존재하지 않는 카테고리입니다."), MATERIAL_NOT_FOUND("P0004", HttpStatus.NOT_FOUND, "존재하지 않는 자료입니다."), UNAUTHORIZED_USER("P0005", HttpStatus.UNAUTHORIZED, "관리자 계정 또는 자료를 업로드한 유저가 아니므로 자료를 삭제할 수 없습니다."), + INVALID_NAME("P0006", HttpStatus.BAD_REQUEST, "올바르지 않은 이름 형식입니다. 다시 입력해주세요. (공백, 특수문자 제외 20자 이내)"), + INVALID_UPLOAD_MATERIAL_REQUEST("P0007", HttpStatus.BAD_REQUEST, "부적절한 자료 업로드 요청입니다. 공백을 제외하고 다시 입력해주세요."), ; public final String code;