Skip to content
This repository was archived by the owner on Apr 5, 2024. It is now read-only.
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
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</parent>
<groupId>de.filefighter</groupId>
<artifactId>rest</artifactId>
<version>0.0.8</version>
<version>0.0.9</version>
<name>RestApi</name>
<description>RestApi for FileFighter</description>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ CommandLineRunner initDataBaseDev(UserRepository userRepository, AccessTokenRepo
log.error("Inserting Users " + MESSAGE_ON_FAILURE);
}

if (fileSystemRepository.findAll().size() == 8) {
if (fileSystemRepository.findAll().size() == 10) {
log.info("Inserting FileSystemEntities " + MESSAGE_ON_SUCCESS);
} else {
log.error("Inserting FileSystemEntities " + MESSAGE_ON_FAILURE);
Expand Down Expand Up @@ -239,7 +239,7 @@ private void addDefaultAdminAndRuntimeUser(UserRepository userRepository, Passwo
}

private void addTestingFileSystemItems(FileSystemRepository fileSystemRepository) {
log.info("Inserting default fsItems:\n {}\n {}\n {}\n {}\n {}\n {}\n {}\n {}.",
log.info("Inserting default fsItems:\n {}\n {}\n {}\n {}\n {}\n {}\n {}\n {}\n {}\n {}.",
fileSystemRepository.save(FileSystemEntity.builder()
.lastUpdatedBy(RUNTIME_USER_ID)
.ownerId(1)
Expand Down Expand Up @@ -306,7 +306,7 @@ private void addTestingFileSystemItems(FileSystemRepository fileSystemRepository
.typeId(FOLDER.getId())
.editableFoGroupIds(new long[]{FAMILY.getGroupId()})
.visibleForGroupIds(new long[]{FAMILY.getGroupId()})
.itemIds(new long[]{4, 5, 6})
.itemIds(new long[]{4, 5, 6, 8})
.build()),
fileSystemRepository.save(FileSystemEntity.builder()
.lastUpdatedBy(1)
Expand Down Expand Up @@ -344,6 +344,29 @@ private void addTestingFileSystemItems(FileSystemRepository fileSystemRepository
.size(1232)
.typeId(VIDEO.getId())
.mimeType("video/mp4")
.build()),
fileSystemRepository.save(FileSystemEntity.builder()
.lastUpdatedBy(1)
.lastUpdated(Instant.now().getEpochSecond())
.ownerId(1)
.fileSystemId(8)
.isFile(false)
.path("/somefolder/folder")
.name("folder")
.size(1232)
.typeId(FOLDER.getId())
.itemIds(new long[]{9})
.build()),
fileSystemRepository.save(FileSystemEntity.builder()
.lastUpdatedBy(1)
.lastUpdated(Instant.now().getEpochSecond())
.ownerId(1)
.fileSystemId(9)
.isFile(true)
.name("anotherVideo.mp4")
.size(1232)
.typeId(VIDEO.getId())
.mimeType("video/mp4")
.build())
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ public class RestConfiguration {
public static final String BASE_API_URI = "v1";
public static final String AUTHORIZATION_BASIC_PREFIX = "Basic ";
public static final String AUTHORIZATION_BEARER_PREFIX = "Bearer ";
public static final String AUTHORIZATION_ACCESS_TOKEN_COOKIE = "token";
public static final String FS_BASE_URI = "/filesystem/";
public static final String FS_PATH_HEADER = "X-FF-PATH";
public static final String FS_CURRENT_ID_HEADER = "X-FF-CURRENT";
public static final String FS_DOWNLOAD_NAME_HEADER = "X-FF-NAME";
public static final String USER_BASE_URI = "/users/";
public static final String DEFAULT_ERROR_URI = "/error";
public static final long RUNTIME_USER_ID = 0;

private RestConfiguration() {
// Cannot be instantiated.
}
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
package de.filefighter.rest.domain.authentication;

import de.filefighter.rest.domain.common.InputSanitizerService;
import de.filefighter.rest.domain.common.Pair;
import de.filefighter.rest.domain.common.exceptions.RequestDidntMeetFormalRequirementsException;
import de.filefighter.rest.domain.token.business.AccessTokenBusinessService;
import de.filefighter.rest.domain.token.data.dto.AccessToken;
import de.filefighter.rest.domain.user.data.dto.User;
import de.filefighter.rest.domain.user.exceptions.UserNotAuthenticatedException;
import de.filefighter.rest.domain.user.group.Group;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;

import static de.filefighter.rest.configuration.RestConfiguration.AUTHORIZATION_BASIC_PREFIX;
import static de.filefighter.rest.configuration.RestConfiguration.AUTHORIZATION_BEARER_PREFIX;

@Service
@Log4j2
public class AuthenticationService implements AuthenticationServiceInterface {

private final AuthenticationBusinessService authenticationBusinessService;
Expand All @@ -37,6 +42,13 @@ public User bearerAuthenticationWithAccessToken(String accessTokenWithHeader) {
return authenticationBusinessService.authenticateUserWithAccessToken(accessToken);
}

@Override
public User cookieAuthenticationWithAccessToken(String accessTokenFromCookie) {
String sanitizedTokenString = inputSanitizerService.sanitizeTokenValue(accessTokenFromCookie);
AccessToken validAccessToken = accessTokenBusinessService.findAccessTokenByValue(sanitizedTokenString);
return authenticationBusinessService.authenticateUserWithAccessToken(validAccessToken);
}

@Override
public User bearerAuthenticationWithRefreshToken(String refreshTokenWithHeader) {
String sanitizedHeaderValue = inputSanitizerService.sanitizeRequestHeader(AUTHORIZATION_BEARER_PREFIX, refreshTokenWithHeader);
Expand All @@ -51,4 +63,25 @@ public void bearerAuthenticationWithAccessTokenAndGroup(String accessTokenWithHe
AccessToken validAccessToken = accessTokenBusinessService.findAccessTokenByValue(sanitizedTokenString);
authenticationBusinessService.authenticateUserWithAccessTokenAndGroup(validAccessToken, group);
}

@Override
public User authenticateUserWithCookieOrHeader(Pair<String, String> accessTokenValueOrHeader) {
String tokenFromCookie = accessTokenValueOrHeader.getFirst();
String tokenFromHeader = accessTokenValueOrHeader.getSecond();

User authenticatedUser = null;
try {
authenticatedUser = this.bearerAuthenticationWithAccessToken(tokenFromHeader);
} catch (RequestDidntMeetFormalRequirementsException ex) {
log.debug("Header {} was not valid. Trying cookies next...", tokenFromHeader);

try {
authenticatedUser = this.cookieAuthenticationWithAccessToken(tokenFromCookie);
} catch (RequestDidntMeetFormalRequirementsException exception) {
log.debug("Cookie {} was also not valid. Throwing Exception...", tokenFromCookie);
throw new UserNotAuthenticatedException("No user found with this authentication.");
}
}
return authenticatedUser;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.filefighter.rest.domain.authentication;

import de.filefighter.rest.domain.common.Pair;
import de.filefighter.rest.domain.user.data.dto.User;
import de.filefighter.rest.domain.user.group.Group;

Expand All @@ -8,7 +9,11 @@ public interface AuthenticationServiceInterface {

User bearerAuthenticationWithAccessToken(String accessTokenWithHeader);

User cookieAuthenticationWithAccessToken(String accessToken);

User bearerAuthenticationWithRefreshToken(String refreshTokenWithHeader);

void bearerAuthenticationWithAccessTokenAndGroup(String accessTokenWithHeader, Group group);

User authenticateUserWithCookieOrHeader(Pair<String, String> accessTokenValueOrHeader);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,31 @@
import de.filefighter.rest.domain.filesystem.data.persistence.FileSystemRepository;
import de.filefighter.rest.domain.filesystem.exceptions.FileSystemContentsNotAccessibleException;
import de.filefighter.rest.domain.filesystem.exceptions.FileSystemItemCouldNotBeDeletedException;
import de.filefighter.rest.domain.filesystem.exceptions.FileSystemItemCouldNotBeDownloadedException;
import de.filefighter.rest.domain.filesystem.exceptions.FileSystemItemNotFoundException;
import de.filefighter.rest.domain.filesystem.type.FileSystemType;
import de.filefighter.rest.domain.filesystem.type.FileSystemTypeRepository;
import de.filefighter.rest.domain.user.business.UserBusinessService;
import de.filefighter.rest.domain.user.data.dto.User;
import de.filefighter.rest.domain.user.exceptions.UserNotFoundException;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Log4j2
@Service
public class FileSystemBusinessService {

public static final String DELETION_FAILED_MSG = "Failed to delete FileSystemEntity with id ";
private final FileSystemRepository fileSystemRepository;
private final FileSystemHelperService fileSystemHelperService;
private final FileSystemTypeRepository fileSystemTypeRepository;
private final UserBusinessService userBusinessService;

public static final String DELETION_FAILED_MSG = "Failed to delete FileSystemEntity with id ";

public FileSystemBusinessService(FileSystemRepository fileSystemRepository, FileSystemHelperService fileSystemHelperService, FileSystemTypeRepository fileSystemTypeRepository, UserBusinessService userBusinessService) {
this.fileSystemRepository = fileSystemRepository;
this.fileSystemHelperService = fileSystemHelperService;
Expand Down Expand Up @@ -158,7 +159,7 @@ public List<FileSystemItem> deleteFileSystemItemById(long fsItemId, User authent
return returnList;
}

private RecursiveReturn recursivlyDeleteFileSystemEntity(FileSystemEntity parentEntity, User authenticatedUser, ArrayList<FileSystemItem> returnList) {
private Pair<Boolean, Boolean> recursivlyDeleteFileSystemEntity(FileSystemEntity parentEntity, User authenticatedUser, ArrayList<FileSystemItem> returnList) {
boolean foundNonDeletable = false;
boolean foundInvisible = false;

Expand All @@ -173,9 +174,9 @@ private RecursiveReturn recursivlyDeleteFileSystemEntity(FileSystemEntity parent
for (FileSystemEntity item : items) {
if (fileSystemHelperService.userIsAllowedToInteractWithFileSystemEntity(item, authenticatedUser, InteractionType.READ)) {
if (fileSystemHelperService.userIsAllowedToInteractWithFileSystemEntity(item, authenticatedUser, InteractionType.DELETE)) {
RecursiveReturn recursiveReturn = recursivlyDeleteFileSystemEntity(item, authenticatedUser, returnList);
foundInvisible = recursiveReturn.foundInvisibleEntities || foundInvisible;
foundNonDeletable = recursiveReturn.foundNonDeletableEntities || foundNonDeletable;
Pair<Boolean, Boolean> recursiveReturn = recursivlyDeleteFileSystemEntity(item, authenticatedUser, returnList);
foundInvisible = recursiveReturn.getFirst() || foundInvisible;
foundNonDeletable = recursiveReturn.getSecond() || foundNonDeletable;
} else {
// a entity could not be removed disable the deletion of the parent folder. (current Entity)
foundNonDeletable = true;
Expand Down Expand Up @@ -206,12 +207,57 @@ private RecursiveReturn recursivlyDeleteFileSystemEntity(FileSystemEntity parent
returnList.add(fileSystemHelperService.createDTO(parentEntity, authenticatedUser, null));
}
}
return new RecursiveReturn(foundInvisible, foundNonDeletable);
return new Pair<>(foundInvisible, foundNonDeletable);
}

@AllArgsConstructor
private static class RecursiveReturn {
private final boolean foundInvisibleEntities;
private final boolean foundNonDeletableEntities;
public Pair<List<FileSystemItem>, String> downloadFileSystemEntity(List<Long> ids, User authenticatedUser) {
// validate input and check for parent
if (ids.isEmpty())
return new Pair<>(new ArrayList<>(), null);

List<FileSystemEntity> uncheckedEntities = ids.stream()
.filter(Objects::nonNull)
.map(id -> {
FileSystemEntity possibleEntity = fileSystemRepository.findByFileSystemId(id);
if (null == possibleEntity)
throw new FileSystemItemCouldNotBeDownloadedException("FileSystemEntity does not exist or you are not allowed to see the entity.");

return possibleEntity;
}).collect(Collectors.toList());

List<FileSystemEntity> checkedEntities = uncheckedEntities.stream()
.filter(entity -> fileSystemHelperService.userIsAllowedToInteractWithFileSystemEntity(entity, authenticatedUser, InteractionType.READ))
.collect(Collectors.toList());

if (checkedEntities.size() != uncheckedEntities.size()) {
log.debug("Entities size and ids size does not match after validation. pre: {} / after: {}", uncheckedEntities.size(), checkedEntities.size());
throw new FileSystemItemCouldNotBeDownloadedException("FileSystemEntity does not exist or you are not allowed to see the entity.");
}

boolean allEntitiesAreInRoot = checkedEntities.stream().allMatch(entity -> !entity.isFile() && entity.getPath().equals("/"));
boolean singleEntity = checkedEntities.size() == 1;

List<FileSystemItem> returnList = new ArrayList<>();
String zipName;

if (singleEntity) {
FileSystemEntity currentEntity = checkedEntities.get(0);
zipName = fileSystemHelperService.getNameOfZipWhenOnlyOneEntityNeedsToBeDownloaded(currentEntity, allEntitiesAreInRoot);
fileSystemHelperService.getContentsOfFolderRecursivly(returnList, currentEntity, authenticatedUser, "", false);

} else {
zipName = fileSystemHelperService.getNameOfZipWhenMultipleEntitiesNeedToBeDownloaded(checkedEntities, allEntitiesAreInRoot);
if (!allEntitiesAreInRoot) {
long countOfDifferentParents = checkedEntities.stream()
.map(entity -> fileSystemHelperService.getParentNameEntity().apply(entity))
.distinct()
.count();

if (countOfDifferentParents != 1)
throw new FileSystemItemCouldNotBeDownloadedException("FileSystemEntity need to have a common parent entity.");
}
checkedEntities.forEach(entity -> fileSystemHelperService.getContentsOfFolderRecursivly(returnList, entity, authenticatedUser, "", true));
}
return new Pair<>(returnList, zipName);
}
}
Loading