Skip to content

Commit

Permalink
Merge pull request #59 from CaritasDeutschland/feat-mime-time-detecti…
Browse files Browse the repository at this point in the history
…on-of-uploaded-files

feat: detect mime type of uploaded file
  • Loading branch information
hill-daniel authored Mar 1, 2022
2 parents f359734 + ff7d06f commit 2f1646c
Show file tree
Hide file tree
Showing 12 changed files with 367 additions and 108 deletions.
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@
<version>${log4j.version}</version>
</dependency>

<!-- Tika -->
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>2.3.0</version>
</dependency>

<!-- Test scope dependencies -->
<dependency>
<groupId>com.h2database</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@

import de.caritas.cob.uploadservice.api.exception.KeycloakException;
import de.caritas.cob.uploadservice.api.helper.AuthenticatedUser;
import de.caritas.cob.uploadservice.media.MimeTypeDetector;
import de.caritas.cob.uploadservice.media.TikaMimeTypeDetector;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import org.apache.tika.Tika;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.keycloak.representations.AccessToken;
Expand Down Expand Up @@ -166,4 +169,9 @@ public Executor taskExecutor() {
public MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}

@Bean
public MimeTypeDetector mimeTypeDetector() {
return new TikaMimeTypeDetector(new Tika());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@

import org.springframework.web.multipart.MultipartException;

/** Exception for wrong file type (upload) */
/**
* Exception for wrong file type (upload)
*/
public class InvalidFileTypeException extends MultipartException {

public InvalidFileTypeException(String msg) {
super(msg);
}

/**
* Exception for wrong file type (upload).
*
* @param msg String
* @param msg String
* @param cause Throwable
*/
public InvalidFileTypeException(String msg, Throwable cause) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import de.caritas.cob.uploadservice.api.helper.AuthenticatedUserHelper;
import de.caritas.cob.uploadservice.api.helper.RocketChatUploadParameterEncrypter;
import de.caritas.cob.uploadservice.api.helper.RocketChatUploadParameterSanitizer;
import de.caritas.cob.uploadservice.api.service.FileService;
import de.caritas.cob.uploadservice.api.service.LiveEventNotificationService;
import de.caritas.cob.uploadservice.api.service.LogService;
import de.caritas.cob.uploadservice.api.service.RocketChatService;
Expand All @@ -35,6 +36,7 @@ public class UploadFacade {
private final @NonNull UploadTrackingService uploadTrackingService;
private final @NonNull StatisticsService statisticsService;
private final @NonNull AuthenticatedUser authenticatedUser;
private final @NonNull FileService fileService;

/**
* Upload a file with a message to a Rocket.Chat room. The message and the description are
Expand All @@ -43,7 +45,7 @@ public class UploadFacade {
* <p>If the statistics function is enabled, the assignment of the enquired is processed as
* statistical event.
*
* @param rocketChatCredentials {@link RocketChatCredentials} container
* @param rocketChatCredentials {@link RocketChatCredentials} container
* @param rocketChatUploadParameter {@link RocketChatUploadParameter} container
*/
public void uploadFileToRoom(
Expand Down Expand Up @@ -80,7 +82,7 @@ private UserRole resolveUserRole(AuthenticatedUser authenticatedUser) {
* Upload a file with a message to a Rocket.Chat feedback room. The message and the description
* are encrypted before it is sent to Rocket.Chat.
*
* @param rocketChatCredentials {@link RocketChatCredentials} container
* @param rocketChatCredentials {@link RocketChatCredentials} container
* @param rocketChatUploadParameter {@link RocketChatUploadParameter} container
*/
public void uploadFileToFeedbackRoom(
Expand All @@ -104,6 +106,7 @@ private void sanitizeAndEncryptParametersAndUploadToRocketChatRoom(
RocketChatUploadParameter rocketChatUploadParameter) {

rocketChatUploadParameterSanitizer.sanitize(rocketChatUploadParameter);
fileService.verifyMimeType(rocketChatUploadParameter.getFile());
RocketChatUploadParameter encryptedRocketChatUploadParameter;
try {
encryptedRocketChatUploadParameter =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package de.caritas.cob.uploadservice.api.service;

import static java.util.Objects.isNull;

import de.caritas.cob.uploadservice.api.exception.InvalidFileTypeException;
import de.caritas.cob.uploadservice.api.exception.httpresponses.InternalServerErrorException;
import de.caritas.cob.uploadservice.media.MimeTypeDetector;
import java.util.Optional;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

@RequiredArgsConstructor
@Service
public class FileService {

private final MimeTypeDetector mimeTypeDetector;
@Value("#{${mime-type-whitelist}}")
private final Set<String> mimeTypeWhitelist;

public void verifyMimeType(MultipartFile multipartFile) {
if (isNull(multipartFile)) {
return;
}

Optional<String> mimeType;
try {
mimeType = mimeTypeDetector.detect(multipartFile.getInputStream());
} catch (Exception e) {
throw new InternalServerErrorException(
"failed to detect mime type of file " + multipartFile.getOriginalFilename(), e,
LogService::logInternalServerError);
}
if (mimeType.isEmpty() || !mimeTypeWhitelist.contains(mimeType.get())) {
throw new InvalidFileTypeException(
"invalid mime type " + mimeType + " of file " + multipartFile.getOriginalFilename());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package de.caritas.cob.uploadservice.media;

import java.io.InputStream;
import java.util.Optional;

public interface MimeTypeDetector {

Optional<String> detect(InputStream input);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package de.caritas.cob.uploadservice.media;

import static java.util.Objects.isNull;

import java.io.InputStream;
import java.util.Optional;
import org.apache.tika.Tika;

public class TikaMimeTypeDetector implements MimeTypeDetector {

private final Tika tika;

public TikaMimeTypeDetector(Tika tika) {
this.tika = tika;
}

@Override
public Optional<String> detect(InputStream input) {
if (isNull(input)) {
return Optional.empty();
}
try {
return Optional.ofNullable(tika.detect(input));
} catch (Exception e) {
throw new RuntimeException("failed to detect media type from input stream", e);
}
}
}
3 changes: 3 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,6 @@ spring.rabbitmq.password=admin
# Statistics
statistics.enabled=false
statistics.rabbitmq.exchange.name=statistics.topic

# MIME type whitelist for file upload. Supports png, jpeg, doc, docx and pdf.
mime-type-whitelist={'image/png','image/jpeg','application/msword','application/vnd.openxmlformats-officedocument.wordprocessingml.document','application/pdf','application/x-tika-ooxml'}
Loading

0 comments on commit 2f1646c

Please sign in to comment.