diff --git a/README.md b/README.md index f8883f6..08f31a1 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ This service is designed to integrate seamlessly with **Vault Web**, sharing its - 🔹 **File Explorer-like API** for user files - 🔹 **CRUD operations** on files and folders - 🔹 **Secure access via JWT tokens** using Vault Web's master key + **Pagination and sorting for file listings --- @@ -70,6 +71,27 @@ Then visit: --- +Usage +Pagination Example +List files with pagination + GET /api/files/list?page=0&size=20&sort=name,asc +Sample JSON response: +{ + "content": [ + { + "name": "Doc1.txt", + "path": "/user/files/Doc1.txt", + "size": 12345, + "mimeType": "text/plain" + } + // ... + ], + "pageNumber": 0, + "totalElements": 52, + "totalPages": 3 +} + + ## Notes * This service **depends on Vault Web** for database and authentication. diff --git a/backend/pom.xml b/backend/pom.xml index 7ddb3d8..987da6a 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -100,6 +100,13 @@ runtime + + javax.persistence + javax.persistence-api + 2.2 + + + org.springdoc springdoc-openapi-starter-webmvc-ui diff --git a/backend/src/main/java/cloudpage/controller/FileController.java b/backend/src/main/java/cloudpage/controller/FileController.java index e92638e..a6b0301 100644 --- a/backend/src/main/java/cloudpage/controller/FileController.java +++ b/backend/src/main/java/cloudpage/controller/FileController.java @@ -1,5 +1,6 @@ package cloudpage.controller; +import cloudpage.service.FileEntityService; import cloudpage.service.FileService; import cloudpage.service.FolderService; import cloudpage.service.UserService; @@ -10,6 +11,11 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import cloudpage.dto.FileDto; +import cloudpage.model.File; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Pageable; import java.io.IOException; import java.nio.file.Files; @@ -24,6 +30,8 @@ public class FileController { private final FileService fileService; private final UserService userService; private final FolderService folderService; + private final FileEntityService fileEntityService; +; @PostMapping("/upload") public void uploadFile(@RequestParam String folderPath, @RequestParam MultipartFile file) throws IOException { @@ -88,4 +96,23 @@ public ResponseEntity viewFile(@RequestParam String path) throws IOExc .header(HttpHeaders.CONTENT_TYPE, mimeType) .body(resource); } + @GetMapping("/list") +public ResponseEntity> listFilesWithPagination( + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size, + @RequestParam(defaultValue = "name,asc") String[] sort +) { + // Example sort param: ["name", "asc"] + Sort.Direction direction = sort[1].equalsIgnoreCase("desc") ? Sort.Direction.DESC : Sort.Direction.ASC; + Pageable pageable = PageRequest.of(page, size, Sort.by(direction, sort[0])); + var filePage = fileEntityService.getAllFiles(pageable); + + FileDto response = new FileDto<>( + filePage.getContent(), + filePage.getNumber(), + filePage.getTotalElements(), + filePage.getTotalPages() + ); + return ResponseEntity.ok(response); +} } \ No newline at end of file diff --git a/backend/src/main/java/cloudpage/dto/FileDto.java b/backend/src/main/java/cloudpage/dto/FileDto.java index cc4c353..8b6c495 100644 --- a/backend/src/main/java/cloudpage/dto/FileDto.java +++ b/backend/src/main/java/cloudpage/dto/FileDto.java @@ -3,13 +3,98 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; +import java.util.List; @Getter @Setter @AllArgsConstructor -public class FileDto { +public class FileDto { private String name; private String path; private long size; private String mimeType; + private List content; + private int pageNumber; + private long totalElements; + private int totalPages; + + public FileDto(List content, int pageNumber, long totalElements, int totalPages) { + this.content = content; + this.pageNumber = pageNumber; + this.totalElements = totalElements; + this.totalPages = totalPages; + } + public FileDto() { + } + public FileDto(String name, String path, long size, String mimeType) { + this.name = name; + this.path = path; + this.size = size; + this.mimeType = mimeType; +} + + public String getName() { + return name; +} + +public void setName(String name) { + this.name = name; +} + +public String getPath() { + return path; +} + +public void setPath(String path) { + this.path = path; +} + +public long getSize() { + return size; +} + +public void setSize(long size) { + this.size = size; +} + +public String getMimeType() { + return mimeType; +} + +public void setMimeType(String mimeType) { + this.mimeType = mimeType; +} + +public List getContent() { + return content; +} + +public void setContent(List content) { + this.content = content; +} + +public int getPageNumber() { + return pageNumber; +} + +public void setPageNumber(int pageNumber) { + this.pageNumber = pageNumber; +} + +public long getTotalElements() { + return totalElements; +} + +public void setTotalElements(long totalElements) { + this.totalElements = totalElements; +} + +public int getTotalPages() { + return totalPages; +} + +public void setTotalPages(int totalPages) { + this.totalPages = totalPages; +} + } diff --git a/backend/src/main/java/cloudpage/model/File.java b/backend/src/main/java/cloudpage/model/File.java new file mode 100644 index 0000000..dc39ee0 --- /dev/null +++ b/backend/src/main/java/cloudpage/model/File.java @@ -0,0 +1,50 @@ +package cloudpage.model; + +import javax.persistence.Entity; +import javax.persistence.Table; +import javax.persistence.Id; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; + +@Entity +@Table(name = "files") +public class File { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + private String path; + + private Long size; + + private String fileType; + + // Constructors + public File() {} + + public File(String name, String path, Long size, String fileType) { + this.name = name; + this.path = path; + this.size = size; + this.fileType = fileType; + } + + // Getters and setters + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + + public String getName() { return name; } + public void setName(String name) { this.name = name; } + + public String getPath() { return path; } + public void setPath(String path) { this.path = path; } + + public Long getSize() { return size; } + public void setSize(Long size) { this.size = size; } + + public String getFileType() { return fileType; } + public void setFileType(String fileType) { this.fileType = fileType; } +} diff --git a/backend/src/main/java/cloudpage/repository/FileRepository.java b/backend/src/main/java/cloudpage/repository/FileRepository.java new file mode 100644 index 0000000..3c8c0a9 --- /dev/null +++ b/backend/src/main/java/cloudpage/repository/FileRepository.java @@ -0,0 +1,11 @@ +package cloudpage.repository; + +import cloudpage.model.File; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface FileRepository extends PagingAndSortingRepository { + // Define custom queries here (if needed) +} + diff --git a/backend/src/main/java/cloudpage/service/FileEntityService.java b/backend/src/main/java/cloudpage/service/FileEntityService.java new file mode 100644 index 0000000..6c7fa3a --- /dev/null +++ b/backend/src/main/java/cloudpage/service/FileEntityService.java @@ -0,0 +1,9 @@ +package cloudpage.service; + +import cloudpage.model.File; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface FileEntityService { + Page getAllFiles(Pageable pageable); +} diff --git a/backend/src/main/java/cloudpage/service/FileService.java b/backend/src/main/java/cloudpage/service/FileService.java index 8e5d110..922fc9e 100644 --- a/backend/src/main/java/cloudpage/service/FileService.java +++ b/backend/src/main/java/cloudpage/service/FileService.java @@ -8,6 +8,9 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import cloudpage.model.File; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; @Service public class FileService { @@ -54,4 +57,5 @@ private void validatePath(String rootPath, Path path) { throw new IllegalArgumentException("Access outside the user's root folder is forbidden: " + path); } } + } \ No newline at end of file diff --git a/backend/src/main/java/cloudpage/service/impl/FileEntityServiceImpl.java b/backend/src/main/java/cloudpage/service/impl/FileEntityServiceImpl.java new file mode 100644 index 0000000..f592b75 --- /dev/null +++ b/backend/src/main/java/cloudpage/service/impl/FileEntityServiceImpl.java @@ -0,0 +1,21 @@ +package cloudpage.service.impl; + +import cloudpage.model.File; +import cloudpage.repository.FileRepository; +import cloudpage.service.FileEntityService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +@Service +public class FileEntityServiceImpl implements FileEntityService { + + @Autowired + private FileRepository fileRepository; + + @Override + public Page getAllFiles(Pageable pageable) { + return fileRepository.findAll(pageable); + } +}