DocumentUploadController.java
package com.tdmconsult.ete.api;
import com.tdmconsult.ete.configuration.CustomJwtAuthenticationToken.CustomUserPrincipal;
import com.tdmconsult.ete.documents.DocumentAuthorizationService;
import com.tdmconsult.ete.documents.DocumentCreationRequestDto;
import com.tdmconsult.ete.documents.DocumentDto;
import com.tdmconsult.ete.documents.DocumentIndexDto;
import com.tdmconsult.ete.documents.DocumentUpdateRequestDto;
import com.tdmconsult.ete.documents.UploadDocumentService;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@Tag(name = "NAme", description = "Description")
@RestController
@RequestMapping(value = "/api/documents", produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
public class DocumentUploadController {
private final UploadDocumentService uploadDocumentService;
private final DocumentAuthorizationService documentAuthorizationService;
@PreAuthorize("@documentAuthorizationService.isAllowedToCreateDocument(principal)")
@PostMapping(consumes = "multipart/form-data")
public ResponseEntity<Void> createUploadDocument(
final @Valid DocumentCreationRequestDto requestDto,
final @AuthenticationPrincipal CustomUserPrincipal userDetails) throws IOException {
final var publicId = uploadDocumentService.createUploadDocument(requestDto, userDetails);
return ResponseEntity.created(URI.create("/api/documents/" + publicId)).build();
}
@PreAuthorize("@documentAuthorizationService.isAllowedToListDocuments(principal)")
@GetMapping
public ResponseEntity<List<DocumentIndexDto>> getUploadDocumentIndex(
final @AuthenticationPrincipal CustomUserPrincipal userDetails) throws IOException {
final var index = uploadDocumentService.getUploadDocumentIndex(userDetails);
return ResponseEntity.ok(index);
}
@PreAuthorize("@documentAuthorizationService.isAllowedToShowDocument(#publicId, principal)")
@GetMapping("{publicId}")
public ResponseEntity<DocumentDto> getUploadDocument(
final @PathVariable String publicId,
final @RequestParam(required = false) Boolean excludeContent) {
final var document = uploadDocumentService.getUploadDocument(publicId, excludeContent);
return ResponseEntity.ok(document);
}
@PreAuthorize("@documentAuthorizationService.isAllowedToEditDocument(#publicId, principal)")
@PutMapping(value = "{publicId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<DocumentDto> updateUploadDocument(
final @PathVariable String publicId,
final @RequestPart @Valid DocumentUpdateRequestDto requestDto,
final @RequestParam(required = false) Map<String, MultipartFile> attachmentsByPublicId,
final @AuthenticationPrincipal CustomUserPrincipal userDetails) throws IOException {
uploadDocumentService.updateUploadDocument(publicId, requestDto, attachmentsByPublicId, userDetails);
return ResponseEntity.noContent().build();
}
@PreAuthorize("@documentAuthorizationService.isAllowedToEditDocument(#publicId, principal)")
@DeleteMapping("{publicId}")
public ResponseEntity<DocumentDto> deleteDocument(
final @PathVariable String publicId) throws IOException {
uploadDocumentService.deleteUploadDocument(publicId);
return ResponseEntity.noContent().build();
}
@PreAuthorize("@documentAuthorizationService.isAllowedToShowDocument(#publicId, principal)")
@GetMapping("{publicId}/attachments/{attachmentPublicId}")
public ResponseEntity<Resource> downloadAttachment(
final @PathVariable String publicId,
final @PathVariable String attachmentPublicId) {
final var attachment = uploadDocumentService.getAttachment(publicId, attachmentPublicId);
final var resource = new ByteArrayResource(attachment.fileData());
final var mediaType = MediaType.parseMediaType(attachment.fileContentType());
return ResponseEntity.ok()
// Signallisiert dem Browser, dass es ein Download ist und setzt den Dateinamen
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + attachment.fileName() + "\"")
// Teilt dem Browser die genaue Dateigröße in Bytes mit
.contentLength(attachment.fileSize())
// Reines Binärformat (verhindert, dass der Browser versucht es als JSON zu interpretieren)
.contentType(mediaType)
.body(resource);
}
}