Merge branch 'Stirling-2.0' of https://github.com/reecebrowne/Stirling-PDF into Stirling-2.0

This commit is contained in:
Reece
2025-05-19 13:14:58 +01:00
36 changed files with 79294 additions and 70 deletions

View File

@@ -59,7 +59,8 @@ public class AnalysisController {
description = "Returns title, author, subject, etc. Input:PDF Output:JSON Type:SISO")
public Map<String, String> getDocumentProperties(@ModelAttribute PDFFile file)
throws IOException {
// Load the document in read-only mode to prevent modifications and ensure the integrity of the original file.
// Load the document in read-only mode to prevent modifications and ensure the integrity of
// the original file.
try (PDDocument document = pdfDocumentFactory.load(file.getFileInput(), true)) {
PDDocumentInformation info = document.getDocumentInformation();
Map<String, String> properties = new HashMap<>();

View File

@@ -146,8 +146,8 @@ public class CertSignController {
summary = "Sign PDF with a Digital Certificate",
description =
"This endpoint accepts a PDF file, a digital certificate and related"
+ " information to sign the PDF. It then returns the digitally signed PDF"
+ " file. Input:PDF Output:PDF Type:SISO")
+ " information to sign the PDF. It then returns the digitally signed PDF"
+ " file. Input:PDF Output:PDF Type:SISO")
public ResponseEntity<byte[]> signPDFWithCert(@ModelAttribute SignPDFWithCertRequest request)
throws Exception {
MultipartFile pdf = request.getFileInput();

View File

@@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.web;
package stirling.software.SPDF.controller.api;
import java.io.IOException;
import java.io.InputStream;
@@ -9,10 +9,7 @@ import java.util.Map;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.*;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -25,65 +22,39 @@ import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.Dependency;
@Controller
@Slf4j
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
@Slf4j
public class HomeWebController {
private final ApplicationProperties applicationProperties;
@GetMapping("/about")
@Hidden
public String gameForm(Model model) {
model.addAttribute("currentPage", "about");
return "about";
}
@GetMapping("/licenses")
@Hidden
public String licensesForm(Model model) {
model.addAttribute("currentPage", "licenses");
Resource resource = new ClassPathResource("static/3rdPartyLicenses.json");
try {
InputStream is = resource.getInputStream();
String json = new String(is.readAllBytes(), StandardCharsets.UTF_8);
ObjectMapper mapper = new ObjectMapper();
Map<String, List<Dependency>> data =
mapper.readValue(json, new TypeReference<Map<String, List<Dependency>>>() {});
model.addAttribute("dependencies", data.get("dependencies"));
} catch (IOException e) {
log.error("exception", e);
}
return "licenses";
}
@GetMapping("/releases")
public String getReleaseNotes(Model model) {
return "releases";
}
@GetMapping("/")
public String home(Model model) {
model.addAttribute("currentPage", "home");
/** Returns the visibility settings for things like surveys. */
@GetMapping("/env")
public Map<String, Object> getEnvironmentFlags() {
String showSurvey = System.getenv("SHOW_SURVEY");
boolean showSurveyValue = showSurvey == null || "true".equalsIgnoreCase(showSurvey);
model.addAttribute("showSurveyFromDocker", showSurveyValue);
return "home";
return Map.of("showSurvey", showSurveyValue);
}
@GetMapping("/home")
public String root(Model model) {
return "redirect:/";
}
@GetMapping("/home-legacy")
public String homeLegacy(Model model) {
model.addAttribute("currentPage", "home-legacy");
return "home-legacy";
/** Returns the third-party licenses as a JSON list. */
@GetMapping("/licenses")
public List<Dependency> getLicenses() {
Resource resource = new ClassPathResource("static/3rdPartyLicenses.json");
try (InputStream is = resource.getInputStream()) {
String json = new String(is.readAllBytes(), StandardCharsets.UTF_8);
ObjectMapper mapper = new ObjectMapper();
Map<String, List<Dependency>> data = mapper.readValue(json, new TypeReference<>() {});
return data.get("dependencies");
} catch (IOException e) {
log.error("Failed to read licenses JSON", e);
throw new RuntimeException("Could not load license data", e);
}
}
/** Dynamic generation of robots.txt based on configuration. */
@GetMapping(value = "/robots.txt", produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
@Hidden
public String getRobotsTxt() {
Boolean allowGoogle = applicationProperties.getSystem().getGooglevisibility();

View File

@@ -0,0 +1,18 @@
package stirling.software.SPDF.controller.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class ReactRoutingController {
@GetMapping("/{path:^(?!api|static|robots\\.txt|favicon\\.ico)[^\\.]*$}")
public String forwardRootPaths() {
return "forward:/index.html";
}
@GetMapping("/{path:^(?!api|static)[^\\.]*}/{subpath:^(?!.*\\.).*$}")
public String forwardNestedPaths() {
return "forward:/index.html";
}
}

View File

@@ -4,7 +4,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

View File

@@ -2,36 +2,32 @@ package stirling.software.SPDF.config.security.mail;
import static org.mockito.Mockito.*;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.web.multipart.MultipartFile;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.api.Email;
@ExtendWith(MockitoExtension.class)
public class EmailServiceTest {
@Mock
private JavaMailSender mailSender;
@Mock private JavaMailSender mailSender;
@Mock
private ApplicationProperties applicationProperties;
@Mock private ApplicationProperties applicationProperties;
@Mock
private ApplicationProperties.Mail mailProperties;
@Mock private ApplicationProperties.Mail mailProperties;
@Mock
private MultipartFile fileInput;
@Mock private MultipartFile fileInput;
@InjectMocks
private EmailService emailService;
@InjectMocks private EmailService emailService;
@Test
void testSendEmailWithAttachment() throws MessagingException {

View File

@@ -4,7 +4,6 @@ import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import jakarta.mail.MessagingException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -14,6 +13,9 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.multipart.MultipartFile;
import jakarta.mail.MessagingException;
import stirling.software.SPDF.config.security.mail.EmailService;
import stirling.software.SPDF.model.api.Email;