Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/chung step2 #6

Merged
merged 17 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 0 additions & 11 deletions src/main/java/com/c4cometrue/mystorage/dto/FileDeleteRequest.java

This file was deleted.

This file was deleted.

13 changes: 0 additions & 13 deletions src/main/java/com/c4cometrue/mystorage/dto/FileUploadRequest.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import lombok.AllArgsConstructor;
import lombok.Getter;


@Getter
@AllArgsConstructor
public enum ErrorCode {
Expand All @@ -17,7 +16,12 @@ public enum ErrorCode {

FILE_DELETE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "파일 삭제 중 오류가 발생했습니다."),

DUPLICATE_FILE_NAME(HttpStatus.BAD_REQUEST, "파일 업로드에 중복이 발생 했습니다");
DUPLICATE_FILE_NAME(HttpStatus.BAD_REQUEST, "파일 업로드에 중복이 발생 했습니다"),

FOLDER_CREATE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "폴더 생성 중 오류가 발생했습니다"),
UNAUTHORIZED_FOLDER_ACCESS(HttpStatus.FORBIDDEN, "비정상적인 요청입니다."),
DUPLICATE_FOLDER_NAME(HttpStatus.BAD_REQUEST, "폴더 업로드에 중복이 발생 했습니다"),
CANNOT_FOUND_FOLDER(HttpStatus.NOT_FOUND, "해당 폴더를 찾을 수 없습니다.");

private final HttpStatus httpStatus;
private final String message;
Expand Down
16 changes: 9 additions & 7 deletions src/main/java/com/c4cometrue/mystorage/file/FileController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.c4cometrue.mystorage.dto.FileDeleteRequest;
import com.c4cometrue.mystorage.dto.FileDownloadRequest;
import com.c4cometrue.mystorage.dto.FileUploadRequest;
import com.c4cometrue.mystorage.file.dto.FileDeleteRequest;
import com.c4cometrue.mystorage.file.dto.FileDownloadRequest;
import com.c4cometrue.mystorage.file.dto.FileUploadRequest;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

@RestController
Expand All @@ -22,19 +24,19 @@ public class FileController {

@PostMapping
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metadata 컨트롤러로 인해 파일 업로드를 이동하셨군요..
그리고 메타데이터 서비스가 파일과 폴더 서비스를 다시 의존하고 있군요..

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

파일과 폴더 서비스에 의존성이 생기는 게 자연스러운가 생각해서
Metadata 서비스를 만들어서 의존을 관리하고자 했습니다
지금 생각해보니
네이밍이 MetadataFasade 쪽으로 됐어야 하고
파일과 폴더 사이 의존에 대해 좀 더 생각해봐야겠네요

@ResponseStatus(HttpStatus.CREATED)
public void uploadFile(FileUploadRequest fileUploadRequest) {
fileService.uploadFile(fileUploadRequest.multipartFile(), fileUploadRequest.userId());
public void uploadFile(@Valid @ModelAttribute FileUploadRequest req) {
fileService.uploadFile(req.multipartFile(), req.userId(), req.parentId());
}

@DeleteMapping
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteFile(FileDeleteRequest request) {
public void deleteFile(@Valid FileDeleteRequest request) {
fileService.deleteFile(request.fileId(), request.userId());
}

@GetMapping
@ResponseStatus(HttpStatus.NO_CONTENT)
public void downloadFile(FileDownloadRequest request) {
public void downloadFile(@Valid FileDownloadRequest request) {
fileService.downloadFile(request.fileId(), request.userPath(), request.userId());
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.c4cometrue.mystorage.file;

import java.util.List;

import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.c4cometrue.mystorage.exception.ErrorCode;

import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class FileDataHandlerService {
private final FileRepository fileRepository;
@Transactional
public void deleteBy(Long fileId) {
existBy(fileId);
fileRepository.deleteById(fileId);
}

private void existBy(Long fileId) {
if (!fileRepository.existsById(fileId)) {
throw ErrorCode.CANNOT_FOUND_FILE.serviceException("fileId : {}", fileId);
}
}

public FileMetadata findBy(Long fileId, Long userId) {
return fileRepository.findByIdAndUploaderId(fileId, userId)
.orElseThrow(() -> ErrorCode.CANNOT_FOUND_FILE.serviceException("fileId : {}, userId : {}", fileId,
userId));
}

@Transactional
public void persist(FileMetadata fileMetadata, Long userId, Long parentId) {
validateFileOwnershipBy(parentId, userId);
duplicateBy(parentId, userId, fileMetadata.getOriginalFileName());
fileRepository.save(fileMetadata);
}

private void duplicateBy(Long parentId, Long userId, String fileName) {
if (fileRepository.checkDuplicateFileName(parentId, userId, fileName)) {
throw ErrorCode.DUPLICATE_FILE_NAME.serviceException("fileName : {}", fileName);
}
}

public List<FileMetadata> findChildBy(Long parentId, Long userId) {
validateFileOwnershipBy(parentId, userId);
return fileRepository.findByParentIdAndUploaderId(parentId, userId);
}

private void validateFileOwnershipBy(Long folderId, Long userId) {
if (folderId != null && !fileRepository.existsByIdAndUploaderId(folderId, userId)) {
throw ErrorCode.UNAUTHORIZED_FILE_ACCESS.serviceException();
}
}

public List<FileMetadata> getFileList(Long parentId, Long cursorId, Long userId, Pageable page) {
return cursorId == null ? fileRepository.findAllByParentIdAndUploaderIdOrderByIdDesc(parentId, userId, page)
: fileRepository.findByParentIdAndUploaderIdAndIdLessThanOrderByIdDesc(parentId, cursorId, userId, page);
}

public Boolean hashNext(Long parentId, Long userId, Long lastIdOfList) {
return fileRepository.existsByParentIdAndUploaderIdAndIdLessThan(parentId, userId, lastIdOfList);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,27 @@

import java.util.UUID;

import com.c4cometrue.mystorage.meta.MetadataType;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "Metadata", indexes = @Index(name = "index_uploaderId", columnList = "uploaderId"))
public class Metadata {
@Table(name = "file_metadata", indexes = @Index(name = "index_parentId", columnList = "parentId"))
public class FileMetadata {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand All @@ -30,19 +35,24 @@ public class Metadata {
private String filePath;
@Column(nullable = false)
private Long uploaderId;
private Long parentId;

@Column(nullable = false)
@Enumerated(EnumType.STRING)
private MetadataType metadataType;

public static String storedName() {
return UUID.randomUUID().toString();
}

private Metadata(String originalFileName, String storedFileName, String filePath, Long uploaderId) {
@Builder
public FileMetadata(String originalFileName, String storedFileName, String filePath, Long uploaderId,
Long parentId) {
this.originalFileName = originalFileName;
this.storedFileName = storedFileName;
this.filePath = filePath;
this.uploaderId = uploaderId;
}

public static Metadata of(String originalFileName, String storedFileName, String filePath, Long uploaderId) {
return new Metadata(originalFileName, storedFileName, filePath, uploaderId);
this.parentId = parentId;
this.metadataType = MetadataType.FILE;
}
}
9 changes: 0 additions & 9 deletions src/main/java/com/c4cometrue/mystorage/file/FileReader.java

This file was deleted.

25 changes: 17 additions & 8 deletions src/main/java/com/c4cometrue/mystorage/file/FileRepository.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
package com.c4cometrue.mystorage.file;

import java.util.List;
import java.util.Optional;

import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface FileRepository extends JpaRepository<Metadata, Long> {
Optional<Metadata> findByIdAndUploaderId(Long id, Long uploaderId);
public interface FileRepository extends JpaRepository<FileMetadata, Long> {
Optional<FileMetadata> findByIdAndUploaderId(Long id, Long uploaderId);

@Query("SELECT CASE WHEN COUNT(m) > 0 "
+ "THEN TRUE "
+ "ELSE FALSE END "
+ "FROM Metadata m "
+ "WHERE m.uploaderId = :uploaderId "
@Query("SELECT CASE WHEN COUNT(m) > 0 " + "THEN TRUE " + "ELSE FALSE END " + "FROM FileMetadata m " + "WHERE "
+ "(m.parentId = :parentId OR (m.parentId IS NULL AND :parentId IS NULL)) " + "AND m.uploaderId = :uploaderId "
+ "AND m.originalFileName = :fileName ")
boolean checkDuplicateFileName(String fileName, Long uploaderId);
boolean checkDuplicateFileName(Long parentId, Long uploaderId, String fileName);

List<FileMetadata> findByParentIdAndUploaderId(Long parentId, Long userId);

Boolean existsByIdAndUploaderId(Long parentId, Long userId);

List<FileMetadata> findAllByParentIdAndUploaderIdOrderByIdDesc(Long parentId, Long uploaderId, Pageable page);

List<FileMetadata> findByParentIdAndUploaderIdAndIdLessThanOrderByIdDesc(Long parentId, Long userId, Long cursorId,
Pageable pageable);

Boolean existsByParentIdAndUploaderIdAndIdLessThan(Long parentId, Long uploaderId, Long id);
}
Loading