Commit c64ae23e authored by Matija Obreza's avatar Matija Obreza

Merge branch '30-blacklist-originalfilenames-in-repository' into 'master'

Resolve "Blacklist originalFilenames in Repository"

Closes #30

See merge request !34
parents e25f6d2c f85c65ec
Pipeline #11855 passed with stage
in 1 minute and 21 seconds
...@@ -26,6 +26,7 @@ import java.util.ArrayList; ...@@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Pattern;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
...@@ -56,6 +57,7 @@ import org.slf4j.Logger; ...@@ -56,6 +57,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
...@@ -106,7 +108,21 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea ...@@ -106,7 +108,21 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
/** The ACL service */ /** The ACL service */
@Autowired @Autowired
private CustomAclService aclService; private CustomAclService aclService;
/** The blacklist file names regexp */
@Value("${repository.blacklist.filename}")
private String blacklistFileNameRegex;
/** The blacklist folder names regexp */
@Value("${repository.blacklist.foldername}")
private String blacklistFolderNameRegex;
/** The pattern of blacklist file names */
private Pattern blacklistFileNamePattern;
/** The pattern of blacklist folder names */
private Pattern blacklistFolderNamePattern;
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
...@@ -114,6 +130,8 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea ...@@ -114,6 +130,8 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
addMissingHashSums(); addMissingHashSums();
blacklistFileNamePattern = Pattern.compile(blacklistFileNameRegex, Pattern.CASE_INSENSITIVE);
blacklistFolderNamePattern = Pattern.compile(blacklistFolderNameRegex, Pattern.CASE_INSENSITIVE);
} }
private <T extends RepositoryFile> T lazyLoad(T repositoryFile) { private <T extends RepositoryFile> T lazyLoad(T repositoryFile) {
...@@ -173,6 +191,9 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea ...@@ -173,6 +191,9 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
if ((originalFilename == null) || (contentType == null) || (bytes == null)) { if ((originalFilename == null) || (contentType == null) || (bytes == null)) {
throw new InvalidRepositoryFileDataException(); throw new InvalidRepositoryFileDataException();
} }
if (blacklistFileNamePattern.matcher(originalFilename).find()) {
throw new InvalidRepositoryFileDataException("Invalid file name: " + originalFilename);
}
if (contentType.startsWith("image/")) { if (contentType.startsWith("image/")) {
// Handle images differently // Handle images differently
...@@ -244,6 +265,9 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea ...@@ -244,6 +265,9 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
if ((originalFilename == null) || (contentType == null) || (bytes == null)) { if ((originalFilename == null) || (contentType == null) || (bytes == null)) {
throw new InvalidRepositoryFileDataException(); throw new InvalidRepositoryFileDataException();
} }
if (blacklistFileNamePattern.matcher(originalFilename).find()) {
throw new InvalidRepositoryFileDataException("Invalid file name: " + originalFilename);
}
RepositoryImage repositoryImage = new RepositoryImage(); RepositoryImage repositoryImage = new RepositoryImage();
...@@ -884,7 +908,11 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea ...@@ -884,7 +908,11 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
} }
return null; return null;
} else { } else {
PathValidator.checkValidFolderName(folderPath.getFileName().toString()); String folderNameToCheck = folderPath.getFileName().toString();
if (blacklistFolderNamePattern.matcher(folderNameToCheck).find()) {
throw new InvalidRepositoryPathException("Invalid folder name: " + folderNameToCheck);
}
PathValidator.checkValidFolderName(folderNameToCheck);
} }
RepositoryFolder folder = folderRepository.findByPath(folderPath.toString()); RepositoryFolder folder = folderRepository.findByPath(folderPath.toString());
...@@ -931,7 +959,11 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea ...@@ -931,7 +959,11 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
} }
return null; return null;
} else { } else {
PathValidator.checkValidFolderName(folderPath.getFileName().toString()); String folderNameToCheck = folderPath.getFileName().toString();
if (blacklistFolderNamePattern.matcher(folderNameToCheck).find()) {
throw new InvalidRepositoryPathException("Invalid folder name: " + folderNameToCheck);
}
PathValidator.checkValidFolderName(folderNameToCheck);
} }
RepositoryFolder folder = folderRepository.findByPath(folderPath.toString()); RepositoryFolder folder = folderRepository.findByPath(folderPath.toString());
......
...@@ -18,4 +18,8 @@ ...@@ -18,4 +18,8 @@
s3.accessKey= s3.accessKey=
s3.secretKey= s3.secretKey=
s3.bucket= s3.bucket=
s3.region= s3.region=
\ No newline at end of file
# Regular expressions to blacklist file and folder names
repository.blacklist.filename=^(\\.|\\~)|^Thumbs.db$
repository.blacklist.foldername=(^\\.)|[~!\\/]
...@@ -279,6 +279,48 @@ public class FileRepositoryAddTest extends RepositoryServiceTest { ...@@ -279,6 +279,48 @@ public class FileRepositoryAddTest extends RepositoryServiceTest {
repositoryService.addFile(Paths.get("/invalidpath/ orhere/"), "originalFilename.txt", "contentType", FileRepositoryAddTest.EMPTY_BYTES, null); repositoryService.addFile(Paths.get("/invalidpath/ orhere/"), "originalFilename.txt", "contentType", FileRepositoryAddTest.EMPTY_BYTES, null);
} }
/**
* Filename mustn't start with . test.
*
* @throws InvalidRepositoryPathException the invalid repository path exception
* @throws InvalidRepositoryFileDataException the invalid repository file data
* exception
* @throws IOException
*/
@Test(expected = InvalidRepositoryFileDataException.class)
public void invalidDotAtTheStartOfFilename() throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
String invalidFilename = ".orignalFilename.txt";
repositoryService.addFile(Paths.get("/valid/path"), invalidFilename, null, FileRepositoryAddTest.EMPTY_BYTES, null);
}
/**
* Filename mustn't start with ~ test.
*
* @throws InvalidRepositoryPathException the invalid repository path exception
* @throws InvalidRepositoryFileDataException the invalid repository file data
* exception
* @throws IOException
*/
@Test(expected = InvalidRepositoryFileDataException.class)
public void invalidTildeAtTheStartOfFilename() throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
String invalidFilename = "~orignalFilename.txt";
repositoryService.addFile(Paths.get("/valid/path"), invalidFilename, null, FileRepositoryAddTest.EMPTY_BYTES, null);
}
/**
* Filename mustn't be Thumbs.db test.
*
* @throws InvalidRepositoryPathException the invalid repository path exception
* @throws InvalidRepositoryFileDataException the invalid repository file data
* exception
* @throws IOException
*/
@Test(expected = InvalidRepositoryFileDataException.class)
public void invalidFilenameFromBlacklist() throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
String invalidFilename = "Thumbs.db";
repositoryService.addFile(Paths.get("/valid/path"), invalidFilename, null, FileRepositoryAddTest.EMPTY_BYTES, null);
}
/** /**
* Check that SHA1 and MD5 sums are generated on add * Check that SHA1 and MD5 sums are generated on add
* *
......
...@@ -111,22 +111,6 @@ public class FileRepositoryExtensionTest extends RepositoryServiceTest { ...@@ -111,22 +111,6 @@ public class FileRepositoryExtensionTest extends RepositoryServiceTest {
fileRepoService.removeFile(repoFile); fileRepoService.removeFile(repoFile);
} }
/**
* Extension dot file is null on add.
*
* @throws NoSuchRepositoryFileException the no such repository file exception
* @throws InvalidRepositoryPathException the invalid repository path exception
* @throws InvalidRepositoryFileDataException the invalid repository file data
* exception
* @throws IOException Signals that an I/O exception has occurred.
*/
@Test
public void extensionDotFileIsNullOnAdd() throws NoSuchRepositoryFileException, InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
final RepositoryFile repoFile = fileRepoService.addFile(initialPath, ".gitignore", initialContentType, EMPTY_BYTES, null);
FileRepositoryTestUtil.checkFile(repoFile, initialPath, ".gitignore", null, initialContentType);
fileRepoService.removeFile(repoFile);
}
/** /**
* Extension dot file is null on update. * Extension dot file is null on update.
* *
......
...@@ -121,6 +121,24 @@ public class RepositoryFolderTest extends RepositoryServiceTest { ...@@ -121,6 +121,24 @@ public class RepositoryFolderTest extends RepositoryServiceTest {
repositoryService.renamePath(path, newPath); repositoryService.renamePath(path, newPath);
} }
@Test(expected = InvalidRepositoryPathException.class)
public void failDotAtTheStartOfFolderName() throws InvalidRepositoryPathException {
Path path = Paths.get("/bbbb/cccc/dddd/.eeee");
repositoryService.ensureFolder(path);
}
@Test(expected = InvalidRepositoryPathException.class)
public void failTildeAtTheStartOfFolderName() throws InvalidRepositoryPathException {
Path path = Paths.get("/bbbb/cccc/dddd/~eeee");
repositoryService.ensureFolder(path);
}
@Test(expected = InvalidRepositoryPathException.class)
public void failExclamationMarkAtTheStartOfFolderName() throws InvalidRepositoryPathException {
Path path = Paths.get("/bbbb/cccc/dddd/!eeee");
repositoryService.ensureFolder(path);
}
@Test(expected = InvalidRepositoryPathException.class) @Test(expected = InvalidRepositoryPathException.class)
public void failRenamePathToExisting2() throws InvalidRepositoryPathException { public void failRenamePathToExisting2() throws InvalidRepositoryPathException {
Path path = Paths.get("/bbbb/cccc/dddd/eeee"); Path path = Paths.get("/bbbb/cccc/dddd/eeee");
......
...@@ -83,6 +83,48 @@ public class RepositoryImageAddTest { ...@@ -83,6 +83,48 @@ public class RepositoryImageAddTest {
fileRepoService.removeFile(repoImage); fileRepoService.removeFile(repoImage);
} }
/**
* Filename mustn't start with . test.
*
* @throws InvalidRepositoryPathException the invalid repository path exception
* @throws InvalidRepositoryFileDataException the invalid repository file data
* exception
* @throws IOException
*/
@Test(expected = InvalidRepositoryFileDataException.class)
public void invalidDotAtTheStartOfFilename() throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
String invalidFilename = "." + initialOriginalFilename;
fileRepoService.addImage(initialPath, invalidFilename, initialContentType, EMPTY_BYTES, null);
}
/**
* Filename mustn't start with ~ test.
*
* @throws InvalidRepositoryPathException the invalid repository path exception
* @throws InvalidRepositoryFileDataException the invalid repository file data
* exception
* @throws IOException
*/
@Test(expected = InvalidRepositoryFileDataException.class)
public void invalidTildeAtTheStartOfFilename() throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
String invalidFilename = "~" + initialOriginalFilename;
fileRepoService.addImage(initialPath, invalidFilename, initialContentType, EMPTY_BYTES, null);
}
/**
* Filename mustn't be Thumbs.db test.
*
* @throws InvalidRepositoryPathException the invalid repository path exception
* @throws InvalidRepositoryFileDataException the invalid repository file data
* exception
* @throws IOException
*/
@Test(expected = InvalidRepositoryFileDataException.class)
public void invalidFilenameFromBlacklist() throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
String invalidFilename = "Thumbs.db";
fileRepoService.addImage(initialPath, invalidFilename, initialContentType, EMPTY_BYTES, null);
}
/** /**
* Test metadata submission to image repository. * Test metadata submission to image repository.
* *
......
...@@ -29,3 +29,7 @@ s3.secretKey= ...@@ -29,3 +29,7 @@ s3.secretKey=
s3.bucket= s3.bucket=
s3.prefix= s3.prefix=
s3.region= s3.region=
# Regular expressions to blacklist file and folder names
repository.blacklist.filename=^(\\.|\\~)|^Thumbs.db$
repository.blacklist.foldername=(^\\.)|[~!\\/]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment