Skip to content
Open
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
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

---

Expand Down Expand Up @@ -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
}


Comment on lines +74 to +94
Copy link
Member

Choose a reason for hiding this comment

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

Please remove these lines from the readme

## Notes

* This service **depends on Vault Web** for database and authentication.
Expand Down
7 changes: 7 additions & 0 deletions backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>


<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
Expand Down
27 changes: 27 additions & 0 deletions backend/src/main/java/cloudpage/controller/FileController.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package cloudpage.controller;

import cloudpage.service.FileEntityService;
import cloudpage.service.FileService;
import cloudpage.service.FolderService;
import cloudpage.service.UserService;
Expand All @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -88,4 +96,23 @@ public ResponseEntity<Resource> viewFile(@RequestParam String path) throws IOExc
.header(HttpHeaders.CONTENT_TYPE, mimeType)
.body(resource);
}
@GetMapping("/list")
Copy link
Member

Choose a reason for hiding this comment

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

The new /list endpoint introduces database-backed pagination via FileEntityService.
While the implementation is clean, Cloud Page is designed to manage files directly on the filesystem.
Pagination should be implemented in FolderService.getFolderTree() instead, since the folder/file structure is dynamic and filesystem-based.
I recommend removing this endpoint to avoid confusion and duplication.

public ResponseEntity<FileDto<File>> 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<File> response = new FileDto<>(
filePage.getContent(),
filePage.getNumber(),
filePage.getTotalElements(),
filePage.getTotalPages()
);
return ResponseEntity.ok(response);
}
}
87 changes: 86 additions & 1 deletion backend/src/main/java/cloudpage/dto/FileDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> {
private String name;
private String path;
private long size;
private String mimeType;
private List<T> content;
private int pageNumber;
private long totalElements;
private int totalPages;

public FileDto(List<T> 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<T> getContent() {
return content;
}

public void setContent(List<T> 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;
}

}
50 changes: 50 additions & 0 deletions backend/src/main/java/cloudpage/model/File.java
Copy link
Member

Choose a reason for hiding this comment

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

I don't think that its smart to save the files in the db.
Assume the Server changes => then the db must synchronize with the corresponding folder.
Cloud Page intentionally manages files stored on disk — introducing a JPA layer means the filesystem and database will quickly get out of sync.

Original file line number Diff line number Diff line change
@@ -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; }
}
11 changes: 11 additions & 0 deletions backend/src/main/java/cloudpage/repository/FileRepository.java
Copy link
Member

Choose a reason for hiding this comment

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

shouldn’t exist unless the project’s architecture explicitly shifts from filesystem-based storage to database-indexed file metadata.

Original file line number Diff line number Diff line change
@@ -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<File, Long> {
// Define custom queries here (if needed)
}

Copy link
Member

Choose a reason for hiding this comment

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

you dont need this. There already exists a FileService

Original file line number Diff line number Diff line change
@@ -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<File> getAllFiles(Pageable pageable);
}
4 changes: 4 additions & 0 deletions backend/src/main/java/cloudpage/service/FileService.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -54,4 +57,5 @@ private void validatePath(String rootPath, Path path) {
throw new IllegalArgumentException("Access outside the user's root folder is forbidden: " + path);
}
}

}
Copy link
Member

Choose a reason for hiding this comment

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

This FileEntityService and DB-based approach is unnecessary—FileService already handles all filesystem operations, and pagination should be implemented in FolderService directly!

Original file line number Diff line number Diff line change
@@ -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<File> getAllFiles(Pageable pageable) {
return fileRepository.findAll(pageable);
}
}