Added SignalController with setup monitoring method; Added check for validity of zip file and xml file, extentions and sizes; Added SignalError enum with error codes and messages; Added dummy FailureAnswerGenerator;

This commit is contained in:
Mikhail Trofimov 2025-06-03 16:54:35 +03:00
parent 291ab1a206
commit c0f855c2a0
5 changed files with 168 additions and 1 deletions

View file

@ -0,0 +1,27 @@
package ru.nbch.credit_tracker.controller;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import ru.nbch.credit_tracker.facade.SignalFacade;
@RestController
@RequestMapping("/api/v1/signal")
public class SignalController {
private final SignalFacade signalFacade;
public SignalController(SignalFacade signalFacade) {
this.signalFacade = signalFacade;
}
@PostMapping("/set")
public ResponseEntity<String> setupMonitoring(@RequestParam("file") MultipartFile file) {
return signalFacade.setupMonitoring(file);
}
}

View file

@ -0,0 +1,26 @@
package ru.nbch.credit_tracker.enums;
import lombok.Getter;
@Getter
public enum SignalError {
ERROR_001("001", "Ошибка распаковки архива"),
ERROR_002("002", "Отсутствует обязательный элемент: "),
ERROR_003("003", "Элемент ClientId не соответствует формату XXXXXXXXX"),
ERROR_004("004", "Указан неуникальный Id в пакете: "),
ERROR_005("005", "Неверный логин или пароль"),
ERROR_006("006", "Доступ к услуге закрыт, обратитесь к курирующему менеджеру"),
ERROR_007("007", "В системе уже существует пакет с таким именем"),
ERROR_008("008", "PackageName не соответствует допустимому формату"),
ERROR_009("009", "Превышен допустимый размер пакета"),
ERROR_010("010", "Идентификатор субъекта (Id) не соответствует допустимому формату"),
ERROR_011("011", "Получен невалидный XML");
private final String code;
private final String message;
SignalError(String code, String message) {
this.code = code;
this.message = message;
}
}

View file

@ -0,0 +1,96 @@
package ru.nbch.credit_tracker.facade;
import lombok.Getter;
import lombok.Setter;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import ru.nbch.credit_tracker.enums.SignalError;
import ru.nbch.credit_tracker.service.FailureAnswerGenerator;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@Service
public class SignalFacade {
private static final long MAX_XML_FILE_SIZE = 2L * 1024 * 1024 * 1024;
private final FailureAnswerGenerator failureAnswerGenerator;
public SignalFacade(FailureAnswerGenerator failureAnswerGenerator) {
this.failureAnswerGenerator = failureAnswerGenerator;
}
public ResponseEntity<String> setupMonitoring(MultipartFile file) {
if (file.isEmpty()) {
return ResponseEntity.badRequest().body(failureAnswerGenerator.generateFailureAnswer(SignalError.ERROR_001));
}
if (!isZipFile(file)) {
return ResponseEntity.badRequest().body(failureAnswerGenerator.generateFailureAnswer(SignalError.ERROR_001));
}
try (ZipInputStream zipInputStream = new ZipInputStream(file.getInputStream())) {
int fileCount = 0;
ZipEntry xmlEntry = null;
ZipEntry entry = zipInputStream.getNextEntry();
while (entry != null) {
if (!entry.isDirectory()) {
fileCount++;
if (fileCount > 1) { // Архив должен содержать ровно один XML-файл
return ResponseEntity.badRequest().body(failureAnswerGenerator.generateFailureAnswer(SignalError.ERROR_001));
}
if (!entry.getName().toLowerCase().endsWith(".xml")) { // Файл должен быть с расширением xml
return ResponseEntity.badRequest().body(failureAnswerGenerator.generateFailureAnswer(SignalError.ERROR_001));
}
xmlEntry = entry;
} else {
return ResponseEntity.badRequest().body(failureAnswerGenerator.generateFailureAnswer(SignalError.ERROR_001)); // Архив должен содержать ровно один XML-файл. Никаких доп директорий
}
zipInputStream.closeEntry();
entry = zipInputStream.getNextEntry();
}
if (fileCount == 0) { // Архив должен содержать ровно один XML-файл
return ResponseEntity.badRequest().body(failureAnswerGenerator.generateFailureAnswer(SignalError.ERROR_001));
}
if (xmlEntry.getSize() > MAX_XML_FILE_SIZE) { // максимально 2 Гб до запаковки
return ResponseEntity.badRequest().body(failureAnswerGenerator.generateFailureAnswer(SignalError.ERROR_009));
}
AuthInfoData authInfoData = parseAuthInfo(zipInputStream); // TODO authorize
// TODO process xml file
} catch (IOException e) {
return ResponseEntity.internalServerError().body(failureAnswerGenerator.generateFailureAnswer(SignalError.ERROR_001));
}
return ResponseEntity.ok().body("OK"); // TODO generate success response
}
private boolean isZipFile(MultipartFile file) {
return file.getContentType() != null &&
(file.getContentType().equals("application/zip") || file.getContentType().equals("application/x-zip-compressed")) ||
file.getOriginalFilename() != null && file.getOriginalFilename().toLowerCase().endsWith(".zip");
}
private AuthInfoData parseAuthInfo(ZipInputStream zipInputStream) throws IOException {
return new AuthInfoData();
}
@Getter
@Setter
private static class AuthInfoData {
private String username;
private String password;
}
}

View file

@ -0,0 +1,13 @@
package ru.nbch.credit_tracker.service;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.enums.SignalError;
// TODO generate xml error file (mb return path ?)
@Service
public class FailureAnswerGenerator {
public String generateFailureAnswer(SignalError error) {
return error.getCode() + ": " + error.getMessage();
}
}

View file

@ -18,3 +18,8 @@ ct.scoring-data-source-settings.driver=com.ibm.db2.jcc.DB2Driver
ct.scoring-data-source-settings.url=jdbc:db2://10.230.227.101:2668/cprosd22:currentSchema=TEST_2_INDIC;
ct.scoring-data-source-settings.username=tester
ct.scoring-data-source-settings.password=tester
# TODO Increase file size limit if needed
#spring.servlet.multipart.max-file-size=10MB
#spring.servlet.multipart.max-request-size=10MB