Skip to content

Commit

Permalink
feat: auth data for webhooks
Browse files Browse the repository at this point in the history
Refs: #169
  • Loading branch information
grigoriev committed Sep 1, 2024
1 parent 16684ea commit 95bebf0
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 27 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ ch.sbb.polarion.extension.pdf-exporter.internalizeExternalCss=true
## Extension Configuration

1. On the top of the project's navigation pane click ⚙ (Actions) ➙ 🔧 Administration. Project's administration page will be opened.
2. On the administration's navigation pane select `PDF Export`. There are 5 sub-menus with different configuration options for PDF Exporter.
3. For 5 of these options (Cover page, Header and Footer, Localization, Webhooks and Filename template) `Quick Help` section available with option short description. For the rest 2
2. On the administration's navigation pane select `PDF Export`. There are expandable sub-menus with different configuration options for PDF Exporter.
3. For some of these options (Cover page, Header and Footer, Localization, Webhooks and Filename template) `Quick Help` section available with option short description. For the rest
(Style package, Stylesheets) there's no `Quick Help` section as their content is self-evident.
4. To change configuration of PDF exporter extension just edit corresponding section and press `Save` button.
4. To change configuration of PDF Exporter extension just edit corresponding section and press `Save` button.

## Usage

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package ch.sbb.polarion.extension.pdf.exporter.converter;

import ch.sbb.polarion.extension.generic.rest.filter.AuthenticationFilter;
import ch.sbb.polarion.extension.generic.settings.NamedSettings;
import ch.sbb.polarion.extension.generic.settings.SettingId;
import ch.sbb.polarion.extension.generic.util.ScopeUtils;
Expand All @@ -10,6 +9,7 @@
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.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;
Expand Down Expand Up @@ -54,6 +54,7 @@
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;
Expand Down Expand Up @@ -205,24 +206,24 @@ private static void addAuthHeader(@NotNull WebhookConfig webhookConfig, @NotNull
return;
}

String authInfoFromUserAccountVault = getAuthInfoFromUserAccountVault(webhookConfig.getAuthTokenName());
switch (webhookConfig.getAuthType()) {
case BEARER_TOKEN -> requestBuilder.header(HttpHeaders.AUTHORIZATION, AuthenticationFilter.BEARER + " " + authInfoFromUserAccountVault);
case XSRF_TOKEN -> requestBuilder.header(AuthenticationFilter.X_POLARION_REST_TOKEN_HEADER, webhookConfig.getAuthTokenName());
String authInfoFromUserAccountVault = getAuthInfoFromUserAccountVault(webhookConfig.getAuthType(), webhookConfig.getAuthTokenName());
if (authInfoFromUserAccountVault == null) {
return;
}

if (webhookConfig.getAuthType() != null && webhookConfig.getAuthTokenName() != null) {
requestBuilder.header(HttpHeaders.AUTHORIZATION, webhookConfig.getAuthType() + " " + webhookConfig.getAuthTokenName());
}
requestBuilder.header(HttpHeaders.AUTHORIZATION, webhookConfig.getAuthType().getAuthHeaderPrefix() + " " + authInfoFromUserAccountVault);
}

private static String getAuthInfoFromUserAccountVault(String authTokenName) {
if (authTokenName != null && authTokenName.isEmpty()) {
return UserAccountVault.getInstance()
.getCredentialsForKey(authTokenName)
.getPassword();
}
return null;
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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
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,
XSRF_TOKEN;
BEARER_TOKEN("Bearer"),
BASIC_AUTH("Basic");

private final String authHeaderPrefix;

AuthType(String authHeaderPrefix) {
this.authHeaderPrefix = authHeaderPrefix;
}

@JsonCreator
public static AuthType forName(String name) {
Expand Down
13 changes: 7 additions & 6 deletions src/main/resources/webapp/pdf-exporter-admin/js/webhooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ const Webhooks = {
if (webhooksModel.bundleTimestamp !== SbbCommon.getValueById('bundle-timestamp')) {
Webhooks.loadDefaultContent()
.then((responseText) => {
const defaultHooksModel = JSON.parse(responseText);
SbbCommon.setNewerVersionNotificationVisible(webhooksModel.webhooks && defaultHooksModel.webhooks
&& (webhooksModel.webhooks.length !== defaultHooksModel.webhooks.length
const defaultWebhooksModel = JSON.parse(responseText);
SbbCommon.setNewerVersionNotificationVisible(webhooksModel.webhooks && defaultWebhooksModel.webhooks
&& (webhooksModel.webhooks.length !== defaultWebhooksModel.webhooks.length
|| webhooksModel.webhooks.every(function (value, index) {
return value === defaultHooksModel.hooks[index]
return value === defaultWebhooksModel.hooks[index]
})));
})
}
Expand Down Expand Up @@ -172,11 +172,11 @@ const Webhooks = {

const authTypeCombobox = document.createElement('select');
authTypeCombobox.setAttribute('name', 'auth_type');
authTypeCombobox.innerHTML = '<option value="BEARER_TOKEN">Bearer Token</option><option value="XSRF_TOKEN">XSRF Token</option>';
authTypeCombobox.innerHTML = '<option value="BEARER_TOKEN">Bearer Token</option><option value="BASIC_AUTH">Basic</option>';
if (webhookConfig?.authType) {
switch (webhookConfig.authType) {
case 'BEARER_TOKEN': authTypeCombobox.selectedIndex = 0; break;
case 'XSRF_TOKEN': authTypeCombobox.selectedIndex = 1; break;
case 'BASIC_AUTH': authTypeCombobox.selectedIndex = 1; break;
}
} else {
authTypeCombobox.style.display = 'none';
Expand All @@ -191,6 +191,7 @@ const Webhooks = {

const authTokenNameField = document.createElement('input');
authTokenNameField.setAttribute('name', 'auth_token_name');
authTokenNameField.setAttribute('placeholder', 'Polarion Vault entry name');
if (webhookConfig?.authType) {
authTokenNameField.setAttribute('value', webhookConfig.authTokenName ? webhookConfig.authTokenName : '');
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@
#webhooks-table {
width: 1100px;
table-layout: fixed;
}
.webhook-row td {
vertical-align: top;
}
.webhook-row td:first-child {
width: 20px;
width: 30px;
}
.webhook-row td:nth-child(2) {
Expand Down Expand Up @@ -119,6 +120,12 @@
A webhook is a REST endpoint accepting initial HTML as a string (POST request), making some modification to this HTML and returning resulting HTML as a string back in body of response.
A webhook endpoint can locate anywhere, either within Polarion itself or outside of it.
</p>
<h3>Webhook configuration</h3>
<p>
Each webhook has an URL and optional auth info. The URL is the endpoint to invoke. The auth info is a authentication for this endpoint.
The auth info can be either a basic auth with username and password or a Bearer token. The auth info should be stored in Polarion Vault.
Here should be provided a name of the vault entry with auth info.
</p>
<h3>Webhooks processing</h3>
<p>
Webhooks to run they should be selected in appropriate style package, or during PDF exporting. They are invoked in an order they entered on this page.
Expand Down

0 comments on commit 95bebf0

Please sign in to comment.