Skip to content
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
2ece31a
refactor(DocumentController): url 변경
Chan531 Nov 19, 2024
543fa14
chore(DocumentController): created URI 수정
Chan531 Nov 19, 2024
2450ed9
chore(DocumentController): folderId 타입 수정
Chan531 Nov 19, 2024
57f419e
feat(DocumentService): 폴더 검증 로직 추가
Chan531 Nov 19, 2024
5e3865a
feat(DocumentService): 파일 이름 중복 검증 로직 추가
Chan531 Nov 19, 2024
44c0260
feat(ErrorCode): 중복된 파일 이름 관련 에러 코드 추가
Chan531 Nov 19, 2024
1d57b96
feat(DocumentService): 파일 이름 중복 여부 검증
Chan531 Nov 19, 2024
0e0af79
chore(DocumentService): 미사용 메소드 제거
Chan531 Nov 19, 2024
1880878
feat(Folder): 팀 아이디 검증 기능 추가
Chan531 Nov 19, 2024
35acb3c
refactor(DocumentService): 팀 아이디 검증 책임 변경
Chan531 Nov 19, 2024
2241f3f
refactor(DocumentController): folderId 파라미터 추가
Chan531 Nov 19, 2024
dec324a
refactor(DocumentService): folderId 파라미터 적용
Chan531 Nov 19, 2024
1601f99
refactor(DocumentService): 파일 아이디 리스트 생성 로직 메소드 분리
Chan531 Nov 19, 2024
6a57b01
style(DocumentService): 메소드 선언 순서 변경
Chan531 Nov 19, 2024
739d99d
refactor(DocumentsCreateRequest): 폴더 id 요청 제거
Chan531 Nov 19, 2024
728eccc
refactor(FolderController): url 변경
Chan531 Nov 19, 2024
83d625c
style(DocumentController): 미사용 import문 제거
Chan531 Nov 19, 2024
1d93bdd
refactor(FolderController): teamId 수정
Chan531 Nov 19, 2024
4d56713
refactor(FolderController): 폴더 id 파라미터 추가
Chan531 Nov 19, 2024
37c005a
refactor(FolderService): 폴더 찾기 시, 팀 아이디 검증 로직 추가
Chan531 Nov 19, 2024
9338065
refactor(FolderController): url에서 path 제거
Chan531 Nov 19, 2024
28400df
refactor(FolderService): path 전달 방식 수정
Chan531 Nov 19, 2024
b9561b4
refactor(FolderCreateRequest): 부모 폴더 id 제거
Chan531 Nov 19, 2024
f521403
refactor(FolderService): 폴더 path 추출 로직 메소드 분리
Chan531 Nov 19, 2024
aa0600b
feat(Folder): 자식 폴더 path 반환
Chan531 Nov 19, 2024
f50af72
feat(ErrorCode): 중복된 폴더 이름 관련 에러 코드 추가
Chan531 Nov 19, 2024
1056a11
feat(FolderService): 폴더 이름 중복 여부 검증
Chan531 Nov 19, 2024
af6c18d
feat(ErrorHandler): FolderException 추가
Chan531 Nov 19, 2024
8e7e44c
chore(ErrorHandler): 메소드명 수정
Chan531 Nov 19, 2024
6bab42d
fix(FolderService): 자식 주소를 반환하도록 수정
Chan531 Nov 19, 2024
45d23c3
feat(Constant): 구분자 상수 추가
Chan531 Nov 19, 2024
c9c53db
refactor(Folder): 상수 적용
Chan531 Nov 19, 2024
1f2c80f
refactor(FolderService): getFolder, getFolderPath 중복 코드 삭제
Chan531 Nov 19, 2024
c1d186c
refactor(FolderService): 메소드명 수정
Chan531 Nov 19, 2024
9423c57
refactor(DocumentController): 파일 업로드 응답 제거
Chan531 Nov 19, 2024
a67e400
refactor(DocumentService): 파일 업로드 응답 제거
Chan531 Nov 19, 2024
f2b413e
chore(FolderService): 메소드 네이밍 변경 적용
Chan531 Nov 20, 2024
3b03318
chore(DocumentService): 메소드 네이밍 변경 적용
Chan531 Nov 20, 2024
9a0cf94
chore(DocumentService): 파라미터 final 키워드 적용
Chan531 Nov 20, 2024
256e0d9
chore(Folder): 파라미터 final 키워드 적용
Chan531 Nov 20, 2024
357b0db
chore(DocumentController): 파라미터 final 키워드 적용
Chan531 Nov 20, 2024
249d188
chore(FolderController): 파라미터 final 키워드 적용
Chan531 Nov 20, 2024
a0f350a
chore(FolderFinder): 파라미터 final 키워드 적용
Chan531 Nov 20, 2024
d6a2eb8
chore(FolderSaver): 파리미터 final 키워드 적용
Chan531 Nov 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions src/main/java/com/tiki/server/common/handler/ErrorHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.tiki.server.auth.exception.AuthException;
import com.tiki.server.common.dto.ErrorCodeResponse;
import com.tiki.server.emailverification.exception.EmailVerificationException;
import com.tiki.server.folder.exception.FolderException;
import com.tiki.server.note.exception.NoteException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -79,14 +80,21 @@ public ResponseEntity<BaseResponse> externalException(ExternalException exceptio
}

@ExceptionHandler(EmailVerificationException.class)
public ResponseEntity<BaseResponse> MailException(EmailVerificationException exception) {
public ResponseEntity<BaseResponse> mailException(EmailVerificationException exception) {
log.error(exception.getMessage());
val errorCode = exception.getErrorCode();
return ResponseEntity.status(errorCode.getHttpStatus()).body(ErrorResponse.of(errorCode.getMessage()));
}

@ExceptionHandler(FolderException.class)
public ResponseEntity<BaseResponse> folderException(FolderException exception) {
log.error(exception.getMessage());
val errorCode = exception.getErrorCode();
return ResponseEntity.status(errorCode.getHttpStatus()).body(ErrorResponse.of(errorCode.getMessage()));
}

@ExceptionHandler(AuthException.class)
public ResponseEntity<BaseResponse> AuthException(AuthException exception) {
public ResponseEntity<BaseResponse> authException(AuthException exception) {
log.error(exception.getMessage());
val errorCode = exception.getErrorCode();
return ResponseEntity.status(errorCode.getHttpStatus()).body(
Expand All @@ -101,7 +109,7 @@ public ResponseEntity<BaseResponse> httpMessageNotReadableException(HttpMessageN
}

@ExceptionHandler(Exception.class)
public ResponseEntity<BaseResponse> Exception(Exception exception) {
public ResponseEntity<BaseResponse> exception(Exception exception) {
log.error(exception.getMessage());
val errorCode = UNCAUGHT_SERVER_EXCEPTION;
return ResponseEntity.status(errorCode.getHttpStatus()).body(ErrorResponse.of(errorCode.getMessage()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
Expand Down Expand Up @@ -57,16 +56,17 @@ public ResponseEntity<?> deleteDocument(
return ResponseEntity.noContent().build();
}

@PostMapping("/documents")
public ResponseEntity<SuccessResponse<DocumentsCreateResponse>> createDocuments(
@PostMapping("/teams/{teamId}/documents")
public ResponseEntity<SuccessResponse<?>> createDocuments(
Principal principal,
@RequestHeader("team-id") long teamId,
@PathVariable long teamId,
@RequestParam(required = false) Long folderId,
@RequestBody DocumentsCreateRequest request
) {
long memberId = Long.parseLong(principal.getName());
DocumentsCreateResponse response = documentService.createDocuments(memberId, teamId, request);
return ResponseEntity.created(UriGenerator.getUri("api/v1/documents"))
.body(SuccessResponse.success(SUCCESS_CREATE_DOCUMENTS.getMessage(), response));
documentService.createDocuments(memberId, teamId, folderId, request);
return ResponseEntity.created(UriGenerator.getUri("teams/" + teamId + "/documents"))
.body(SuccessResponse.success(SUCCESS_CREATE_DOCUMENTS.getMessage()));
}

@GetMapping("/teams/{teamId}/documents")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.util.List;

public record DocumentsCreateRequest(
List<DocumentCreateRequest> documents,
Long folderId
List<DocumentCreateRequest> documents
) {
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.tiki.server.document.message;

import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CONFLICT;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.NOT_FOUND;

Expand All @@ -20,7 +21,10 @@ public enum ErrorCode {
INVALID_AUTHORIZATION(FORBIDDEN, "문서에 대한 권한이 없습니다."),

/* 404 NOT_FOUND : 자원을 찾을 수 없음 */
INVALID_DOCUMENT(NOT_FOUND, "유효하지 않은 문서입니다.");
INVALID_DOCUMENT(NOT_FOUND, "유효하지 않은 문서입니다."),

/* 409 CONFLICT : 중복된 자원 */
DOCUMENT_NAME_DUPLICATE(CONFLICT, "중복된 파일 이름입니다.");

private final HttpStatus httpStatus;
private final String message;
Expand Down
41 changes: 31 additions & 10 deletions src/main/java/com/tiki/server/document/service/DocumentService.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.tiki.server.document.service;

import static com.tiki.server.document.message.ErrorCode.DOCUMENT_NAME_DUPLICATE;

import java.util.List;

import org.springframework.stereotype.Service;
Expand All @@ -14,7 +16,9 @@
import com.tiki.server.document.dto.response.DocumentsCreateResponse;
import com.tiki.server.document.dto.response.DocumentsGetResponse;
import com.tiki.server.document.entity.Document;
import com.tiki.server.document.exception.DocumentException;
import com.tiki.server.folder.adapter.FolderFinder;
import com.tiki.server.folder.entity.Folder;
import com.tiki.server.memberteammanager.adapter.MemberTeamManagerFinder;
import com.tiki.server.memberteammanager.entity.MemberTeamManager;

Expand Down Expand Up @@ -47,13 +51,12 @@ public void deleteDocument(long memberId, long teamId, long documentId) {
}

@Transactional
public DocumentsCreateResponse createDocuments(long memberId, long teamId, DocumentsCreateRequest request) {
public void createDocuments(final long memberId, final long teamId,
final Long folderId, final DocumentsCreateRequest request) {
memberTeamManagerFinder.findByMemberIdAndTeamIdOrElseThrow(memberId, teamId);
checkFolderIsExist(request.folderId());
List<Long> documentIds = request.documents().stream()
.map(document -> saveDocument(teamId, request.folderId(), document).getId())
.toList();
return DocumentsCreateResponse.from(documentIds);
validateFolder(folderId, teamId);
validateFileName(folderId, teamId, request);
saveDocuments(teamId, folderId, request);
}

public DocumentsGetResponse get(final long memberId, final long teamId, final Long folderId) {
Expand All @@ -67,16 +70,34 @@ private DocumentsGetResponse getAllDocumentsByType(long teamId, Position accessi
return DocumentsGetResponse.from(documents);
}

private void checkFolderIsExist(Long folderId) {
private void validateFolder(Long folderId, long teamId) {
if (folderId == null) {
return;
}
folderFinder.findById(folderId);
Folder folder = folderFinder.findById(folderId);
folder.validateTeamId(teamId);
}

private void validateFileName(final Long folderId, final long teamId, final DocumentsCreateRequest request) {
List<Document> documents = documentFinder.findByTeamIdAndFolderId(teamId, folderId);
for (Document document : documents) {
checkFileNameIsDuplicated(document.getFileName(), request);
}
}

private void checkFileNameIsDuplicated(final String fileName, final DocumentsCreateRequest request) {
if (request.documents().stream().anyMatch(document -> document.fileName().equals(fileName))) {
throw new DocumentException(DOCUMENT_NAME_DUPLICATE);
}
}

private void saveDocuments(final long teamId, final Long folderId, final DocumentsCreateRequest request) {
request.documents().forEach(document -> saveDocument(teamId, folderId, document));
}

private Document saveDocument(long teamId, Long folderId, DocumentCreateRequest request) {
private void saveDocument(long teamId, Long folderId, DocumentCreateRequest request) {
Document document = Document.of(
request.fileName(), request.fileUrl(), request.capacity(), teamId, folderId);
return documentSaver.save(document);
documentSaver.save(document);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
public class Constant {

public static final String ROOT_PATH = "";
public static final String SEPARATOR = "/";
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -27,30 +27,31 @@

@RestController
@RequiredArgsConstructor
@RequestMapping("api/v1/folders")
@RequestMapping("api/v1")
public class FolderController {

private final FolderService folderService;

@GetMapping()
@GetMapping("/teams/{teamId}/folders")
public ResponseEntity<SuccessResponse<FoldersGetResponse>> getFolders(
final Principal principal,
@RequestHeader("team-id") long teamId,
@RequestParam(defaultValue = ROOT_PATH) String path
@PathVariable long teamId,
@RequestParam(required = false) Long folderId
) {
long memberId = Long.parseLong(principal.getName());
FoldersGetResponse response = folderService.get(memberId, teamId, path);
FoldersGetResponse response = folderService.get(memberId, teamId, folderId);
return ResponseEntity.ok(success(SUCCESS_GET_FOLDERS.getMessage(), response));
}

@PostMapping()
@PostMapping("/teams/{teamId}/folders")
public ResponseEntity<SuccessResponse<FolderCreateResponse>> createFolder(
Principal principal,
@RequestHeader("team-id") long teamId,
@PathVariable long teamId,
@RequestParam(required = false) Long folderId,
@RequestBody FolderCreateRequest request
) {
long memberId = Long.parseLong(principal.getName());
FolderCreateResponse response = folderService.create(memberId, teamId, request);
FolderCreateResponse response = folderService.create(memberId, teamId, folderId, request);
return ResponseEntity.created(UriGenerator.getUri("api/v1/folders/" + response.folderId()))
.body(success(SUCCESS_CREATE_FOLDER.getMessage(), response));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import lombok.NonNull;

public record FolderCreateRequest(
@NonNull String name,
Long parentId
@NonNull String name
) {
}
18 changes: 16 additions & 2 deletions src/main/java/com/tiki/server/folder/entity/Folder.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.tiki.server.folder.entity;

import static com.tiki.server.document.message.ErrorCode.INVALID_AUTHORIZATION;
import static com.tiki.server.folder.constant.Constant.ROOT_PATH;
import static com.tiki.server.folder.constant.Constant.SEPARATOR;
import static jakarta.persistence.GenerationType.IDENTITY;

import com.tiki.server.common.entity.BaseTime;
import com.tiki.server.document.exception.DocumentException;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
Expand Down Expand Up @@ -31,10 +35,20 @@ public Folder(String name, Folder parentFolder, long teamId) {
this.teamId = teamId;
}

public void validateTeamId(final long teamId) {
if (this.teamId != teamId) {
throw new DocumentException(INVALID_AUTHORIZATION);
}
}

public String getChildPath() {
return path + SEPARATOR + id;
}

private String generatePath(Folder parentFolder) {
if (parentFolder == null) {
return "";
return ROOT_PATH;
}
return parentFolder.getPath() + "/" + parentFolder.getId();
return parentFolder.getPath() + SEPARATOR + parentFolder.getId();
}
}
6 changes: 5 additions & 1 deletion src/main/java/com/tiki/server/folder/message/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tiki.server.folder.message;

import static org.springframework.http.HttpStatus.CONFLICT;
import static org.springframework.http.HttpStatus.NOT_FOUND;

import org.springframework.http.HttpStatus;
Expand All @@ -12,7 +13,10 @@
public enum ErrorCode {

/* 404 NOT_FOUND : 자원을 찾을 수 없음 */
INVALID_FOLDER(NOT_FOUND, "유효하지 않은 폴더입니다.");
INVALID_FOLDER(NOT_FOUND, "유효하지 않은 폴더입니다."),

/* 409 CONFLICT : 중복된 자원 */
FOLDER_NAME_DUPLICATE(CONFLICT, "중복된 폴더 이름입니다.");;

private final HttpStatus httpStatus;
private final String message;
Expand Down
37 changes: 31 additions & 6 deletions src/main/java/com/tiki/server/folder/service/FolderService.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.tiki.server.folder.service;

import static com.tiki.server.folder.constant.Constant.ROOT_PATH;
import static com.tiki.server.folder.message.ErrorCode.FOLDER_NAME_DUPLICATE;

import java.util.List;

import org.springframework.stereotype.Service;
Expand All @@ -11,6 +14,7 @@
import com.tiki.server.folder.dto.response.FolderCreateResponse;
import com.tiki.server.folder.dto.response.FoldersGetResponse;
import com.tiki.server.folder.entity.Folder;
import com.tiki.server.folder.exception.FolderException;
import com.tiki.server.memberteammanager.adapter.MemberTeamManagerFinder;

import lombok.RequiredArgsConstructor;
Expand All @@ -24,25 +28,46 @@ public class FolderService {
private final FolderSaver folderSaver;
private final MemberTeamManagerFinder memberTeamManagerFinder;

public FoldersGetResponse get(final long memberId, final long teamId, final String path) {
public FoldersGetResponse get(final long memberId, final long teamId,
final Long folderId) {
memberTeamManagerFinder.findByMemberIdAndTeamId(memberId, teamId);
Folder folder = getFolder(teamId, folderId);
String path = getChildFolderPath(folder);
List<Folder> folders = folderFinder.findByTeamIdAndPath(teamId, path);
return FoldersGetResponse.from(folders);
}

@Transactional
public FolderCreateResponse create(long memberId, long teamId, FolderCreateRequest request) {
// 같은 레벨 파일명 중복 방지 로직 추가 필요
public FolderCreateResponse create(final long memberId, final long teamId,
final Long folderId, final FolderCreateRequest request) {
memberTeamManagerFinder.findByMemberIdAndTeamIdOrElseThrow(memberId, teamId);
Folder parentFolder = getFolder(request.parentId());
Folder parentFolder = getFolder(teamId, folderId);
String path = getChildFolderPath(parentFolder);
validateFolderName(teamId, path, request);
Folder folder = folderSaver.save(new Folder(request.name(), parentFolder, teamId));
return FolderCreateResponse.from(folder.getId());
}

private Folder getFolder(Long folderId) {
private Folder getFolder(final long teamId, final Long folderId) {
if (folderId == null) {
return null;
}
return folderFinder.findById(folderId);
Folder folder = folderFinder.findById(folderId);
folder.validateTeamId(teamId);
return folder;
}

private String getChildFolderPath(final Folder folder) {
if (folder == null) {
return ROOT_PATH;
}
return folder.getChildPath();
}

private void validateFolderName(final long teamId, final String path, final FolderCreateRequest request) {
List<Folder> folders = folderFinder.findByTeamIdAndPath(teamId, path);
if (folders.stream().anyMatch(folder -> folder.getName().equals(request.name()))) {
throw new FolderException(FOLDER_NAME_DUPLICATE);
}
}
}
Loading