start adding global config page + fix

* fix missing columns on some form components
* fix raw form rendering
* update globalconfig tests
* add all forms utils and global_config_builder to builder.py
This commit is contained in:
Jordan Blasenhauer 2024-07-23 10:07:46 +02:00
parent 162e7a43e9
commit d1cafdc3c0
10 changed files with 4937 additions and 805 deletions

View file

@ -1,5 +1,6 @@
import base64
import json
import copy
def stat_widget(link, containerColums, title, subtitle, subtitle_color, stat, icon_name):
@ -116,7 +117,7 @@ def home_builder(data):
title="home_plugins",
subtitle="home_errors_found" if data.get("plugins_errors") > 0 else "home_no_error",
subtitle_color="error" if data.get("plugins_errors") > 0 else "success",
stat="42",
stat=data.get("plugins_number"),
icon_name="puzzle",
)
@ -169,3 +170,421 @@ def instances_builder(instances: list):
builder.append(instance)
return base64.b64encode(bytes(json.dumps(builder), "utf-8")).decode("ascii")
def get_forms(templates=[], plugins=[], settings={}):
"""
Will generate every needed form using templates, plugins and settings.
We will run on each plugins, set template value if one, and override by the custom settings value if exists.
We will format to fit each form type (easy, advanced, raw).
"""
forms = {"advanced": {}, "easy": {}, "raw": {}}
for template in templates:
forms["advanced"][template.get("name")] = set_advanced(template, plugins, settings)
forms["raw"][template.get("name")] = set_raw(template, plugins, settings)
forms["easy"][template.get("name")] = set_easy(template, plugins, settings)
return forms
def set_easy(template, plugins_base, settings):
"""
Prepare the easy form based on the template and plugins data.
We need to loop on each steps and prepare settings and configs for each step.
"""
template_settings = template.get("settings")
plugins = copy.deepcopy(plugins_base)
steps = template.get("steps")
for step in steps:
step_settings = step.get("settings", {})
# Loop on step settings to set the settings value
loop_id = 0
step_settings_output = {}
for setting in step_settings:
loop_id += 1
# Get relate setting from plugins using setting name
plugin = next(
(plugin for plugin in plugins if setting in plugin.get("settings")),
None,
)
if not plugin:
continue
if not plugin.get("settings").get(setting):
continue
plugin_setting = copy.deepcopy(plugin.get("settings").get(setting))
plugin_setting = format_setting(
setting,
plugin_setting,
len(step_settings),
loop_id,
template_settings,
settings,
)
step_settings_output[setting] = plugin_setting
step["settings"] = step_settings_output
return steps
def set_raw(template, plugins_base, settings):
"""
Set the raw form based on the template and plugins data.
It consists of keeping only the value or default value for each plugin settings.
"""
template_settings = template.get("settings")
raw_settings = {}
# Copy of the plugins base
plugins = copy.deepcopy(plugins_base)
# Update settings with global config data
for plugin in plugins:
for setting, value in plugin.get("settings").items():
# avoid some methods from services_settings
if setting in settings and settings[setting].get("method", "ui") not in ("ui", "default", "manual"):
continue
raw_value = None
# Start by setting template value if exists
if setting in template_settings:
# Update value or set default as value
raw_value = template_settings.get(setting, value.get("default"))
# Then override by service settings
if setting in settings:
raw_value = settings[setting].get("value", value.get("value", value.get("default")))
# Add value only if exists
if raw_value:
raw_settings[setting] = raw_value
return raw_settings
def set_advanced(template, plugins_base, settings):
"""
Set the advanced form based on the template and plugins data.
It consists of formatting each plugin settings to be used in the advanced form.
"""
template_settings = template.get("settings")
# Copy of the plugins base data
plugins = copy.deepcopy(plugins_base)
# Update settings with global config data
for plugin in plugins:
loop_id = 0
total_settings = len(plugin.get("settings"))
for setting, value in plugin.get("settings").items():
loop_id += 1
value = format_setting(
setting,
value,
total_settings,
loop_id,
template_settings,
settings,
)
set_multiples(template, plugins, settings)
return plugins
def get_multiple_from_template(template, multiples):
"""
We are gonna loop on each plugins multiples group, in case a setting is matching a template setting,
we will create a group using the prefix as key (or "0" if no prefix) with default settings at first.
Then we will override by the template value in case there is one.
This will return something of this type :
{'0' : {'setting' : value, 'setting2': value2}, '1' : {'setting_1': value, 'setting2_1': value}} }
"""
# Loop on each plugin and loop on multiples key
# Check if the name us matching a template key
multiple_plugin = copy.deepcopy(multiples)
multiple_template = {}
for setting, value in template.get("settings").items():
# Sanitize setting name to remove prefix of type _1 if exists
# Slipt by _ and check if last element is a digit
format_setting = setting
setting_split = setting.split("_")
prefix = "0"
if setting_split[-1].isdigit():
prefix = setting_split[-1]
format_setting = "_".join(setting_split[:-1])
# loop on settings of a multiple group
for mult_name, mult_settings in multiple_plugin.items():
# Check if at least one multiple plugin setting is matching the template setting
if format_setting in mult_settings:
if not mult_name in multiple_template:
multiple_template[mult_name] = {}
# Case it is, we will check if already a group with the right prefix exists
# If not, we will create it
if not prefix in multiple_template[mult_name]:
# We want each settings to have the prefix if exists
# We will get the value of the setting without the prefix and create a prefix key with the same value
# And after that we can delete the original setting
new_multiple_group = {}
for multSett, multValue in mult_settings.items():
new_multiple_group[f"{multSett}{f'_{prefix}' if prefix != '0' else ''}"] = multValue
new_multiple_group = copy.deepcopy(new_multiple_group)
# Update id for each settings
for multSett, multValue in new_multiple_group.items():
multValue["id"] = f"{multValue['id']}{f'-{prefix}' if prefix != '0' else ''}"
multiple_template[mult_name][prefix] = new_multiple_group
# We can now add the template value to setting using the same setting name with prefix
multiple_template[mult_name][prefix][setting]["value"] = value
# Sort key incrementally
for mult_name, mult_settings in multiple_template.items():
multiple_template[mult_name] = dict(sorted(mult_settings.items(), key=lambda item: int(item[0])))
return multiple_template
def get_multiple_from_settings(settings, multiples):
"""
We are gonna loop on each plugins multiples group, in case a setting is matching a service / global config setting,
we will create a group using the prefix as key (or "0" if no prefix) with default settings at first.
Then we will override by the service / global config value in case there is one.
This will return something of this type :
{'0' : {'setting' : value, 'setting2': value2}, '1' : {'setting_1': value, 'setting2_1': value}} }
"""
# Loop on each plugin and loop on multiples key
# Check if the name us matching a template key
multiple_plugins = copy.deepcopy(multiples)
multiple_settings = {}
for setting, value in settings.items():
# Sanitize setting name to remove prefix of type _1 if exists
# Slipt by _ and check if last element is a digit
format_setting = setting
setting_split = setting.split("_")
prefix = "0"
if setting_split[-1].isdigit():
prefix = setting_split[-1]
format_setting = "_".join(setting_split[:-1])
# loop on settings of a multiple group
for mult_name, mult_settings in multiple_plugins.items():
# Check if at least one multiple plugin setting is matching the template setting
if format_setting in mult_settings:
if not mult_name in multiple_settings:
multiple_settings[mult_name] = {}
# Case it is, we will check if already a group with the right prefix exists
# If not, we will create it
if not prefix in multiple_settings:
# We want each settings to have the prefix if exists
# We will get the value of the setting without the prefix and create a prefix key with the same value
# And after that we can delete the original setting
new_multiple_group = {}
for multSett, multValue in mult_settings.items():
new_multiple_group[f"{multSett}{f'_{prefix}' if prefix != '0' else ''}"] = multValue
new_multiple_group = copy.deepcopy(new_multiple_group)
# Update id for each settings
for multSett, multValue in new_multiple_group.items():
multValue["id"] = f"{multValue['id']}{f'-{prefix}' if prefix != '0' else ''}"
multiple_settings[mult_name][prefix] = new_multiple_group
# We can now add the template value to setting using the same setting name with prefix
multiple_settings[mult_name][prefix][setting]["value"] = value.get("value", multiple_settings[mult_name][prefix][setting]["value"])
multiple_settings[mult_name][prefix][setting]["method"] = value.get("method", "ui")
multiple_settings[mult_name][prefix][setting]["disabled"] = False if value.get("method", "ui") in ("ui", "default", "manual") else True
if multiple_settings[mult_name][prefix][setting].get("disabled", False):
multiple_settings[mult_name][prefix][setting]["popovers"] = [
{
"iconName": "trespass",
"text": "inp_popover_method_disabled",
}
] + multiple_settings[mult_name][prefix][setting].get("popovers", [])
return multiple_settings
def set_multiples(template, format_plugins, service_settings):
"""
Set the multiples settings for each plugin.
"""
# copy of format plugins
for plugin in format_plugins:
# Get multiples
multiples = {}
settings_to_delete = []
total_settings = len(plugin.get("settings"))
zindex = 0
for setting, value in plugin.get("settings").items():
if not value.get("multiple"):
continue
zindex += 1
value["containerClass"] = f"z-{total_settings - zindex}"
mult_name = value.get("multiple")
# Get the multiple value and set it as key if not in multiples dict
if mult_name not in multiples:
multiples[mult_name] = {}
multiples[mult_name][setting] = value
settings_to_delete.append(setting)
# Delete multiple settings from regular settings
for setting in settings_to_delete:
del plugin["settings"][setting]
if len(multiples):
# Add multiple schema with default values to plugin
plugin["multiples_schema"] = multiples
# Now that we have for each plugin the multiples settings, we need to do the following
# Get all settings from template that are multiples
template_multiples = get_multiple_from_template(template, multiples)
# Get all settings from service settings / global config that are multiples
service_multiples = get_multiple_from_settings(service_settings, multiples)
# Get service multiples if at least one, else use template multiples
plugin["multiples"] = service_multiples if len(service_multiples) else template_multiples
return format_plugins
def format_setting(
setting_name,
setting_value,
total_settings,
loop_id,
template_settings,
service_settings,
):
"""
Format a setting in order to be used with form builder.
This will only set value for none multiple settings.
Additionnel set_multiples function will handle multiple settings.
"""
# add zindex for field in case not a multiple
# Case multiple, this will be set on the group level
if not "multiple" in setting_value:
setting_value["containerClass"] = f"z-{total_settings - loop_id}"
# regex by pattern
setting_value["pattern"] = setting_value.get("regex", "")
# set inpType based on type define for each settings
inpType = (
"checkbox"
if setting_value.get("type") == "check"
else ("select" if setting_value.get("type") == "select" else "datepicker" if setting_value.get("type") == "date" else "input")
)
setting_value["inpType"] = inpType
# set name using the label
setting_value["name"] = setting_value.get("label")
# case select
if inpType == "select":
# replace "select" key by "values"
setting_value["values"] = setting_value.pop("select")
# add columns
setting_value["columns"] = {"pc": 4, "tablet": 6, "mobile": 12}
# By default, the input is enabled unless specific method
setting_value["disabled"] = False
setting_value["value"] = setting_value.get("default")
# Start by setting template value if exists
if setting_name in template_settings and not "multiple" in setting_value:
# Update value or set default as value
setting_value["value"] = template_settings.get(setting_name, setting_value.get("default"))
# Then override by service settings if not a multiple
# Case multiple, we need to keep the default value and override only each multiple group
if setting_name in service_settings and not "multiple" in setting_value:
setting_value["value"] = service_settings[setting_name].get("value", setting_value.get("value", setting_value.get("default")))
setting_value["method"] = service_settings[setting_name].get("method", "ui")
# Then override by service settings
if setting_name in service_settings:
setting_value["disabled"] = False if service_settings[setting_name].get("method", "ui") in ("ui", "default", "manual") else True
# Prepare popover checking "help", "context"
popovers = []
if (setting_value.get("disabled", False)) and service_settings[setting_name].get("method", "ui") not in ("ui", "default", "manual"):
popovers.append(
{
"iconName": "trespass",
"text": "inp_popover_method_disabled",
}
)
if setting_value.get("context"):
popovers.append(
{
"iconName": ("disk" if setting_value.get("context") == "multisite" else "globe"),
"text": ("inp_popover_multisite" if setting_value.get("context") == "multisite" else "inp_popover_global"),
}
)
if setting_value.get("help"):
popovers.append(
{
"iconName": "info",
"text": setting_value.get("help"),
}
)
setting_value["popovers"] = popovers
return setting_value
def global_config_builder(plugins, settings):
"""Render forms with global config data.
ATM we don't need templates but we need to pass at least one to the function (it will simply not override anything).
"""
templates = [
{
"name": "default",
"steps": [],
"configs": {},
"settings": {},
}
]
builder = [
{
"type": "card",
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
"widgets": [
{
"type": "Title",
"data": {"title": "global_config_title", "type": "container"},
},
{
"type": "Subtitle",
"data": {"subtitle": "global_config_subtitle", "type": "container"},
},
{
"type": "Templates",
"data": {
"templates": get_forms(templates, plugins, settings),
},
},
],
}
]
return base64.b64encode(bytes(json.dumps(builder), "utf-8")).decode("ascii")

View file

@ -100,11 +100,7 @@ const buttonSave = {
color: "success",
size: "normal",
type: "button",
attrs: {
"data-submit-form": JSON.stringify(advancedForm.templateBase),
},
containerClass: "flex justify-center",
iconName: "plus",
};
const filters = [

View file

@ -60,7 +60,7 @@ const props = defineProps({
columns: {
type: Object,
required: false,
default: {},
default: { pc: 12, tablet: 12, mobile: 12 },
},
});
@ -90,7 +90,7 @@ function setValidity() {
}
const buttonSave = {
id: uuidv4(),
id: `easy-mode-${uuidv4()}`,
text: "action_save",
color: "success",
size: "normal",
@ -99,14 +99,14 @@ const buttonSave = {
};
const buttonPrev = {
id: uuidv4(),
id: `easy-mode-${uuidv4()}`,
text: "action_previous",
color: "info",
size: "normal",
};
const buttonNext = {
id: uuidv4(),
id: `easy-mode-${uuidv4()}`,
text: "action_next",
color: "info",
size: "normal",

View file

@ -39,7 +39,7 @@ const props = defineProps({
columns: {
type: Object,
required: false,
default: {},
default: { pc: 12, tablet: 12, mobile: 12 },
},
});
@ -126,12 +126,6 @@ const buttonSave = {
color: "success",
size: "normal",
containerClass: "flex justify-center",
attrs: data.isValid
? {
"data-submit-form":
data.inp.replace(/\n/g, "") || data.entry.replace(/\n/g, ""),
}
: {},
};
</script>

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@ import json
import copy
import base64
# Default plugins from docker-compose.ui.yml
plugins = [
{
"id": "general",
@ -3002,76 +3002,344 @@ plugins = [
},
]
template_settings = {
"ERRORS": "",
"USE_UI": "no",
"USE_CORS": "no",
"REVERSE_PROXY_HOST_1": "template1",
"REVERSE_PROXY_HOST_2": "template2",
}
# Service settings
service_settings = {
"ERRORS": {"value": "", "global": True, "method": "scheduler"},
"USE_UI": {"value": "yes", "global": True, "method": "ui"},
"USE_CORS": {"value": "yes", "global": True, "method": "scheduler"},
"REVERSE_PROXY_HOST_1": {"value": "yes", "global": True, "method": "scheduler"},
"REVERSE_PROXY_HOST": {"value": "no", "global": True, "method": "ui"},
}
# Default template
default_template = {
"name": "default",
"steps": [
{
"title": "Title 1",
"subtitle": "subtitle 1",
"settings": ["USE_UI", "USE_CORS"],
},
{
"title": "Title 2",
"subtitle": "subtitle 2",
"settings": ["USE_UI", "USE_CORS"],
},
],
"configs": {},
"settings": {
"USE_UI": "no",
"USE_CORS": "no",
"USE_GZIP": "dsfrgrdgrdgrdhgd",
"REVERSE_PROXY_HOST_1": "template1",
"REVERSE_PROXY_HOST_2": "template2",
"REVERSE_PROXY_HOST": "template",
# Default global config with methods=True from docker-compose.ui.yml
global_config = {
"ERRORS": {"value": "", "global": True, "method": "default"},
"USE_UI": {"value": "no", "global": True, "method": "default"},
"USE_CORS": {"value": "no", "global": True, "method": "default"},
"USE_GZIP": {"value": "yes", "global": True, "method": "scheduler"},
"USE_DNSBL": {"value": "yes", "global": True, "method": "default"},
"USE_REDIS": {"value": "no", "global": True, "method": "default"},
"IS_LOADING": {"value": "no", "global": True, "method": "default"},
"REMOTE_PHP": {"value": "", "global": True, "method": "default"},
"USE_BACKUP": {"value": "yes", "global": True, "method": "default"},
"USE_BROTLI": {"value": "no", "global": True, "method": "default"},
"INJECT_BODY": {"value": "", "global": True, "method": "default"},
"REDIRECT_TO": {"value": "", "global": True, "method": "default"},
"USE_ANTIBOT": {"value": "no", "global": True, "method": "default"},
"USE_METRICS": {"value": "yes", "global": True, "method": "default"},
"USE_REAL_IP": {"value": "no", "global": True, "method": "default"},
"DATABASE_URI": {"value": "sqlite:////var/lib/bunkerweb/db.sqlite3", "global": True, "method": "default"},
"USE_GREYLIST": {"value": "no", "global": True, "method": "default"},
"CUSTOM_HEADER": {"value": "", "global": True, "method": "default"},
"USE_BLACKLIST": {"value": "no", "global": True, "method": "scheduler"},
"USE_BUNKERNET": {"value": "no", "global": True, "method": "scheduler"},
"USE_LIMIT_REQ": {"value": "yes", "global": True, "method": "default"},
"USE_WHITELIST": {"value": "no", "global": True, "method": "scheduler"},
"USE_AUTH_BASIC": {"value": "no", "global": True, "method": "default"},
"USE_CUSTOM_SSL": {"value": "no", "global": True, "method": "default"},
"PRO_LICENSE_KEY": {"value": "", "global": True, "method": "default"},
"SESSIONS_SECRET": {"value": "random", "global": True, "method": "default"},
"USE_MODSECURITY": {"value": "yes", "global": True, "method": "default"},
"USE_BAD_BEHAVIOR": {"value": "yes", "global": True, "method": "default"},
"USE_CLIENT_CACHE": {"value": "yes", "global": True, "method": "scheduler"},
"USE_REVERSE_SCAN": {"value": "no", "global": True, "method": "default"},
"AUTO_LETS_ENCRYPT": {"value": "no", "global": True, "method": "default"},
"BLACKLIST_COUNTRY": {"value": "", "global": True, "method": "default"},
"USE_REVERSE_PROXY": {"value": "no", "global": True, "method": "default"},
"DISABLE_DEFAULT_SERVER": {"value": "yes", "global": True, "method": "scheduler"},
"GENERATE_SELF_SIGNED_SSL": {"value": "no", "global": True, "method": "default"},
"UI_HOST": {"value": "", "global": True, "method": "default"},
"DNSBL_LIST": {"value": "bl.blocklist.de problems.dnsbl.sorbs.net sbl.spamhaus.org xbl.spamhaus.org", "global": True, "method": "default"},
"GZIP_TYPES": {
"value": "application/atom+xml application/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype application/x-font-ttf application/x-javascript application/xhtml+xml application/xml font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml",
"global": True,
"method": "default",
},
"REDIS_HOST": {"value": "", "global": True, "method": "default"},
"ANTIBOT_URI": {"value": "/challenge", "global": True, "method": "default"},
"GREYLIST_IP": {"value": "", "global": True, "method": "default"},
"BLACKLIST_IP": {"value": "", "global": True, "method": "default"},
"BROTLI_TYPES": {
"value": "application/atom+xml application/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype application/x-font-ttf application/x-javascript application/xhtml+xml application/xml font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml",
"global": True,
"method": "default",
},
"NGINX_PREFIX": {"value": "/etc/nginx/", "global": True, "method": "default"},
"WHITELIST_IP": {
"value": "20.191.45.212 40.88.21.235 40.76.173.151 40.76.163.7 20.185.79.47 52.142.26.175 20.185.79.15 52.142.24.149 40.76.162.208 40.76.163.23 40.76.162.191 40.76.162.247",
"global": True,
"method": "default",
},
"LIMIT_REQ_URL": {"value": "/", "global": True, "method": "default"},
"SESSIONS_NAME": {"value": "random", "global": True, "method": "default"},
"REMOVE_HEADERS": {"value": "Server Expect-CT X-Powered-By X-AspNet-Version X-AspNetMvc-Version Public-Key-Pins", "global": True, "method": "default"},
"BACKUP_SCHEDULE": {"value": "daily", "global": True, "method": "default"},
"CUSTOM_SSL_CERT": {"value": "", "global": True, "method": "default"},
"REMOTE_PHP_PATH": {"value": "", "global": True, "method": "default"},
"BUNKERNET_SERVER": {"value": "https://api.bunkerweb.io", "global": True, "method": "default"},
"CORS_ALLOW_ORIGIN": {"value": "self", "global": True, "method": "default"},
"WHITELIST_COUNTRY": {"value": "", "global": True, "method": "default"},
"EMAIL_LETS_ENCRYPT": {"value": "", "global": True, "method": "default"},
"REVERSE_SCAN_PORTS": {"value": "22 80 443 3128 8000 8080", "global": True, "method": "default"},
"USE_PROXY_PROTOCOL": {"value": "no", "global": True, "method": "default"},
"AUTH_BASIC_LOCATION": {"value": "sitewide", "global": True, "method": "default"},
"METRICS_MEMORY_SIZE": {"value": "16m", "global": True, "method": "default"},
"USE_MODSECURITY_CRS": {"value": "yes", "global": True, "method": "default"},
"DATABASE_URI_READONLY": {"value": "", "global": True, "method": "default"},
"SELF_SIGNED_SSL_EXPIRY": {"value": "365", "global": True, "method": "default"},
"CLIENT_CACHE_EXTENSIONS": {"value": "jpg|jpeg|png|bmp|ico|svg|tif|css|js|otf|ttf|eot|woff|woff2", "global": True, "method": "default"},
"INTERCEPTED_ERROR_CODES": {"value": "400 401 403 404 405 413 429 500 501 502 503 504", "global": True, "method": "default"},
"REDIRECT_TO_REQUEST_URI": {"value": "no", "global": True, "method": "default"},
"BAD_BEHAVIOR_STATUS_CODES": {"value": "400 401 403 404 405 429 444", "global": True, "method": "default"},
"REVERSE_PROXY_INTERCEPT_ERRORS": {"value": "yes", "global": True, "method": "default"},
"DISABLE_DEFAULT_SERVER_STRICT_SNI": {"value": "no", "global": True, "method": "default"},
"HTTP_PORT": {"value": "8080", "global": True, "method": "default"},
"LOCAL_PHP": {"value": "", "global": True, "method": "default"},
"REDIS_PORT": {"value": "6379", "global": True, "method": "default"},
"REAL_IP_FROM": {"value": "192.168.0.0/16 172.16.0.0/12 10.0.0.0/8", "global": True, "method": "default"},
"GREYLIST_RDNS": {"value": "", "global": True, "method": "default"},
"BLACKLIST_RDNS": {"value": ".shodan.io .censys.io", "global": True, "method": "default"},
"CUSTOM_SSL_KEY": {"value": "", "global": True, "method": "default"},
"LIMIT_REQ_RATE": {"value": "2r/s", "global": True, "method": "default"},
"WHITELIST_RDNS": {
"value": ".google.com .googlebot.com .yandex.ru .yandex.net .yandex.com .search.msn.com .baidu.com .baidu.jp .crawl.yahoo.net .fwd.linkedin.com .twitter.com .twttr.com .discord.com",
"global": True,
"method": "default",
},
"AUTH_BASIC_USER": {"value": "changeme", "global": True, "method": "default"},
"BACKUP_ROTATION": {"value": "7", "global": True, "method": "default"},
"GZIP_MIN_LENGTH": {"value": "1000", "global": True, "method": "default"},
"BROTLI_MIN_LENGTH": {"value": "1000", "global": True, "method": "default"},
"CLIENT_CACHE_ETAG": {"value": "yes", "global": True, "method": "default"},
"CORS_ALLOW_METHODS": {"value": "GET, POST, OPTIONS", "global": True, "method": "default"},
"DATABASE_LOG_LEVEL": {"value": "warning", "global": True, "method": "default"},
"ANTIBOT_TIME_RESOLVE": {"value": "60", "global": True, "method": "default"},
"REVERSE_SCAN_TIMEOUT": {"value": "500", "global": True, "method": "default"},
"SELF_SIGNED_SSL_SUBJ": {"value": "/CN=www.example.com/", "global": True, "method": "default"},
"KEEP_UPSTREAM_HEADERS": {"value": "Content-Security-Policy Permissions-Policy X-Frame-Options", "global": True, "method": "default"},
"BAD_BEHAVIOR_THRESHOLD": {"value": "10", "global": True, "method": "default"},
"REDIRECT_HTTP_TO_HTTPS": {"value": "no", "global": True, "method": "default"},
"REDIRECT_TO_STATUS_CODE": {"value": "301", "global": True, "method": "default"},
"SESSIONS_IDLING_TIMEOUT": {"value": "1800", "global": True, "method": "default"},
"USE_LETS_ENCRYPT_STAGING": {"value": "no", "global": True, "method": "default"},
"REVERSE_PROXY_CUSTOM_HOST": {"value": "", "global": True, "method": "default"},
"USE_MODSECURITY_CRS_PLUGINS": {"value": "yes", "global": True, "method": "default"},
"METRICS_MAX_BLOCKED_REQUESTS": {"value": "100", "global": True, "method": "default"},
"HTTPS_PORT": {"value": "8443", "global": True, "method": "default"},
"LOCAL_PHP_PATH": {"value": "", "global": True, "method": "default"},
"REAL_IP_HEADER": {"value": "X-Forwarded-For", "global": True, "method": "default"},
"REDIS_DATABASE": {"value": "0", "global": True, "method": "default"},
"USE_LIMIT_CONN": {"value": "yes", "global": True, "method": "default"},
"GZIP_COMP_LEVEL": {"value": "5", "global": True, "method": "default"},
"BACKUP_DIRECTORY": {"value": "/var/lib/bunkerweb/backups", "global": True, "method": "default"},
"BROTLI_COMP_LEVEL": {"value": "6", "global": True, "method": "default"},
"ANTIBOT_TIME_VALID": {"value": "86400", "global": True, "method": "default"},
"CORS_ALLOW_HEADERS": {"value": "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range", "global": True, "method": "default"},
"AUTH_BASIC_PASSWORD": {"value": "changeme", "global": True, "method": "default"},
"CLIENT_CACHE_CONTROL": {"value": "public, max-age=15552000", "global": True, "method": "default"},
"CUSTOM_SSL_CERT_DATA": {"value": "", "global": True, "method": "default"},
"GREYLIST_RDNS_GLOBAL": {"value": "yes", "global": True, "method": "default"},
"BLACKLIST_RDNS_GLOBAL": {"value": "yes", "global": True, "method": "default"},
"REVERSE_PROXY_SSL_SNI": {"value": "no", "global": True, "method": "default"},
"WHITELIST_RDNS_GLOBAL": {"value": "yes", "global": True, "method": "default"},
"BAD_BEHAVIOR_COUNT_TIME": {"value": "60", "global": True, "method": "default"},
"MODSECURITY_CRS_VERSION": {"value": "4", "global": True, "method": "default"},
"SESSIONS_ROLLING_TIMEOUT": {"value": "3600", "global": True, "method": "default"},
"STRICT_TRANSPORT_SECURITY": {"value": "max-age=31536000; includeSubDomains; preload", "global": True, "method": "default"},
"AUTO_REDIRECT_HTTP_TO_HTTPS": {"value": "yes", "global": True, "method": "default"},
"LETS_ENCRYPT_CLEAR_OLD_CERTS": {"value": "no", "global": True, "method": "default"},
"MULTISITE": {"value": "yes", "global": True, "method": "scheduler"},
"REDIS_SSL": {"value": "no", "global": True, "method": "default"},
"COOKIE_FLAGS": {"value": "* HttpOnly SameSite=Lax", "global": True, "method": "default"},
"GREYLIST_ASN": {"value": "", "global": True, "method": "default"},
"GZIP_PROXIED": {"value": "no-cache no-store private expired auth", "global": True, "method": "default"},
"BLACKLIST_ASN": {"value": "", "global": True, "method": "default"},
"WHITELIST_ASN": {"value": "32934", "global": True, "method": "default"},
"ALLOWED_METHODS": {"value": "GET|POST|HEAD", "global": True, "method": "default"},
"AUTH_BASIC_TEXT": {"value": "Restricted area", "global": True, "method": "default"},
"REAL_IP_RECURSIVE": {"value": "yes", "global": True, "method": "default"},
"CUSTOM_SSL_KEY_DATA": {"value": "", "global": True, "method": "default"},
"LIMIT_CONN_MAX_HTTP1": {"value": "10", "global": True, "method": "default"},
"BAD_BEHAVIOR_BAN_TIME": {"value": "86400", "global": True, "method": "default"},
"CORS_ALLOW_CREDENTIALS": {"value": "no", "global": True, "method": "default"},
"ANTIBOT_RECAPTCHA_SCORE": {"value": "0.7", "global": True, "method": "default"},
"SESSIONS_ABSOLUTE_TIMEOUT": {"value": "86400", "global": True, "method": "default"},
"REVERSE_PROXY_SSL_SNI_NAME": {"value": "", "global": True, "method": "default"},
"MODSECURITY_CRS_PLUGIN_URLS": {"value": "", "global": True, "method": "default"},
"SERVER_NAME": {"value": "app1.example.com www.example.com", "global": True, "method": "default"},
"MAX_CLIENT_SIZE": {"value": "10m", "global": True, "method": "default"},
"REDIS_SSL_VERIFY": {"value": "no", "global": True, "method": "default"},
"REAL_IP_FROM_URLS": {"value": "", "global": True, "method": "default"},
"SESSIONS_CHECK_IP": {"value": "yes", "global": True, "method": "default"},
"REVERSE_PROXY_HOST": {"value": "", "global": True, "method": "default"},
"CORS_EXPOSE_HEADERS": {"value": "Content-Length,Content-Range", "global": True, "method": "default"},
"GREYLIST_USER_AGENT": {"value": "", "global": True, "method": "default"},
"BLACKLIST_USER_AGENT": {"value": "", "global": True, "method": "default"},
"LIMIT_CONN_MAX_HTTP2": {"value": "100", "global": True, "method": "default"},
"WHITELIST_USER_AGENT": {"value": "", "global": True, "method": "default"},
"COOKIE_AUTO_SECURE_FLAG": {"value": "yes", "global": True, "method": "default"},
"ANTIBOT_RECAPTCHA_SITEKEY": {"value": "", "global": True, "method": "default"},
"MODSECURITY_SEC_AUDIT_ENGINE": {"value": "RelevantOnly", "global": True, "method": "default"},
"SERVE_FILES": {"value": "no", "global": True, "method": "scheduler"},
"GREYLIST_URI": {"value": "", "global": True, "method": "default"},
"BLACKLIST_URI": {"value": "", "global": True, "method": "default"},
"REDIS_TIMEOUT": {"value": "1000", "global": True, "method": "default"},
"WHITELIST_URI": {"value": "", "global": True, "method": "default"},
"WORKER_PROCESSES": {"value": "auto", "global": True, "method": "default"},
"REVERSE_PROXY_URL": {"value": "/", "global": True, "method": "default"},
"LIMIT_CONN_MAX_STREAM": {"value": "10", "global": True, "method": "default"},
"CONTENT_SECURITY_POLICY": {"value": "object-src 'none'; form-action 'self'; frame-ancestors 'self';", "global": True, "method": "default"},
"ANTIBOT_RECAPTCHA_SECRET": {"value": "", "global": True, "method": "default"},
"SESSIONS_CHECK_USER_AGENT": {"value": "yes", "global": True, "method": "default"},
"CROSS_ORIGIN_OPENER_POLICY": {"value": "same-origin", "global": True, "method": "default"},
"MODSECURITY_SEC_RULE_ENGINE": {"value": "On", "global": True, "method": "default"},
"ROOT_FOLDER": {"value": "", "global": True, "method": "default"},
"REDIS_USERNAME": {"value": "", "global": True, "method": "default"},
"GREYLIST_IP_URLS": {"value": "", "global": True, "method": "default"},
"REVERSE_PROXY_WS": {"value": "no", "global": True, "method": "default"},
"WHITELIST_IP_URLS": {"value": "", "global": True, "method": "default"},
"BLACKLIST_IGNORE_IP": {"value": "", "global": True, "method": "default"},
"WORKER_RLIMIT_NOFILE": {"value": "2048", "global": True, "method": "default"},
"ANTIBOT_HCAPTCHA_SITEKEY": {"value": "", "global": True, "method": "default"},
"CROSS_ORIGIN_EMBEDDER_POLICY": {"value": "require-corp", "global": True, "method": "default"},
"MODSECURITY_SEC_AUDIT_LOG_PARTS": {"value": "ABCFHZ", "global": True, "method": "default"},
"CONTENT_SECURITY_POLICY_REPORT_ONLY": {"value": "no", "global": True, "method": "default"},
"SSL_PROTOCOLS": {"value": "TLSv1.2 TLSv1.3", "global": True, "method": "default"},
"REDIS_PASSWORD": {"value": "", "global": True, "method": "default"},
"REFERRER_POLICY": {"value": "strict-origin-when-cross-origin", "global": True, "method": "default"},
"GREYLIST_RDNS_URLS": {"value": "", "global": True, "method": "default"},
"WORKER_CONNECTIONS": {"value": "1024", "global": True, "method": "default"},
"WHITELIST_RDNS_URLS": {"value": "", "global": True, "method": "default"},
"BLACKLIST_IGNORE_RDNS": {"value": "", "global": True, "method": "default"},
"REVERSE_PROXY_HEADERS": {"value": "", "global": True, "method": "default"},
"ANTIBOT_HCAPTCHA_SECRET": {"value": "", "global": True, "method": "default"},
"CROSS_ORIGIN_RESOURCE_POLICY": {"value": "same-site", "global": True, "method": "default"},
"HTTP2": {"value": "yes", "global": True, "method": "default"},
"LOG_FORMAT": {
"value": '$host $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"',
"global": True,
"method": "default",
},
"CORS_MAX_AGE": {"value": "86400", "global": True, "method": "default"},
"GR2024-07-23T07:35:15.190324876Z EYLIST_ASN_URLS": {"value": "", "global": True, "method": "default"},
"PERMISSIONS_POLICY": {
"value": "accelerometer=(), ambient-light-sensor=(), attribution-reporting=(), autoplay=(), battery=(), bluetooth=(), browsing-topics=(), camera=(), compute-pressure=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), identity-credentials-get=(), idle-detection=(), local-fonts=(), magnetometer=(), microphone=(), midi=(), otp-credentials=(), payment=(), picture-in-picture=(), publickey-credentials-create=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), speaker-selection=(), storage-access=(), usb=(), web-share=(), window-management=(), xr-spatial-tracking=()",
"global": True,
"method": "default",
},
"WHITELIST_ASN_URLS": {"value": "", "global": True, "method": "default"},
"BLACKLIST_IGNORE_ASN": {"value": "", "global": True, "method": "default"},
"REDIS_SENTINEL_HOSTS": {"value": "", "global": True, "method": "default"},
"ANTIBOT_TURNSTILE_SITEKEY": {"value": "", "global": True, "method": "default"},
"REVERSE_PROXY_HEADERS_CLIENT": {"value": "", "global": True, "method": "default"},
"HTTP3": {"value": "no", "global": True, "method": "default"},
"LOG_LEVEL": {"value": "info", "global": True, "method": "scheduler"},
"DISABLE_FLOC": {"value": "yes", "global": True, "method": "default"},
"CORS_DENY_REQUEST": {"value": "yes", "global": True, "method": "default"},
"REDIS_SENTINEL_USERNAME": {"value": "", "global": True, "method": "default"},
"REVERSE_PROXY_BUFFERING": {"value": "yes", "global": True, "method": "default"},
"ANTIBOT_TURNSTILE_SECRET": {"value": "", "global": True, "method": "default"},
"GREYLIST_USER_AGENT_URLS": {"value": "", "global": True, "method": "default"},
"WHITELIST_USER_AGENT_URLS": {"value": "", "global": True, "method": "default"},
"BLACKLIST_IGNORE_USER_AGENT": {"value": "", "global": True, "method": "default"},
"DNS_RESOLVERS": {"value": "127.0.0.11", "global": True, "method": "default"},
"X_FRAME_OPTIONS": {"value": "SAMEORIGIN", "global": True, "method": "default"},
"GREYLIST_URI_URLS": {"value": "", "global": True, "method": "default"},
"HTTP3_ALT_SVC_PORT": {"value": "443", "global": True, "method": "default"},
"WHITELIST_URI_URLS": {"value": "", "global": True, "method": "default"},
"BLACKLIST_IGNORE_URI": {"value": "", "global": True, "method": "default"},
"REDIS_SENTINEL_PASSWORD": {"value": "", "global": True, "method": "default"},
"REVERSE_PROXY_KEEPALIVE": {"value": "no", "global": True, "method": "default"},
"LISTEN_HTTP": {"value": "yes", "global": True, "method": "default"},
"BLACKLIST_IP_URLS": {"value": "https://www.dan.me.uk/torlist/?exit", "global": True, "method": "default"},
"DATASTORE_MEMORY_SIZE": {"value": "64m", "global": True, "method": "default"},
"REDIS_SENTINEL_MASTER": {"value": "", "global": True, "method": "default"},
"X_CONTENT_TYPE_OPTIONS": {"value": "nosniff", "global": True, "method": "default"},
"REVERSE_PROXY_AUTH_REQUEST": {"value": "", "global": True, "method": "default"},
"X_XSS_PROTECTION": {"value": "1; mode=block", "global": True, "method": "default"},
"BLACKLIST_RDNS_URLS": {"value": "", "global": True, "method": "default"},
"USE_OPEN_FILE_CACHE": {"value": "no", "global": True, "method": "default"},
"REDIS_KEEPALIVE_IDLE": {"value": "30000", "global": True, "method": "default"},
"CACHESTORE_MEMORY_SIZE": {"value": "64m", "global": True, "method": "default"},
"REVERSE_PROXY_AUTH_REQUEST_SIGNIN_URL": {"value": "", "global": True, "method": "default"},
"OPEN_FILE_CACHE": {"value": "max=1000 inactive=20s", "global": True, "method": "default"},
"BLACKLIST_ASN_URLS": {"value": "", "global": True, "method": "default"},
"REDIS_KEEPALIVE_POOL": {"value": "10", "global": True, "method": "default"},
"X_DNS_PREFETCH_CONTROL": {"value": "off", "global": True, "method": "default"},
"CACHESTORE_IPC_MEMORY_SIZE": {"value": "16m", "global": True, "method": "default"},
"REVERSE_PROXY_AUTH_REQUEST_SET": {"value": "", "global": True, "method": "default"},
"OPEN_FILE_CACHE_ERRORS": {"value": "yes", "global": True, "method": "default"},
"BLACKLIST_USER_AGENT_URLS": {
"value": "https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list",
"global": True,
"method": "default",
},
"CACHESTORE_MISS_MEMORY_SIZE": {"value": "16m", "global": True, "method": "default"},
"REVERSE_PROXY_CONNECT_TIMEOUT": {"value": "60s", "global": True, "method": "default"},
"BLACKLIST_URI_URLS": {"value": "", "global": True, "method": "default"},
"OPEN_FILE_CACHE_MIN_USES": {"value": "2", "global": True, "method": "default"},
"REVERSE_PROXY_READ_TIMEOUT": {"value": "60s", "global": True, "method": "default"},
"CACHESTORE_LOCKS_MEMORY_SIZE": {"value": "16m", "global": True, "method": "default"},
"USE_API": {"value": "yes", "global": True, "method": "default"},
"OPEN_FILE_CACHE_VALID": {"value": "30s", "global": True, "method": "default"},
"BLACKLIST_IGNORE_IP_URLS": {"value": "", "global": True, "method": "default"},
"REVERSE_PROXY_SEND_TIMEOUT": {"value": "60s", "global": True, "method": "default"},
"API_HTTP_PORT": {"value": "5000", "global": True, "method": "default"},
"EXTERNAL_PLUGIN_URLS": {"value": "", "global": True, "method": "default"},
"REVERSE_PROXY_INCLUDES": {"value": "", "global": True, "method": "default"},
"BLACKLIST_IGNORE_RDNS_URLS": {"value": "", "global": True, "method": "default"},
"API_LISTEN_IP": {"value": "0.0.0.0", "global": True, "method": "default"},
"DENY_HTTP_STATUS": {"value": "403", "global": True, "method": "default"},
"BLACKLIST_IGNORE_ASN_URLS": {"value": "", "global": True, "method": "default"},
"REVERSE_PROXY_PASS_REQUEST_BODY": {"value": "yes", "global": True, "method": "default"},
"API_SERVER_NAME": {"value": "bwapi", "global": True, "method": "default"},
"USE_PROXY_CACHE": {"value": "no", "global": True, "method": "default"},
"SEND_ANONYMOUS_REPORT": {"value": "no", "global": True, "method": "scheduler"},
"BLACKLIST_IGNORE_USER_AGENT_URLS": {"value": "", "global": True, "method": "default"},
"API_WHITELIST_IP": {"value": "127.0.0.0/24 10.20.30.0/24", "global": True, "method": "scheduler"},
"PROXY_CACHE_PATH_LEVELS": {"value": "1:2", "global": True, "method": "default"},
"BLACKLIST_IGNORE_URI_URLS": {"value": "", "global": True, "method": "default"},
"AUTOCONF_MODE": {"value": "no", "global": True, "method": "default"},
"PROXY_CACHE_PATH_ZONE_SIZE": {"value": "10m", "global": True, "method": "default"},
"SWARM_MODE": {"value": "no", "global": True, "method": "default"},
"PROXY_CACHE_PATH_PARAMS": {"value": "max_size=100m", "global": True, "method": "default"},
"KUBERNETES_MODE": {"value": "no", "global": True, "method": "default"},
"PROXY_CACHE_METHODS": {"value": "GET HEAD", "global": True, "method": "default"},
"SERVER_TYPE": {"value": "http", "global": True, "method": "default"},
"PROXY_CACHE_MIN_USES": {"value": "2", "global": True, "method": "default"},
"LISTEN_STREAM": {"value": "yes", "global": True, "method": "default"},
"PROXY_CACHE_KEY": {"value": "$scheme$host$request_uri", "global": True, "method": "default"},
"PROXY_CACHE_VALID": {"value": "200=24h 301=1h 302=24h", "global": True, "method": "default"},
"LISTEN_STREAM_PORT": {"value": "1337", "global": True, "method": "default"},
"PROXY_NO_CACHE": {"value": "$http_pragma $http_authorization", "global": True, "method": "default"},
"LISTEN_STREAM_PORT_SSL": {"value": "4242", "global": True, "method": "default"},
"USE_UDP": {"value": "no", "global": True, "method": "default"},
"PROXY_CACHE_BYPASS": {"value": "0", "global": True, "method": "default"},
"USE_IPV6": {"value": "no", "global": True, "method": "default"},
"IS_DRAFT": {"value": "no", "global": True, "method": "default"},
"TIMERS_LOG_LEVEL": {"value": "debug", "global": True, "method": "default"},
"BUNKERWEB_INSTANCES": {"value": "bunkerweb", "global": True, "method": "scheduler"},
}
def get_service_forms(templates=[], plugins=[], service_settings={}):
def get_forms(templates=[], plugins=[], settings={}):
"""
Will generate every needed form using templates, plugins and settings.
We will run on each plugins, set template value if one, and override by the custom settings value if exists.
We will format to fit each form type (easy, advanced, raw).
"""
forms = {"advanced": {}, "easy": {}, "raw": {}}
for template in templates:
forms["advanced"][template.get("name")] = set_advanced(template, plugins, service_settings)
forms["raw"][template.get("name")] = set_raw(template, plugins, service_settings)
forms["easy"][template.get("name")] = set_easy(template, plugins, service_settings)
forms["advanced"][template.get("name")] = set_advanced(template, plugins, settings)
forms["raw"][template.get("name")] = set_raw(template, plugins, settings)
forms["easy"][template.get("name")] = set_easy(template, plugins, settings)
return forms
def set_easy(template, plugins_base, service_settings):
def set_easy(template, plugins_base, settings):
"""
Prepare the easy form based on the template and plugins data.
We need to loop on each steps and prepare settings and configs for each step.
"""
template_settings = template.get("settings")
plugins = copy.deepcopy(plugins_base)
configs = template.get("configs")
steps = template.get("steps")
for step in steps:
step_settings = step.get("settings", {})
step_configs = step.get("configs", {})
# Loop on step settings to set the settings value
loop_id = 0
step_settings_output = {}
@ -3097,7 +3365,7 @@ def set_easy(template, plugins_base, service_settings):
len(step_settings),
loop_id,
template_settings,
service_settings,
settings,
)
step_settings_output[setting] = plugin_setting
@ -3107,13 +3375,12 @@ def set_easy(template, plugins_base, service_settings):
return steps
def set_raw(template, plugins_base, service_settings):
def set_raw(template, plugins_base, settings):
"""
Set the raw form based on the template and plugins data.
It consists of keeping only the value or default value for each plugin settings.
"""
template_settings = template.get("settings")
settings = template.get("settings")
raw_settings = {}
# Copy of the plugins base
plugins = copy.deepcopy(plugins_base)
@ -3121,10 +3388,10 @@ def set_raw(template, plugins_base, service_settings):
for plugin in plugins:
for setting, value in plugin.get("settings").items():
# avoid some methods from services_settings
if setting in service_settings and service_settings[setting].get("method", "ui") not in ("ui", "default", "manual"):
if setting in settings and settings[setting].get("method", "ui") not in ("ui", "default", "manual"):
continue
raw_value = False
raw_value = None
# Start by setting template value if exists
if setting in template_settings:
@ -3132,8 +3399,8 @@ def set_raw(template, plugins_base, service_settings):
raw_value = template_settings.get(setting, value.get("default"))
# Then override by service settings
if setting in service_settings:
raw_value = service_settings[setting].get("value", value.get("value", value.get("default")))
if setting in settings:
raw_value = settings[setting].get("value", value.get("value", value.get("default")))
# Add value only if exists
if raw_value:
@ -3142,7 +3409,7 @@ def set_raw(template, plugins_base, service_settings):
return raw_settings
def set_advanced(template, plugins_base, service_settings):
def set_advanced(template, plugins_base, settings):
"""
Set the advanced form based on the template and plugins data.
It consists of formatting each plugin settings to be used in the advanced form.
@ -3162,10 +3429,10 @@ def set_advanced(template, plugins_base, service_settings):
total_settings,
loop_id,
template_settings,
service_settings,
settings,
)
set_multiples(template, plugins, service_settings)
set_multiples(template, plugins, settings)
return plugins
@ -3424,10 +3691,20 @@ def format_setting(
return setting_value
templates = [default_template]
def global_config_builder(plugins, settings):
"""Render forms with global config data.
ATM we don't need templates but we need to pass at least one to the function (it will simply not override anything).
"""
templates = [
{
"name": "default",
"steps": [],
"configs": {},
"settings": {},
}
]
def global_config_builder():
builder = [
{
"type": "card",
@ -3444,7 +3721,7 @@ def global_config_builder():
{
"type": "Templates",
"data": {
"templates": get_service_forms(templates, plugins, service_settings),
"templates": get_forms(templates, plugins, settings),
},
},
],
@ -3452,9 +3729,11 @@ def global_config_builder():
]
return builder
# return base64.b64encode(bytes(json.dumps(builder), "utf-8")).decode("ascii")
output = global_config_builder()
output = global_config_builder(plugins, global_config)
print(output)
with open("globalconfig.json", "w") as f:
json.dump(output, f, indent=4)

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,5 @@
#!/usr/bin/env python3
import json
import base64
from contextlib import suppress
from math import floor
from os import _exit, getenv, listdir, sep, urandom
@ -11,7 +10,8 @@ from sys import path as sys_path, modules as sys_modules
from pathlib import Path
from typing import Union
from uuid import uuid4
from builder import home_builder, instances_builder
from builder import home_builder, instances_builder, global_config_builder
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",), ("api",), ("db",))]:
if deps_path not in sys_path:
sys_path.append(deps_path)
@ -906,6 +906,7 @@ def account():
totp_qr_image=totp_qr_image,
)
@app.route("/instances", methods=["GET", "POST"])
@login_required
def instances():
@ -1233,8 +1234,11 @@ def global_config():
# Display global config
global_config = app.config["DB"].get_config(global_only=True, methods=True)
# Display global config
plugins = app.config["CONFIG"].get_plugins()
print(global_config, flush=True)
return render_template("global_config.html", global_config=global_config, dumped_global_config=dumps(global_config))
data_server_builder = global_config_builder(plugins, global_config)
return render_template("global_config.html", data_server_builder=global_config, dumped_global_config=dumps(global_config))
@app.route("/configs", methods=["GET", "POST"])