getSettingNames(@NotNull String featureName, @NotNull String scope) {
try {
return NamedSettingsRegistry.INSTANCE.getByFeatureName(featureName).readNames(scope);
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/converter/HtmlToPdfConverter.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/converter/HtmlToPdfConverter.java
index ee4d11d..8ada440 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/converter/HtmlToPdfConverter.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/converter/HtmlToPdfConverter.java
@@ -9,7 +9,7 @@
import ch.sbb.polarion.extension.pdf.exporter.util.PdfExporterFileResourceProvider;
import ch.sbb.polarion.extension.pdf.exporter.util.PdfTemplateProcessor;
import ch.sbb.polarion.extension.pdf.exporter.util.html.HtmlLinksHelper;
-import ch.sbb.polarion.extension.pdf.exporter.util.regex.RegexMatcher;
+import ch.sbb.polarion.extension.generic.regex.RegexMatcher;
import ch.sbb.polarion.extension.pdf.exporter.weasyprint.WeasyPrintOptions;
import ch.sbb.polarion.extension.pdf.exporter.weasyprint.service.WeasyPrintServiceConnector;
import lombok.Getter;
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/converter/PdfConverter.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/converter/PdfConverter.java
index 5879627..2eed861 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/converter/PdfConverter.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/converter/PdfConverter.java
@@ -9,12 +9,14 @@
import ch.sbb.polarion.extension.pdf.exporter.rest.model.conversion.DocumentType;
import ch.sbb.polarion.extension.pdf.exporter.rest.model.conversion.ExportParams;
import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.headerfooter.HeaderFooterModel;
-import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.hooks.WebhooksModel;
+import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.webhooks.AuthType;
+import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.webhooks.WebhookConfig;
+import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.webhooks.WebhooksModel;
import ch.sbb.polarion.extension.pdf.exporter.service.PdfExporterPolarionService;
import ch.sbb.polarion.extension.pdf.exporter.settings.CssSettings;
import ch.sbb.polarion.extension.pdf.exporter.settings.HeaderFooterSettings;
-import ch.sbb.polarion.extension.pdf.exporter.settings.WebhooksSettings;
import ch.sbb.polarion.extension.pdf.exporter.settings.LocalizationSettings;
+import ch.sbb.polarion.extension.pdf.exporter.settings.WebhooksSettings;
import ch.sbb.polarion.extension.pdf.exporter.util.EnumValuesProvider;
import ch.sbb.polarion.extension.pdf.exporter.util.HtmlLogger;
import ch.sbb.polarion.extension.pdf.exporter.util.HtmlProcessor;
@@ -27,11 +29,12 @@
import ch.sbb.polarion.extension.pdf.exporter.util.placeholder.PlaceholderProcessor;
import ch.sbb.polarion.extension.pdf.exporter.util.velocity.VelocityEvaluator;
import ch.sbb.polarion.extension.pdf.exporter.weasyprint.WeasyPrintOptions;
-import com.fasterxml.jackson.databind.ObjectMapper;
import ch.sbb.polarion.extension.pdf.exporter.weasyprint.service.WeasyPrintServiceConnector;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.polarion.alm.tracker.model.ITrackerProject;
import com.polarion.core.util.StringUtils;
import com.polarion.core.util.logging.Logger;
+import com.polarion.platform.internal.security.UserAccountVault;
import lombok.AllArgsConstructor;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
@@ -43,12 +46,15 @@
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
+import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -148,39 +154,43 @@ public byte[] convertToPdf(@NotNull ExportParams exportParams, @Nullable ExportM
private @NotNull String applyWebhooks(@NotNull ExportParams exportParams, @NotNull String htmlContent) {
// Skip webhooks processing among other if this functionality is not enabled by system administrator
- if (!PdfExporterExtensionConfiguration.getInstance().areWebhooksEnabled() || exportParams.getWebhooks() == null) {
+ if (!PdfExporterExtensionConfiguration.getInstance().getWebhooksEnabled() || exportParams.getWebhooks() == null) {
return htmlContent;
}
WebhooksModel webhooksModel = new WebhooksSettings().load(exportParams.getProjectId(), SettingId.fromName(exportParams.getWebhooks()));
String result = htmlContent;
- for (String webhook : webhooksModel.getWebhooks()) {
- result = applyWebhook(webhook, exportParams, result);
+ for (WebhookConfig webhookConfig : webhooksModel.getWebhookConfigs()) {
+ result = applyWebhook(webhookConfig, exportParams, result);
}
return result;
}
- private @NotNull String applyWebhook(@NotNull String webhook, @NotNull ExportParams exportParams, @NotNull String htmlContent) {
+ private @NotNull String applyWebhook(@NotNull WebhookConfig webhookConfig, @NotNull ExportParams exportParams, @NotNull String htmlContent) {
Client client = null;
try {
client = ClientBuilder.newClient();
- WebTarget webTarget = client.target(webhook).register(MultiPartFeature.class);
+ WebTarget webTarget = client.target(webhookConfig.getUrl()).register(MultiPartFeature.class);
FormDataMultiPart multipart = new FormDataMultiPart();
multipart.bodyPart(new FormDataBodyPart("exportParams", new ObjectMapper().writeValueAsString(exportParams), MediaType.APPLICATION_JSON_TYPE));
multipart.bodyPart(new FormDataBodyPart("html", htmlContent.getBytes(StandardCharsets.UTF_8), MediaType.APPLICATION_OCTET_STREAM_TYPE));
- try (Response response = webTarget.request(MediaType.TEXT_PLAIN).post(Entity.entity(multipart, multipart.getMediaType()))) {
+ Invocation.Builder requestBuilder = webTarget.request(MediaType.TEXT_PLAIN);
+
+ addAuthHeader(webhookConfig, requestBuilder);
+
+ try (Response response = requestBuilder.post(Entity.entity(multipart, multipart.getMediaType()))) {
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
try (InputStream inputStream = response.readEntity(InputStream.class)) {
return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
}
} else {
- logger.error(String.format("Could not get proper response from webhook [%s]: response status %s", webhook, response.getStatus()));
+ logger.error(String.format("Could not get proper response from webhook [%s]: response status %s", webhookConfig.getUrl(), response.getStatus()));
}
}
} catch (Exception e) {
- logger.error(String.format("Could not get response from webhook [%s]", webhook), e);
+ logger.error(String.format("Could not get response from webhook [%s]", webhookConfig.getUrl()), e);
} finally {
if (client != null) {
client.close();
@@ -191,6 +201,31 @@ public byte[] convertToPdf(@NotNull ExportParams exportParams, @Nullable ExportM
return htmlContent;
}
+ private static void addAuthHeader(@NotNull WebhookConfig webhookConfig, @NotNull Invocation.Builder requestBuilder) {
+ if (webhookConfig.getAuthType() == null || webhookConfig.getAuthTokenName() == null) {
+ return;
+ }
+
+ String authInfoFromUserAccountVault = getAuthInfoFromUserAccountVault(webhookConfig.getAuthType(), webhookConfig.getAuthTokenName());
+ if (authInfoFromUserAccountVault == null) {
+ return;
+ }
+
+ requestBuilder.header(HttpHeaders.AUTHORIZATION, webhookConfig.getAuthType().getAuthHeaderPrefix() + " " + authInfoFromUserAccountVault);
+ }
+
+ private static @Nullable String getAuthInfoFromUserAccountVault(@NotNull AuthType authType, @NotNull String authTokenName) {
+ @NotNull UserAccountVault.Credentials credentials = UserAccountVault.getInstance().getCredentialsForKey(authTokenName);
+
+ return switch (authType) {
+ case BASIC_AUTH -> {
+ String authInfo = credentials.getUser() + ":" + credentials.getPassword();
+ yield Base64.getEncoder().encodeToString(authInfo.getBytes());
+ }
+ case BEARER_TOKEN -> credentials.getPassword();
+ };
+ }
+
@VisibleForTesting
byte[] generatePdf(
LiveDocHelper.DocumentData documentData,
@@ -219,8 +254,8 @@ String postProcessDocumentContent(@NotNull ExportParams exportParams, @Nullable
@NotNull
@VisibleForTesting
String composeHtml(@NotNull String documentName,
- @NotNull HtmlData htmlData,
- @NotNull ExportParams exportParams) {
+ @NotNull HtmlData htmlData,
+ @NotNull ExportParams exportParams) {
String content = htmlData.headerFooterContent
+ "" + htmlData.documentContent + "
";
return pdfTemplateProcessor.processUsing(exportParams, documentName, htmlData.cssContent, content);
@@ -236,9 +271,9 @@ String getCssContent(
String listStyles = new PdfExporterListStyleProvider(exportParams.getNumberedListStyles()).getStyle();
String css = pdfStyles
+ (exportParams.getHeadersColor() != null ?
- " h1, h2, h3, h4, h5, h6, .content .title {"
- + " color: " + exportParams.getHeadersColor() + ";"
- + " }"
+ " h1, h2, h3, h4, h5, h6, .content .title {" +
+ " color: " + exportParams.getHeadersColor() + ";" +
+ " }"
: "")
+ listStyles;
@@ -279,5 +314,6 @@ private String appendWikiCss(String css) {
return css + System.lineSeparator() + ScopeUtils.getFileContent("default/wiki.css");
}
- record HtmlData(String cssContent, String documentContent, String headerFooterContent) {}
+ record HtmlData(String cssContent, String documentContent, String headerFooterContent) {
+ }
}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/properties/PdfExporterExtensionConfiguration.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/properties/PdfExporterExtensionConfiguration.java
index 6efd98a..e0c3df8 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/properties/PdfExporterExtensionConfiguration.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/properties/PdfExporterExtensionConfiguration.java
@@ -1,12 +1,15 @@
package ch.sbb.polarion.extension.pdf.exporter.properties;
+import ch.sbb.polarion.extension.generic.properties.CurrentExtensionConfiguration;
import ch.sbb.polarion.extension.generic.properties.ExtensionConfiguration;
+import ch.sbb.polarion.extension.generic.util.Discoverable;
import com.polarion.core.config.impl.SystemValueReader;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
+@Discoverable
public class PdfExporterExtensionConfiguration extends ExtensionConfiguration {
public static final String WEASYPRINT_SERVICE = "weasyprint.service";
@@ -28,7 +31,7 @@ public Boolean getInternalizeExternalCss() {
}
@NotNull
- public Boolean areWebhooksEnabled() {
+ public Boolean getWebhooksEnabled() {
return SystemValueReader.getInstance().readBoolean(getPropertyPrefix() + WEBHOOKS_ENABLED, false);
}
@@ -42,16 +45,7 @@ public Boolean areWebhooksEnabled() {
return supportedProperties;
}
- public PdfExporterExtensionConfiguration() {
- super();
- }
-
public static PdfExporterExtensionConfiguration getInstance() {
- return PdfExporterExtensionConfigurationHolder.INSTANCE;
+ return (PdfExporterExtensionConfiguration) CurrentExtensionConfiguration.getInstance().getExtensionConfiguration();
}
-
- private static class PdfExporterExtensionConfigurationHolder {
- private static final PdfExporterExtensionConfiguration INSTANCE = new PdfExporterExtensionConfiguration();
- }
-
}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/ConfigurationApiController.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/ConfigurationApiController.java
index 90b7478..5bc5078 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/ConfigurationApiController.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/ConfigurationApiController.java
@@ -1,8 +1,8 @@
package ch.sbb.polarion.extension.pdf.exporter.rest.controller;
+import ch.sbb.polarion.extension.generic.configuration.ConfigurationStatus;
import ch.sbb.polarion.extension.generic.rest.filter.Secured;
import ch.sbb.polarion.extension.generic.service.PolarionService;
-import ch.sbb.polarion.extension.pdf.exporter.rest.model.configuration.ConfigurationStatus;
import org.jetbrains.annotations.NotNull;
import javax.ws.rs.Path;
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/ConfigurationInternalController.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/ConfigurationInternalController.java
index a3d8855..14d7d30 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/ConfigurationInternalController.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/ConfigurationInternalController.java
@@ -1,7 +1,13 @@
package ch.sbb.polarion.extension.pdf.exporter.rest.controller;
-import ch.sbb.polarion.extension.pdf.exporter.rest.model.configuration.ConfigurationStatus;
-import ch.sbb.polarion.extension.pdf.exporter.util.configuration.ConfigurationStatusUtils;
+import ch.sbb.polarion.extension.generic.configuration.ConfigurationStatus;
+import ch.sbb.polarion.extension.generic.configuration.ConfigurationStatusProvider;
+import ch.sbb.polarion.extension.pdf.exporter.util.configuration.CORSStatusProvider;
+import ch.sbb.polarion.extension.pdf.exporter.util.configuration.DefaultSettingsStatusProvider;
+import ch.sbb.polarion.extension.pdf.exporter.util.configuration.DleToolbarStatusProvider;
+import ch.sbb.polarion.extension.pdf.exporter.util.configuration.DocumentPropertiesPaneStatusProvider;
+import ch.sbb.polarion.extension.pdf.exporter.util.configuration.LiveReportMainHeadStatusProvider;
+import ch.sbb.polarion.extension.pdf.exporter.util.configuration.WeasyPrintStatusProvider;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import org.jetbrains.annotations.NotNull;
@@ -23,7 +29,7 @@ public class ConfigurationInternalController {
@Path("/configuration/default-settings")
@Operation(summary = "Checks default settings configuration")
public @NotNull ConfigurationStatus checkDefaultSettings(@QueryParam("scope") @DefaultValue("") String scope) {
- return ConfigurationStatusUtils.getSettingsStatus(scope);
+ return new DefaultSettingsStatusProvider().getStatus(ConfigurationStatusProvider.Context.builder().scope(scope).build());
}
@GET
@@ -31,7 +37,7 @@ public class ConfigurationInternalController {
@Path("/configuration/document-properties-pane-config")
@Operation(summary = "Checks document properties pane configuration")
public @NotNull ConfigurationStatus checkDocumentPropertiesPaneConfig(@QueryParam("scope") @DefaultValue("") String scope) {
- return ConfigurationStatusUtils.getDocumentPropertiesPaneStatus(scope);
+ return new DocumentPropertiesPaneStatusProvider().getStatus(ConfigurationStatusProvider.Context.builder().scope(scope).build());
}
@GET
@@ -39,7 +45,7 @@ public class ConfigurationInternalController {
@Path("/configuration/dle-toolbar-config")
@Operation(summary = "Checks DLE Toolbar configuration")
public @NotNull ConfigurationStatus checkDleToolbarConfig() {
- return ConfigurationStatusUtils.getDleToolbarStatus();
+ return new DleToolbarStatusProvider().getStatus(ConfigurationStatusProvider.Context.builder().build());
}
@GET
@@ -47,7 +53,7 @@ public class ConfigurationInternalController {
@Path("/configuration/live-report-config")
@Operation(summary = "Checks Live Report configuration")
public @NotNull ConfigurationStatus checkLiveReportConfig() {
- return ConfigurationStatusUtils.getLiveReportMainHeadStatus();
+ return new LiveReportMainHeadStatusProvider().getStatus(ConfigurationStatusProvider.Context.builder().build());
}
@GET
@@ -55,7 +61,7 @@ public class ConfigurationInternalController {
@Path("/configuration/cors-config")
@Operation(summary = "Checks CORS configuration")
public @NotNull ConfigurationStatus checkCORSConfig() {
- return ConfigurationStatusUtils.getCORSStatus();
+ return new CORSStatusProvider().getStatus(ConfigurationStatusProvider.Context.builder().build());
}
@GET
@@ -63,6 +69,6 @@ public class ConfigurationInternalController {
@Path("/configuration/weasyprint")
@Operation(summary = "Checks WeasyPrint configuration")
public @NotNull List checkWeasyPrint() {
- return ConfigurationStatusUtils.getWeasyPrintStatus();
+ return new WeasyPrintStatusProvider().getStatuses(ConfigurationStatusProvider.Context.builder().build());
}
}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/SettingsApiController.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/SettingsApiController.java
index eb21813..2c0e8da 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/SettingsApiController.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/SettingsApiController.java
@@ -2,6 +2,7 @@
import ch.sbb.polarion.extension.generic.rest.filter.Secured;
import ch.sbb.polarion.extension.generic.service.PolarionService;
+import ch.sbb.polarion.extension.generic.settings.SettingName;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import javax.ws.rs.Path;
@@ -39,4 +40,9 @@ public void persistCoverPageTemplate(String template, String scope) {
public void deleteImages(String coverPageName, String scope) {
polarionService.callPrivileged(() -> super.deleteImages(coverPageName, scope));
}
+
+ @Override
+ public Collection getSuitableStylePackageNames(String projectId, String spaceId, String documentName) {
+ return polarionService.callPrivileged(() -> super.getSuitableStylePackageNames(projectId, spaceId, documentName));
+ }
}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/SettingsInternalController.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/SettingsInternalController.java
index 8e62960..b6f683c 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/SettingsInternalController.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/SettingsInternalController.java
@@ -4,6 +4,7 @@
import ch.sbb.polarion.extension.generic.settings.SettingName;
import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.coverpage.CoverPageModel;
import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.localization.LocalizationModel;
+import ch.sbb.polarion.extension.pdf.exporter.service.PdfExporterPolarionService;
import ch.sbb.polarion.extension.pdf.exporter.settings.CoverPageSettings;
import ch.sbb.polarion.extension.pdf.exporter.settings.LocalizationSettings;
import ch.sbb.polarion.extension.pdf.exporter.util.LocalizationHelper;
@@ -14,6 +15,7 @@
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataParam;
+import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
@@ -38,6 +40,7 @@
public class SettingsInternalController {
private Set predefinedCoverPageTemplates;
+ private final PdfExporterPolarionService pdfExporterPolarionService = new PdfExporterPolarionService();
@GET
@Path("/settings/localization/names/{name}/download")
@@ -116,4 +119,17 @@ public void persistCoverPageTemplate(@PathParam("template") String template, @Qu
public void deleteImages(@PathParam("name") String coverPageName, @QueryParam("scope") @DefaultValue("") String scope) {
new CoverPageSettings().deleteCoverPageImages(coverPageName, scope);
}
+
+ @GET
+ @Path("/settings/style-package/suitable-names")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Tag(name = "Settings")
+ @Operation(summary = "Get list of style packages suitable for a document")
+ public Collection getSuitableStylePackageNames(@QueryParam("projectId") String projectId, @QueryParam("spaceId") String spaceId, @QueryParam("documentName") String documentName) {
+ if (projectId == null || spaceId == null || documentName == null) {
+ throw new BadRequestException("Parameters 'projectId', 'spaceId', 'documentName' are required'");
+ }
+ return pdfExporterPolarionService.getSuitableStylePackages(projectId, spaceId, documentName);
+ }
+
}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/UtilityResourcesInternalController.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/UtilityResourcesInternalController.java
index 2d040d3..6bd622b 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/UtilityResourcesInternalController.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/controller/UtilityResourcesInternalController.java
@@ -90,6 +90,6 @@ public String getFileName(@QueryParam("locationPath") String locationPath, @Quer
@Tag(name = "Utility resources")
@Operation(summary = "Gets webhooks status - if they are enabled or not")
public WebhooksStatus getWebhooksStatus() {
- return WebhooksStatus.builder().enabled(PdfExporterExtensionConfiguration.getInstance().areWebhooksEnabled()).build();
+ return WebhooksStatus.builder().enabled(PdfExporterExtensionConfiguration.getInstance().getWebhooksEnabled()).build();
}
}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/WorkItemRefData.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/WorkItemRefData.java
index 63bc247..ed869a6 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/WorkItemRefData.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/WorkItemRefData.java
@@ -1,6 +1,6 @@
package ch.sbb.polarion.extension.pdf.exporter.rest.model;
-import ch.sbb.polarion.extension.pdf.exporter.util.regex.RegexMatcher;
+import ch.sbb.polarion.extension.generic.regex.RegexMatcher;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/configuration/ConfigurationStatus.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/configuration/ConfigurationStatus.java
deleted file mode 100644
index 2477099..0000000
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/configuration/ConfigurationStatus.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package ch.sbb.polarion.extension.pdf.exporter.rest.model.configuration;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.jetbrains.annotations.NotNull;
-
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class ConfigurationStatus {
- private @NotNull String name;
- private @NotNull Status status;
- private @NotNull String details;
-
- public ConfigurationStatus(@NotNull String name, @NotNull Status status) {
- this(name, status, "");
- }
-}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/configuration/Status.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/configuration/Status.java
deleted file mode 100644
index b34d10d..0000000
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/configuration/Status.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package ch.sbb.polarion.extension.pdf.exporter.rest.model.configuration;
-
-public enum Status {
- OK,
- WARNING,
- ERROR;
-
- public String toHtml() {
- String color = switch (this) {
- case OK -> "green";
- case WARNING -> "gray";
- case ERROR -> "red";
- };
- return String.format("%s", color, this.name());
- }
-}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/stylepackage/StylePackageModel.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/stylepackage/StylePackageModel.java
index 2407f0d..8b24dcb 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/stylepackage/StylePackageModel.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/stylepackage/StylePackageModel.java
@@ -23,6 +23,7 @@
@EqualsAndHashCode(callSuper = false)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class StylePackageModel extends SettingsModel {
+ private static final String MATCHING_QUERY_ENTRY_NAME = "MATCHING QUERY";
private static final String EXPOSE_SETTINGS_ENTRY_NAME = "EXPOSE SETTINGS";
private static final String COVER_PAGE_ENTRY_NAME = "COVER PAGE";
private static final String HEADER_FOOTER_ENTRY_NAME = "HEADER FOOTER";
@@ -46,6 +47,7 @@ public class StylePackageModel extends SettingsModel {
private static final String LINKED_WORKITEM_ROLES_ENTRY_NAME = "LINKED WORKITEM ROLES";
private static final String EXPOSE_PAGE_WIDTH_VALIDATION_ENTRY_NAME = "EXPOSE PAGE WIDTH VALIDATION";
+ private String matchingQuery;
private boolean exposeSettings;
private String coverPage;
private String headerFooter;
@@ -71,7 +73,8 @@ public class StylePackageModel extends SettingsModel {
@Override
protected String serializeModelData() {
- return serializeEntry(EXPOSE_SETTINGS_ENTRY_NAME, exposeSettings) +
+ return serializeEntry(MATCHING_QUERY_ENTRY_NAME, matchingQuery) +
+ serializeEntry(EXPOSE_SETTINGS_ENTRY_NAME, exposeSettings) +
serializeEntry(COVER_PAGE_ENTRY_NAME, coverPage) +
serializeEntry(HEADER_FOOTER_ENTRY_NAME, headerFooter) +
serializeEntry(CSS_ENTRY_NAME, css) +
@@ -97,6 +100,7 @@ protected String serializeModelData() {
@Override
protected void deserializeModelData(String serializedString) {
+ matchingQuery = deserializeEntry(MATCHING_QUERY_ENTRY_NAME, serializedString);
exposeSettings = Boolean.parseBoolean(deserializeEntry(EXPOSE_SETTINGS_ENTRY_NAME, serializedString));
coverPage = deserializeEntry(COVER_PAGE_ENTRY_NAME, serializedString);
headerFooter = deserializeEntry(HEADER_FOOTER_ENTRY_NAME, serializedString);
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/webhooks/AuthType.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/webhooks/AuthType.java
new file mode 100644
index 0000000..1af7c7e
--- /dev/null
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/webhooks/AuthType.java
@@ -0,0 +1,26 @@
+package ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.webhooks;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import lombok.Getter;
+
+@Getter
+public enum AuthType {
+ BEARER_TOKEN("Bearer"),
+ BASIC_AUTH("Basic");
+
+ private final String authHeaderPrefix;
+
+ AuthType(String authHeaderPrefix) {
+ this.authHeaderPrefix = authHeaderPrefix;
+ }
+
+ @JsonCreator
+ public static AuthType forName(String name) {
+ for (AuthType authType : values()) {
+ if (authType.name().equalsIgnoreCase(name)) {
+ return authType;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/webhooks/WebhookConfig.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/webhooks/WebhookConfig.java
new file mode 100644
index 0000000..da2a9ba
--- /dev/null
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/webhooks/WebhookConfig.java
@@ -0,0 +1,14 @@
+package ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.webhooks;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class WebhookConfig {
+ private String url;
+ private AuthType authType;
+ private String authTokenName;
+}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/hooks/WebhooksModel.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/webhooks/WebhooksModel.java
similarity index 65%
rename from src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/hooks/WebhooksModel.java
rename to src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/webhooks/WebhooksModel.java
index 34a4717..9fef281 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/hooks/WebhooksModel.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/rest/model/settings/webhooks/WebhooksModel.java
@@ -1,4 +1,4 @@
-package ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.hooks;
+package ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.webhooks;
import ch.sbb.polarion.extension.generic.settings.SettingsModel;
import com.fasterxml.jackson.annotation.JsonInclude;
@@ -25,22 +25,22 @@
public class WebhooksModel extends SettingsModel {
public static final String WEBHOOKS_ENTRY_NAME = "WEBHOOKS";
- private List webhooks = new ArrayList<>();
+ private List webhookConfigs = new ArrayList<>();
@Override
protected String serializeModelData() {
- return serializeEntry(WEBHOOKS_ENTRY_NAME, webhooks);
+ return serializeEntry(WEBHOOKS_ENTRY_NAME, webhookConfigs);
}
@Override
protected void deserializeModelData(String serializedString) {
- String webhooksString = deserializeEntry(WEBHOOKS_ENTRY_NAME, serializedString);
- if (webhooksString != null) {
+ String content = deserializeEntry(WEBHOOKS_ENTRY_NAME, serializedString);
+ if (content != null) {
try {
- String[] webhooksArray = new ObjectMapper().readValue(webhooksString, String[].class);
- webhooks = new ArrayList<>(Arrays.asList(webhooksArray));
+ WebhookConfig[] configs = new ObjectMapper().readValue(content, WebhookConfig[].class);
+ this.webhookConfigs = new ArrayList<>(Arrays.asList(configs));
} catch (JsonProcessingException e) {
- throw new IllegalArgumentException("Webhooks value couldn't be parsed", e);
+ throw new IllegalArgumentException(WEBHOOKS_ENTRY_NAME + " value couldn't be parsed", e);
}
}
}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/service/PdfExporterPolarionService.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/service/PdfExporterPolarionService.java
index 8a4ba1c..a3e23d8 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/service/PdfExporterPolarionService.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/service/PdfExporterPolarionService.java
@@ -1,16 +1,26 @@
package ch.sbb.polarion.extension.pdf.exporter.service;
import ch.sbb.polarion.extension.generic.service.PolarionService;
+import ch.sbb.polarion.extension.generic.settings.NamedSettingsRegistry;
+import ch.sbb.polarion.extension.generic.settings.SettingId;
+import ch.sbb.polarion.extension.generic.settings.SettingName;
import ch.sbb.polarion.extension.generic.util.ScopeUtils;
+import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.stylepackage.StylePackageModel;
+import ch.sbb.polarion.extension.pdf.exporter.settings.StylePackageSettings;
import com.polarion.alm.projects.IProjectService;
import com.polarion.alm.tracker.ITrackerService;
+import com.polarion.alm.tracker.model.IModule;
import com.polarion.alm.tracker.model.ITrackerProject;
import com.polarion.core.util.StringUtils;
import com.polarion.platform.IPlatformService;
+import com.polarion.platform.persistence.IDataService;
+import com.polarion.platform.persistence.model.IPObjectList;
import com.polarion.platform.security.ISecurityService;
import com.polarion.platform.service.repository.IRepositoryService;
import org.jetbrains.annotations.NotNull;
+import java.util.Collection;
+
public class PdfExporterPolarionService extends PolarionService {
public PdfExporterPolarionService() {
@@ -35,4 +45,34 @@ public ITrackerProject getProjectFromScope(String scope) {
}
return project;
}
+
+ public Collection getSuitableStylePackages(@NotNull String projectId, @NotNull String spaceId, @NotNull String documentName) {
+ StylePackageSettings stylePackageSettings = (StylePackageSettings) NamedSettingsRegistry.INSTANCE.getByFeatureName(StylePackageSettings.FEATURE_NAME);
+ Collection stylePackageNames = stylePackageSettings.readNames(ScopeUtils.getScopeFromProject(projectId));
+ return stylePackageNames.stream().filter(stylePackageName -> isStylePackageSuitable(projectId, spaceId, documentName, stylePackageSettings, stylePackageName)).toList();
+ }
+
+ @SuppressWarnings("unchecked")
+ private boolean isStylePackageSuitable(@NotNull String projectId, @NotNull String spaceId, @NotNull String documentName,
+ @NotNull StylePackageSettings stylePackageSettings, @NotNull SettingName stylePackageName) {
+ StylePackageModel model = stylePackageSettings.read(ScopeUtils.getScopeFromProject(projectId), SettingId.fromName(stylePackageName.getName()), null);
+
+ if (StringUtils.isEmpty(model.getMatchingQuery())) {
+ return true;
+ } else {
+ IDataService dataService = getTrackerService().getDataService();
+ IPObjectList suitableDocuments = dataService.searchInstances(dataService.getPrototype("Module"), model.getMatchingQuery(), "name");
+ for (IModule suitableDocument : suitableDocuments) {
+ if (sameDocument(projectId, spaceId, documentName, suitableDocument)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ private boolean sameDocument(@NotNull String projectId, @NotNull String spaceId, @NotNull String documentName, @NotNull IModule document) {
+ return projectId.equals(document.getProjectId()) && String.format("%s/%s", spaceId, documentName).equals(document.getModuleLocation().getLocationPath());
+ }
+
}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/settings/CoverPageSettings.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/settings/CoverPageSettings.java
index 19b7415..5fb77d2 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/settings/CoverPageSettings.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/settings/CoverPageSettings.java
@@ -7,7 +7,7 @@
import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.coverpage.CoverPageModel;
import ch.sbb.polarion.extension.pdf.exporter.service.PdfExporterPolarionService;
import ch.sbb.polarion.extension.pdf.exporter.util.MediaUtils;
-import ch.sbb.polarion.extension.pdf.exporter.util.regex.RegexMatcher;
+import ch.sbb.polarion.extension.generic.regex.RegexMatcher;
import com.polarion.core.util.logging.Logger;
import com.polarion.platform.service.repository.IRepositoryReadOnlyConnection;
import com.polarion.subterra.base.location.ILocation;
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/settings/WebhooksSettings.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/settings/WebhooksSettings.java
index 2f581ec..9ba546a 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/settings/WebhooksSettings.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/settings/WebhooksSettings.java
@@ -2,7 +2,7 @@
import ch.sbb.polarion.extension.generic.settings.GenericNamedSettings;
import ch.sbb.polarion.extension.generic.settings.SettingsService;
-import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.hooks.WebhooksModel;
+import ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.webhooks.WebhooksModel;
import org.jetbrains.annotations.NotNull;
public class WebhooksSettings extends GenericNamedSettings {
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/HtmlProcessor.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/HtmlProcessor.java
index 5260783..04e8c02 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/HtmlProcessor.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/HtmlProcessor.java
@@ -10,8 +10,8 @@
import ch.sbb.polarion.extension.pdf.exporter.settings.LocalizationSettings;
import ch.sbb.polarion.extension.pdf.exporter.util.exporter.CustomPageBreakPart;
import ch.sbb.polarion.extension.pdf.exporter.util.html.HtmlLinksHelper;
-import ch.sbb.polarion.extension.pdf.exporter.util.regex.IRegexEngine;
-import ch.sbb.polarion.extension.pdf.exporter.util.regex.RegexMatcher;
+import ch.sbb.polarion.extension.generic.regex.IRegexEngine;
+import ch.sbb.polarion.extension.generic.regex.RegexMatcher;
import com.polarion.alm.shared.util.StringUtils;
import com.polarion.core.util.xml.CSSStyle;
import lombok.SneakyThrows;
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/LiveDocCommentsProcessor.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/LiveDocCommentsProcessor.java
index df2c76a..d9229bf 100644
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/LiveDocCommentsProcessor.java
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/LiveDocCommentsProcessor.java
@@ -1,7 +1,7 @@
package ch.sbb.polarion.extension.pdf.exporter.util;
import ch.sbb.polarion.extension.pdf.exporter.model.LiveDocComment;
-import ch.sbb.polarion.extension.pdf.exporter.util.regex.RegexMatcher;
+import ch.sbb.polarion.extension.generic.regex.RegexMatcher;
import com.polarion.alm.server.api.model.document.ProxyDocument;
import com.polarion.alm.shared.api.model.comment.CommentBase;
import com.polarion.alm.shared.api.model.comment.CommentBaseFields;
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/configuration/CORSStatusProvider.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/configuration/CORSStatusProvider.java
new file mode 100644
index 0000000..f2dc328
--- /dev/null
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/configuration/CORSStatusProvider.java
@@ -0,0 +1,31 @@
+package ch.sbb.polarion.extension.pdf.exporter.util.configuration;
+
+import ch.sbb.polarion.extension.generic.configuration.ConfigurationStatus;
+import ch.sbb.polarion.extension.generic.configuration.ConfigurationStatusProvider;
+import ch.sbb.polarion.extension.generic.configuration.Status;
+import ch.sbb.polarion.extension.generic.util.Discoverable;
+import com.polarion.core.config.Configuration;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+@Discoverable
+public class CORSStatusProvider extends ConfigurationStatusProvider {
+
+ public static final String CORS = "CORS (Cross-Origin Resource Sharing)";
+
+ @Override
+ public @NotNull ConfigurationStatus getStatus(@NotNull Context context) {
+ boolean restEnabled = Configuration.getInstance().rest().enabled();
+ if (restEnabled) {
+ Set corsAllowedOrigins = Configuration.getInstance().rest().corsAllowedOrigins();
+ if (corsAllowedOrigins.isEmpty()) {
+ return new ConfigurationStatus(CORS, Status.WARNING, "CORS allowed origins are not configured");
+ } else {
+ return new ConfigurationStatus(CORS, Status.OK, "CORS allowed origins: %s".formatted(corsAllowedOrigins.stream().toList()));
+ }
+ } else {
+ return new ConfigurationStatus(CORS, Status.WARNING, "Polarion REST API is not enabled, so CORS is not enabled");
+ }
+ }
+}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/configuration/ConfigurationStatusUtils.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/configuration/ConfigurationStatusUtils.java
deleted file mode 100644
index 831dffd..0000000
--- a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/configuration/ConfigurationStatusUtils.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package ch.sbb.polarion.extension.pdf.exporter.util.configuration;
-
-import ch.sbb.polarion.extension.generic.settings.GenericNamedSettings;
-import ch.sbb.polarion.extension.generic.settings.NamedSettingsRegistry;
-import ch.sbb.polarion.extension.generic.settings.SettingsService;
-import ch.sbb.polarion.extension.generic.util.ScopeUtils;
-import ch.sbb.polarion.extension.pdf.exporter.converter.HtmlToPdfConverter;
-import ch.sbb.polarion.extension.pdf.exporter.rest.model.configuration.ConfigurationStatus;
-import ch.sbb.polarion.extension.pdf.exporter.rest.model.configuration.Status;
-import ch.sbb.polarion.extension.pdf.exporter.rest.model.conversion.Orientation;
-import ch.sbb.polarion.extension.pdf.exporter.rest.model.conversion.PaperSize;
-import ch.sbb.polarion.extension.pdf.exporter.util.regex.RegexMatcher;
-import ch.sbb.polarion.extension.pdf.exporter.weasyprint.service.WeasyPrintServiceConnector;
-import ch.sbb.polarion.extension.pdf.exporter.weasyprint.service.model.WeasyPrintInfo;
-import com.polarion.core.config.Configuration;
-import com.polarion.subterra.base.location.ILocation;
-import lombok.experimental.UtilityClass;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.List;
-import java.util.Set;
-
-@UtilityClass
-public class ConfigurationStatusUtils {
- public static final String DEFAULT_SETTINGS = "Default Settings";
- public static final String DOCUMENT_PROPERTIES_PANE = "Document Properties Pane";
- public static final String DLE_TOOLBAR = "DLE Toolbar";
- public static final String LIVE_REPORT_BUTTON = "LiveReport Button";
- public static final String CORS = "CORS (Cross-Origin Resource Sharing)";
- public static final List WEASY_PRINT = List.of("WeasyPrint Python", "WeasyPrint", "WeasyPrint Service");
-
- @SuppressWarnings("java:S1166") //need by design
- public static @NotNull ConfigurationStatus getSettingsStatus(@NotNull String scope) {
- ConfigurationStatus configurationStatus = new ConfigurationStatus(DEFAULT_SETTINGS, Status.OK, "");
-
- NamedSettingsRegistry.INSTANCE.getAll().stream()
- .map(GenericNamedSettings::getFeatureName)
- .forEach(featureName -> {
- try {
- NamedSettingsRegistry.INSTANCE.getByFeatureName(featureName).readNames(scope);
- } catch (Exception e) {
- configurationStatus.setStatus(Status.ERROR);
- configurationStatus.setDetails(e.getMessage());
- }
- });
-
- return configurationStatus;
- }
-
- public static @NotNull ConfigurationStatus getDocumentPropertiesPaneStatus(@NotNull String scope) {
- ILocation location = ScopeUtils.getContextLocation(scope).append(".polarion/documents/sidebar/document.xml");
- String content = new SettingsService().read(location, null);
-
- if (content == null) {
- location = ScopeUtils.getDefaultLocation().append(".polarion/documents/sidebar/document.xml");
- content = new SettingsService().read(location, null);
- return getConfigurationStatus(DOCUMENT_PROPERTIES_PANE, content, "", new ConfigurationStatus(DOCUMENT_PROPERTIES_PANE, Status.WARNING, "Not configured neither for global scope nor for current project"));
- } else {
- return getConfigurationStatus(DOCUMENT_PROPERTIES_PANE, content, "", new ConfigurationStatus(DOCUMENT_PROPERTIES_PANE, Status.WARNING, "Not configured for current project"));
- }
- }
-
-
- public static @NotNull ConfigurationStatus getDleToolbarStatus() {
- final ILocation location = ScopeUtils.getDefaultLocation().append(".polarion/context.properties");
- final String content = new SettingsService().read(location, null);
-
- return getConfigurationStatus(DLE_TOOLBAR, content, "scriptInjection.dleEditorHead=.*");
- }
-
- public static @NotNull ConfigurationStatus getLiveReportMainHeadStatus() {
- final ILocation location = ScopeUtils.getDefaultLocation().append(".polarion/context.properties");
- final String content = new SettingsService().read(location, null);
-
- return getConfigurationStatus(LIVE_REPORT_BUTTON, content, "scriptInjection.mainHead=.*");
+ }
+}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/configuration/DocumentPropertiesPaneStatusProvider.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/configuration/DocumentPropertiesPaneStatusProvider.java
new file mode 100644
index 0000000..e043269
--- /dev/null
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/configuration/DocumentPropertiesPaneStatusProvider.java
@@ -0,0 +1,30 @@
+package ch.sbb.polarion.extension.pdf.exporter.util.configuration;
+
+import ch.sbb.polarion.extension.generic.configuration.ConfigurationStatus;
+import ch.sbb.polarion.extension.generic.configuration.ConfigurationStatusProvider;
+import ch.sbb.polarion.extension.generic.configuration.Status;
+import ch.sbb.polarion.extension.generic.settings.SettingsService;
+import ch.sbb.polarion.extension.generic.util.Discoverable;
+import ch.sbb.polarion.extension.generic.util.ScopeUtils;
+import com.polarion.subterra.base.location.ILocation;
+import org.jetbrains.annotations.NotNull;
+
+@Discoverable
+public class DocumentPropertiesPaneStatusProvider extends ConfigurationStatusProvider {
+
+ public static final String DOCUMENT_PROPERTIES_PANE = "Document Properties Pane";
+
+ @Override
+ public @NotNull ConfigurationStatus getStatus(@NotNull Context context) {
+ ILocation location = ScopeUtils.getContextLocation(context.getScope()).append(".polarion/documents/sidebar/document.xml");
+ String content = new SettingsService().read(location, null);
+
+ if (content == null) {
+ location = ScopeUtils.getDefaultLocation().append(".polarion/documents/sidebar/document.xml");
+ content = new SettingsService().read(location, null);
+ return getConfigurationStatus(DOCUMENT_PROPERTIES_PANE, content, "", new ConfigurationStatus(DOCUMENT_PROPERTIES_PANE, Status.WARNING, "Not configured neither for global scope nor for current project"));
+ } else {
+ return getConfigurationStatus(DOCUMENT_PROPERTIES_PANE, content, "", new ConfigurationStatus(DOCUMENT_PROPERTIES_PANE, Status.WARNING, "Not configured for current project"));
+ }
+ }
+}
diff --git a/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/configuration/LiveReportMainHeadStatusProvider.java b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/configuration/LiveReportMainHeadStatusProvider.java
new file mode 100644
index 0000000..82978f5
--- /dev/null
+++ b/src/main/java/ch/sbb/polarion/extension/pdf/exporter/util/configuration/LiveReportMainHeadStatusProvider.java
@@ -0,0 +1,23 @@
+package ch.sbb.polarion.extension.pdf.exporter.util.configuration;
+
+import ch.sbb.polarion.extension.generic.configuration.ConfigurationStatus;
+import ch.sbb.polarion.extension.generic.configuration.ConfigurationStatusProvider;
+import ch.sbb.polarion.extension.generic.settings.SettingsService;
+import ch.sbb.polarion.extension.generic.util.Discoverable;
+import ch.sbb.polarion.extension.generic.util.ScopeUtils;
+import com.polarion.subterra.base.location.ILocation;
+import org.jetbrains.annotations.NotNull;
+
+@Discoverable
+public class LiveReportMainHeadStatusProvider extends ConfigurationStatusProvider {
+
+ public static final String LIVE_REPORT_BUTTON = "LiveReport Button";
+
+ @Override
+ public @NotNull ConfigurationStatus getStatus(@NotNull Context context) {
+ ILocation location = ScopeUtils.getDefaultLocation().append(".polarion/context.properties");
+ String content = new SettingsService().read(location, null);
+
+ return getConfigurationStatus(LIVE_REPORT_BUTTON, content, "scriptInjection.mainHead=