mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
fix simple mode setup + filter settings
* now render proper settings on new action * fix disabled state when previous new action and change to edit * now merge and filter in case we have two settings dict (in this case, service settings and security settings) * add editor class as extend of default settings class and start editor handling
This commit is contained in:
parent
fe9a73ed70
commit
d4f6703c95
4 changed files with 173 additions and 208 deletions
|
|
@ -145,12 +145,12 @@ class SettingsService {
|
|||
.querySelector(
|
||||
`button[data-setting-select-dropdown-btn="security-level"][value="custom"]`,
|
||||
)
|
||||
.click();
|
||||
.removeAttribute("disabled");
|
||||
document
|
||||
.querySelector(
|
||||
`button[data-setting-select-dropdown-btn="security-level"][value="custom"]`,
|
||||
)
|
||||
.removeAttribute("disabled");
|
||||
.click();
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
|
|
@ -223,9 +223,11 @@ class SettingsService {
|
|||
}
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
console.log("mainSettings", mainSettings);
|
||||
console.log("compareSettings", compareSettings);
|
||||
// No main settings if new
|
||||
if (action === "new") {
|
||||
mainSettings = JSON.parse(JSON.stringify(compareSettings));
|
||||
compareSettings = null;
|
||||
}
|
||||
|
||||
this.simpleSettings.setSimple(
|
||||
action,
|
||||
|
|
|
|||
|
|
@ -1266,6 +1266,13 @@ class Settings {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
getSuffixNumOrEmpty(name) {
|
||||
const num = !isNaN(Number(name.substring(name.lastIndexOf("_") + 1)))
|
||||
? Number(name.substring(name.lastIndexOf("_") + 1))
|
||||
: "";
|
||||
return num;
|
||||
}
|
||||
}
|
||||
|
||||
class SettingsMultiple extends Settings {
|
||||
|
|
@ -1308,7 +1315,7 @@ class SettingsMultiple extends Settings {
|
|||
const ctnrName = container.getAttribute(
|
||||
`data-${this.prefix}-settings-multiple`,
|
||||
);
|
||||
const num = this.getSuffixNumOrFalse(ctnrName);
|
||||
const num = this.getSuffixNumOrEmpty(ctnrName);
|
||||
if (!isNaN(num) && num > topNum) topNum = num;
|
||||
});
|
||||
//the final number is num
|
||||
|
|
@ -1688,16 +1695,57 @@ class SettingsMultiple extends Settings {
|
|||
}`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getSuffixNumOrFalse(name) {
|
||||
const num = !isNaN(Number(name.substring(name.lastIndexOf("_") + 1)))
|
||||
? Number(name.substring(name.lastIndexOf("_") + 1))
|
||||
: "";
|
||||
return num;
|
||||
class SettingsEditor extends SettingsMultiple {
|
||||
constructor(mode, formEl, multSettingsName, prefix = "services") {
|
||||
super(mode, formEl, multSettingsName, prefix);
|
||||
this.darkMode = document.querySelector("[data-dark-toggle]");
|
||||
this.isDarkMode = this.darkMode.checked;
|
||||
// add editor for configs in simple mode
|
||||
this.editorEls = [];
|
||||
this.initEditors();
|
||||
}
|
||||
|
||||
initEditors() {
|
||||
window.addEventListener("load", () => {
|
||||
this.instanciateEditors();
|
||||
});
|
||||
|
||||
this.darkMode.addEventListener("click", (e) => {
|
||||
this.isDarkMode = e.target.checked;
|
||||
this.updateEditorMode();
|
||||
});
|
||||
}
|
||||
|
||||
instanciateEditors() {
|
||||
const editors = this.container.querySelectorAll("[data-editor]");
|
||||
editors.forEach((editorEl) => {
|
||||
const editor = ace.edit(editorEl.getAttribute("id"));
|
||||
// Handle
|
||||
if (this.isDarkMode) {
|
||||
editor.setTheme("ace/theme/dracula");
|
||||
} else {
|
||||
editor.setTheme("ace/theme/dawn");
|
||||
}
|
||||
//editor options
|
||||
editor.setShowPrintMargin(false);
|
||||
this.editorEls.push(editor);
|
||||
});
|
||||
}
|
||||
|
||||
updateEditorMode() {
|
||||
this.editorEls.forEach((editor) => {
|
||||
if (this.isDarkMode) {
|
||||
editor.setTheme("ace/theme/dracula");
|
||||
} else {
|
||||
editor.setTheme("ace/theme/dawn");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class SettingsAdvanced extends SettingsMultiple {
|
||||
class SettingsAdvanced extends SettingsEditor {
|
||||
constructor(formEl, multSettingsName, prefix = "services") {
|
||||
super("advanced", formEl, multSettingsName, prefix);
|
||||
this.initAdvanced();
|
||||
|
|
@ -1820,7 +1868,7 @@ class SettingsAdvanced extends SettingsMultiple {
|
|||
}
|
||||
}
|
||||
|
||||
class SettingsSimple extends SettingsMultiple {
|
||||
class SettingsSimple extends SettingsEditor {
|
||||
constructor(formEl, multSettingsName, prefix = "services") {
|
||||
super("simple", formEl, multSettingsName, prefix);
|
||||
this.nextBtn = this.container.querySelector("button[data-simple-next]");
|
||||
|
|
@ -1856,10 +1904,11 @@ class SettingsSimple extends SettingsMultiple {
|
|||
emptyServerName = false,
|
||||
resetSteps = false,
|
||||
) {
|
||||
const settings = compareSettings
|
||||
? this.filterSettings(mainSettings, compareSettings)
|
||||
: mainSettings;
|
||||
console.log(settings);
|
||||
const settings =
|
||||
compareSettings && Object.keys(compareSettings).length > 0
|
||||
? this.filterSettings(mainSettings, compareSettings)
|
||||
: mainSettings;
|
||||
console.log("settings", settings);
|
||||
this.updateData(
|
||||
action,
|
||||
oldServName,
|
||||
|
|
@ -1876,8 +1925,97 @@ class SettingsSimple extends SettingsMultiple {
|
|||
}
|
||||
|
||||
filterSettings(mainSettings, compareSettings) {
|
||||
console.log("filter");
|
||||
return {};
|
||||
const mergeSettings = {};
|
||||
// get the highest suffix number in mainSettings
|
||||
let highestMainSuffix = 0;
|
||||
let highestCompareSuffix = 0;
|
||||
for (const [key, value] of Object.entries(mainSettings)) {
|
||||
const mainSuffixeNum = this.getSuffixNumOrEmpty(key);
|
||||
const mainIsSuffixe = !isNaN(mainSuffixeNum);
|
||||
const mainName = mainIsSuffixe
|
||||
? key.replace(`_${highestMainSuffix}`, "").trim()
|
||||
: key.trim();
|
||||
|
||||
// Case same key (same setting) and not a multiple
|
||||
// Keep the one with a method != than ui or default if exists
|
||||
// Else keep the one from compareSettings that is the securityLevel
|
||||
if (key in compareSettings && !mainName.includes(this.multSettingsName)) {
|
||||
const method = mainSettings[key]["method"];
|
||||
if (method !== "ui" && method !== "default") {
|
||||
mergeSettings[key] = value;
|
||||
continue;
|
||||
} else {
|
||||
highestMainSuffix = mergeSettings[key] = compareSettings[key];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Need to check if is a multiple from a list because we can have custom configs with suffixe too
|
||||
if (mainIsSuffixe && mainName.includes(this.multSettingsName)) {
|
||||
highestMainSuffix = mainIsSuffixe
|
||||
? Math.max(highestMainSuffix, suffixeNum)
|
||||
: highestMainSuffix;
|
||||
}
|
||||
|
||||
const compareSuffixeNum = this.getSuffixNumOrEmpty(key);
|
||||
const compareIsSuffixe = !isNaN(compareSuffixeNum);
|
||||
const compareName = compareIsSuffixe
|
||||
? key.replace(`_${highestCompareSuffix}`, "").trim()
|
||||
: key.trim();
|
||||
|
||||
// Need to check if is a multiple from a list because we can have custom configs with suffixe too
|
||||
if (compareIsSuffixe && compareName.includes(this.multSettingsName)) {
|
||||
highestCompareSuffix = compareIsSuffixe
|
||||
? Math.max(highestCompareSuffix, suffixeNum)
|
||||
: highestCompareSuffix;
|
||||
}
|
||||
}
|
||||
|
||||
// Case highest main suffixe is higher than compare suffixe
|
||||
// Start updating starting from the highest suffix looping on all suffixed
|
||||
// Until we reached the highest compare suffixe
|
||||
if (highestCompareSuffix >= highestMainSuffix) {
|
||||
highestMainSuffix++;
|
||||
for (let i = 0; i <= highestCompareSuffix; i++) {
|
||||
// Check if the setting is a multiple and match the current suffixe
|
||||
for (const [key, value] of Object.entries(compareSettings)) {
|
||||
const compareSuffixeNum = this.getSuffixNumOrEmpty(key);
|
||||
const compareIsSuffixe = !isNaN(compareSuffixeNum);
|
||||
const compareName = compareIsSuffixe
|
||||
? key.replace(`_${highestCompareSuffix}`, "").trim()
|
||||
: key.trim();
|
||||
// Need to check if is a multiple from a list because we can have custom configs with suffixe too
|
||||
if (
|
||||
!compareIsSuffixe ||
|
||||
compareSuffixeNum != i ||
|
||||
!compareName.includes(this.multSettingsName)
|
||||
)
|
||||
continue;
|
||||
// Case multiple, update suffixe to the highest available if needed
|
||||
const newNameSuffixe = key.replace(
|
||||
`_${compareSuffixeNum}`,
|
||||
`_${highestMainSuffix}`,
|
||||
);
|
||||
mergeSettings[newNameSuffixe] = value;
|
||||
}
|
||||
// Update for the next loop to get the next suffixe
|
||||
highestMainSuffix++;
|
||||
}
|
||||
}
|
||||
// Else, add compare settings without changing anything
|
||||
else {
|
||||
for (const [key, value] of Object.entries(compareSettings)) {
|
||||
const compareSuffixeNum = this.getSuffixNumOrEmpty(key);
|
||||
const compareIsSuffixe = !isNaN(compareSuffixeNum);
|
||||
const compareName = compareIsSuffixe
|
||||
? key.replace(`_${highestCompareSuffix}`, "").trim()
|
||||
: key.trim();
|
||||
// Need to check if is a multiple from a list because we can have custom configs with suffixe too
|
||||
if (!compareIsSuffixe || !compareName.includes(this.multSettingsName))
|
||||
continue;
|
||||
mergeSettings[key] = value;
|
||||
}
|
||||
}
|
||||
return mergeSettings;
|
||||
}
|
||||
|
||||
setSettingsSimple(settings, setMethodUI = false, forceEnabled = false) {
|
||||
|
|
@ -2137,189 +2275,6 @@ class SettingsSwitch {
|
|||
}
|
||||
}
|
||||
|
||||
class SettingsEditor {
|
||||
constructor() {
|
||||
this.darkMode = document.querySelector("[data-dark-toggle]");
|
||||
this.isDarkMode = this.darkMode.checked;
|
||||
|
||||
// add editor for configs in simple mode
|
||||
this.editorEls = [];
|
||||
|
||||
this.initEditors();
|
||||
}
|
||||
|
||||
initEditors() {
|
||||
window.addEventListener("load", () => {
|
||||
this.instanciateEditors();
|
||||
});
|
||||
|
||||
this.darkMode.addEventListener("click", (e) => {
|
||||
this.isDarkMode = e.target.checked;
|
||||
this.updateEditorMode();
|
||||
});
|
||||
|
||||
// MULTIPLE ACTIONS
|
||||
this.container.addEventListener("click", (e) => {
|
||||
// Add btn
|
||||
try {
|
||||
if (
|
||||
e.target
|
||||
.closest("button")
|
||||
.hasAttribute(`data-${this.prefix}-multiple-add`)
|
||||
) {
|
||||
//get plugin from btn
|
||||
const btn = e.target.closest("button");
|
||||
const attName = btn.getAttribute(`data-${this.prefix}-multiple-add`);
|
||||
//get all multiple groups
|
||||
const multipleEls = this.container.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple*="${attName}"]`,
|
||||
);
|
||||
|
||||
//case no schema
|
||||
if (multipleEls.length <= 0) return;
|
||||
|
||||
//get the next container number logic
|
||||
//default is 0
|
||||
let topNum = 0;
|
||||
//loop on curr multiples, get the name suffix for each
|
||||
//and keep the highest num
|
||||
multipleEls.forEach((container) => {
|
||||
const ctnrName = container.getAttribute(
|
||||
`data-${this.prefix}-settings-multiple`,
|
||||
);
|
||||
const num = this.getSuffixNumOrFalse(ctnrName);
|
||||
if (!isNaN(num) && num > topNum) topNum = num;
|
||||
});
|
||||
//the final number is num
|
||||
//num is total - 1 because of hidden SCHEMA container
|
||||
const currNum = `${multipleEls.length >= 2 ? topNum + 1 : topNum}`;
|
||||
const setNum = +currNum === 0 ? `` : `_${currNum}`;
|
||||
//the default (schema) group is the last group
|
||||
const schema = this.container.querySelector(
|
||||
`[data-${this.prefix}-settings-multiple="${attName}_SCHEMA"]`,
|
||||
);
|
||||
//clone schema to create a group with new num
|
||||
const schemaClone = schema.cloneNode(true);
|
||||
|
||||
//add special attribute for disabled logic
|
||||
this.changeCloneSuffix(schemaClone, setNum);
|
||||
//set disabled / enabled state
|
||||
this.setDisabledMultNew(schemaClone);
|
||||
this.showClone(schema, schemaClone);
|
||||
//insert new group before first one
|
||||
//show all groups
|
||||
this.showMultByAtt(attName);
|
||||
}
|
||||
} catch (err) {}
|
||||
|
||||
//TOGGLE BTN
|
||||
try {
|
||||
if (
|
||||
e.target
|
||||
.closest("button")
|
||||
.hasAttribute(`data-${this.prefix}-multiple-toggle`)
|
||||
) {
|
||||
const att = e.target
|
||||
.closest("button")
|
||||
.getAttribute(`data-${this.prefix}-multiple-toggle`);
|
||||
this.toggleMultByAtt(att);
|
||||
}
|
||||
//remove last child
|
||||
} catch (err) {}
|
||||
|
||||
//REMOVE BTN
|
||||
try {
|
||||
if (
|
||||
e.target
|
||||
.closest("button")
|
||||
.hasAttribute(`data-${this.prefix}-multiple-delete`)
|
||||
) {
|
||||
// We are not removing it really, just hiding it and update values to default
|
||||
// By setting default value, group will be send to server and delete (because a setting with default value is useless to keep)
|
||||
const multContainer = e.target.closest(
|
||||
`[data-${this.prefix}-settings-multiple]`,
|
||||
);
|
||||
multContainer.classList.add("hidden-multiple");
|
||||
// get setting container
|
||||
const settings = multContainer.querySelectorAll(
|
||||
`[data-setting-container]`,
|
||||
);
|
||||
settings.forEach((setting) => {
|
||||
// for regular input
|
||||
try {
|
||||
const inps = setting.querySelectorAll("input");
|
||||
inps.forEach((inp) => {
|
||||
// case checkbox
|
||||
if (inp.getAttribute("type") === "checkbox") {
|
||||
const defaultVal = inp.getAttribute("data-default") || "";
|
||||
|
||||
if (defaultVal === "yes" && !inp.checked) {
|
||||
inp.click();
|
||||
}
|
||||
}
|
||||
|
||||
// case regular
|
||||
if (inp.getAttribute("type") !== "checkbox") {
|
||||
const defaultVal = inp.getAttribute("data-default") || "";
|
||||
inp.setAttribute("value", defaultVal);
|
||||
inp.value = defaultVal;
|
||||
}
|
||||
});
|
||||
} catch (e) {}
|
||||
// for select
|
||||
try {
|
||||
const selects = setting.querySelectorAll(
|
||||
"button[data-setting-select]",
|
||||
);
|
||||
selects.forEach((select) => {
|
||||
const defaultVal = select.getAttribute("data-default") || "";
|
||||
select
|
||||
.querySelector("data-setting-select-text")
|
||||
.setAttribute("data-value", defaultVal);
|
||||
select.querySelector("data-setting-select-text").textContent =
|
||||
defaultVal;
|
||||
const dropdown = this.container.querySelector(
|
||||
`[data-setting-select-dropdown="${select.getAttribute(
|
||||
"data-setting-select",
|
||||
)}"]`,
|
||||
);
|
||||
dropdown.querySelector(`button[value=${defaultVal}]`).click();
|
||||
});
|
||||
} catch (e) {}
|
||||
});
|
||||
}
|
||||
//remove last child
|
||||
} catch (err) {}
|
||||
});
|
||||
}
|
||||
|
||||
instanciateEditors() {
|
||||
const editors = this.container.querySelectorAll("[data-editor]");
|
||||
editors.forEach((editorEl) => {
|
||||
const editor = ace.edit(editorEl.getAttribute("id"));
|
||||
// Handle
|
||||
if (this.isDarkMode) {
|
||||
editor.setTheme("ace/theme/dracula");
|
||||
} else {
|
||||
editor.setTheme("ace/theme/dawn");
|
||||
}
|
||||
//editor options
|
||||
editor.setShowPrintMargin(false);
|
||||
this.editorEls.push(editor);
|
||||
});
|
||||
}
|
||||
|
||||
updateEditorMode() {
|
||||
this.editorEls.forEach((editor) => {
|
||||
if (this.isDarkMode) {
|
||||
editor.setTheme("ace/theme/dracula");
|
||||
} else {
|
||||
editor.setTheme("ace/theme/dawn");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
Popover,
|
||||
Tabs,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,14 @@
|
|||
"value": "test",
|
||||
"method": "default"
|
||||
},
|
||||
"CUSTOM_CONFIG_MODSEC_1" : {
|
||||
"value": "test",
|
||||
"method": "default"
|
||||
},
|
||||
"CUSTOM_CONFIG_MODSEC_2" : {
|
||||
"value": "test",
|
||||
"method": "default"
|
||||
},
|
||||
}%}
|
||||
|
||||
{% set advanced = {
|
||||
|
|
@ -46,8 +54,8 @@
|
|||
{"plugin_id" : "antibot", "setting_id": "USE_ANTIBOT", "title" : "Define the type of your antibot", "subtitle" : "Javascript, Captcha or Cookie don't need additionnal settings to be fill. Recaptcha, Hcaptcha and Turnstile need secret key and site key delivered from providers." },
|
||||
],
|
||||
"configs": [
|
||||
{"name": "my_config_1", "type": "modsec", "subtitle" : "This will determine the modsecurity rules to apply to this service."},
|
||||
{"name": "my_config_2", "type": "server-http", "subtitle" : "This will determine the server http..."}
|
||||
{"id" : "CUSTOM_CONFIG_MODSEC_1", "name": "my_config_1", "type": "modsec", "subtitle" : "This will determine the modsecurity rules to apply to this service."},
|
||||
{"id" : "CUSTOM_CONFIG_MODSEC_2", "name": "my_config_2", "type": "server-http", "subtitle" : "This will determine the server http..."}
|
||||
]
|
||||
},
|
||||
]
|
||||
|
|
|
|||
8
src/ui/templates/settings_simple.html
vendored
8
src/ui/templates/settings_simple.html
vendored
|
|
@ -71,7 +71,7 @@
|
|||
|
||||
<!-- custom configs -->
|
||||
{% for config in configs %}
|
||||
<div data-simple id="{{ config['type'] }}-simple"
|
||||
<div data-simple data-config-container
|
||||
class="w-full h-full px-1 mt-4 mb-2 col-span-12 grid grid-cols-12 h-full items-end">
|
||||
<!-- title and desc -->
|
||||
<div class="col-span-12" data-setting-header>
|
||||
|
|
@ -82,10 +82,10 @@
|
|||
<p class="max-w-[550px] sm:pl-3 sm:pr-2 text-sm dark:text-gray-300 mb-0">{{ config['subtitle'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full col-span-12 px-4">
|
||||
<textarea data-simple-default-editor-content class="hidden" id="{{config['name']}}-content" name="{{config['name']}}-content"></textarea>
|
||||
<div data-editor-container class="w-full col-span-12 px-4">
|
||||
<textarea data-editor-input class="hidden" name="{{config['type']}}_SERVER_NAME_{{config['name']}}"></textarea>
|
||||
<!-- editor-->
|
||||
<div data-simple-editor id="{{config['name']}}-editor" class="text-base w-full h-50 overflow-hidden overflow-y-auto my-2 border border-gray-300 dark:border-slate-800">
|
||||
<div data-editor id="{{config['id']}}" class="text-base w-full h-50 overflow-hidden overflow-y-auto my-2 border border-gray-300 dark:border-slate-800">
|
||||
</div>
|
||||
<!-- editor-->
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue