implemented security level + fix

* update templates to handle attribute level security for a setting (in case exists)
* switching SECURITY_LEVEL will update simple mode settings
* add delay on switch SECURITY_LEVEL to avoid updating the previous value (race condition)
* next / prev btn fix when no +1
* fix data-value not updating on custom select
* avoid some settings (like SECURITY_LEVEL) to be update by methods
* reset simple mode when closing / opening modal working
This commit is contained in:
Jordan Blasenhauer 2024-04-22 21:31:59 +02:00
parent 90e957674c
commit 76d3fa67d6
9 changed files with 104 additions and 30 deletions

View file

@ -248,6 +248,17 @@ class ServiceModal {
this.openModal();
}
} catch (err) {}
// security lrbrl
try {
if (
e.target
.closest("button")
.getAttribute("data-setting-select-dropdown-btn") ==
"security-level"
) {
this.updateSecuLevel();
}
} catch (err) {}
});
}
@ -262,11 +273,26 @@ class ServiceModal {
});
const firstStep = this.simpleForm.querySelector("[data-step='1']");
firstStep.classList.remove("hidden");
this.updateSimpleActions();
// we want to update settings by current security level
const securityLevelValue = this.simpleForm.querySelector(
'[data-setting-select-text="security-level"]',
);
this.setSettingsByAtt(this.simpleForm, "");
this.updateSecuLevel();
}
updateSecuLevel() {
// Add timeout to let dropdown update attribute values
// This avoid using previous value
setTimeout(() => {
const secuLevelValue = this.simpleForm
.querySelector('[data-setting-select-text="security-level"]')
.textContent.toLowerCase()
.trim();
this.setSettingsByAtt(
this.simpleForm,
"data-default-method",
`data-security-level-${secuLevelValue}`,
);
}, 30);
}
nextSimpleStep() {
@ -357,18 +383,37 @@ class ServiceModal {
});
}
isAvoidInpList(inp, inpName) {
if (
inpName === "csrf_token" ||
inpName === "OLD_SERVER_NAME" ||
inpName === "mode" ||
inpName === "security-level" ||
inpName === "is_draft" ||
inpName === "operation" ||
inpName === "settings-filter" ||
inp.hasAttribute("data-combobox")
)
return true;
isAvoidInpList(type, inp, inpName, containerEl) {
if (type === "input") {
if (
inpName === "csrf_token" ||
inpName === "OLD_SERVER_NAME" ||
inpName === "mode" ||
inpName === "security-level" ||
inpName === "is_draft" ||
inpName === "operation" ||
inpName === "settings-filter" ||
inp.hasAttribute("data-combobox") ||
(containerEl === this.simpleForm && inpName === "SERVER_NAME")
)
return true;
}
if (type === "select") {
if (
inpName === "csrf_token" ||
inpName === "OLD_SERVER_NAME" ||
inpName === "mode" ||
inpName === "security-level" ||
inpName === "is_draft" ||
inpName === "operation" ||
inpName === "settings-filter" ||
inp.hasAttribute("data-combobox") ||
(containerEl === this.simpleForm && inpName === "SECURITY_LEVEL")
)
return true;
}
return false;
}
@ -413,7 +458,7 @@ class ServiceModal {
inps.forEach((inp) => {
// form related values are excludes
const inpName = inp.getAttribute("name");
if (this.isAvoidInpList(inp, inpName)) return;
if (this.isAvoidInpList("input", inp, inpName, parentEl)) return;
//for all other settings values
const defaultMethod = inp.getAttribute(attMethodName);
@ -428,6 +473,16 @@ class ServiceModal {
// Select only
const selects = parentEl.querySelectorAll("select");
selects.forEach((select) => {
if (
this.isAvoidInpList(
"select",
select,
select.getAttribute("name"),
parentEl,
)
)
return;
const defaultMethod = select.getAttribute(attMethodName);
const defaultVal = select.getAttribute(attValueName);
//click the custom select dropdown to update select value
@ -728,7 +783,7 @@ class ServiceModal {
//form related values are excludes
const inpName = inp.getAttribute("name");
if (this.isAvoidInpList(inp, inpName)) return;
if (this.isAvoidInpList("input", inp, inpName, this.modal)) return;
//SET DISABLED / ENABLED
//for regular input
@ -753,7 +808,7 @@ class ServiceModal {
}
// Reset simple mode, we want to override default value by default security level
// this.resetSimpleMode();
this.resetSimpleMode();
// Global reset
this.resetFilterInp();

View file

@ -126,6 +126,7 @@ class Select {
selectCustom.querySelector(`[data-setting-select-text]`).textContent =
btnValue;
//add selected to new value
selectCustom
.querySelector(`[data-setting-select-text]`)
.setAttribute("data-value", btnValue);

View file

@ -99,7 +99,7 @@
<input type="hidden" id="operation" value="new" name="operation" />
<input type="hidden" value="new" name="OLD_SERVER_NAME" />
<input type="hidden" value="no" name="is_draft" />
<input type="hidden" value="mode" name="advanced" />
<input type="hidden" value="advanced" name="mode" />
{% include "settings_plugins.html" %}
<!-- action button -->

View file

@ -3,8 +3,8 @@
"name" : "STEP 1 - STARTING UP",
"description" : "we need some information to get started.",
"settings" : [
{"plugin_id" : "general", "setting_id": "SERVER_NAME", "title" : "DEFINE HOST", "subtitle" : "We need this to connect BunkerWeb to your application. You need to set your domain name.", "levels" : False },
{"plugin_id" : "security-level", "setting_id": "SECURITY_LEVEL", "title" : "DEFINE SECURITY LEVEL", "subtitle" : "This will determine default settings value for the next steps. You'll be allow to modify settings to match your case if needed.", "levels" : False, "setting" : {'context': 'global', 'default': 'standard', 'help': 'Determine the default settings value. You can override them.', 'id': 'security-level', 'label': 'Security level', 'regex': '^(standard|advanced|bunker)$', 'type': 'select', 'select': ['standard', 'advanced', 'bunker']} }
{"plugin_id" : "general", "setting_id": "SERVER_NAME", "title" : "DEFINE HOST", "subtitle" : "We need this to connect BunkerWeb to your application. You need to set your domain name.", "levels" : {} },
{"plugin_id" : "security-level", "setting_id": "SECURITY_LEVEL", "title" : "DEFINE SECURITY LEVEL", "subtitle" : "This will determine default settings value for the next steps. You'll be allow to modify settings to match your case if needed.", "levels" : {}, "setting" : {'context': 'global', 'default': 'standard', 'help': 'Determine the default settings value. You can override them.', 'id': 'security-level', 'label': 'Security level', 'regex': '^(standard|advanced|bunker)$', 'type': 'select', 'select': ['standard', 'elevated', 'lockdown']} }
],
"configs": [
{"name": "my_config_1", "type": "modsec", "data": "..."},
@ -15,7 +15,7 @@
"name" : "STEP 2 - ANTIBOT",
"description" : "Avoid spammer and bot to access your website.",
"settings" : [
{"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.", "levels" : {"standard" : "no", "advanced" : "no", "high" : "no"} },
{"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.", "levels" : {"standard" : "no", "elevated" : "javascript", "lockdown" : "javascript"} },
],
"configs": [
{"name": "my_config_1", "type": "modsec", "data": "..."},
@ -46,7 +46,7 @@
<input type="hidden" value="new" name="operation" />
<input type="hidden" value="" name="OLD_SERVER_NAME" />
<input type="hidden" value="no" name="is_draft" />
<input type="hidden" value="mode" name="easy" />
<input type="hidden" value="easy" name="mode" />
{% for step in steps %}
<div data-step="{{loop.index}}" class="flex flex-col {% if loop.index != 1 %} hidden {% endif %}">

View file

@ -5,6 +5,7 @@
{% set inp_regex = setting_input['regex'] %}
{% set inp_default = setting_input['default'] %}
{% set inp_value = setting_input['value'] %}
{% set inp_levels = setting_input['levels'] %}
{% set global_config_method = global_config.get(inp_name, {'method' : inp_method }).get('method') %}
{% set global_config_value = global_config.get(inp_name, {'value' : inp_value }).get('value') %}
@ -22,7 +23,11 @@
class="checkbox"
type="checkbox"
data-pattern="{{ inp_regex|safe }}"
value="{{ global_config_value }}" />
value="{{ global_config_value }}"
{% for level_name, value in inp_levels.items() %}
data-security-level-{{level_name}}="{{value}}"
{% endfor %}
/>
<svg data-checkbox-handler="{{ inp_id }}"
class="pointer-events-none absolute fill-white dark:fill-gray-300 left-0 top-0 translate-x-1 translate-y-2 h-3 w-3"
xmlns="http://www.w3.org/2000/svg"

View file

@ -6,6 +6,7 @@
{% set inp_default = setting_input['default'] %}
{% set inp_value = setting_input['value'] %}
{% set inp_regex = setting_input['regex'] %}
{% set inp_levels = setting_input['levels'] %}
{% set global_config_method = global_config.get(inp_name, {'method' : inp_method }).get('method') %}
{% set global_config_value = global_config.get(inp_name, {'value' : inp_value }).get('value') %}
@ -21,7 +22,11 @@
class="regular-input"
value="{% if global_config_value %} {{ global_config_value }} {% else %} {{ inp_default }} {% endif %}"
type="{{ inp_type }}"
pattern="{{ inp_regex|safe }}" />
pattern="{{ inp_regex|safe }}"
{% for level_name, value in inp_levels.items() %}
data-security-level-{{level_name}}="{{value}}"
{% endfor %}
/>
{% if inp_type == "password" %}
<div data-setting-password-container class="absolute flex right-2 h-5 w-5">
<button type="button"

View file

@ -5,6 +5,7 @@
{% set inp_value = setting_input['value'] %}
{% set inp_method = setting_input['method'] %}
{% set inp_items = setting_input['select'] %}
{% set inp_levels = setting_input['levels'] %}
{% set inp_id = setting_input['id'] %}
{% set inp_is_simple = setting_input['is_simple'] %}
{% set global_config_method = global_config.get(inp_name, {'method' : inp_method }).get('method') %}
@ -17,7 +18,11 @@
name="{{ inp_name_mult }}"
data-setting-select-default="{{ inp_id }}"
data-type="form-select"
class="hidden">
class="hidden"
{% for level_name, value in inp_levels.items() %}
data-security-level-{{level_name}}="{{value}}"
{% endfor %}
>
{% for item in inp_items %}
<option {% if not item %}label="empty"{% endif %}
value="{{ item }}"
@ -35,6 +40,9 @@
data-default-method="{{ global_config_method }}"
aria-controls="{{ inp_id }}-dropdown"
type="button"
{% for level_name, value in inp_levels.items() %}
data-security-level-{{level_name}}="{{value}}"
{% endfor %}
class="custom-select-btn">
{% for item in inp_items %}
{% if global_config_value and

View file

@ -52,7 +52,7 @@
<div data-plugin-settings class="w-full grid grid-cols-12">
<!-- plugin settings not multiple -->
{% for setting, value in plugin["settings"].items() %}
{% set setting_input = { "name" : setting, "context" : value.get("context"), "method" : value.get("method"), "help" : value.get("help"), "label" : value.get("label"), "id" : value.get("id"), "type" : value.get("type"), "default" : value.get("default"), "select" : value.get("select"), "regex" : value.get("regex"), "value" : value.get("value"), "is_multiple" : False} %}
{% set setting_input = { "name" : setting, "context" : value.get("context"), "method" : value.get("method"), "help" : value.get("help"), "label" : value.get("label"), "id" : value.get("id"), "type" : value.get("type"), "default" : value.get("default"), "select" : value.get("select"), "regex" : value.get("regex"), "value" : value.get("value"), "is_multiple" : False, "levels" : value.get('levels', {})} %}
{% if setting != "IS_DRAFT" and (current_endpoint == "global-config" and setting not in ["SERVER_NAME", "IS_LOADING"] or current_endpoint == "services" and value['context'] == "multisite") %}
{% if value['multiple'] and value['multiple'] not in multList %}
@ -96,7 +96,7 @@
<!-- multiple settings -->
<div data-{{ current_endpoint }}-settings-multiple="{{ multiple }}_SCHEMA" class="bg-gray-50 dark:bg-slate-900/30 hidden w-full my-4 grid-cols-12 border dark:border-gray-700 rounded">
{% for setting, value in plugin["settings"].items() %}
{% set setting_input = { "name" : setting, "context" : value.get("context"), "method" : value.get("method"), "help" : value.get("help"), "label" : value.get("label"), "id" : value.get("id"), "type" : value.get("type"), "default" : value.get("default"), "select" : value.get("select"), "regex" : value.get("regex"), "value" : value.get("value"), "is_multiple" : True} %}
{% set setting_input = { "name" : setting, "context" : value.get("context"), "method" : value.get("method"), "help" : value.get("help"), "label" : value.get("label"), "id" : value.get("id"), "type" : value.get("type"), "default" : value.get("default"), "select" : value.get("select"), "regex" : value.get("regex"), "value" : value.get("value"), "is_multiple" : True, "levels" : value.get('levels', {})} %}
{# render only setting that match the multiple id and context #}
{% if value['multiple'] == multiple and (

View file

@ -2,7 +2,7 @@
<!-- plugin item -->
{% for setting_simple in plugin_simple %}
{% set setting_input = { "name" : setting_simple.get('setting_id'), "method" : setting_simple.get('setting').get("method", "default"), "help" : setting_simple.get('setting').get("help"), "label" : setting_simple.get('setting').get("label"), "id" : setting_simple.get('setting').get("id"), "type" : setting_simple.get('setting').get("type"), "default" : setting_simple.get('setting').get("default", "default"), "select" : setting_simple.get('setting').get("select"), "regex" : setting_simple.get('setting').get("regex"), "value" : setting_simple.get('setting').get("value"), "is_multiple" : True if setting_simple.get('setting').get("type") == "multiple" else False } %}
{% set setting_input = { "name" : setting_simple.get('setting_id'), "method" : setting_simple.get('setting').get("method", "default"), "help" : setting_simple.get('setting').get("help"), "label" : setting_simple.get('setting').get("label"), "id" : setting_simple.get('setting').get("id"), "type" : setting_simple.get('setting').get("type"), "default" : setting_simple.get('setting').get("default", "default"), "select" : setting_simple.get('setting').get("select"), "regex" : setting_simple.get('setting').get("regex"), "value" : setting_simple.get('setting').get("value"), "is_multiple" : True if setting_simple.get('setting').get("type") == "multiple" else False, "levels" : setting_simple.get('levels', {}) } %}
<div data-simple id="{{ setting_simple['plugin_id'] }}-simple"
class="w-full px-1 mb-2">
<!-- title and desc -->