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 Aug 28, 2024
1 parent 36c7cb1 commit 16684ea
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 70 deletions.
2 changes: 1 addition & 1 deletion docs/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1165,7 +1165,7 @@
"description": "default response"
}
},
"summary": "Returns boolean value telling if webhooks are enabled or not",
"summary": "Gets webhooks status - if they are enabled or not",
"tags": [
"Utility resources"
]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
package ch.sbb.polarion.extension.pdf.exporter.rest.model.settings.webhooks;

import com.fasterxml.jackson.annotation.JsonCreator;

public enum AuthType {
BEARER_TOKEN,
XSRF_TOKEN
XSRF_TOKEN;

@JsonCreator
public static AuthType forName(String name) {
for (AuthType authType : values()) {
if (authType.name().equalsIgnoreCase(name)) {
return authType;
}
}
return null;
}
}
211 changes: 153 additions & 58 deletions src/main/resources/webapp/pdf-exporter-admin/js/webhooks.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
const WebHooks = {
const Webhooks = {

saveHooks : function () {
saveWebhooks: function () {
SbbCommon.hideActionAlerts();

const webhookRows = Array.from(document.querySelectorAll('#webhooks-table tr'));
const webhookConfigs = webhookRows
.map(row => {
return {
url: row.querySelector('input[name="url"]')?.value,
authType: row.querySelector('input[name="auth"]')?.checked ? row.querySelector('select[name="auth_type"]')?.value : null,
authTokenName: row.querySelector('input[name="auth"]')?.checked ? row.querySelector('input[name="auth_token_name"]')?.value : null
};
});

SbbCommon.callAsync({
method: 'PUT',
url: `/polarion/${SbbCommon.extension}/rest/internal/settings/${SbbCommon.setting}/names/${Configurations.getSelectedConfiguration()}/content?scope=${SbbCommon.scope}`,
contentType: 'application/json',
body: JSON.stringify({
'webhooks': Array.from(document.getElementsByClassName("webhook")).map(input => input.value).filter(value => value),
'webhookConfigs': webhookConfigs,
}),
onOk: () => {
SbbCommon.showSaveSuccessAlert();
Expand All @@ -19,36 +29,38 @@ const WebHooks = {
});
},

setHooks: function(text) {
setWebhooks: function (text) {
document.getElementById('webhooks-table').innerHTML = ""; // Remove all records currently displayed first
const webhooksModel = JSON.parse(text);
if (webhooksModel.webhooks) {
webhooksModel.webhooks.forEach(hook => {
WebHooks.addHook(hook);
if (webhooksModel.webhookConfigs) {
webhooksModel.webhookConfigs.forEach(webhookConfig => {
Webhooks.addWebhook(webhookConfig);
});
}
if (webhooksModel.bundleTimestamp !== SbbCommon.getValueById('bundle-timestamp')) {
WebHooks.loadDefaultContent()
Webhooks.loadDefaultContent()
.then((responseText) => {
const defaultHooksModel = JSON.parse(responseText);
SbbCommon.setNewerVersionNotificationVisible(webhooksModel.webhooks && defaultHooksModel.webhooks
&& (webhooksModel.webhooks.length !== defaultHooksModel.webhooks.length
|| webhooksModel.webhooks.every(function(value, index) { return value === defaultHooksModel.hooks[index]})));
|| webhooksModel.webhooks.every(function (value, index) {
return value === defaultHooksModel.hooks[index]
})));
})
}
},

revertToDefault: function() {
if (confirm("Are you sure you want to return the default value?")) {
WebHooks.loadDefaultContent()
revertToDefault: function () {
if (confirm('Are you sure you want to return the default value?')) {
Webhooks.loadDefaultContent()
.then((responseText) => {
WebHooks.setHooks(responseText);
Webhooks.setWebhooks(responseText);
SbbCommon.showRevertedToDefaultAlert();
})
}
},

loadDefaultContent: function() {
loadDefaultContent: function () {
return new Promise((resolve, reject) => {
SbbCommon.setLoadingErrorNotificationVisible(false);
SbbCommon.hideActionAlerts();
Expand All @@ -66,54 +78,137 @@ const WebHooks = {
});
},

addHook: function(value) {
const table = document.getElementById('webhooks-table');
const tableRow = document.createElement('tr');
tableRow.classList.add('webhook-row');

const buttonCell = document.createElement('td');
const removeButton = document.createElement('button');
removeButton.classList.add('toolbar-button', 'webhook-button');
removeButton.setAttribute('title', 'Delete this webhook');
const image = document.createElement('img');
image.setAttribute('src', '/polarion/ria/images/control/tableMinus.png');
removeButton.appendChild(image);
removeButton.addEventListener('click', function () {
tableRow.remove();
})
buttonCell.appendChild(removeButton);
tableRow.appendChild(buttonCell);

const labelCell = document.createElement('td');
const fieldLabel = document.createElement('label');
fieldLabel.innerHTML = 'Webhook URL: ';
labelCell.appendChild(fieldLabel);
tableRow.appendChild(labelCell);

const fieldCell = document.createElement('td');
const field = document.createElement('input');
field.classList.add('fs-14', 'webhook');
field.setAttribute("placeholder", "https://my.domain.com/my-webhook");
if (value) {
field.setAttribute("value", value);
addWebhook: function (webhookConfig) {
function createTableRow() {
const tableRow = document.createElement('tr');
tableRow.classList.add('webhook-row');
return tableRow;
}

function createControlButtonCell() {
const cell = document.createElement('td');
const removeButton = document.createElement('button');
removeButton.classList.add('toolbar-button', 'webhook-button');
removeButton.setAttribute('title', 'Delete this webhook');
const removeButtonImage = document.createElement('img');
removeButtonImage.setAttribute('src', '/polarion/ria/images/control/tableMinus.png');
removeButton.appendChild(removeButtonImage);
removeButton.addEventListener('click', function () {
tableRow.remove();
})
cell.appendChild(removeButton);
return cell;
}

function createUrlLabelCell() {
const cell = document.createElement('td');
const fieldLabel = document.createElement('label');
fieldLabel.innerHTML = 'URL: ';
cell.appendChild(fieldLabel);
return cell;
}

function createUrlInputCell() {
const cell = document.createElement('td');

const urlInput = document.createElement('input');
urlInput.classList.add('fs-14', 'webhook');
urlInput.setAttribute('name', 'url');
urlInput.setAttribute('placeholder', 'https://my.domain.com/my-webhook');
if (webhookConfig?.url) {
urlInput.setAttribute('value', webhookConfig.url);
}

const invalidUrlError = document.createElement('div');
invalidUrlError.innerHTML = 'WARNING: Entered value doesn\'t seem to be a valid URL';
invalidUrlError.classList.add('invalid-webhook', 'hidden');
urlInput.addEventListener("keyup", (event) => {
const urlPattern = /^(http(s)?:\/\/.)[-a-zA-Z0-9@:%._+~#=]{2,256}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$/g;
if (!event.target.value || urlPattern.test(event.target.value)) {
invalidUrlError.classList.add('hidden');
} else {
invalidUrlError.classList.remove('hidden');
}
});

cell.appendChild(urlInput);
cell.appendChild(invalidUrlError);
return cell;
}

function createAuthCheckboxCell() {
const cell = document.createElement('td');

const authCheckbox = document.createElement('input');
authCheckbox.setAttribute('type', 'checkbox');
authCheckbox.setAttribute('name', 'auth');
if (webhookConfig?.authType) {
authCheckbox.setAttribute('checked', 'checked');
}

authCheckbox.addEventListener('change', (event) => {
const authTypeCombobox = event.target.parentElement.parentElement.querySelector('select[name="auth_type"]');
const authTokenNameField = event.target.parentElement.parentElement.querySelector('input[name="auth_token_name"]');
if (event.target.checked) {
authTypeCombobox.style.display = 'block';
authTokenNameField.style.display = 'block';
} else {
authTypeCombobox.style.display = 'none';
authTokenNameField.style.display = 'none';
}
});

const authLabel = document.createElement('label');
authLabel.setAttribute('for', 'auth');
authLabel.innerHTML = 'Auth';

cell.appendChild(authCheckbox);
cell.appendChild(authLabel);
return cell;
}

function createAuthTypeComboboxCell() {
const cell = document.createElement('td');

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>';
if (webhookConfig?.authType) {
switch (webhookConfig.authType) {
case 'BEARER_TOKEN': authTypeCombobox.selectedIndex = 0; break;
case 'XSRF_TOKEN': authTypeCombobox.selectedIndex = 1; break;
}
} else {
authTypeCombobox.style.display = 'none';
}

cell.appendChild(authTypeCombobox);
return cell;
}
fieldCell.appendChild(field);

const invalidUrlError = document.createElement('div');
invalidUrlError.innerHTML = "WARNING: Entered value doesn't seem to be a valid URL";
invalidUrlError.classList.add('invalid-webhook', 'hidden');
field.addEventListener("keyup", (event) => {
const urlPattern = /^(http(s)?:\/\/.)[-a-zA-Z0-9@:%._+~#=]{2,256}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$/g;
if (!event.target.value || urlPattern.test(event.target.value)) {
invalidUrlError.classList.add('hidden');

function createAuthTokenNameInput() {
const cell = document.createElement('td');

const authTokenNameField = document.createElement('input');
authTokenNameField.setAttribute('name', 'auth_token_name');
if (webhookConfig?.authType) {
authTokenNameField.setAttribute('value', webhookConfig.authTokenName ? webhookConfig.authTokenName : '');
} else {
invalidUrlError.classList.remove('hidden');
authTokenNameField.style.display = 'none';
}
});
fieldCell.appendChild(invalidUrlError);

tableRow.appendChild(fieldCell);
cell.appendChild(authTokenNameField);
return cell;
}

const table = document.getElementById('webhooks-table');
const tableRow = createTableRow();
tableRow.appendChild(createControlButtonCell());
tableRow.appendChild(createUrlLabelCell());
tableRow.appendChild(createUrlInputCell());
tableRow.appendChild(createAuthCheckboxCell());
tableRow.appendChild(createAuthTypeComboboxCell());
tableRow.appendChild(createAuthTokenNameInput());
table.appendChild(tableRow);
},
}
Expand All @@ -125,7 +220,7 @@ SbbCommon.init({
});

Configurations.init({
setConfigurationContentCallback: WebHooks.setHooks
setConfigurationContentCallback: Webhooks.setWebhooks
});

Configurations.loadConfigurationNames();
Loading

0 comments on commit 16684ea

Please sign in to comment.