TraceAttachmentServiceImpl.java
package fr.avenirsesr.portfolio.file.domain.service;
import fr.avenirsesr.portfolio.file.domain.exception.FileSizeTooBigException;
import fr.avenirsesr.portfolio.file.domain.model.TraceAttachment;
import fr.avenirsesr.portfolio.file.domain.model.shared.EFileType;
import fr.avenirsesr.portfolio.file.domain.model.shared.FileResource;
import fr.avenirsesr.portfolio.file.domain.port.input.TraceAttachmentService;
import fr.avenirsesr.portfolio.file.domain.port.output.repository.TraceAttachmentRepository;
import fr.avenirsesr.portfolio.file.domain.port.output.service.FileStorageService;
import fr.avenirsesr.portfolio.trace.domain.exception.TraceNotFoundException;
import fr.avenirsesr.portfolio.trace.domain.model.Trace;
import fr.avenirsesr.portfolio.trace.domain.port.input.TraceService;
import fr.avenirsesr.portfolio.trace.domain.port.output.repository.TraceRepository;
import fr.avenirsesr.portfolio.user.domain.exception.UserNotAuthorizedException;
import fr.avenirsesr.portfolio.user.domain.model.Student;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import java.util.stream.Stream;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@AllArgsConstructor
public class TraceAttachmentServiceImpl implements TraceAttachmentService {
private final TraceAttachmentRepository traceAttachmentRepository;
private final TraceRepository traceRepository;
private final FileStorageService fileStorageService;
private final TraceService traceService;
@Override
public TraceAttachment uploadTraceAttachment(
Student student, UUID traceId, String fileName, String mimeType, long size, byte[] content)
throws IOException {
var trace = traceRepository.findById(traceId).orElseThrow(TraceNotFoundException::new);
var allTraceAttachments = traceAttachmentRepository.findByTrace(trace);
if (!trace.getUser().equals(student.getUser())) {
throw new UserNotAuthorizedException();
}
try {
var fileType = EFileType.fromMimeType(mimeType);
if (fileType.getSizeLimit().isLessThan(size)) {
throw new FileSizeTooBigException();
}
var fileResource = new FileResource(UUID.randomUUID(), fileName, fileType, size, content);
var uri = fileStorageService.upload(fileResource);
var newAttachment = createAttachment(student, allTraceAttachments, fileResource, trace, uri);
traceAttachmentRepository.saveAll(
Stream.concat(allTraceAttachments.stream(), Stream.of(newAttachment)).toList());
log.info("New trace attachment saved: {}", newAttachment);
return newAttachment;
} catch (Exception e) {
log.error("Failed to upload trace attachment for trace {}", trace, e);
if (allTraceAttachments.isEmpty()) {
traceService.deleteById(student.getUser(), trace.getId());
}
throw e;
}
}
private static TraceAttachment createAttachment(
Student student,
List<TraceAttachment> allTraceAttachments,
FileResource fileResource,
Trace trace,
String uri) {
var version =
allTraceAttachments.stream()
.map(TraceAttachment::getVersion)
.max(Integer::compareTo)
.orElse(0)
+ 1;
allTraceAttachments.forEach(a -> a.setActiveVersion(false));
return TraceAttachment.create(
fileResource.id(),
trace,
fileResource.fileName(),
fileResource.fileType(),
fileResource.size(),
version,
true,
uri,
student.getUser());
}
}