Skip to content
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ See also [postman collection example](docs/FileServer.postman_collection.json).
* __GET__ http://localhost:8888/services/files/audit/** - get audit data for the resource.
``curl -X GET http://localhost:8888/services/files/audit/path/to/source -b /tmp/cookies.txt``

#### Compress file
* __POST__ http://localhost:8888/services/files/compress/** - compress file with specified compression extension.
``curl -X POST http://localhost:8888/services/files/compress/path/to/source -b /tmp/cookies.txt -d '{ "processedFilePath": "path/to/destination/of/compressed/file" }''``

#### Decompress file
* __POST__ http://localhost:8888/services/files/decompress/** - decompress file with specified compression extension.
``curl -X POST http://localhost:8888/services/files/decompress/path/to/source -b /tmp/cookies.txt -d '{ "processedFilePath": "path/to/destination/of/decompressed/file" }''``


### Security
In order to use file server REST endpoints above, user's http session must be authorized.
Users have defined their roles and access rights to files and directories.
Expand Down
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ repositories {

dependencies {
implementation('org.springframework.boot:spring-boot-starter-web')
implementation('org.apache.commons:commons-compress:1.26.1')
implementation('org.tukaani:xz:1.9')
testImplementation('org.springframework.boot:spring-boot-starter-test')
testImplementation('org.mockito:mockito-core:4.6.1')
testImplementation('net.bytebuddy:byte-buddy:1.12.10')
Expand Down
40 changes: 40 additions & 0 deletions docs/FileServer.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,46 @@
"description": ""
},
"response": []
},
{
"name": "Compress file",
"request": {
"url": "http://localhost:8888/services/files/compress/sourceOfFile",
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json",
"description": ""
}
],
"body": {
"mode": "raw",
"raw": "{\n\t\"processedFilePath\": \"value\"\n}"
},
"description": ""
},
"response": []
},
{
"name": "Decompress file",
"request": {
"url": "http://localhost:8888/services/files/decompress/sourceOfFile",
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json",
"description": ""
}
],
"body": {
"mode": "raw",
"raw": "{\n\t\"processedFilePath\": \"value\"\n}"
},
"description": ""
},
"response": []
}
]
}
Expand Down
1 change: 0 additions & 1 deletion src/main/java/itx/fileserver/FileServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@
import itx.fileserver.services.data.AuditService;
import itx.fileserver.services.data.FileAccessManagerService;
import itx.fileserver.services.data.UserManagerService;
import itx.fileserver.services.data.filesystem.AuditServiceFilesystem;
import itx.fileserver.services.data.filesystem.FileAccessManagerServiceFilesystem;
import itx.fileserver.services.data.filesystem.PersistenceService;
import itx.fileserver.services.data.filesystem.PersistenceServiceImpl;
import itx.fileserver.services.data.filesystem.UserManagerServiceFilesystem;
import itx.fileserver.services.data.filesystem.*;
import itx.fileserver.services.data.inmemory.AuditServiceInmemory;
import itx.fileserver.services.data.inmemory.FileAccessManagerServiceInmemory;
import itx.fileserver.services.data.inmemory.UserManagerServiceInmemory;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/itx/fileserver/config/SessionListener.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package itx.fileserver.config;

import itx.fileserver.services.SecurityService;
import itx.fileserver.dto.SessionId;
import itx.fileserver.services.SecurityService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
Expand Down
19 changes: 2 additions & 17 deletions src/main/java/itx/fileserver/controler/AdminController.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,17 @@
package itx.fileserver.controler;

import itx.fileserver.dto.UserConfig;
import itx.fileserver.dto.*;
import itx.fileserver.services.FileService;
import itx.fileserver.services.SecurityService;
import itx.fileserver.services.data.AuditService;
import itx.fileserver.services.data.FileAccessManagerService;
import itx.fileserver.services.data.UserManagerService;
import itx.fileserver.dto.AuditQuery;
import itx.fileserver.dto.AuditRecord;
import itx.fileserver.dto.FileStorageInfo;
import itx.fileserver.dto.FilterConfig;
import itx.fileserver.dto.RoleId;
import itx.fileserver.dto.SessionId;
import itx.fileserver.dto.Sessions;
import itx.fileserver.dto.UserData;
import itx.fileserver.dto.UserId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.time.Instant;
Expand Down
8 changes: 2 additions & 6 deletions src/main/java/itx/fileserver/controler/AdminFilter.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package itx.fileserver.controler;

import itx.fileserver.services.SecurityService;
import itx.fileserver.dto.SessionId;
import itx.fileserver.services.SecurityService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
Expand Down
8 changes: 2 additions & 6 deletions src/main/java/itx/fileserver/controler/AuthController.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
package itx.fileserver.controler;

import itx.fileserver.services.SecurityService;
import itx.fileserver.dto.LoginRequest;
import itx.fileserver.dto.SessionId;
import itx.fileserver.dto.UserData;
import itx.fileserver.services.SecurityService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.Optional;
Expand Down
36 changes: 24 additions & 12 deletions src/main/java/itx/fileserver/controler/FileServerController.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package itx.fileserver.controler;

import itx.fileserver.dto.MoveRequest;
import itx.fileserver.dto.*;
import itx.fileserver.services.FileService;
import itx.fileserver.services.FileUtils.OperationMode;
import itx.fileserver.services.OperationNotAllowedException;
import itx.fileserver.services.SecurityService;
import itx.fileserver.dto.FileList;
import itx.fileserver.dto.ResourceAccessInfo;
import itx.fileserver.dto.SessionId;
import itx.fileserver.dto.UserData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -16,13 +13,7 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
Expand All @@ -46,6 +37,8 @@ public class FileServerController {
public static final String CREATEDIR_PREFIX = "/createdir/";
public static final String MOVE_PREFIX = "/move/";
public static final String AUDIT_PREFIX = "/audit/";
public static final String COMPRESS_PREFIX = "/compress/";
public static final String DECOMPRESS_PREFIX = "/decompress/";

private final FileService fileService;
private final SecurityService securityService;
Expand Down Expand Up @@ -185,6 +178,25 @@ public ResponseEntity<Resource> move(@RequestBody MoveRequest moveRequest) {
}
}

@PostMapping({COMPRESS_PREFIX + "**", DECOMPRESS_PREFIX + "**"})
public ResponseEntity<Resource> processFile(@RequestBody CompressDecompressRequest compressRequest) {
try {
String contextPath = httpServletRequest.getRequestURI();
SessionId sessionId = new SessionId(httpServletRequest.getSession().getId());
Optional<UserData> userData = securityService.isAuthorized(sessionId);
if (userData.isPresent()) {
OperationMode mode = contextPath.startsWith(URI_PREFIX + COMPRESS_PREFIX) ? OperationMode.COMPRESS : OperationMode.DECOMPRESS;
Path sourcePath = Paths.get(contextPath.substring((URI_PREFIX + (mode == OperationMode.COMPRESS ? COMPRESS_PREFIX : DECOMPRESS_PREFIX)).length()));
Path destinationPath = Paths.get(compressRequest.getProcessedFilePath());
fileService.processFile(userData.get(), sourcePath, destinationPath, mode);
return ResponseEntity.ok().build();
}
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
} catch (OperationNotAllowedException e) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
}

@GetMapping(AUDIT_PREFIX + "**")
public ResponseEntity<ResourceAccessInfo> getAuditInfo() {
try {
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/itx/fileserver/dto/CompressDecompressRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package itx.fileserver.dto;

public class CompressDecompressRequest {

private String processedFilePath;

public CompressDecompressRequest() {
}

public CompressDecompressRequest(String processedFilePath) {
this.processedFilePath = processedFilePath;
}

public String getProcessedFilePath() {
return processedFilePath;
}

public void setProcessedFilePath(String processedFilePath) {
this.processedFilePath = processedFilePath;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package itx.fileserver.services;

import itx.fileserver.services.data.FileAccessManagerService;
import itx.fileserver.dto.AccessType;
import itx.fileserver.dto.FileAccessFilter;
import itx.fileserver.dto.RoleId;
import itx.fileserver.services.data.FileAccessManagerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down
24 changes: 17 additions & 7 deletions src/main/java/itx/fileserver/services/FileService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import itx.fileserver.dto.FileStorageInfo;
import itx.fileserver.dto.ResourceAccessInfo;
import itx.fileserver.dto.UserData;
import itx.fileserver.services.FileUtils.OperationMode;
import org.springframework.core.io.Resource;

import java.io.FileNotFoundException;
Expand All @@ -24,7 +25,7 @@ public interface FileService {

/**
* Get info about resource access.
* @param userData users's data accessing this resource.
* @param userData user data accessing this resource.
* @param filePath relative path to file or directory.
* @return {@link ResourceAccessInfo} access info about this resource.
* @throws OperationNotAllowedException
Expand All @@ -34,7 +35,7 @@ public interface FileService {
/**
* Create {@link Resource} for given file.
* @param filePath relative path to file.
* @param userData users's data accessing this file
* @param userData user data accessing this file
* @return {@link Resource} representing the file.
* @throws FileNotFoundException
* @throws OperationNotAllowedException
Expand All @@ -44,7 +45,7 @@ public interface FileService {
/**
* Get information about file or list content of directory.
* @param filePath relative path to file or directory.
* @param userData users's data accessing this file or directory.
* @param userData user data accessing this file or directory.
* @return meta data about file or directory content list.
* @throws IOException
* @throws OperationNotAllowedException
Expand All @@ -54,7 +55,7 @@ public interface FileService {
/**
* Writes data in {@link InputStream} into file specified by relative path.
* @param filePath relative path to file.
* @param userData users's data writing into target directory.
* @param userData user data writing into target directory.
* @param inputStream data to be written into that file.
* @throws IOException
* @throws OperationNotAllowedException
Expand All @@ -64,7 +65,7 @@ public interface FileService {
/**
* Deletes file or directory. Directories are deleted even when not empty.
* @param filePath relative path to file or directory.
* @param userData users's data accessing this file or directory.
* @param userData user data accessing this file or directory.
* @throws IOException
* @throws OperationNotAllowedException
*/
Expand All @@ -73,20 +74,29 @@ public interface FileService {
/**
* Creates new empty directory.
* @param filePath relative path to directory.
* @param userData users's data accessing this directory.
* @param userData user data accessing this directory.
* @throws IOException
* @throws OperationNotAllowedException
*/
void createDirectory(UserData userData, Path filePath) throws IOException, OperationNotAllowedException;

/**
* Move file or directory from source to destination.
* @param userData users's data accessing source and destination.
* @param userData user data accessing source and destination.
* @param sourcePath relative path to source file or directory.
* @param destinationPath relative path to destination file or directory.
* @throws IOException
* @throws OperationNotAllowedException
*/
void move(UserData userData, Path sourcePath, Path destinationPath) throws IOException, OperationNotAllowedException;

/**
* Process file to compress it or decompress it to a destination.
* @param userData user data accessing source and destination.
* @param sourcePath relative path to source file or directory.
* @param outputFilePath relative path to processed file or directory.
* @param mode relative to the kind of process (compress/decompress).
* @throws OperationNotAllowedException
*/
void processFile(UserData userData, Path sourcePath, Path outputFilePath, OperationMode mode) throws OperationNotAllowedException;
}
Loading