fixes for user permissions (#892)
This commit is contained in:
parent
82c4e9cf41
commit
121af0501a
12 changed files with 163 additions and 152 deletions
|
@ -33,6 +33,7 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
|
||||||
curl \
|
curl \
|
||||||
openjdk17-jre \
|
openjdk17-jre \
|
||||||
su-exec \
|
su-exec \
|
||||||
|
shadow \
|
||||||
# Doc conversion
|
# Doc conversion
|
||||||
libreoffice@testing \
|
libreoffice@testing \
|
||||||
# OCR MY PDF (unpaper for descew and other advanced featues)
|
# OCR MY PDF (unpaper for descew and other advanced featues)
|
||||||
|
@ -52,8 +53,8 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
|
||||||
chmod +x /scripts/init.sh && \
|
chmod +x /scripts/init.sh && \
|
||||||
# User permissions
|
# User permissions
|
||||||
addgroup -S stirlingpdfgroup && adduser -S stirlingpdfuser -G stirlingpdfgroup && \
|
addgroup -S stirlingpdfgroup && adduser -S stirlingpdfuser -G stirlingpdfgroup && \
|
||||||
chown -R stirlingpdfuser:stirlingpdfgroup $HOME /scripts /usr/share/fonts/opentype/noto /configs /customFiles /pipeline && \
|
chown -R stirlingpdfuser:stirlingpdfgroup $HOME /scripts /usr/share/fonts/opentype/noto /configs /customFiles /pipeline && \
|
||||||
chown stirlingpdfuser:stirlingpdfgroup /app.jar
|
chown stirlingpdfuser:stirlingpdfgroup /app.jar
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,10 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
|
||||||
tini \
|
tini \
|
||||||
bash \
|
bash \
|
||||||
curl \
|
curl \
|
||||||
|
gcc \
|
||||||
openjdk17-jre \
|
openjdk17-jre \
|
||||||
su-exec \
|
su-exec \
|
||||||
|
shadow \
|
||||||
# Doc conversion
|
# Doc conversion
|
||||||
libreoffice@testing \
|
libreoffice@testing \
|
||||||
# python and pip
|
# python and pip
|
||||||
|
|
|
@ -30,6 +30,7 @@ RUN mkdir /configs /logs /customFiles && \
|
||||||
bash \
|
bash \
|
||||||
curl \
|
curl \
|
||||||
su-exec \
|
su-exec \
|
||||||
|
shadow \
|
||||||
openjdk17-jre && \
|
openjdk17-jre && \
|
||||||
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
|
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
|
||||||
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
|
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
|
||||||
|
|
|
@ -12,7 +12,7 @@ plugins {
|
||||||
import com.github.jk1.license.render.*
|
import com.github.jk1.license.render.*
|
||||||
|
|
||||||
group = 'stirling.software'
|
group = 'stirling.software'
|
||||||
version = '0.22.0'
|
version = '0.22.1'
|
||||||
sourceCompatibility = '17'
|
sourceCompatibility = '17'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
|
|
@ -21,6 +21,9 @@ services:
|
||||||
environment:
|
environment:
|
||||||
DOCKER_ENABLE_SECURITY: "true"
|
DOCKER_ENABLE_SECURITY: "true"
|
||||||
SECURITY_ENABLELOGIN: "true"
|
SECURITY_ENABLELOGIN: "true"
|
||||||
|
PUID: 1002
|
||||||
|
GGID: 1002
|
||||||
|
UMASK: "022"
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
SYSTEM_DEFAULTLOCALE: en-US
|
||||||
UI_APPNAME: Stirling-PDF
|
UI_APPNAME: Stirling-PDF
|
||||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest with Security
|
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest with Security
|
||||||
|
|
|
@ -5,19 +5,18 @@ if [ ! -z "$PUID" ] && [ "$PUID" != "$(id -u stirlingpdfuser)" ]; then
|
||||||
usermod -o -u "$PUID" stirlingpdfuser
|
usermod -o -u "$PUID" stirlingpdfuser
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -z "$PGID" ] && [ "$PGID" != "$(id -g stirlingpdfgroup)" ]; then
|
if [ ! -z "$PGID" ] && [ "$PGID" != "$(getent group stirlingpdfgroup | cut -d: -f3)" ]; then
|
||||||
groupmod -o -g "$PGID" stirlingpdfgroup
|
groupmod -o -g "$PGID" stirlingpdfgroup
|
||||||
fi
|
fi
|
||||||
umask "$UMASK"
|
umask "$UMASK"
|
||||||
|
|
||||||
echo "Setting permissions and ownership for necessary directories..."
|
echo "Setting permissions and ownership for necessary directories..."
|
||||||
chown -R stirlingpdfuser:stirlingpdfgroup /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles
|
chown -R stirlingpdfuser:stirlingpdfgroup $HOME /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles /pipeline /app.jar
|
||||||
chmod -R 755 /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles
|
chmod -R 755 /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles /pipeline /app.jar
|
||||||
if [[ "$INSTALL_BOOK_AND_ADVANCED_HTML_OPS" == "true" ]]; then
|
if [[ "$INSTALL_BOOK_AND_ADVANCED_HTML_OPS" == "true" ]]; then
|
||||||
apk add --no-cache calibre@testing
|
apk add --no-cache calibre@testing
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
/scripts/download-security-jar.sh
|
/scripts/download-security-jar.sh
|
||||||
|
|
||||||
# Run the main command
|
# Run the main command
|
||||||
|
|
|
@ -13,20 +13,20 @@ if [ -d /usr/share/tesseract-ocr/5/tessdata ]; then
|
||||||
cp -r /usr/share/tesseract-ocr/5/tessdata/* /usr/share/tessdata || true;
|
cp -r /usr/share/tesseract-ocr/5/tessdata/* /usr/share/tessdata || true;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Update the user and group IDs as per environment variables
|
# Update the user and group IDs as per environment variables
|
||||||
if [ ! -z "$PUID" ] && [ "$PUID" != "$(id -u stirlingpdfuser)" ]; then
|
if [ ! -z "$PUID" ] && [ "$PUID" != "$(id -u stirlingpdfuser)" ]; then
|
||||||
usermod -o -u "$PUID" stirlingpdfuser
|
usermod -o -u "$PUID" stirlingpdfuser
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -z "$PGID" ] && [ "$PGID" != "$(id -g stirlingpdfgroup)" ]; then
|
|
||||||
|
if [ ! -z "$PGID" ] && [ "$PGID" != "$(getent group stirlingpdfgroup | cut -d: -f3)" ]; then
|
||||||
groupmod -o -g "$PGID" stirlingpdfgroup
|
groupmod -o -g "$PGID" stirlingpdfgroup
|
||||||
fi
|
fi
|
||||||
umask "$UMASK"
|
umask "$UMASK"
|
||||||
|
|
||||||
echo "Setting permissions and ownership for necessary directories..."
|
echo "Setting permissions and ownership for necessary directories..."
|
||||||
chown -R stirlingpdfuser:stirlingpdfgroup /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles
|
chown -R stirlingpdfuser:stirlingpdfgroup $HOME /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles /pipeline /app.jar
|
||||||
chmod -R 755 /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles
|
chmod -R 755 /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles /pipeline /app.jar
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,5 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
|
||||||
return user.isPresent()
|
return user.isPresent()
|
||||||
&& user.get().getAuthorities().stream()
|
&& user.get().getAuthorities().stream()
|
||||||
.anyMatch(authority -> "ROLE_DEMO_USER".equals(authority.getAuthority()));
|
.anyMatch(authority -> "ROLE_DEMO_USER".equals(authority.getAuthority()));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,10 +66,11 @@ public class SecurityConfiguration {
|
||||||
sessionManagement ->
|
sessionManagement ->
|
||||||
sessionManagement
|
sessionManagement
|
||||||
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
|
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
|
||||||
.maximumSessions(3)
|
.maximumSessions(10)
|
||||||
.maxSessionsPreventsLogin(true)
|
.maxSessionsPreventsLogin(false)
|
||||||
.sessionRegistry(sessionRegistry())
|
.sessionRegistry(sessionRegistry())
|
||||||
.expiredUrl("/login?logout=true"));
|
.expiredUrl("/login?logout=true"));
|
||||||
|
|
||||||
http.formLogin(
|
http.formLogin(
|
||||||
formLogin ->
|
formLogin ->
|
||||||
formLogin
|
formLogin
|
||||||
|
@ -92,8 +93,7 @@ public class SecurityConfiguration {
|
||||||
.addLogoutHandler(
|
.addLogoutHandler(
|
||||||
(request, response, authentication) -> {
|
(request, response, authentication) -> {
|
||||||
HttpSession session =
|
HttpSession session =
|
||||||
request.getSession(
|
request.getSession(false);
|
||||||
false);
|
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
String sessionId = session.getId();
|
String sessionId = session.getId();
|
||||||
sessionRegistry()
|
sessionRegistry()
|
||||||
|
|
|
@ -56,8 +56,8 @@ public class UserController {
|
||||||
@PostMapping("/change-username")
|
@PostMapping("/change-username")
|
||||||
public RedirectView changeUsername(
|
public RedirectView changeUsername(
|
||||||
Principal principal,
|
Principal principal,
|
||||||
@RequestParam String currentPassword,
|
@RequestParam(name = "currentPassword") String currentPassword,
|
||||||
@RequestParam String newUsername,
|
@RequestParam(name = "newUsername") String newUsername,
|
||||||
HttpServletRequest request,
|
HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
RedirectAttributes redirectAttributes) {
|
RedirectAttributes redirectAttributes) {
|
||||||
|
@ -95,8 +95,8 @@ public class UserController {
|
||||||
@PostMapping("/change-password-on-login")
|
@PostMapping("/change-password-on-login")
|
||||||
public RedirectView changePasswordOnLogin(
|
public RedirectView changePasswordOnLogin(
|
||||||
Principal principal,
|
Principal principal,
|
||||||
@RequestParam String currentPassword,
|
@RequestParam(name = "currentPassword") String currentPassword,
|
||||||
@RequestParam String newPassword,
|
@RequestParam(name = "newPassword") String newPassword,
|
||||||
HttpServletRequest request,
|
HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
RedirectAttributes redirectAttributes) {
|
RedirectAttributes redirectAttributes) {
|
||||||
|
@ -128,8 +128,8 @@ public class UserController {
|
||||||
@PostMapping("/change-password")
|
@PostMapping("/change-password")
|
||||||
public RedirectView changePassword(
|
public RedirectView changePassword(
|
||||||
Principal principal,
|
Principal principal,
|
||||||
@RequestParam String currentPassword,
|
@RequestParam(name = "currentPassword") String currentPassword,
|
||||||
@RequestParam String newPassword,
|
@RequestParam(name = "newPassword") String newPassword,
|
||||||
HttpServletRequest request,
|
HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
RedirectAttributes redirectAttributes) {
|
RedirectAttributes redirectAttributes) {
|
||||||
|
@ -180,9 +180,9 @@ public class UserController {
|
||||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
@PostMapping("/admin/saveUser")
|
@PostMapping("/admin/saveUser")
|
||||||
public RedirectView saveUser(
|
public RedirectView saveUser(
|
||||||
@RequestParam String username,
|
@RequestParam(name = "username") String username,
|
||||||
@RequestParam String password,
|
@RequestParam(name = "password") String password,
|
||||||
@RequestParam String role,
|
@RequestParam(name = "role") String role,
|
||||||
@RequestParam(name = "forceChange", required = false, defaultValue = "false")
|
@RequestParam(name = "forceChange", required = false, defaultValue = "false")
|
||||||
boolean forceChange) {
|
boolean forceChange) {
|
||||||
|
|
||||||
|
@ -207,7 +207,8 @@ public class UserController {
|
||||||
|
|
||||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
@PostMapping("/admin/deleteUser/{username}")
|
@PostMapping("/admin/deleteUser/{username}")
|
||||||
public RedirectView deleteUser(@PathVariable String username, Authentication authentication) {
|
public RedirectView deleteUser(
|
||||||
|
@PathVariable(name = "username") String username, Authentication authentication) {
|
||||||
|
|
||||||
if (!userService.usernameExists(username)) {
|
if (!userService.usernameExists(username)) {
|
||||||
return new RedirectView("/addUsers?messageType=deleteUsernameExists");
|
return new RedirectView("/addUsers?messageType=deleteUsernameExists");
|
||||||
|
|
|
@ -72,130 +72,133 @@ public class ExtractImageScansController {
|
||||||
String extension = fileName.substring(fileName.lastIndexOf(".") + 1);
|
String extension = fileName.substring(fileName.lastIndexOf(".") + 1);
|
||||||
|
|
||||||
List<String> images = new ArrayList<>();
|
List<String> images = new ArrayList<>();
|
||||||
|
|
||||||
List<Path> tempImageFiles = new ArrayList<>();
|
List<Path> tempImageFiles = new ArrayList<>();
|
||||||
Path tempInputFile = null;
|
Path tempInputFile = null;
|
||||||
Path tempZipFile = null;
|
Path tempZipFile = null;
|
||||||
List<Path> tempDirs = new ArrayList<>();
|
List<Path> tempDirs = new ArrayList<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Check if input file is a PDF
|
// Check if input file is a PDF
|
||||||
if ("pdf".equalsIgnoreCase(extension)) {
|
if ("pdf".equalsIgnoreCase(extension)) {
|
||||||
// Load PDF document
|
// Load PDF document
|
||||||
try (PDDocument document = Loader.loadPDF(form.getFileInput().getBytes())) {
|
try (PDDocument document = Loader.loadPDF(form.getFileInput().getBytes())) {
|
||||||
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
||||||
int pageCount = document.getNumberOfPages();
|
int pageCount = document.getNumberOfPages();
|
||||||
images = new ArrayList<>();
|
images = new ArrayList<>();
|
||||||
|
|
||||||
// Create images of all pages
|
// Create images of all pages
|
||||||
for (int i = 0; i < pageCount; i++) {
|
for (int i = 0; i < pageCount; i++) {
|
||||||
// Create temp file to save the image
|
// Create temp file to save the image
|
||||||
Path tempFile = Files.createTempFile("image_", ".png");
|
Path tempFile = Files.createTempFile("image_", ".png");
|
||||||
|
|
||||||
// Render image and save as temp file
|
// Render image and save as temp file
|
||||||
BufferedImage image = pdfRenderer.renderImageWithDPI(i, 300);
|
BufferedImage image = pdfRenderer.renderImageWithDPI(i, 300);
|
||||||
ImageIO.write(image, "png", tempFile.toFile());
|
ImageIO.write(image, "png", tempFile.toFile());
|
||||||
|
|
||||||
// Add temp file path to images list
|
// Add temp file path to images list
|
||||||
images.add(tempFile.toString());
|
images.add(tempFile.toString());
|
||||||
tempImageFiles.add(tempFile);
|
tempImageFiles.add(tempFile);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tempInputFile = Files.createTempFile("input_", "." + extension);
|
|
||||||
Files.copy(
|
|
||||||
form.getFileInput().getInputStream(),
|
|
||||||
tempInputFile,
|
|
||||||
StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
// Add input file path to images list
|
|
||||||
images.add(tempInputFile.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<byte[]> processedImageBytes = new ArrayList<>();
|
|
||||||
|
|
||||||
// Process each image
|
|
||||||
for (int i = 0; i < images.size(); i++) {
|
|
||||||
|
|
||||||
Path tempDir = Files.createTempDirectory("openCV_output");
|
|
||||||
tempDirs.add(tempDir);
|
|
||||||
List<String> command =
|
|
||||||
new ArrayList<>(
|
|
||||||
Arrays.asList(
|
|
||||||
"python3",
|
|
||||||
"./scripts/split_photos.py",
|
|
||||||
images.get(i),
|
|
||||||
tempDir.toString(),
|
|
||||||
"--angle_threshold",
|
|
||||||
String.valueOf(form.getAngleThreshold()),
|
|
||||||
"--tolerance",
|
|
||||||
String.valueOf(form.getTolerance()),
|
|
||||||
"--min_area",
|
|
||||||
String.valueOf(form.getMinArea()),
|
|
||||||
"--min_contour_area",
|
|
||||||
String.valueOf(form.getMinContourArea()),
|
|
||||||
"--border_size",
|
|
||||||
String.valueOf(form.getBorderSize())));
|
|
||||||
|
|
||||||
// Run CLI command
|
|
||||||
ProcessExecutorResult returnCode =
|
|
||||||
ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV)
|
|
||||||
.runCommandWithOutputHandling(command);
|
|
||||||
|
|
||||||
// Read the output photos in temp directory
|
|
||||||
List<Path> tempOutputFiles = Files.list(tempDir).sorted().collect(Collectors.toList());
|
|
||||||
for (Path tempOutputFile : tempOutputFiles) {
|
|
||||||
byte[] imageBytes = Files.readAllBytes(tempOutputFile);
|
|
||||||
processedImageBytes.add(imageBytes);
|
|
||||||
}
|
|
||||||
// Clean up the temporary directory
|
|
||||||
FileUtils.deleteDirectory(tempDir.toFile());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create zip file if multiple images
|
|
||||||
if (processedImageBytes.size() > 1) {
|
|
||||||
String outputZipFilename = fileName.replaceFirst("[.][^.]+$", "") + "_processed.zip";
|
|
||||||
tempZipFile = Files.createTempFile("output_", ".zip");
|
|
||||||
|
|
||||||
try (ZipOutputStream zipOut =
|
|
||||||
new ZipOutputStream(new FileOutputStream(tempZipFile.toFile()))) {
|
|
||||||
// Add processed images to the zip
|
|
||||||
for (int i = 0; i < processedImageBytes.size(); i++) {
|
|
||||||
ZipEntry entry =
|
|
||||||
new ZipEntry(
|
|
||||||
fileName.replaceFirst("[.][^.]+$", "")
|
|
||||||
+ "_"
|
|
||||||
+ (i + 1)
|
|
||||||
+ ".png");
|
|
||||||
zipOut.putNextEntry(entry);
|
|
||||||
zipOut.write(processedImageBytes.get(i));
|
|
||||||
zipOut.closeEntry();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] zipBytes = Files.readAllBytes(tempZipFile);
|
|
||||||
|
|
||||||
// Clean up the temporary zip file
|
|
||||||
Files.delete(tempZipFile);
|
|
||||||
|
|
||||||
return WebResponseUtils.bytesToWebResponse(
|
|
||||||
zipBytes, outputZipFilename, MediaType.APPLICATION_OCTET_STREAM);
|
|
||||||
} else {
|
|
||||||
// Return the processed image as a response
|
|
||||||
byte[] imageBytes = processedImageBytes.get(0);
|
|
||||||
return WebResponseUtils.bytesToWebResponse(
|
|
||||||
imageBytes,
|
|
||||||
fileName.replaceFirst("[.][^.]+$", "") + ".png",
|
|
||||||
MediaType.IMAGE_PNG);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
// Cleanup logic for all temporary files and directories
|
|
||||||
tempImageFiles.forEach(path -> {
|
|
||||||
try {
|
|
||||||
Files.deleteIfExists(path);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("Failed to delete temporary image file: " + path, e);
|
|
||||||
}
|
}
|
||||||
});
|
} else {
|
||||||
|
tempInputFile = Files.createTempFile("input_", "." + extension);
|
||||||
|
Files.copy(
|
||||||
|
form.getFileInput().getInputStream(),
|
||||||
|
tempInputFile,
|
||||||
|
StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
// Add input file path to images list
|
||||||
|
images.add(tempInputFile.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<byte[]> processedImageBytes = new ArrayList<>();
|
||||||
|
|
||||||
|
// Process each image
|
||||||
|
for (int i = 0; i < images.size(); i++) {
|
||||||
|
|
||||||
|
Path tempDir = Files.createTempDirectory("openCV_output");
|
||||||
|
tempDirs.add(tempDir);
|
||||||
|
List<String> command =
|
||||||
|
new ArrayList<>(
|
||||||
|
Arrays.asList(
|
||||||
|
"python3",
|
||||||
|
"./scripts/split_photos.py",
|
||||||
|
images.get(i),
|
||||||
|
tempDir.toString(),
|
||||||
|
"--angle_threshold",
|
||||||
|
String.valueOf(form.getAngleThreshold()),
|
||||||
|
"--tolerance",
|
||||||
|
String.valueOf(form.getTolerance()),
|
||||||
|
"--min_area",
|
||||||
|
String.valueOf(form.getMinArea()),
|
||||||
|
"--min_contour_area",
|
||||||
|
String.valueOf(form.getMinContourArea()),
|
||||||
|
"--border_size",
|
||||||
|
String.valueOf(form.getBorderSize())));
|
||||||
|
|
||||||
|
// Run CLI command
|
||||||
|
ProcessExecutorResult returnCode =
|
||||||
|
ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV)
|
||||||
|
.runCommandWithOutputHandling(command);
|
||||||
|
|
||||||
|
// Read the output photos in temp directory
|
||||||
|
List<Path> tempOutputFiles =
|
||||||
|
Files.list(tempDir).sorted().collect(Collectors.toList());
|
||||||
|
for (Path tempOutputFile : tempOutputFiles) {
|
||||||
|
byte[] imageBytes = Files.readAllBytes(tempOutputFile);
|
||||||
|
processedImageBytes.add(imageBytes);
|
||||||
|
}
|
||||||
|
// Clean up the temporary directory
|
||||||
|
FileUtils.deleteDirectory(tempDir.toFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create zip file if multiple images
|
||||||
|
if (processedImageBytes.size() > 1) {
|
||||||
|
String outputZipFilename =
|
||||||
|
fileName.replaceFirst("[.][^.]+$", "") + "_processed.zip";
|
||||||
|
tempZipFile = Files.createTempFile("output_", ".zip");
|
||||||
|
|
||||||
|
try (ZipOutputStream zipOut =
|
||||||
|
new ZipOutputStream(new FileOutputStream(tempZipFile.toFile()))) {
|
||||||
|
// Add processed images to the zip
|
||||||
|
for (int i = 0; i < processedImageBytes.size(); i++) {
|
||||||
|
ZipEntry entry =
|
||||||
|
new ZipEntry(
|
||||||
|
fileName.replaceFirst("[.][^.]+$", "")
|
||||||
|
+ "_"
|
||||||
|
+ (i + 1)
|
||||||
|
+ ".png");
|
||||||
|
zipOut.putNextEntry(entry);
|
||||||
|
zipOut.write(processedImageBytes.get(i));
|
||||||
|
zipOut.closeEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] zipBytes = Files.readAllBytes(tempZipFile);
|
||||||
|
|
||||||
|
// Clean up the temporary zip file
|
||||||
|
Files.delete(tempZipFile);
|
||||||
|
|
||||||
|
return WebResponseUtils.bytesToWebResponse(
|
||||||
|
zipBytes, outputZipFilename, MediaType.APPLICATION_OCTET_STREAM);
|
||||||
|
} else {
|
||||||
|
// Return the processed image as a response
|
||||||
|
byte[] imageBytes = processedImageBytes.get(0);
|
||||||
|
return WebResponseUtils.bytesToWebResponse(
|
||||||
|
imageBytes,
|
||||||
|
fileName.replaceFirst("[.][^.]+$", "") + ".png",
|
||||||
|
MediaType.IMAGE_PNG);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
// Cleanup logic for all temporary files and directories
|
||||||
|
tempImageFiles.forEach(
|
||||||
|
path -> {
|
||||||
|
try {
|
||||||
|
Files.deleteIfExists(path);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Failed to delete temporary image file: " + path, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (tempZipFile != null && Files.exists(tempZipFile)) {
|
if (tempZipFile != null && Files.exists(tempZipFile)) {
|
||||||
try {
|
try {
|
||||||
|
@ -205,13 +208,14 @@ public class ExtractImageScansController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tempDirs.forEach(dir -> {
|
tempDirs.forEach(
|
||||||
try {
|
dir -> {
|
||||||
FileUtils.deleteDirectory(dir.toFile());
|
try {
|
||||||
} catch (IOException e) {
|
FileUtils.deleteDirectory(dir.toFile());
|
||||||
logger.error("Failed to delete temporary directory: " + dir, e);
|
} catch (IOException e) {
|
||||||
}
|
logger.error("Failed to delete temporary directory: " + dir, e);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3
test.sh
3
test.sh
|
@ -18,7 +18,8 @@ check_health() {
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
echo -e "\n$service_name is healthy!"
|
echo -e "\n$service_name is healthy!"
|
||||||
|
echo "Printing logs for $service_name:"
|
||||||
|
docker logs "$service_name"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue