mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
move client/builder + continue updating base format
This commit is contained in:
parent
2b8d16aa0e
commit
a9ea59c74c
81 changed files with 486 additions and 46197 deletions
|
|
@ -1,38 +0,0 @@
|
|||
from .utils.form import get_forms, get_service_settings
|
||||
|
||||
|
||||
def advanced_mode_builder(templates: list[dict], plugins: list, global_config: dict, total_config: dict, service_name: str, is_new: bool = False) -> str:
|
||||
"""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).
|
||||
"""
|
||||
settings = get_service_settings(service_name, global_config, total_config)
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": service_name,
|
||||
"type": "container",
|
||||
"lowercase": True,
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Subtitle",
|
||||
"data": {"subtitle": "services_manage_subtitle", "type": "container"},
|
||||
},
|
||||
{
|
||||
"type": "Templates",
|
||||
"data": {
|
||||
"templates": get_forms(templates, plugins, settings, ("advanced",), is_new, True),
|
||||
"operation": "new" if is_new else "edit",
|
||||
"oldServerName": service_name if service_name else "",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
from .utils.form import get_forms, get_service_settings
|
||||
|
||||
|
||||
def easy_mode_builder(templates: list[dict], plugins: list, global_config: dict, total_config: dict, service_name: str, is_new: bool = False) -> str:
|
||||
"""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).
|
||||
"""
|
||||
|
||||
# We need
|
||||
settings = get_service_settings(service_name, global_config, total_config)
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": service_name,
|
||||
"type": "container",
|
||||
"lowercase": True,
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Subtitle",
|
||||
"data": {"subtitle": "services_manage_subtitle", "type": "container"},
|
||||
},
|
||||
{
|
||||
"type": "Templates",
|
||||
"data": {
|
||||
"templates": get_forms(templates, plugins, settings, ("easy",), is_new, True),
|
||||
"operation": "new" if is_new else "edit",
|
||||
"oldServerName": service_name if service_name else "",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
from .utils.form import get_forms
|
||||
|
||||
|
||||
def global_config_builder(templates: list[dict], plugins: list, settings: dict) -> str:
|
||||
"""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).
|
||||
"""
|
||||
|
||||
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, ("advanced", "raw")),
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
from .utils.widgets import stat_widget
|
||||
|
||||
|
||||
def home_builder(data: dict) -> str:
|
||||
"""
|
||||
It returns the needed format from data to render the home page in JSON format for the Vue.js builder
|
||||
"""
|
||||
version_card = stat_widget(
|
||||
link="https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui#pro",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
title="home_version",
|
||||
subtitle=(
|
||||
"home_all_features_available"
|
||||
if data.get("is_pro_version")
|
||||
else (
|
||||
"home_awaiting_compliance"
|
||||
if data.get("pro_status") == "active" and data.get("pro_overlapped")
|
||||
else (
|
||||
"home_renew_license"
|
||||
if data.get("pro_status") == "expired"
|
||||
else "home_talk_to_team" if data.get("pro_status") == "suspended" else "home_upgrade_to_pro"
|
||||
)
|
||||
)
|
||||
),
|
||||
subtitle_color="success" if data.get("is_pro_version") else "warning",
|
||||
stat=(
|
||||
"home_pro"
|
||||
if data.get("is_pro_version")
|
||||
else (
|
||||
"home_pro_locked"
|
||||
if data.get("pro_status") == "active" and data.get("pro_overlapped")
|
||||
else "home_expired" if data.get("pro_status") == "expired" else "home_suspended" if data.get("pro_status") == "suspended" else "home_free"
|
||||
)
|
||||
),
|
||||
icon_name="crown" if data.get("is_pro_version") else "key",
|
||||
)
|
||||
|
||||
version_num_card = stat_widget(
|
||||
link="https://github.com/bunkerity/bunkerweb",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
title="home_version_number",
|
||||
subtitle=(
|
||||
"home_couldnt_find_remote"
|
||||
if not data.get("remote_version")
|
||||
else "home_latest_version" if data.get("remote_version") and data.get("check_version") else "home_update_available"
|
||||
),
|
||||
subtitle_color=("error" if not data.get("remote_version") else "success" if data.get("remote_version") and data.get("check_version") else "warning"),
|
||||
stat=data.get("version"),
|
||||
icon_name="wire",
|
||||
)
|
||||
|
||||
instances_card = stat_widget(
|
||||
link="instances",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
title="home_instances",
|
||||
subtitle="home_total_number",
|
||||
subtitle_color="info",
|
||||
stat=data.get("instances_number"),
|
||||
icon_name="box",
|
||||
)
|
||||
|
||||
services_card = stat_widget(
|
||||
link="services",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
title="home_services",
|
||||
subtitle="home_all_methods_included",
|
||||
subtitle_color="info",
|
||||
stat=data.get("services_number"),
|
||||
icon_name="disk",
|
||||
)
|
||||
|
||||
plugins_card = stat_widget(
|
||||
link="plugins",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
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=data.get("plugins_number"),
|
||||
icon_name="puzzle",
|
||||
)
|
||||
|
||||
builder = [version_card, version_num_card, instances_card, services_card, plugins_card]
|
||||
|
||||
return builder
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
from .utils.widgets import instance_widget
|
||||
|
||||
|
||||
def instances_builder(instances: List[Instance]) -> str:
|
||||
"""
|
||||
It returns the needed format from data to render the instances page in JSON format for the Vue.js builder
|
||||
"""
|
||||
builder = []
|
||||
|
||||
for instance in instances:
|
||||
# setup actions buttons
|
||||
actions = ["reload", "stop"] if instance.status == "up" else ["start"]
|
||||
|
||||
buttons = [
|
||||
{
|
||||
"attrs": {
|
||||
"data-submit-form": f"""{{"INSTANCE_ID" : "{instance.hostname}", "operation" : "{action}" }}""",
|
||||
},
|
||||
"text": f"action_{action}",
|
||||
"color": "success" if action == "start" else "error" if action == "stop" else "warning",
|
||||
}
|
||||
for action in actions
|
||||
]
|
||||
|
||||
instance = instance_widget(
|
||||
containerColumns={"pc": 6, "tablet": 6, "mobile": 12},
|
||||
pairs=[
|
||||
{"key": "instances_name", "value": instance.name},
|
||||
{"key": "instances_hostname", "value": instance.hostname},
|
||||
{"key": "instances_type", "value": instance.type},
|
||||
{"key": "instances_method", "value": instance.method},
|
||||
{"key": "instances_creation_date", "value": instance.creation_date.strftime("%d-%m-%Y %H:%M:%S")},
|
||||
{"key": "instances_last_seen", "value": instance.last_seen.strftime("%d-%m-%Y %H:%M:%S")},
|
||||
],
|
||||
status="success" if instance.status == "up" else "error",
|
||||
title=instance.hostname,
|
||||
buttons=buttons,
|
||||
)
|
||||
|
||||
builder.append(instance)
|
||||
|
||||
return builder
|
||||
|
|
@ -1,290 +0,0 @@
|
|||
from .utils.widgets import title_widget, table_widget
|
||||
|
||||
|
||||
def jobs_builder(jobs):
|
||||
|
||||
jobs_list = get_jobs_list(jobs)
|
||||
|
||||
intervals = ["all"]
|
||||
|
||||
# loop on each job
|
||||
for job in jobs_list:
|
||||
# loop on each item
|
||||
for item in job:
|
||||
# get the interval if not already in intervals
|
||||
if item.get("every") and item.get("every") not in intervals:
|
||||
intervals.append(item.get("every"))
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
title_widget("jobs_title"),
|
||||
table_widget(
|
||||
positions=[3, 2, 1, 1, 1, 1, 3],
|
||||
header=[
|
||||
"jobs_table_name",
|
||||
"jobs_table_plugin_id",
|
||||
"jobs_table_interval",
|
||||
"jobs_table_reload",
|
||||
"jobs_table_success",
|
||||
"jobs_table_history",
|
||||
"jobs_table_cache_downloadable",
|
||||
],
|
||||
items=jobs_list,
|
||||
filters=[
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "keyword",
|
||||
"type": "keyword",
|
||||
"value": "",
|
||||
"keys": ["name", "plugin_id"],
|
||||
"field": {
|
||||
"id": "jobs-keyword",
|
||||
"value": "",
|
||||
"type": "text",
|
||||
"name": "jobs-keyword",
|
||||
"label": "jobs_search",
|
||||
"placeholder": "inp_keyword",
|
||||
"isClipboard": False,
|
||||
"popovers": [
|
||||
{
|
||||
"text": "jobs_search_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "every",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["every"],
|
||||
"field": {
|
||||
"id": "jobs-every",
|
||||
"value": "all",
|
||||
"values": intervals,
|
||||
"name": "jobs-every",
|
||||
"onlyDown": True,
|
||||
"label": "jobs_interval",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "jobs_interval_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "reload",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["reload"],
|
||||
"field": {
|
||||
"id": "jobs-last-run",
|
||||
"value": "all",
|
||||
"values": ["all", "success", "failed"],
|
||||
"name": "jobs-last-run",
|
||||
"onlyDown": True,
|
||||
"label": "jobs_reload",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "jobs_reload_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "success",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["success"],
|
||||
"field": {
|
||||
"id": "jobs-success",
|
||||
"value": "all",
|
||||
"values": ["all", "success", "failed"],
|
||||
"name": "jobs-success",
|
||||
"onlyDown": True,
|
||||
"label": "jobs_success",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "jobs_success_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
],
|
||||
minWidth="lg",
|
||||
title="jobs_table_title",
|
||||
),
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
return builder
|
||||
|
||||
|
||||
def get_jobs_list(jobs):
|
||||
data = []
|
||||
# loop on each dict
|
||||
for key, value in jobs.items():
|
||||
item = []
|
||||
item.append({"name": key, "type": "Text", "data": {"text": key}})
|
||||
# loop on each value
|
||||
for k, v in value.items():
|
||||
# override widget type for some keys
|
||||
if k in ("reload", "history"):
|
||||
is_success = v if k == "reload" else v[0].get("success")
|
||||
item.append(
|
||||
{
|
||||
k: "success" if is_success else "failed",
|
||||
"type": "Icons",
|
||||
"data": {
|
||||
"iconName": "check" if is_success else "cross",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if k not in ("history"):
|
||||
continue
|
||||
|
||||
if k in ("plugin_id", "every"):
|
||||
item.append({k: v, "type": "Text", "data": {"text": v}})
|
||||
continue
|
||||
|
||||
if k in ("history"):
|
||||
items = []
|
||||
for hist in v:
|
||||
items.append(
|
||||
[
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": hist["start_date"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": hist["end_date"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Icons",
|
||||
"data": {
|
||||
"iconName": "check" if hist["success"] else "cross",
|
||||
},
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
item.append(
|
||||
{
|
||||
"type": "Button",
|
||||
"data": {
|
||||
"id": f"open-modal-history-{k}",
|
||||
"text": "jobs_history",
|
||||
"hideText": True,
|
||||
"color": "blue",
|
||||
"size": "normal",
|
||||
"iconName": "document",
|
||||
"iconColor": "white",
|
||||
"modal": {
|
||||
"widgets": [
|
||||
{"type": "Title", "data": {"title": key}},
|
||||
{"type": "Subtitle", "data": {"subtitle": "jobs_history_subtitle"}},
|
||||
{
|
||||
"type": "Table",
|
||||
"data": {
|
||||
"title": "jobs_history_table_title",
|
||||
"minWidth": "",
|
||||
"header": [
|
||||
"jobs_table_start_run",
|
||||
"jobs_table_end_run",
|
||||
"jobs_table_success",
|
||||
],
|
||||
"positions": [5, 5, 2],
|
||||
"items": items,
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "ButtonGroup",
|
||||
"data": {
|
||||
"buttons": [
|
||||
{
|
||||
"id": f"close-history-{k}",
|
||||
"text": "action_close",
|
||||
"color": "close",
|
||||
"size": "normal",
|
||||
"attrs": {"data-close-modal": ""},
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if k in ("cache") and len(v) <= 0:
|
||||
item.append({k: v, "type": "Text", "data": {"text": ""}})
|
||||
continue
|
||||
|
||||
if k in ("cache") and len(v) > 0:
|
||||
files = []
|
||||
# loop on each cache item
|
||||
for cache in v:
|
||||
file_name = f"{cache['file_name']} [{cache['service_id']}]" if cache["service_id"] else f"{cache['file_name']}"
|
||||
files.append(file_name)
|
||||
|
||||
item.append(
|
||||
{
|
||||
k: " ".join(files),
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"attrs": {
|
||||
"data-plugin-id": value.get("plugin_id", ""),
|
||||
"data-job-name": key,
|
||||
},
|
||||
"id": f"{key}_cache",
|
||||
"label": f"{key}_cache",
|
||||
"hideLabel": True,
|
||||
"inpType": "select",
|
||||
"name": f"{key}_cache",
|
||||
"value": "download file",
|
||||
"values": files,
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12,
|
||||
},
|
||||
"overflowAttrEl": "data-table-body",
|
||||
"containerClass": "table download-cache-file",
|
||||
"maxBtnChars": 16,
|
||||
"popovers": [
|
||||
{
|
||||
"iconName": "info",
|
||||
"text": "jobs_download_cache_file",
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
data.append(item)
|
||||
|
||||
return data
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
from .utils.widgets import title_widget
|
||||
|
||||
|
||||
def logs_builder(files: list[str] = [], current_file: str = "", raw_data: str = "") -> str:
|
||||
|
||||
if not files:
|
||||
builder = [
|
||||
{
|
||||
"type": "void",
|
||||
"widgets": [{"type": "MessageUnmatch", "data": {"text": "logs_no_files_found"}}],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
||||
file_select = {
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"id": "logs-select-file",
|
||||
"label": "logs_log_file",
|
||||
"inpType": "select",
|
||||
"name": "logs-select-file",
|
||||
"onlyDown": True,
|
||||
"value": current_file or "Select a file",
|
||||
"values": files,
|
||||
"columns": {
|
||||
"pc": 4,
|
||||
"tablet": 6,
|
||||
"mobile": 12,
|
||||
},
|
||||
"maxBtnChars": 20,
|
||||
"attrs": {
|
||||
"data-log": "true",
|
||||
},
|
||||
"popovers": [
|
||||
{
|
||||
"iconName": "info",
|
||||
"text": "logs_select_file_info",
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
if not raw_data:
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [title_widget("logs_title"), file_select, {"type": "MessageUnmatch", "data": {"text": "logs_not_selected_or_not_found"}}],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
||||
editor = {
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"containerClass": "mt-4",
|
||||
"id": "logs-file-content",
|
||||
"label": "logs_file_content",
|
||||
"inpType": "editor",
|
||||
"name": "logs-file-content",
|
||||
"value": raw_data,
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12,
|
||||
},
|
||||
"editorClass" : "min-h-[500px]",
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [title_widget("logs_title"), file_select, editor],
|
||||
}
|
||||
]
|
||||
|
||||
return builder
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
from .utils.form import get_forms, get_service_settings
|
||||
|
||||
|
||||
def raw_mode_builder(templates: list[dict], plugins: list, global_config: dict, total_config: dict, service_name: str, is_new: bool = False) -> str:
|
||||
"""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).
|
||||
"""
|
||||
|
||||
# We need
|
||||
settings = get_service_settings(service_name, global_config, total_config)
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": service_name,
|
||||
"type": "container",
|
||||
"lowercase": True,
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Subtitle",
|
||||
"data": {"subtitle": "services_manage_subtitle", "type": "container"},
|
||||
},
|
||||
{
|
||||
"type": "Templates",
|
||||
"data": {
|
||||
"templates": get_forms(templates, plugins, settings, ("raw",), is_new, True),
|
||||
"operation": "new" if is_new else "edit",
|
||||
"oldServerName": service_name if service_name else "",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
|
@ -1,379 +0,0 @@
|
|||
from typing import Union
|
||||
|
||||
from .utils.widgets import title_widget, table_widget
|
||||
|
||||
|
||||
def services_builder(services):
|
||||
# get method for each service["SERVER_NAME"]["method"]
|
||||
methods = list(set([service["SERVER_NAME"]["method"] for service in services]))
|
||||
|
||||
services_list = get_services_list(services)
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
title_widget("services_title"),
|
||||
{
|
||||
"type": "Button",
|
||||
"data": {
|
||||
"id": "services-new",
|
||||
"text": "services_new",
|
||||
"color": "success",
|
||||
"size": "normal",
|
||||
"iconName": "plus",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(server_name="new", operation="new", title="services_new_title", subtitle="services_new_subtitle"),
|
||||
"containerClass": "col-span-12 flex justify-center",
|
||||
},
|
||||
},
|
||||
table_widget(
|
||||
positions=[4, 4, 4],
|
||||
header=[
|
||||
"services_table_name",
|
||||
"services_table_method",
|
||||
"services_table_actions",
|
||||
],
|
||||
items=services_list,
|
||||
filters=[
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "keyword",
|
||||
"type": "keyword",
|
||||
"value": "",
|
||||
"keys": ["name"],
|
||||
"field": {
|
||||
"id": "services-keyword",
|
||||
"value": "",
|
||||
"type": "text",
|
||||
"name": "services-keyword",
|
||||
"label": "services_search",
|
||||
"placeholder": "inp_keyword",
|
||||
"isClipboard": False,
|
||||
"popovers": [
|
||||
{
|
||||
"text": "services_search_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "method",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["method"],
|
||||
"field": {
|
||||
"id": "services-methods",
|
||||
"value": "all",
|
||||
"values": methods,
|
||||
"name": "services-methods",
|
||||
"onlyDown": True,
|
||||
"label": "services_methods",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "services_methods_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "draft",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["draft"],
|
||||
"field": {
|
||||
"id": "services-draft",
|
||||
"value": "all",
|
||||
"values": ["all", "online", "draft"],
|
||||
"name": "services-draft",
|
||||
"onlyDown": True,
|
||||
"label": "services_draft",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "services_draft_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
],
|
||||
minWidth="md",
|
||||
title="services_table_title",
|
||||
),
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
return builder
|
||||
|
||||
|
||||
def services_settings(settings: dict) -> dict:
|
||||
# deep copy settings dict
|
||||
settings = settings.copy()
|
||||
# remove "SERVER_NAME" and "IS_DRAFT" key
|
||||
settings.pop("SERVER_NAME", None)
|
||||
settings.pop("IS_DRAFT", None)
|
||||
# Create table with settings remaining keys
|
||||
settings_table_items = []
|
||||
for key, value in settings.items():
|
||||
format_key = key.replace("USE_", "").replace("_", " ")
|
||||
settings_table_items.append(
|
||||
[
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {"text": format_key},
|
||||
},
|
||||
{
|
||||
"type": "Icons",
|
||||
"data": {
|
||||
"iconName": "check" if value.get("value") == "yes" else "cross",
|
||||
},
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
table = table_widget(
|
||||
positions=[8, 4],
|
||||
header=["services_settings_table_name", "services_settings_table_status"],
|
||||
items=settings_table_items,
|
||||
filters=[],
|
||||
minWidth="",
|
||||
title="services_settings_table_title",
|
||||
)
|
||||
|
||||
return table
|
||||
|
||||
|
||||
def services_action(
|
||||
server_name: str = "",
|
||||
operation: str = "",
|
||||
title: str = "",
|
||||
subtitle: str = "",
|
||||
additional: str = "",
|
||||
is_draft: Union[bool, None] = None,
|
||||
service: dict = None,
|
||||
) -> dict:
|
||||
|
||||
buttons = [
|
||||
{
|
||||
"id": f"close-service-btn-{server_name}",
|
||||
"text": "action_close",
|
||||
"disabled": False,
|
||||
"color": "close",
|
||||
"size": "normal",
|
||||
"attrs": {"data-close-modal": ""},
|
||||
},
|
||||
]
|
||||
|
||||
if operation == "delete":
|
||||
buttons.append(
|
||||
{
|
||||
"id": f"{operation}-service-btn-{server_name}",
|
||||
"text": f"action_{operation}",
|
||||
"disabled": False,
|
||||
"color": "delete",
|
||||
"size": "normal",
|
||||
"attrs": {
|
||||
"data-submit-form": f"""{{"SERVER_NAME" : "{server_name}", "operation" : "{operation}" }}""",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if operation == "draft":
|
||||
draft_value = "yes" if is_draft else "no"
|
||||
buttons.append(
|
||||
{
|
||||
"id": f"{operation}-service-btn-{server_name}",
|
||||
"text": "action_switch",
|
||||
"disabled": False,
|
||||
"color": "success",
|
||||
"size": "normal",
|
||||
"attrs": {
|
||||
"data-submit-form": f"""{{"SERVER_NAME" : "{server_name}", "OLD_SERVER_NAME" : "{server_name}", "operation" : "edit", "IS_DRAFT" : "{draft_value}" }}""",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
content = [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": title,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
if subtitle:
|
||||
content.append(
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": subtitle,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if additional:
|
||||
content.append(
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"bold": True,
|
||||
"text": additional,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if operation == "plugins":
|
||||
settings = services_settings(service)
|
||||
content.append(settings)
|
||||
|
||||
if operation == "delete":
|
||||
content.append(
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "",
|
||||
"bold": True,
|
||||
"text": server_name,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if operation == "edit" or operation == "new":
|
||||
modes = ("easy", "advanced", "raw")
|
||||
mode_buttons = []
|
||||
for mode in modes:
|
||||
mode_buttons.append(
|
||||
{
|
||||
"id": f"{operation}-service-btn-{server_name}",
|
||||
"text": f"services_mode_{mode}",
|
||||
"disabled": False,
|
||||
"color": "info",
|
||||
"size": "normal",
|
||||
"attrs": {
|
||||
"role": "link",
|
||||
"data-link": f"modes?service_name={server_name}&mode={mode}" if operation != "new" else f"modes?mode={mode}",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
content.append(
|
||||
{
|
||||
"type": "ButtonGroup",
|
||||
"data": {"buttons": mode_buttons},
|
||||
}
|
||||
)
|
||||
|
||||
content.append(
|
||||
{
|
||||
"type": "ButtonGroup",
|
||||
"data": {"buttons": buttons},
|
||||
},
|
||||
)
|
||||
|
||||
modal = {
|
||||
"widgets": content,
|
||||
}
|
||||
|
||||
return modal
|
||||
|
||||
|
||||
def get_services_list(services):
|
||||
data = []
|
||||
for index, service in enumerate(services):
|
||||
server_name = service["SERVER_NAME"]["value"]
|
||||
server_method = service["SERVER_NAME"]["method"]
|
||||
is_draft = True if service["IS_DRAFT"]["value"] == "yes" else False
|
||||
is_deletable = False if server_method in ("autoconf", "scheduler") else True
|
||||
|
||||
item = []
|
||||
# Get name
|
||||
item.append({"name": server_name, "type": "Text", "data": {"text": server_name}})
|
||||
item.append({"method": server_method, "type": "Text", "data": {"text": server_method}})
|
||||
item.append(
|
||||
{
|
||||
"type": "ButtonGroup",
|
||||
"data": {
|
||||
"buttons": [
|
||||
{
|
||||
"id": f"open-modal-plugins-{index}",
|
||||
"text": "plugins",
|
||||
"hideText": True,
|
||||
"color": "success",
|
||||
"size": "normal",
|
||||
"iconName": "eye",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(
|
||||
server_name=server_name,
|
||||
operation="plugins",
|
||||
title="services_plugins_title",
|
||||
subtitle="",
|
||||
service=service,
|
||||
),
|
||||
},
|
||||
{
|
||||
"attrs": {"data-server-name": server_name},
|
||||
"id": f"open-modal-manage-{index}",
|
||||
"text": "manage",
|
||||
"hideText": True,
|
||||
"color": "edit",
|
||||
"size": "normal",
|
||||
"iconName": "pen",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(
|
||||
server_name=server_name,
|
||||
operation="edit",
|
||||
title="services_edit_title",
|
||||
subtitle="services_edit_subtitle",
|
||||
additional=server_name,
|
||||
),
|
||||
},
|
||||
{
|
||||
"attrs": {"data-server-name": server_name, "data-is-draft": "yes" if is_draft else "no"},
|
||||
"id": f"open-modal-draft-{index}",
|
||||
"text": "draft" if is_draft else "online",
|
||||
"hideText": True,
|
||||
"color": "blue",
|
||||
"size": "normal",
|
||||
"iconName": "document" if is_draft else "globe",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(
|
||||
server_name=server_name,
|
||||
operation="draft",
|
||||
title="services_draft_title",
|
||||
subtitle="services_draft_subtitle" if is_draft else "services_online_subtitle",
|
||||
additional="services_draft_switch_subtitle" if is_draft else "services_online_switch_subtitle",
|
||||
is_draft=is_draft,
|
||||
),
|
||||
},
|
||||
{
|
||||
"attrs": {"data-server-name": server_name},
|
||||
"id": f"open-modal-delete-{index}",
|
||||
"text": "delete",
|
||||
"disabled": not is_deletable,
|
||||
"hideText": True,
|
||||
"color": "red",
|
||||
"size": "normal",
|
||||
"iconName": "trash",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(
|
||||
server_name=server_name, operation="delete", title="services_delete_title", subtitle="services_delete_subtitle"
|
||||
),
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
data.append(item)
|
||||
|
||||
return data
|
||||
|
|
@ -1,494 +0,0 @@
|
|||
import copy
|
||||
from typing import Union
|
||||
|
||||
|
||||
def get_setting_data(template_settings: dict, settings: dict, setting: str, value: dict, is_multiple_setting: bool = False, is_new: bool = False) -> tuple:
|
||||
template_value = template_settings.get(setting, None)
|
||||
current_value = settings[setting].get("value", None) if setting in settings else None
|
||||
default_value = value.get("default")
|
||||
is_disabled_method = (
|
||||
True if settings.get(setting, {}).get("method", "ui") not in ("ui", "default", "manual") and not is_new and not is_multiple_setting else False
|
||||
)
|
||||
is_current_from_template = True if settings.get(setting, {}).get("template", None) is not None and template_value is not None else False
|
||||
is_current_default = current_value is not None and current_value == default_value
|
||||
setting_value = current_value if current_value is not None and not is_new and not is_multiple_setting else default_value
|
||||
return template_value, current_value, default_value, is_disabled_method, is_current_from_template, is_current_default, setting_value
|
||||
|
||||
|
||||
def get_service_settings(service_name: str, global_config: dict, total_config: dict) -> dict:
|
||||
"""
|
||||
total_config is a dict that contains global settings and services settings (format SERVICE_NAME_SETTING - www.example.com_USE_ANTIBOT for example -).
|
||||
We will only keep settings that are related to the service_name (with prefix SERVICE_NAME_).
|
||||
Then we will loop on global key and override value from global config by service config if exists.
|
||||
"""
|
||||
|
||||
# Get service settings
|
||||
service_settings = {}
|
||||
for key, value in total_config.items():
|
||||
if not key.startswith(f"{service_name}_"):
|
||||
continue
|
||||
|
||||
service_settings[key.replace(f"{service_name}_", "")] = value
|
||||
|
||||
# Loop on global settings to override by service settings
|
||||
for key, value in service_settings.items():
|
||||
global_config[key] = value
|
||||
|
||||
return global_config
|
||||
|
||||
|
||||
def get_plugins_multisite(plugins: list) -> list:
|
||||
# loop on plugins with list index
|
||||
plugins_multisite = []
|
||||
for index, plugin in enumerate(plugins):
|
||||
multisite_settings = {}
|
||||
# loop on settings
|
||||
for setting, value in plugin.get("settings").items():
|
||||
# check if setting is multisite
|
||||
if value.get("context") != "multisite":
|
||||
continue
|
||||
# add multisite key to plugin
|
||||
multisite_settings[setting] = value
|
||||
|
||||
# add multisite settings to plugin
|
||||
if len(multisite_settings):
|
||||
plugin_multisite = copy.deepcopy(plugin)
|
||||
plugin_multisite["settings"] = multisite_settings
|
||||
plugins_multisite.append(plugin_multisite)
|
||||
|
||||
return plugins_multisite
|
||||
|
||||
|
||||
def get_forms(
|
||||
templates_ui: list = [],
|
||||
plugins: list = [],
|
||||
settings: dict = {},
|
||||
render_forms: tuple = ("advanced", "easy", "raw"),
|
||||
is_new: bool = False,
|
||||
only_multisite: bool = False,
|
||||
) -> dict:
|
||||
"""
|
||||
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) in case
|
||||
"""
|
||||
# Copy of the plugins, and get the plugins by context if needed
|
||||
# In services page, we want only multisite settings, but in global config we want both
|
||||
plugins_base = get_plugins_multisite(plugins) if only_multisite else plugins
|
||||
|
||||
# This template will be used to show default value or value if exists
|
||||
templates = [
|
||||
{
|
||||
"name": "default",
|
||||
"steps": [],
|
||||
"configs": {},
|
||||
"settings": {},
|
||||
}
|
||||
]
|
||||
|
||||
for key, value in templates_ui.items():
|
||||
value["label"] = value["name"]
|
||||
value["name"] = key
|
||||
templates.append(value)
|
||||
|
||||
# Update SERVER_NAME to be empty if new
|
||||
if is_new and "SERVER_NAME" in settings:
|
||||
settings["SERVER_NAME"]["value"] = ""
|
||||
|
||||
if is_new and not "SERVER_NAME" in settings:
|
||||
settings["SERVER_NAME"] = {"value": "", "method": "ui", "global": False}
|
||||
|
||||
forms = {}
|
||||
for form in render_forms:
|
||||
forms[form] = {}
|
||||
|
||||
for template in templates:
|
||||
if "advanced" in forms:
|
||||
forms["advanced"][template.get("name")] = set_advanced(template, plugins_base, settings, is_new)
|
||||
|
||||
if "raw" in forms:
|
||||
forms["raw"][template.get("name")] = set_raw(template, plugins_base, settings, is_new)
|
||||
|
||||
if "easy" in forms:
|
||||
forms["easy"][template.get("name")] = set_easy(template, plugins_base, settings, is_new)
|
||||
|
||||
return forms
|
||||
|
||||
|
||||
def set_easy(template: list, plugins_base: list, settings: dict, is_new: bool) -> dict:
|
||||
"""
|
||||
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)
|
||||
# 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, is_new)
|
||||
|
||||
set_multiples(template, plugins, settings)
|
||||
|
||||
steps = template.get("steps")
|
||||
for step in steps:
|
||||
step_settings = step.get("settings", {})
|
||||
|
||||
for plugin in plugins:
|
||||
step_settings_output = {}
|
||||
for setting, value in plugin.get("settings").items():
|
||||
if setting not in step_settings:
|
||||
continue
|
||||
|
||||
step_settings_output[setting] = value
|
||||
|
||||
# Case at least one key in step settings, we can add the plugin settings to the step
|
||||
if len(step_settings_output) and not "plugins" in step:
|
||||
step["plugins"] = []
|
||||
|
||||
if len(step_settings_output):
|
||||
step_plugin = copy.deepcopy(plugin)
|
||||
step_plugin["settings"] = step_settings_output
|
||||
step["plugins"].append(step_plugin)
|
||||
|
||||
# remove settings key form step
|
||||
step.pop("settings", None)
|
||||
return steps
|
||||
|
||||
|
||||
def set_raw(template: list, plugins_base: list, settings: dict, is_new: bool = False) -> dict:
|
||||
"""
|
||||
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():
|
||||
|
||||
is_multiple_setting = "multiple" in value
|
||||
|
||||
# By default, we will loop on one setting (not multiple)
|
||||
total_settings = {setting: value}
|
||||
|
||||
# Case multiple, retrieve all settings that start with setting name
|
||||
if is_multiple_setting:
|
||||
# get all settings that start with setting name
|
||||
total_settings = {k: v for k, v in settings.items() if k.startswith(f"{setting}")}
|
||||
|
||||
# Loop in a same way it is a multiple or regular setting
|
||||
for mult_setting, mult_value in total_settings.items():
|
||||
|
||||
# Get setting data
|
||||
# We need to send setting and not mult_setting because mult_setting is unknown on plugin side
|
||||
template_value, current_value, default_value, is_disabled_method, is_current_from_template, is_current_default, setting_value = (
|
||||
get_setting_data(template_settings, settings, mult_setting, mult_value)
|
||||
)
|
||||
|
||||
if current_value is not None:
|
||||
raw_settings[mult_setting] = current_value
|
||||
continue
|
||||
|
||||
if template_value is not None:
|
||||
raw_settings[mult_setting] = template_value
|
||||
continue
|
||||
|
||||
return raw_settings
|
||||
|
||||
|
||||
def set_advanced(template: list, plugins_base: list, settings: dict, is_new: bool) -> dict:
|
||||
"""
|
||||
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, is_new)
|
||||
|
||||
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 setting is matching a multiple setting
|
||||
if not format_setting in mult_settings:
|
||||
continue
|
||||
|
||||
# Case we have at least one multiple setting, we can check if multiple name exists or create it
|
||||
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
|
||||
multiple_template[mult_name][prefix][setting]["prev_value"] = value
|
||||
multiple_template[mult_name][prefix][setting]["method"] = "default"
|
||||
|
||||
# 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 setting is matching a multiple setting
|
||||
if not format_setting in mult_settings:
|
||||
continue
|
||||
|
||||
# Case we have at least one multiple setting, we can check if multiple name exists or create it
|
||||
if not mult_name in multiple_settings:
|
||||
multiple_settings[mult_name] = {}
|
||||
# Now check if prefix exist for this mult
|
||||
if not prefix in multiple_settings[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_settings[mult_name][prefix] = new_multiple_group
|
||||
|
||||
# Update multiple template with real data
|
||||
multiple_settings[mult_name][prefix][setting]["value"] = value.get("value", multiple_settings[mult_name][prefix][setting]["value"])
|
||||
multiple_settings[mult_name][prefix][setting]["prev_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
|
||||
|
||||
# Add popovers if setting is disabled else stop
|
||||
if not multiple_settings[mult_name][prefix][setting].get("disabled", False):
|
||||
continue
|
||||
|
||||
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, 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(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(
|
||||
name: str,
|
||||
value: Union[str, int],
|
||||
total_settings: Union[str, int],
|
||||
loop_id: Union[str, int],
|
||||
template_settings: dict,
|
||||
settings: dict,
|
||||
is_new: bool = False,
|
||||
) -> dict:
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
|
||||
is_multiple_setting = value.get("multiple", False)
|
||||
|
||||
template_value, current_value, default_value, is_disabled_method, is_current_from_template, is_current_default, setting_value = get_setting_data(
|
||||
template_settings, settings, name, value, is_multiple_setting, is_new
|
||||
) # regex by pattern
|
||||
|
||||
value["pattern"] = value.get("regex", "")
|
||||
|
||||
# set inpType based on type define for each settings
|
||||
inpType = (
|
||||
"checkbox"
|
||||
if value.get("type") == "check"
|
||||
else ("select" if value.get("type") == "select" else "datepicker" if value.get("type") == "date" else "input")
|
||||
)
|
||||
value["inpType"] = inpType
|
||||
|
||||
if inpType == "select":
|
||||
# replace "select" key by "values"
|
||||
value["values"] = value.pop("select")
|
||||
|
||||
value["columns"] = {"pc": 4, "tablet": 6, "mobile": 12}
|
||||
value["disabled"] = is_disabled_method
|
||||
value["value"] = default_value
|
||||
value["name"] = value.get("label")
|
||||
value["prev_value"] = value.get("value")
|
||||
|
||||
# Prepare popover checking "help", "context"
|
||||
popovers = []
|
||||
|
||||
if is_disabled_method:
|
||||
popovers.append(
|
||||
{
|
||||
"iconName": "trespass",
|
||||
"text": "inp_popover_method_disabled",
|
||||
}
|
||||
)
|
||||
|
||||
if value.get("context"):
|
||||
popovers.append(
|
||||
{
|
||||
"iconName": ("disk" if value.get("context") == "multisite" else "globe"),
|
||||
"text": ("inp_popover_multisite" if value.get("context") == "multisite" else "inp_popover_global"),
|
||||
}
|
||||
)
|
||||
|
||||
if value.get("help"):
|
||||
popovers.append(
|
||||
{
|
||||
"iconName": "info",
|
||||
"text": value.get("help"),
|
||||
}
|
||||
)
|
||||
|
||||
value["popovers"] = popovers
|
||||
|
||||
# Case multiple, stop here
|
||||
if "multiple" in value:
|
||||
return value
|
||||
|
||||
# Else, we can add additional final data
|
||||
value["method"] = settings.get(name, {}).get("method", "ui")
|
||||
value["containerClass"] = f"z-{total_settings - loop_id}"
|
||||
|
||||
if current_value is not None and not is_current_default:
|
||||
value["value"] = current_value
|
||||
elif template_value is not None:
|
||||
value["value"] = template_value
|
||||
else:
|
||||
value["value"] = setting_value
|
||||
|
||||
return value
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
|||
import json
|
||||
import base64
|
||||
|
||||
from pages.advanced_mode import advanced_mode_builder
|
||||
from builder.advanced_mode import advanced_mode_builder
|
||||
|
||||
# Default plugins from docker-compose.ui.yml
|
||||
plugins = [
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
from .utils.form import get_forms, get_service_settings
|
||||
|
||||
|
||||
def advanced_mode_builder(templates: list[dict], plugins: list, global_config: dict, total_config: dict, service_name: str, is_new: bool = False) -> str:
|
||||
"""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).
|
||||
"""
|
||||
settings = get_service_settings(service_name, global_config, total_config)
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": service_name,
|
||||
"type": "container",
|
||||
"lowercase": True,
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Subtitle",
|
||||
"data": {"subtitle": "services_manage_subtitle", "type": "container"},
|
||||
},
|
||||
{
|
||||
"type": "Templates",
|
||||
"data": {
|
||||
"templates": get_forms(templates, plugins, settings, ("advanced",), is_new, True),
|
||||
"operation": "new" if is_new else "edit",
|
||||
"oldServerName": service_name if service_name else "",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
import json
|
||||
import base64
|
||||
|
||||
# TODO : REMOVE operation by custom endpoint
|
||||
|
||||
from builder.utils.widgets import button, button_group, title, text, tabulator, fields, upload, datepicker, input, select
|
||||
|
||||
bans_columns = [
|
||||
|
|
@ -33,7 +35,7 @@ bans_filters = [
|
|||
"name": "select-ban-reason",
|
||||
"label": "bans_select_reason", # keep it (a18n)
|
||||
"value": "all", # keep "all"
|
||||
"values": ["all", "antibot"], # keep "all" and add your reasons
|
||||
"values": ["all", "antibot"], # keep "all" and add your reasons dynamically
|
||||
"inpType": "select",
|
||||
"onlyDown": True,
|
||||
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
|
||||
|
|
@ -165,7 +167,7 @@ builder = [
|
|||
"display": ["main", 1],
|
||||
"widgets": [
|
||||
tabulator(
|
||||
id="table-core-plugins",
|
||||
id="table-bans-list",
|
||||
columns=bans_columns,
|
||||
items=bans_items,
|
||||
filters=bans_filters,
|
||||
|
|
@ -241,7 +241,7 @@ configs_items = [
|
|||
hideText=True,
|
||||
color="yellow",
|
||||
size="normal",
|
||||
attrs={"data-display": "display_index"}, # replace by the display index of the related in order to display it
|
||||
attrs={"data-display": "display_index"}, # replace by the display index of the related form in order to display it
|
||||
)["data"],
|
||||
# Delete button with modal to confirm
|
||||
button(
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import json
|
||||
import base64
|
||||
|
||||
from pages.easy_mode import easy_mode_builder
|
||||
from builder.easy_mode import easy_mode_builder
|
||||
|
||||
# Default plugins from docker-compose.ui.yml
|
||||
plugins = [
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
from .utils.form import get_forms, get_service_settings
|
||||
|
||||
|
||||
def easy_mode_builder(templates: list[dict], plugins: list, global_config: dict, total_config: dict, service_name: str, is_new: bool = False) -> str:
|
||||
"""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).
|
||||
"""
|
||||
|
||||
# We need
|
||||
settings = get_service_settings(service_name, global_config, total_config)
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": service_name,
|
||||
"type": "container",
|
||||
"lowercase": True,
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Subtitle",
|
||||
"data": {"subtitle": "services_manage_subtitle", "type": "container"},
|
||||
},
|
||||
{
|
||||
"type": "Templates",
|
||||
"data": {
|
||||
"templates": get_forms(templates, plugins, settings, ("easy",), is_new, True),
|
||||
"operation": "new" if is_new else "edit",
|
||||
"oldServerName": service_name if service_name else "",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
from .utils.form import get_forms
|
||||
|
||||
|
||||
def global_config_builder(templates: list[dict], plugins: list, settings: dict) -> str:
|
||||
"""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).
|
||||
"""
|
||||
|
||||
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, ("advanced", "raw")),
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import json
|
||||
import base64
|
||||
|
||||
from pages.global_config import global_config_builder
|
||||
from builder.global_config import global_config_builder
|
||||
|
||||
# Default plugins from docker-compose.ui.yml
|
||||
plugins = [
|
||||
|
|
|
|||
|
|
@ -1,84 +1,99 @@
|
|||
from .utils.widgets import stat_widget
|
||||
import json
|
||||
import base64
|
||||
|
||||
home = [
|
||||
{
|
||||
"type": "card",
|
||||
"link": "https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui#pro",
|
||||
"containerColumns": {"pc": 4, "tablet": 6, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_version",
|
||||
"subtitle": "home_upgrade_to_pro",
|
||||
"subtitleColor": "warning",
|
||||
"stat": "home_free",
|
||||
"iconName": "key",
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"link": "https://github.com/bunkerity/bunkerweb",
|
||||
"containerColumns": {"pc": 4, "tablet": 6, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_version_number",
|
||||
"subtitle": "home_update_available",
|
||||
"subtitleColor": "warning",
|
||||
"stat": "1.5.8",
|
||||
"iconName": "wire",
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"link": "/instances",
|
||||
"containerColumns": {"pc": 4, "tablet": 6, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_instances",
|
||||
"subtitle": "home_total_number",
|
||||
"subtitleColor": "info",
|
||||
"stat": 1,
|
||||
"iconName": "box",
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"link": "/services",
|
||||
"containerColumns": {"pc": 4, "tablet": 6, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_services",
|
||||
"subtitle": "home_all_methods_included",
|
||||
"subtitleColor": "info",
|
||||
"stat": 2,
|
||||
"iconName": "disk",
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"link": "/plugins",
|
||||
"containerColumns": {"pc": 4, "tablet": 6, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_plugins",
|
||||
"subtitle": "home_no_error",
|
||||
"subtitleColor": "success",
|
||||
"stat": "42",
|
||||
"iconName": "puzzle",
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
def home_builder(data: dict) -> str:
|
||||
"""
|
||||
It returns the needed format from data to render the home page in JSON format for the Vue.js builder
|
||||
"""
|
||||
version_card = stat_widget(
|
||||
link="https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui#pro",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
title="home_version",
|
||||
subtitle=(
|
||||
"home_all_features_available"
|
||||
if data.get("is_pro_version")
|
||||
else (
|
||||
"home_awaiting_compliance"
|
||||
if data.get("pro_status") == "active" and data.get("pro_overlapped")
|
||||
else (
|
||||
"home_renew_license"
|
||||
if data.get("pro_status") == "expired"
|
||||
else "home_talk_to_team" if data.get("pro_status") == "suspended" else "home_upgrade_to_pro"
|
||||
)
|
||||
)
|
||||
),
|
||||
subtitle_color="success" if data.get("is_pro_version") else "warning",
|
||||
stat=(
|
||||
"home_pro"
|
||||
if data.get("is_pro_version")
|
||||
else (
|
||||
"home_pro_locked"
|
||||
if data.get("pro_status") == "active" and data.get("pro_overlapped")
|
||||
else "home_expired" if data.get("pro_status") == "expired" else "home_suspended" if data.get("pro_status") == "suspended" else "home_free"
|
||||
)
|
||||
),
|
||||
icon_name="crown" if data.get("is_pro_version") else "key",
|
||||
)
|
||||
# store on a file
|
||||
with open("home.json", "w") as f:
|
||||
json.dump(home, f, indent=4)
|
||||
output_base64_bytes = base64.b64encode(bytes(json.dumps(home), "utf-8"))
|
||||
output_base64_string = output_base64_bytes.decode("ascii")
|
||||
|
||||
version_num_card = stat_widget(
|
||||
link="https://github.com/bunkerity/bunkerweb",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
title="home_version_number",
|
||||
subtitle=(
|
||||
"home_couldnt_find_remote"
|
||||
if not data.get("remote_version")
|
||||
else "home_latest_version" if data.get("remote_version") and data.get("check_version") else "home_update_available"
|
||||
),
|
||||
subtitle_color=("error" if not data.get("remote_version") else "success" if data.get("remote_version") and data.get("check_version") else "warning"),
|
||||
stat=data.get("version"),
|
||||
icon_name="wire",
|
||||
)
|
||||
|
||||
instances_card = stat_widget(
|
||||
link="instances",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
title="home_instances",
|
||||
subtitle="home_total_number",
|
||||
subtitle_color="info",
|
||||
stat=data.get("instances_number"),
|
||||
icon_name="box",
|
||||
)
|
||||
|
||||
services_card = stat_widget(
|
||||
link="services",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
title="home_services",
|
||||
subtitle="home_all_methods_included",
|
||||
subtitle_color="info",
|
||||
stat=data.get("services_number"),
|
||||
icon_name="disk",
|
||||
)
|
||||
|
||||
plugins_card = stat_widget(
|
||||
link="plugins",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
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=data.get("plugins_number"),
|
||||
icon_name="puzzle",
|
||||
)
|
||||
|
||||
builder = [version_card, version_num_card, instances_card, services_card, plugins_card]
|
||||
|
||||
return builder
|
||||
with open("home.txt", "w") as f:
|
||||
f.write(output_base64_string)
|
||||
|
|
|
|||
|
|
@ -1,46 +1,33 @@
|
|||
from .utils.widgets import instance_widget
|
||||
import json
|
||||
import base64
|
||||
|
||||
from typing import List
|
||||
|
||||
# from src.instance import Instance
|
||||
from builder.instances import instances_builder
|
||||
|
||||
|
||||
def instances_builder(instances: List[Instance]) -> str:
|
||||
"""
|
||||
It returns the needed format from data to render the instances page in JSON format for the Vue.js builder
|
||||
"""
|
||||
builder = []
|
||||
# Create instance class using keys from the instances list
|
||||
class Instance:
|
||||
def __init__(self, _type, health, _id, hostname, name):
|
||||
self._type = _type
|
||||
self.health = health
|
||||
self._id = _id
|
||||
self.hostname = hostname
|
||||
self.name = name
|
||||
|
||||
for instance in instances:
|
||||
# setup actions buttons
|
||||
actions = ["reload", "stop"] if instance.status == "up" else ["start"]
|
||||
|
||||
buttons = [
|
||||
{
|
||||
"attrs": {
|
||||
"data-submit-form": f"""{{"INSTANCE_ID" : "{instance.hostname}", "operation" : "{action}" }}""",
|
||||
},
|
||||
"text": f"action_{action}",
|
||||
"color": "success" if action == "start" else "error" if action == "stop" else "warning",
|
||||
}
|
||||
for action in actions
|
||||
]
|
||||
instances = [
|
||||
Instance("manual", True, "bunkerweb", "bunkerweb", "bunkerweb"),
|
||||
Instance("manual", True, "bunkerweb", "bunkerweb", "bunkerweb"),
|
||||
]
|
||||
|
||||
instance = instance_widget(
|
||||
containerColumns={"pc": 6, "tablet": 6, "mobile": 12},
|
||||
pairs=[
|
||||
{"key": "instances_name", "value": instance.name},
|
||||
{"key": "instances_hostname", "value": instance.hostname},
|
||||
{"key": "instances_type", "value": instance.type},
|
||||
{"key": "instances_method", "value": instance.method},
|
||||
{"key": "instances_creation_date", "value": instance.creation_date.strftime("%d-%m-%Y %H:%M:%S")},
|
||||
{"key": "instances_last_seen", "value": instance.last_seen.strftime("%d-%m-%Y %H:%M:%S")},
|
||||
],
|
||||
status="success" if instance.status == "up" else "error",
|
||||
title=instance.hostname,
|
||||
buttons=buttons,
|
||||
)
|
||||
|
||||
builder.append(instance)
|
||||
builder = instances_builder(instances)
|
||||
|
||||
return builder
|
||||
# store on a file
|
||||
with open("instances.json", "w") as f:
|
||||
json.dump(builder, f)
|
||||
|
||||
output_base64_bytes = base64.b64encode(bytes(json.dumps(builder), "utf-8"))
|
||||
output_base64_string = output_base64_bytes.decode("ascii")
|
||||
|
||||
with open("instances.txt", "w") as f:
|
||||
f.write(output_base64_string)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import json
|
||||
import base64
|
||||
|
||||
# TODO : REMOVE operation by custom endpoint
|
||||
|
||||
from builder.utils.widgets import button, button_group, title, text, tabulator, input
|
||||
|
||||
columns = [
|
||||
|
|
@ -10,6 +12,7 @@ columns = [
|
|||
{"title": "Method", "field": "method", "formatter": "text"},
|
||||
{"title": "Creation date", "field": "creation_date", "formatter": "text"},
|
||||
{"title": "Last seen", "field": "last_seen", "formatter": "text"},
|
||||
{"title": "health", "field": "health", "formatter": "text"}, # up, down, loading
|
||||
{
|
||||
"title": "Actions",
|
||||
"field": "actions",
|
||||
|
|
@ -157,6 +160,7 @@ items = [
|
|||
]
|
||||
|
||||
|
||||
# TODO : Add warning that port and server_name will be override by scheduler
|
||||
instance_create_form_widgets = [
|
||||
input(
|
||||
id="instance-name",
|
||||
|
|
@ -1,290 +1,226 @@
|
|||
from .utils.widgets import title_widget, table_widget
|
||||
import json
|
||||
import base64
|
||||
|
||||
from builder.jobs import jobs_builder
|
||||
|
||||
|
||||
def jobs_builder(jobs):
|
||||
jobs = {
|
||||
"anonymous-report": {
|
||||
"plugin_id": "misc",
|
||||
"every": "day",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:03 PM", "end_date": "07/08/2024, 01:10:04 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"backup-data": {
|
||||
"plugin_id": "backup",
|
||||
"every": "day",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"blacklist-download": {
|
||||
"plugin_id": "blacklist",
|
||||
"every": "hour",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:01 PM", "end_date": "07/08/2024, 01:10:02 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"bunkernet-data": {
|
||||
"plugin_id": "bunkernet",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"bunkernet-register": {
|
||||
"plugin_id": "bunkernet",
|
||||
"every": "hour",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:02 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"certbot-new": {
|
||||
"plugin_id": "letsencrypt",
|
||||
"every": "once",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"certbot-renew": {
|
||||
"plugin_id": "letsencrypt",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:03 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"cleanup-excess-jobs-runs": {
|
||||
"plugin_id": "db",
|
||||
"every": "day",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"coreruleset-nightly": {
|
||||
"plugin_id": "modsecurity",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:01 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"custom-cert": {
|
||||
"plugin_id": "customcert",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"default-server-cert": {
|
||||
"plugin_id": "misc",
|
||||
"every": "once",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [
|
||||
{
|
||||
"service_id": None,
|
||||
"file_name": "default-server-cert.pem",
|
||||
"last_update": "07/08/2024, 01:10:03 PM",
|
||||
"checksum": "203da9e16dabe522a3080c3b9efc5c2dc8054f47e98d995fe1812f4c498b4feb519ef080b7dfeaba0095c1393793815c23f22072daf5703b02762504b211db20",
|
||||
},
|
||||
{
|
||||
"service_id": None,
|
||||
"file_name": "default-server-cert.key",
|
||||
"last_update": "07/08/2024, 01:10:03 PM",
|
||||
"checksum": "7f86b1fffb8fe2011365d76e5a0955344a03c3bdb7b04aff13f8ad5b6178804290c0cd6c8f29dda9e981e3193cf5acda2a92f72312d514514305b8485667d573",
|
||||
},
|
||||
],
|
||||
},
|
||||
"download-crs-plugins": {
|
||||
"plugin_id": "modsecurity",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:03 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"download-plugins": {
|
||||
"plugin_id": "misc",
|
||||
"every": "once",
|
||||
"reload": False,
|
||||
"history": [
|
||||
{"start_date": "07/08/2024, 01:10:04 PM", "end_date": "07/08/2024, 01:10:05 PM", "success": True},
|
||||
{"start_date": "07/08/2024, 01:09:59 PM", "end_date": "07/08/2024, 01:10:00 PM", "success": True},
|
||||
],
|
||||
"cache": [],
|
||||
},
|
||||
"download-pro-plugins": {
|
||||
"plugin_id": "pro",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [
|
||||
{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:04 PM", "success": True},
|
||||
{"start_date": "07/08/2024, 01:10:00 PM", "end_date": "07/08/2024, 01:10:01 PM", "success": False},
|
||||
],
|
||||
"cache": [],
|
||||
},
|
||||
"failover-backup": {
|
||||
"plugin_id": "jobs",
|
||||
"every": "once",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:07 PM", "end_date": "07/08/2024, 01:10:08 PM", "success": True}],
|
||||
"cache": [
|
||||
{
|
||||
"service_id": None,
|
||||
"file_name": "folder:/var/tmp/bunkerweb/failover.tgz",
|
||||
"last_update": "07/08/2024, 01:10:14 PM",
|
||||
"checksum": "d22a7a696d4b44bcef6a3ac06b2d7e2b2de128243000f58202c0e82b0bf54510ade7329eca14ca478a28d46201410ea1fd8002349b7b9aa51dd0d07d2fb2f51e",
|
||||
}
|
||||
],
|
||||
},
|
||||
"greylist-download": {
|
||||
"plugin_id": "greylist",
|
||||
"every": "hour",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"mmdb-asn": {
|
||||
"plugin_id": "jobs",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:04 PM", "end_date": "07/08/2024, 01:10:06 PM", "success": True}],
|
||||
"cache": [
|
||||
{
|
||||
"service_id": None,
|
||||
"file_name": "asn.mmdb",
|
||||
"last_update": "07/08/2024, 01:10:05 PM",
|
||||
"checksum": "0beed65a84e63cf5dd6753ecc1aa6399dddaf5eb24fb22839f4cd72cbc9805cddf72be068649d111a3c21e2ac7de4a6f930c859286a25a7e937da017406d2596",
|
||||
}
|
||||
],
|
||||
},
|
||||
"mmdb-country": {
|
||||
"plugin_id": "jobs",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:04 PM", "success": True}],
|
||||
"cache": [
|
||||
{
|
||||
"service_id": None,
|
||||
"file_name": "country.mmdb",
|
||||
"last_update": "07/08/2024, 01:10:03 PM",
|
||||
"checksum": "5f0d2e2c92840747886924adc1e6ff3668882990e0cd8a4d60750fe1bddb66c3e175c8717d073b48ebda41cce4c505d434dc2a6a469823fcd41c62c4f875b212",
|
||||
}
|
||||
],
|
||||
},
|
||||
"realip-download": {
|
||||
"plugin_id": "realip",
|
||||
"every": "hour",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"self-signed": {
|
||||
"plugin_id": "selfsigned",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [
|
||||
{
|
||||
"service_id": "www.example.com",
|
||||
"file_name": "cert.pem",
|
||||
"last_update": "07/08/2024, 01:10:03 PM",
|
||||
"checksum": "fc33700719f6a58336e3c3b735ad3fdf0b15ebd0afbe6b4a3b02a4a92e0ab4f1761409a7a1d1ca965d59b4196a81c1d150a12ae0170f7bb3a1bc7cf02300fbe9",
|
||||
},
|
||||
{
|
||||
"service_id": "www.example.com",
|
||||
"file_name": "key.pem",
|
||||
"last_update": "07/08/2024, 01:10:03 PM",
|
||||
"checksum": "0e6eee34ab7b2a41cb21e49ebd35ce29a1b8d12b55aad3911b6357c73792eef7084fbb4eeba8bff73eb7a8789b5f486f6edb6d4b1c38a54bd0dcee1bf438f23d",
|
||||
},
|
||||
],
|
||||
},
|
||||
"update-check": {
|
||||
"plugin_id": "jobs",
|
||||
"every": "day",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:06 PM", "end_date": "07/08/2024, 01:10:07 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"whitelist-download": {
|
||||
"plugin_id": "whitelist",
|
||||
"every": "hour",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:02 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
}
|
||||
|
||||
jobs_list = get_jobs_list(jobs)
|
||||
output = jobs_builder(jobs)
|
||||
|
||||
intervals = ["all"]
|
||||
# store on a file
|
||||
with open("jobs.json", "w") as f:
|
||||
json.dump(output, f, indent=4)
|
||||
output_base64_bytes = base64.b64encode(bytes(json.dumps(output), "utf-8"))
|
||||
output_base64_string = output_base64_bytes.decode("ascii")
|
||||
|
||||
# loop on each job
|
||||
for job in jobs_list:
|
||||
# loop on each item
|
||||
for item in job:
|
||||
# get the interval if not already in intervals
|
||||
if item.get("every") and item.get("every") not in intervals:
|
||||
intervals.append(item.get("every"))
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
title_widget("jobs_title"),
|
||||
table_widget(
|
||||
positions=[3, 2, 1, 1, 1, 1, 3],
|
||||
header=[
|
||||
"jobs_table_name",
|
||||
"jobs_table_plugin_id",
|
||||
"jobs_table_interval",
|
||||
"jobs_table_reload",
|
||||
"jobs_table_success",
|
||||
"jobs_table_history",
|
||||
"jobs_table_cache_downloadable",
|
||||
],
|
||||
items=jobs_list,
|
||||
filters=[
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "keyword",
|
||||
"type": "keyword",
|
||||
"value": "",
|
||||
"keys": ["name", "plugin_id"],
|
||||
"field": {
|
||||
"id": "jobs-keyword",
|
||||
"value": "",
|
||||
"type": "text",
|
||||
"name": "jobs-keyword",
|
||||
"label": "jobs_search",
|
||||
"placeholder": "inp_keyword",
|
||||
"isClipboard": False,
|
||||
"popovers": [
|
||||
{
|
||||
"text": "jobs_search_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "every",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["every"],
|
||||
"field": {
|
||||
"id": "jobs-every",
|
||||
"value": "all",
|
||||
"values": intervals,
|
||||
"name": "jobs-every",
|
||||
"onlyDown": True,
|
||||
"label": "jobs_interval",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "jobs_interval_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "reload",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["reload"],
|
||||
"field": {
|
||||
"id": "jobs-last-run",
|
||||
"value": "all",
|
||||
"values": ["all", "success", "failed"],
|
||||
"name": "jobs-last-run",
|
||||
"onlyDown": True,
|
||||
"label": "jobs_reload",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "jobs_reload_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "success",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["success"],
|
||||
"field": {
|
||||
"id": "jobs-success",
|
||||
"value": "all",
|
||||
"values": ["all", "success", "failed"],
|
||||
"name": "jobs-success",
|
||||
"onlyDown": True,
|
||||
"label": "jobs_success",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "jobs_success_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
],
|
||||
minWidth="lg",
|
||||
title="jobs_table_title",
|
||||
),
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
return builder
|
||||
|
||||
|
||||
def get_jobs_list(jobs):
|
||||
data = []
|
||||
# loop on each dict
|
||||
for key, value in jobs.items():
|
||||
item = []
|
||||
item.append({"name": key, "type": "Text", "data": {"text": key}})
|
||||
# loop on each value
|
||||
for k, v in value.items():
|
||||
# override widget type for some keys
|
||||
if k in ("reload", "history"):
|
||||
is_success = v if k == "reload" else v[0].get("success")
|
||||
item.append(
|
||||
{
|
||||
k: "success" if is_success else "failed",
|
||||
"type": "Icons",
|
||||
"data": {
|
||||
"iconName": "check" if is_success else "cross",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if k not in ("history"):
|
||||
continue
|
||||
|
||||
if k in ("plugin_id", "every"):
|
||||
item.append({k: v, "type": "Text", "data": {"text": v}})
|
||||
continue
|
||||
|
||||
if k in ("history"):
|
||||
items = []
|
||||
for hist in v:
|
||||
items.append(
|
||||
[
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": hist["start_date"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": hist["end_date"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Icons",
|
||||
"data": {
|
||||
"iconName": "check" if hist["success"] else "cross",
|
||||
},
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
item.append(
|
||||
{
|
||||
"type": "Button",
|
||||
"data": {
|
||||
"id": f"open-modal-history-{k}",
|
||||
"text": "jobs_history",
|
||||
"hideText": True,
|
||||
"color": "blue",
|
||||
"size": "normal",
|
||||
"iconName": "document",
|
||||
"iconColor": "white",
|
||||
"modal": {
|
||||
"widgets": [
|
||||
{"type": "Title", "data": {"title": key}},
|
||||
{"type": "Subtitle", "data": {"subtitle": "jobs_history_subtitle"}},
|
||||
{
|
||||
"type": "Table",
|
||||
"data": {
|
||||
"title": "jobs_history_table_title",
|
||||
"minWidth": "",
|
||||
"header": [
|
||||
"jobs_table_start_run",
|
||||
"jobs_table_end_run",
|
||||
"jobs_table_success",
|
||||
],
|
||||
"positions": [5, 5, 2],
|
||||
"items": items,
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "ButtonGroup",
|
||||
"data": {
|
||||
"buttons": [
|
||||
{
|
||||
"id": f"close-history-{k}",
|
||||
"text": "action_close",
|
||||
"color": "close",
|
||||
"size": "normal",
|
||||
"attrs": {"data-close-modal": ""},
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if k in ("cache") and len(v) <= 0:
|
||||
item.append({k: v, "type": "Text", "data": {"text": ""}})
|
||||
continue
|
||||
|
||||
if k in ("cache") and len(v) > 0:
|
||||
files = []
|
||||
# loop on each cache item
|
||||
for cache in v:
|
||||
file_name = f"{cache['file_name']} [{cache['service_id']}]" if cache["service_id"] else f"{cache['file_name']}"
|
||||
files.append(file_name)
|
||||
|
||||
item.append(
|
||||
{
|
||||
k: " ".join(files),
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"attrs": {
|
||||
"data-plugin-id": value.get("plugin_id", ""),
|
||||
"data-job-name": key,
|
||||
},
|
||||
"id": f"{key}_cache",
|
||||
"label": f"{key}_cache",
|
||||
"hideLabel": True,
|
||||
"inpType": "select",
|
||||
"name": f"{key}_cache",
|
||||
"value": "download file",
|
||||
"values": files,
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12,
|
||||
},
|
||||
"overflowAttrEl": "data-table-body",
|
||||
"containerClass": "table download-cache-file",
|
||||
"maxBtnChars": 16,
|
||||
"popovers": [
|
||||
{
|
||||
"iconName": "info",
|
||||
"text": "jobs_download_cache_file",
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
data.append(item)
|
||||
|
||||
return data
|
||||
with open("jobs.txt", "w") as f:
|
||||
f.write(output_base64_string)
|
||||
|
|
|
|||
|
|
@ -1,83 +1,17 @@
|
|||
from .utils.widgets import title_widget
|
||||
import json
|
||||
import base64
|
||||
|
||||
from builder.logs import logs_builder
|
||||
|
||||
def logs_builder(files: list[str] = [], current_file: str = "", raw_data: str = "") -> str:
|
||||
files = ["file1", "file2"]
|
||||
current_file = ""
|
||||
raw_data = "gefesfesfsefes"
|
||||
output = logs_builder(files, current_file, raw_data)
|
||||
|
||||
if not files:
|
||||
builder = [
|
||||
{
|
||||
"type": "void",
|
||||
"widgets": [{"type": "MessageUnmatch", "data": {"text": "logs_no_files_found"}}],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
with open("logs.json", "w") as f:
|
||||
json.dump(output, f, indent=4)
|
||||
|
||||
file_select = {
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"id": "logs-select-file",
|
||||
"label": "logs_log_file",
|
||||
"inpType": "select",
|
||||
"name": "logs-select-file",
|
||||
"onlyDown": True,
|
||||
"value": current_file or "Select a file",
|
||||
"values": files,
|
||||
"columns": {
|
||||
"pc": 4,
|
||||
"tablet": 6,
|
||||
"mobile": 12,
|
||||
},
|
||||
"maxBtnChars": 20,
|
||||
"attrs": {
|
||||
"data-log": "true",
|
||||
},
|
||||
"popovers": [
|
||||
{
|
||||
"iconName": "info",
|
||||
"text": "logs_select_file_info",
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
if not raw_data:
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [title_widget("logs_title"), file_select, {"type": "MessageUnmatch", "data": {"text": "logs_not_selected_or_not_found"}}],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
||||
editor = {
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"containerClass": "mt-4",
|
||||
"id": "logs-file-content",
|
||||
"label": "logs_file_content",
|
||||
"inpType": "editor",
|
||||
"name": "logs-file-content",
|
||||
"value": raw_data,
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12,
|
||||
},
|
||||
"editorClass" : "min-h-[500px]",
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [title_widget("logs_title"), file_select, editor],
|
||||
}
|
||||
]
|
||||
|
||||
return builder
|
||||
output_base64_bytes = base64.b64encode(bytes(json.dumps(output), "utf-8"))
|
||||
output_base64_string = output_base64_bytes.decode("ascii")
|
||||
with open("logs.txt", "w") as f:
|
||||
f.write(output_base64_string)
|
||||
|
|
|
|||
|
|
@ -1,17 +1,24 @@
|
|||
import json
|
||||
import base64
|
||||
|
||||
# TODO : REMOVE operation by custom endpoint
|
||||
|
||||
from builder.utils.widgets import button, button_group, title, text, tabulator, fields, upload, checkbox
|
||||
|
||||
core_columns = [
|
||||
|
||||
# Here all plugins unless external
|
||||
core_pro_columns = [
|
||||
{"title": "Name", "field": "name", "formatter": "text"},
|
||||
{"title": "Description", "field": "description", "formatter": "text"},
|
||||
{"title": "Type", "field": "type", "formatter": "text"},
|
||||
{"title": "version", "field": "version", "formatter": "text"},
|
||||
{"title": "stream", "field": "type", "stream": "text"}, # "yes" "no" "partial"
|
||||
{"title": "Documentation page", "field": "documentation_page", "formatter": "buttonGroup"},
|
||||
{"title": "Plugin page", "field": "plugin_page", "formatter": "buttonGroup"},
|
||||
]
|
||||
|
||||
|
||||
core_filters = [
|
||||
core_pro_filters = [
|
||||
{
|
||||
"type": "like",
|
||||
"fields": ["name"],
|
||||
|
|
@ -27,7 +34,7 @@ core_filters = [
|
|||
]
|
||||
|
||||
|
||||
core_items = [
|
||||
core_pro_items = [
|
||||
{
|
||||
"name": text(text="Name")["data"],
|
||||
"description": text(text="Description")["data"],
|
||||
|
|
@ -63,24 +70,25 @@ core_items = [
|
|||
]
|
||||
|
||||
|
||||
register_columns = [
|
||||
registry_columns = [
|
||||
{"title": "Select", "field": "select", "formatter": "fields"}, # checkbox
|
||||
{"title": "Name", "field": "name", "formatter": "text"},
|
||||
{"title": "Description", "field": "description", "formatter": "text"},
|
||||
{"title": "Type", "field": "type", "formatter": "text"},
|
||||
{"title": "Install", "field": "install", "formatter": "text"},
|
||||
{"title": "Documentation page", "field": "documentation_page", "formatter": "buttonGroup"},
|
||||
{"title": "version", "field": "version", "formatter": "text"},
|
||||
{"title": "stream", "field": "type", "stream": "text"}, # "yes" "no" "partial"
|
||||
{"title": "Plugin page", "field": "plugin_page", "formatter": "buttonGroup"},
|
||||
]
|
||||
|
||||
|
||||
register_filters = [
|
||||
registry_filters = [
|
||||
{
|
||||
"type": "like",
|
||||
"fields": ["name"],
|
||||
"setting": {
|
||||
"id": "input-search-register-name",
|
||||
"name": "input-search-register-name",
|
||||
"id": "input-search-registry-name",
|
||||
"name": "input-search-registry-name",
|
||||
"label": "plugins_search_name", # keep it (a18n)
|
||||
"value": "",
|
||||
"inpType": "input",
|
||||
|
|
@ -91,8 +99,8 @@ register_filters = [
|
|||
"type": "=",
|
||||
"fields": ["type"],
|
||||
"setting": {
|
||||
"id": "select-register-type",
|
||||
"name": "select-register-type",
|
||||
"id": "select-registry-type",
|
||||
"name": "select-registry-type",
|
||||
"label": "plugins_select_type", # keep it (a18n)
|
||||
"value": "all",
|
||||
"values": ["all", "pro", "external"],
|
||||
|
|
@ -105,8 +113,8 @@ register_filters = [
|
|||
"type": "=",
|
||||
"fields": ["install"],
|
||||
"setting": {
|
||||
"id": "select-register-install",
|
||||
"name": "select-register-install",
|
||||
"id": "select-registry-install",
|
||||
"name": "select-registry-install",
|
||||
"label": "plugins_select_install", # keep it (a18n)
|
||||
"value": "all",
|
||||
"values": ["all", "yes", "no"],
|
||||
|
|
@ -118,7 +126,7 @@ register_filters = [
|
|||
]
|
||||
|
||||
|
||||
register_items = [
|
||||
registry_items = [
|
||||
{
|
||||
"select": checkbox(
|
||||
inputType="checkbox",
|
||||
|
|
@ -164,6 +172,7 @@ register_items = [
|
|||
},
|
||||
]
|
||||
|
||||
# Here all plugins with type external
|
||||
upload_columns = [
|
||||
{"title": "Select", "field": "select", "formatter": "fields"}, # checkbox
|
||||
{"title": "Name", "field": "name", "formatter": "text"},
|
||||
|
|
@ -241,9 +250,9 @@ builder = [
|
|||
"widgets": [
|
||||
tabulator(
|
||||
id="table-core-plugins",
|
||||
columns=core_columns,
|
||||
items=core_items,
|
||||
filters=core_filters,
|
||||
columns=core_pro_columns,
|
||||
items=core_pro_items,
|
||||
filters=core_pro_filters,
|
||||
)
|
||||
],
|
||||
},
|
||||
|
|
@ -252,10 +261,10 @@ builder = [
|
|||
"display": ["main", 2],
|
||||
"widgets": [
|
||||
tabulator(
|
||||
id="table-register-plugins",
|
||||
columns=register_columns,
|
||||
items=register_items,
|
||||
filters=register_filters,
|
||||
id="table-registry-plugins",
|
||||
columns=registry_columns,
|
||||
items=registry_items,
|
||||
filters=registry_filters,
|
||||
)
|
||||
],
|
||||
},
|
||||
|
|
@ -1,20 +1,37 @@
|
|||
import json
|
||||
import base64
|
||||
|
||||
# TODO : REMOVE operation by custom endpoint
|
||||
|
||||
from builder.utils.widgets import button, button_group, title, text, tabulator, fields, upload, input, combobox, checkbox, select, editor
|
||||
|
||||
# Define data to put in profile widgets
|
||||
# - username
|
||||
# - email
|
||||
# - created_method
|
||||
# - is_superadmin
|
||||
# - role
|
||||
# - role_description
|
||||
# - permissions (liste of permissions [])
|
||||
# - creation_date
|
||||
# - last_update (last time update user info)
|
||||
profile_widgets = []
|
||||
|
||||
# Define data to put in profile form widgets
|
||||
# - update password
|
||||
# - update email
|
||||
# - update username
|
||||
user_widgets = []
|
||||
account_widgets = []
|
||||
|
||||
# Define data to put in totp widgets
|
||||
# - enable totp: what we need ?
|
||||
# - disable totp: what we need ?
|
||||
# if want to enable totp (currently disabled):
|
||||
# text with state
|
||||
# show QRcode SVG
|
||||
# - form (endpoint /totp-enable) : totp secret (type password), totp code, password
|
||||
# Case currently enabled :
|
||||
# text with state
|
||||
# after first totp setup, show recovery codes
|
||||
# form refresh recovery codes button that will redisplay recovery (endpoint /totp-refresh) : password (warning that will remove previous)
|
||||
# form disabled (endpoint /totp-disable) : totp code || recovery code, password
|
||||
totp_widgets = []
|
||||
|
||||
builder = [
|
||||
|
|
@ -29,7 +46,7 @@ builder = [
|
|||
"type": "card",
|
||||
"display": ["main", 2],
|
||||
"widgets": [
|
||||
user_widgets,
|
||||
account_widgets,
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
from .utils.form import get_forms, get_service_settings
|
||||
|
||||
|
||||
def raw_mode_builder(templates: list[dict], plugins: list, global_config: dict, total_config: dict, service_name: str, is_new: bool = False) -> str:
|
||||
"""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).
|
||||
"""
|
||||
|
||||
# We need
|
||||
settings = get_service_settings(service_name, global_config, total_config)
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": service_name,
|
||||
"type": "container",
|
||||
"lowercase": True,
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Subtitle",
|
||||
"data": {"subtitle": "services_manage_subtitle", "type": "container"},
|
||||
},
|
||||
{
|
||||
"type": "Templates",
|
||||
"data": {
|
||||
"templates": get_forms(templates, plugins, settings, ("raw",), is_new, True),
|
||||
"operation": "new" if is_new else "edit",
|
||||
"oldServerName": service_name if service_name else "",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
|
@ -3,10 +3,13 @@ import base64
|
|||
|
||||
from builder.utils.widgets import button, button_group, title, text, tabulator, fields, upload, datepicker
|
||||
|
||||
# TODO : REMOVE operation by custom endpoint
|
||||
|
||||
reports_columns = [
|
||||
{"title": "Date", "field": "date", "formatter": "fields"}, # datepicker
|
||||
{"title": "IP", "field": "ip", "formatter": "text"},
|
||||
{"title": "Country", "field": "country", "formatter": "text"},
|
||||
{"title": "Server name", "field": "server_name", "formatter": "text"},
|
||||
{"title": "Method", "field": "method", "formatter": "text"},
|
||||
{"title": "URL", "field": "url", "formatter": "text"},
|
||||
{"title": "Code", "field": "code", "formatter": "text"},
|
||||
|
|
@ -1,379 +1,46 @@
|
|||
import json
|
||||
import base64
|
||||
from typing import Union
|
||||
|
||||
from .utils.widgets import title_widget, table_widget
|
||||
from builder.services import services_builder
|
||||
|
||||
services = [
|
||||
{
|
||||
"USE_REVERSE_PROXY": {"value": "yes", "method": "scheduler", "global": False},
|
||||
"IS_DRAFT": {"value": "no", "method": "default", "global": False},
|
||||
"SERVE_FILES": {"value": "no", "method": "scheduler", "global": True},
|
||||
"REMOTE_PHP": {"value": "", "method": "default", "global": True},
|
||||
"AUTO_LETS_ENCRYPT": {"value": "no", "method": "default", "global": True},
|
||||
"USE_CUSTOM_SSL": {"value": "no", "method": "default", "global": True},
|
||||
"USE_MODSECURITY": {"value": "yes", "method": "default", "global": True},
|
||||
"USE_BAD_BEHAVIOR": {"value": "yes", "method": "default", "global": True},
|
||||
"USE_LIMIT_REQ": {"value": "yes", "method": "default", "global": True},
|
||||
"USE_DNSBL": {"value": "yes", "method": "default", "global": True},
|
||||
"SERVER_NAME": {"value": "app1.example.com", "method": "scheduler", "global": False},
|
||||
},
|
||||
{
|
||||
"USE_REVERSE_PROXY": {"value": "yes", "method": "scheduler", "global": False},
|
||||
"IS_DRAFT": {"value": "yes", "method": "default", "global": False},
|
||||
"SERVE_FILES": {"value": "no", "method": "scheduler", "global": True},
|
||||
"REMOTE_PHP": {"value": "", "method": "default", "global": True},
|
||||
"AUTO_LETS_ENCRYPT": {"value": "no", "method": "default", "global": True},
|
||||
"USE_CUSTOM_SSL": {"value": "no", "method": "default", "global": True},
|
||||
"USE_MODSECURITY": {"value": "yes", "method": "default", "global": True},
|
||||
"USE_BAD_BEHAVIOR": {"value": "yes", "method": "default", "global": True},
|
||||
"USE_LIMIT_REQ": {"value": "yes", "method": "default", "global": True},
|
||||
"USE_DNSBL": {"value": "yes", "method": "default", "global": True},
|
||||
"SERVER_NAME": {"value": "www.example.com", "method": "ui", "global": False},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def services_builder(services):
|
||||
# get method for each service["SERVER_NAME"]["method"]
|
||||
methods = list(set([service["SERVER_NAME"]["method"] for service in services]))
|
||||
output = services_builder(services)
|
||||
|
||||
services_list = get_services_list(services)
|
||||
# store on a file
|
||||
with open("services.json", "w") as f:
|
||||
json.dump(output, f, indent=4)
|
||||
output_base64_bytes = base64.b64encode(bytes(json.dumps(output), "utf-8"))
|
||||
output_base64_string = output_base64_bytes.decode("ascii")
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
title_widget("services_title"),
|
||||
{
|
||||
"type": "Button",
|
||||
"data": {
|
||||
"id": "services-new",
|
||||
"text": "services_new",
|
||||
"color": "success",
|
||||
"size": "normal",
|
||||
"iconName": "plus",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(server_name="new", operation="new", title="services_new_title", subtitle="services_new_subtitle"),
|
||||
"containerClass": "col-span-12 flex justify-center",
|
||||
},
|
||||
},
|
||||
table_widget(
|
||||
positions=[4, 4, 4],
|
||||
header=[
|
||||
"services_table_name",
|
||||
"services_table_method",
|
||||
"services_table_actions",
|
||||
],
|
||||
items=services_list,
|
||||
filters=[
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "keyword",
|
||||
"type": "keyword",
|
||||
"value": "",
|
||||
"keys": ["name"],
|
||||
"field": {
|
||||
"id": "services-keyword",
|
||||
"value": "",
|
||||
"type": "text",
|
||||
"name": "services-keyword",
|
||||
"label": "services_search",
|
||||
"placeholder": "inp_keyword",
|
||||
"isClipboard": False,
|
||||
"popovers": [
|
||||
{
|
||||
"text": "services_search_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "method",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["method"],
|
||||
"field": {
|
||||
"id": "services-methods",
|
||||
"value": "all",
|
||||
"values": methods,
|
||||
"name": "services-methods",
|
||||
"onlyDown": True,
|
||||
"label": "services_methods",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "services_methods_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "draft",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["draft"],
|
||||
"field": {
|
||||
"id": "services-draft",
|
||||
"value": "all",
|
||||
"values": ["all", "online", "draft"],
|
||||
"name": "services-draft",
|
||||
"onlyDown": True,
|
||||
"label": "services_draft",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "services_draft_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
],
|
||||
minWidth="md",
|
||||
title="services_table_title",
|
||||
),
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
return builder
|
||||
|
||||
|
||||
def services_settings(settings: dict) -> dict:
|
||||
# deep copy settings dict
|
||||
settings = settings.copy()
|
||||
# remove "SERVER_NAME" and "IS_DRAFT" key
|
||||
settings.pop("SERVER_NAME", None)
|
||||
settings.pop("IS_DRAFT", None)
|
||||
# Create table with settings remaining keys
|
||||
settings_table_items = []
|
||||
for key, value in settings.items():
|
||||
format_key = key.replace("USE_", "").replace("_", " ")
|
||||
settings_table_items.append(
|
||||
[
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {"text": format_key},
|
||||
},
|
||||
{
|
||||
"type": "Icons",
|
||||
"data": {
|
||||
"iconName": "check" if value.get("value") == "yes" else "cross",
|
||||
},
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
table = table_widget(
|
||||
positions=[8, 4],
|
||||
header=["services_settings_table_name", "services_settings_table_status"],
|
||||
items=settings_table_items,
|
||||
filters=[],
|
||||
minWidth="",
|
||||
title="services_settings_table_title",
|
||||
)
|
||||
|
||||
return table
|
||||
|
||||
|
||||
def services_action(
|
||||
server_name: str = "",
|
||||
operation: str = "",
|
||||
title: str = "",
|
||||
subtitle: str = "",
|
||||
additional: str = "",
|
||||
is_draft: Union[bool, None] = None,
|
||||
service: dict = None,
|
||||
) -> dict:
|
||||
|
||||
buttons = [
|
||||
{
|
||||
"id": f"close-service-btn-{server_name}",
|
||||
"text": "action_close",
|
||||
"disabled": False,
|
||||
"color": "close",
|
||||
"size": "normal",
|
||||
"attrs": {"data-close-modal": ""},
|
||||
},
|
||||
]
|
||||
|
||||
if operation == "delete":
|
||||
buttons.append(
|
||||
{
|
||||
"id": f"{operation}-service-btn-{server_name}",
|
||||
"text": f"action_{operation}",
|
||||
"disabled": False,
|
||||
"color": "delete",
|
||||
"size": "normal",
|
||||
"attrs": {
|
||||
"data-submit-form": f"""{{"SERVER_NAME" : "{server_name}", "operation" : "{operation}" }}""",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if operation == "draft":
|
||||
draft_value = "yes" if is_draft else "no"
|
||||
buttons.append(
|
||||
{
|
||||
"id": f"{operation}-service-btn-{server_name}",
|
||||
"text": "action_switch",
|
||||
"disabled": False,
|
||||
"color": "success",
|
||||
"size": "normal",
|
||||
"attrs": {
|
||||
"data-submit-form": f"""{{"SERVER_NAME" : "{server_name}", "OLD_SERVER_NAME" : "{server_name}", "operation" : "edit", "IS_DRAFT" : "{draft_value}" }}""",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
content = [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": title,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
if subtitle:
|
||||
content.append(
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": subtitle,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if additional:
|
||||
content.append(
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"bold": True,
|
||||
"text": additional,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if operation == "plugins":
|
||||
settings = services_settings(service)
|
||||
content.append(settings)
|
||||
|
||||
if operation == "delete":
|
||||
content.append(
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "",
|
||||
"bold": True,
|
||||
"text": server_name,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if operation == "edit" or operation == "new":
|
||||
modes = ("easy", "advanced", "raw")
|
||||
mode_buttons = []
|
||||
for mode in modes:
|
||||
mode_buttons.append(
|
||||
{
|
||||
"id": f"{operation}-service-btn-{server_name}",
|
||||
"text": f"services_mode_{mode}",
|
||||
"disabled": False,
|
||||
"color": "info",
|
||||
"size": "normal",
|
||||
"attrs": {
|
||||
"role": "link",
|
||||
"data-link": f"modes?service_name={server_name}&mode={mode}" if operation != "new" else f"modes?mode={mode}",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
content.append(
|
||||
{
|
||||
"type": "ButtonGroup",
|
||||
"data": {"buttons": mode_buttons},
|
||||
}
|
||||
)
|
||||
|
||||
content.append(
|
||||
{
|
||||
"type": "ButtonGroup",
|
||||
"data": {"buttons": buttons},
|
||||
},
|
||||
)
|
||||
|
||||
modal = {
|
||||
"widgets": content,
|
||||
}
|
||||
|
||||
return modal
|
||||
|
||||
|
||||
def get_services_list(services):
|
||||
data = []
|
||||
for index, service in enumerate(services):
|
||||
server_name = service["SERVER_NAME"]["value"]
|
||||
server_method = service["SERVER_NAME"]["method"]
|
||||
is_draft = True if service["IS_DRAFT"]["value"] == "yes" else False
|
||||
is_deletable = False if server_method in ("autoconf", "scheduler") else True
|
||||
|
||||
item = []
|
||||
# Get name
|
||||
item.append({"name": server_name, "type": "Text", "data": {"text": server_name}})
|
||||
item.append({"method": server_method, "type": "Text", "data": {"text": server_method}})
|
||||
item.append(
|
||||
{
|
||||
"type": "ButtonGroup",
|
||||
"data": {
|
||||
"buttons": [
|
||||
{
|
||||
"id": f"open-modal-plugins-{index}",
|
||||
"text": "plugins",
|
||||
"hideText": True,
|
||||
"color": "success",
|
||||
"size": "normal",
|
||||
"iconName": "eye",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(
|
||||
server_name=server_name,
|
||||
operation="plugins",
|
||||
title="services_plugins_title",
|
||||
subtitle="",
|
||||
service=service,
|
||||
),
|
||||
},
|
||||
{
|
||||
"attrs": {"data-server-name": server_name},
|
||||
"id": f"open-modal-manage-{index}",
|
||||
"text": "manage",
|
||||
"hideText": True,
|
||||
"color": "edit",
|
||||
"size": "normal",
|
||||
"iconName": "pen",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(
|
||||
server_name=server_name,
|
||||
operation="edit",
|
||||
title="services_edit_title",
|
||||
subtitle="services_edit_subtitle",
|
||||
additional=server_name,
|
||||
),
|
||||
},
|
||||
{
|
||||
"attrs": {"data-server-name": server_name, "data-is-draft": "yes" if is_draft else "no"},
|
||||
"id": f"open-modal-draft-{index}",
|
||||
"text": "draft" if is_draft else "online",
|
||||
"hideText": True,
|
||||
"color": "blue",
|
||||
"size": "normal",
|
||||
"iconName": "document" if is_draft else "globe",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(
|
||||
server_name=server_name,
|
||||
operation="draft",
|
||||
title="services_draft_title",
|
||||
subtitle="services_draft_subtitle" if is_draft else "services_online_subtitle",
|
||||
additional="services_draft_switch_subtitle" if is_draft else "services_online_switch_subtitle",
|
||||
is_draft=is_draft,
|
||||
),
|
||||
},
|
||||
{
|
||||
"attrs": {"data-server-name": server_name},
|
||||
"id": f"open-modal-delete-{index}",
|
||||
"text": "delete",
|
||||
"disabled": not is_deletable,
|
||||
"hideText": True,
|
||||
"color": "red",
|
||||
"size": "normal",
|
||||
"iconName": "trash",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(
|
||||
server_name=server_name, operation="delete", title="services_delete_title", subtitle="services_delete_subtitle"
|
||||
),
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
data.append(item)
|
||||
|
||||
return data
|
||||
with open("services.txt", "w") as f:
|
||||
f.write(output_base64_string)
|
||||
|
|
|
|||
|
|
@ -4,12 +4,14 @@ import base64
|
|||
from builder.utils.widgets import button, button_group, title, text, tabulator, fields, upload, input, combobox, checkbox, select, editor, datepicker
|
||||
|
||||
|
||||
# TODO : REMOVE operation by custom endpoint
|
||||
def generate_form(
|
||||
username: str = "",
|
||||
password: str = "",
|
||||
email: str = "",
|
||||
is_new: bool = True,
|
||||
role: str = "",
|
||||
roles: list = [],
|
||||
password: str = "",
|
||||
display_index: int = 1,
|
||||
):
|
||||
|
||||
|
|
@ -88,8 +90,10 @@ def get_forms():
|
|||
users_columns = [
|
||||
{"title": "Username", "field": "username", "formatter": "text"},
|
||||
{"title": "Role", "field": "role", "formatter": "text"},
|
||||
{"title": "creation_date", "field": "creation_date", "formatter": "fields"}, # datepicker
|
||||
{"title": "last_login", "field": "last_login", "formatter": "fields"}, # datepicker
|
||||
{"title": "Creation date", "field": "creation_date", "formatter": "fields"}, # datepicker
|
||||
{"title": "Last login", "field": "last_login", "formatter": "fields"}, # datepicker of last login
|
||||
{"title": "Last login IP", "field": "last_login_ip", "formatter": "fields"}, # datepicker of last login
|
||||
{"title": "Login count", "field": "login_count", "formatter": "fields"}, # datepicker of last login
|
||||
{"title": "totp (state)", "field": "totp", "formatter": "icons"}, # icon check or cross
|
||||
{
|
||||
"title": "actions",
|
||||
|
|
@ -146,7 +146,7 @@ import Container from "@components/Widget/Container.vue";
|
|||
* }
|
||||
* }
|
||||
* },
|
||||
* @param {object<object>} multiples - The multiples settings to display. This needs to be a dict of settings using default field format.
|
||||
* @param {object} multiples - The multiples settings to display. This needs to be a dict of settings using default field format.
|
||||
* @param {object} [columns={"pc": "12", "tablet": "12", "mobile": "12"}] - Field has a grid system. This allow to get multiple field in the same row if needed.
|
||||
* @param {string} [containerClass=""] - Additionnal class to add to the container
|
||||
* @param {string} [tadId=contentIndex] - The tabindex of the field, by default it is the contentIndex
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -1,669 +0,0 @@
|
|||
[
|
||||
{
|
||||
"type": "void",
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Button",
|
||||
"data": {
|
||||
"text": "bans_not_found"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": "bans_title"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Table",
|
||||
"data": {
|
||||
"title": "bans_table_title",
|
||||
"minWidth": "xl",
|
||||
"header": [
|
||||
"bans_table_select",
|
||||
"bans_table_ip",
|
||||
"bans_table_reason",
|
||||
"bans_table_ban_start",
|
||||
"bans_table_ban_end",
|
||||
"bans_table_remain",
|
||||
"bans_table_term"
|
||||
],
|
||||
"positions": [1, 1, 1, 3, 3, 2, 1],
|
||||
"items": [
|
||||
[
|
||||
{
|
||||
"select": false,
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": false,
|
||||
"value": "no",
|
||||
"inpType": "checkbox",
|
||||
"id": "select-ban-1",
|
||||
"name": "select-ban-1",
|
||||
"label": "select-ban-1",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ip": "127.0.0.1",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "127.0.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"reason": "ui",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "ui"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ban_start": "1719393920",
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": true,
|
||||
"value": 1719393920,
|
||||
"inpType": "datepicker",
|
||||
"id": "datepicker-ban-ban-start-1",
|
||||
"name": "datepicker-ban-ban-start-1",
|
||||
"label": "datepicker-ban-ban-start-1",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ban_end": "1719393920",
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": true,
|
||||
"value": 1719393920,
|
||||
"inpType": "datepicker",
|
||||
"id": "datepicker-ban-ban-end-1",
|
||||
"name": "datepicker-ban-ban-end-1",
|
||||
"label": "datepicker-ban-ban-end-1",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"remain": "23 hours and 49 minutes",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "23 hours and 49 minutes"
|
||||
}
|
||||
},
|
||||
{
|
||||
"term": "hour(s)",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "hour(s)"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"select": false,
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": false,
|
||||
"value": "no",
|
||||
"inpType": "checkbox",
|
||||
"id": "select-ban-2",
|
||||
"name": "select-ban-2",
|
||||
"label": "select-ban-2",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ip": "127.0.0.1",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "127.0.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"reason": "ui",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "ui"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ban_start": "1719393920",
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": true,
|
||||
"value": 1719393920,
|
||||
"inpType": "datepicker",
|
||||
"id": "datepicker-ban-ban-start-2",
|
||||
"name": "datepicker-ban-ban-start-2",
|
||||
"label": "datepicker-ban-ban-start-2",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ban_end": "1719393920",
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": true,
|
||||
"value": 1719393920,
|
||||
"inpType": "datepicker",
|
||||
"id": "datepicker-ban-ban-end-2",
|
||||
"name": "datepicker-ban-ban-end-2",
|
||||
"label": "datepicker-ban-ban-end-2",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"remain": "23 hours and 49 minutes",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "23 hours and 49 minutes"
|
||||
}
|
||||
},
|
||||
{
|
||||
"term": "day(s)",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "day(s)"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"select": false,
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": false,
|
||||
"value": "no",
|
||||
"inpType": "checkbox",
|
||||
"id": "select-ban-3",
|
||||
"name": "select-ban-3",
|
||||
"label": "select-ban-3",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ip": "127.0.0.1",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "127.0.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"reason": "cor",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "cor"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ban_start": "1719393920",
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": true,
|
||||
"value": 1719393920,
|
||||
"inpType": "datepicker",
|
||||
"id": "datepicker-ban-ban-start-3",
|
||||
"name": "datepicker-ban-ban-start-3",
|
||||
"label": "datepicker-ban-ban-start-3",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ban_end": "1719393920",
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": true,
|
||||
"value": 1719393920,
|
||||
"inpType": "datepicker",
|
||||
"id": "datepicker-ban-ban-end-3",
|
||||
"name": "datepicker-ban-ban-end-3",
|
||||
"label": "datepicker-ban-ban-end-3",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"remain": "23 hours and 49 minutes",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "23 hours and 49 minutes"
|
||||
}
|
||||
},
|
||||
{
|
||||
"term": "hour(s)",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "hour(s)"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"select": false,
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": false,
|
||||
"value": "no",
|
||||
"inpType": "checkbox",
|
||||
"id": "select-ban-4",
|
||||
"name": "select-ban-4",
|
||||
"label": "select-ban-4",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ip": "127.0.0.1",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "127.0.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"reason": "ui",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "ui"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ban_start": "1719393920",
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": true,
|
||||
"value": 1719393920,
|
||||
"inpType": "datepicker",
|
||||
"id": "datepicker-ban-ban-start-4",
|
||||
"name": "datepicker-ban-ban-start-4",
|
||||
"label": "datepicker-ban-ban-start-4",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ban_end": "1719393920",
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": true,
|
||||
"value": 1719393920,
|
||||
"inpType": "datepicker",
|
||||
"id": "datepicker-ban-ban-end-4",
|
||||
"name": "datepicker-ban-ban-end-4",
|
||||
"label": "datepicker-ban-ban-end-4",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"remain": "23 hours and 49 minutes",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "23 hours and 49 minutes"
|
||||
}
|
||||
},
|
||||
{
|
||||
"term": "hour(s)",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "hour(s)"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"select": false,
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": false,
|
||||
"value": "no",
|
||||
"inpType": "checkbox",
|
||||
"id": "select-ban-5",
|
||||
"name": "select-ban-5",
|
||||
"label": "select-ban-5",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ip": "127.0.0.1",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "127.0.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"reason": "ui",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "ui"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ban_start": "1719393920",
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": true,
|
||||
"value": 1719393920,
|
||||
"inpType": "datepicker",
|
||||
"id": "datepicker-ban-ban-start-5",
|
||||
"name": "datepicker-ban-ban-start-5",
|
||||
"label": "datepicker-ban-ban-start-5",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ban_end": "1719393920",
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": true,
|
||||
"value": 1719393920,
|
||||
"inpType": "datepicker",
|
||||
"id": "datepicker-ban-ban-end-5",
|
||||
"name": "datepicker-ban-ban-end-5",
|
||||
"label": "datepicker-ban-ban-end-5",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"remain": "23 hours and 49 minutes",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "23 hours and 49 minutes"
|
||||
}
|
||||
},
|
||||
{
|
||||
"term": "hour(s)",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "hour(s)"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"select": false,
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": false,
|
||||
"value": "no",
|
||||
"inpType": "checkbox",
|
||||
"id": "select-ban-6",
|
||||
"name": "select-ban-6",
|
||||
"label": "select-ban-6",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ip": "127.0.0.1",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "127.0.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"reason": "ui",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "ui"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ban_start": "1719393920",
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": true,
|
||||
"value": 1719393920,
|
||||
"inpType": "datepicker",
|
||||
"id": "datepicker-ban-ban-start-6",
|
||||
"name": "datepicker-ban-ban-start-6",
|
||||
"label": "datepicker-ban-ban-start-6",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ban_end": "1719393920",
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"disabled": true,
|
||||
"value": 1719393920,
|
||||
"inpType": "datepicker",
|
||||
"id": "datepicker-ban-ban-end-6",
|
||||
"name": "datepicker-ban-ban-end-6",
|
||||
"label": "datepicker-ban-ban-end-6",
|
||||
"hideLabel": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"remain": "23 hours and 49 minutes",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "23 hours and 49 minutes"
|
||||
}
|
||||
},
|
||||
{
|
||||
"term": "hour(s)",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "hour(s)"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"filters": [
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "keyword",
|
||||
"type": "keyword",
|
||||
"value": "",
|
||||
"keys": ["ip", "ban_start", "ban_end"],
|
||||
"field": {
|
||||
"id": "bans-keyword",
|
||||
"value": "",
|
||||
"type": "text",
|
||||
"name": "bans-keyword",
|
||||
"label": "bans_search",
|
||||
"placeholder": "inp_keyword",
|
||||
"isClipboard": false,
|
||||
"popovers": [
|
||||
{
|
||||
"text": "bans_search_desc",
|
||||
"iconName": "info"
|
||||
}
|
||||
],
|
||||
"columns": {
|
||||
"pc": 3,
|
||||
"tablet": 4,
|
||||
"mobile": 12
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "reason",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["reason"],
|
||||
"field": {
|
||||
"id": "bans-reason",
|
||||
"value": "all",
|
||||
"values": ["all", "ui", "cor"],
|
||||
"name": "bans-reason",
|
||||
"onlyDown": true,
|
||||
"label": "bans_reason",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "bans_reason_desc",
|
||||
"iconName": "info"
|
||||
}
|
||||
],
|
||||
"columns": {
|
||||
"pc": 3,
|
||||
"tablet": 4,
|
||||
"mobile": 12
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "term",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["term"],
|
||||
"field": {
|
||||
"id": "bans-terms",
|
||||
"value": "all",
|
||||
"values": ["all", "hour(s)", "day(s)"],
|
||||
"name": "bans-terms",
|
||||
"onlyDown": true,
|
||||
"label": "bans_terms",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "bans_terms_desc",
|
||||
"iconName": "info"
|
||||
}
|
||||
],
|
||||
"columns": {
|
||||
"pc": 3,
|
||||
"tablet": 4,
|
||||
"mobile": 12
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
@ -1,296 +0,0 @@
|
|||
import json
|
||||
|
||||
no_bans = []
|
||||
|
||||
|
||||
bans = [
|
||||
{
|
||||
"reason": "ui",
|
||||
"date": 1719393920,
|
||||
"ip": "127.0.0.1",
|
||||
"remain": "23 hours and 49 minutes",
|
||||
"term": "hour(s)",
|
||||
"ban_start": 1719393920,
|
||||
"ban_end": 1719393920,
|
||||
},
|
||||
{
|
||||
"reason": "ui",
|
||||
"date": 1719393920,
|
||||
"ip": "127.0.0.1",
|
||||
"remain": "23 hours and 49 minutes",
|
||||
"term": "day(s)",
|
||||
"ban_start": 1719393920,
|
||||
"ban_end": 1719393920,
|
||||
},
|
||||
{
|
||||
"reason": "core",
|
||||
"date": 1719393920,
|
||||
"ip": "127.0.0.1",
|
||||
"remain": "23 hours and 49 minutes",
|
||||
"term": "hour(s)",
|
||||
"ban_start": 1719393920,
|
||||
"ban_end": 1719393920,
|
||||
},
|
||||
{
|
||||
"reason": "ui",
|
||||
"date": 1719393920,
|
||||
"ip": "127.0.0.1",
|
||||
"remain": "23 hours and 49 minutes",
|
||||
"term": "hour(s)",
|
||||
"ban_start": 1719393920,
|
||||
"ban_end": 1719393920,
|
||||
},
|
||||
{
|
||||
"reason": "ui",
|
||||
"date": 1719393920,
|
||||
"ip": "127.0.0.1",
|
||||
"remain": "23 hours and 49 minutes",
|
||||
"term": "hour(s)",
|
||||
"ban_start": 1719393920,
|
||||
"ban_end": 1719393920,
|
||||
},
|
||||
{
|
||||
"reason": "ui",
|
||||
"date": 1719393920,
|
||||
"ip": "127.0.0.1",
|
||||
"remain": "23 hours and 49 minutes",
|
||||
"term": "hour(s)",
|
||||
"ban_start": 1719393920,
|
||||
"ban_end": 1719393920,
|
||||
},
|
||||
]
|
||||
# Reorder bans dict
|
||||
for ban in bans:
|
||||
ban.pop("date")
|
||||
ban["ip"] = ban.pop("ip")
|
||||
ban["reason"] = ban.pop("reason")
|
||||
ban["ban_start"] = ban.pop("ban_start")
|
||||
ban["ban_end"] = ban.pop("ban_end")
|
||||
ban["remain"] = ban.pop("remain")
|
||||
ban["term"] = ban.pop("term")
|
||||
|
||||
|
||||
def get_bans_filter(bans):
|
||||
|
||||
if len(bans) <= 5:
|
||||
return []
|
||||
|
||||
total_reasons = ["all"]
|
||||
total_terms = ["all"]
|
||||
|
||||
for ban in bans:
|
||||
if ban.get("reason") and ban.get("reason") not in total_reasons:
|
||||
total_reasons.append(ban.get("reason"))
|
||||
|
||||
if ban.get("term") and ban.get("term") not in total_terms:
|
||||
total_terms.append(ban.get("term"))
|
||||
|
||||
filters = []
|
||||
|
||||
filters.append(
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "keyword",
|
||||
"type": "keyword",
|
||||
"value": "",
|
||||
"keys": ["ip", "ban_start", "ban_end"],
|
||||
"field": {
|
||||
"id": "bans-keyword",
|
||||
"value": "",
|
||||
"type": "text",
|
||||
"name": "bans-keyword",
|
||||
"label": "bans_search",
|
||||
"placeholder": "inp_keyword",
|
||||
"isClipboard": False,
|
||||
"popovers": [
|
||||
{
|
||||
"text": "bans_search_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if len(total_reasons) > 2:
|
||||
filters.append(
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "reason",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["reason"],
|
||||
"field": {
|
||||
"id": "bans-reason",
|
||||
"value": "all",
|
||||
"values": total_reasons,
|
||||
"name": "bans-reason",
|
||||
"onlyDown": True,
|
||||
"label": "bans_reason",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "bans_reason_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if len(total_terms) > 2:
|
||||
filters.append(
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "term",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["term"],
|
||||
"field": {
|
||||
"id": "bans-terms",
|
||||
"value": "all",
|
||||
"values": total_terms,
|
||||
"name": "bans-terms",
|
||||
"onlyDown": True,
|
||||
"label": "bans_terms",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "bans_terms_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
)
|
||||
return filters
|
||||
|
||||
|
||||
def get_bans_list(bans):
|
||||
data = []
|
||||
# loop on each dict
|
||||
id = 0
|
||||
for ban in bans:
|
||||
id += 1
|
||||
item = []
|
||||
item.append(
|
||||
{
|
||||
"select": False,
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"disabled": False,
|
||||
"value": "no",
|
||||
"inpType": "checkbox",
|
||||
"id": f"select-ban-{id}",
|
||||
"name": f"select-ban-{id}",
|
||||
"label": f"select-ban-{id}",
|
||||
"hideLabel": True,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
for k, v in ban.items():
|
||||
|
||||
if k in ("date", "ban_start", "ban_end"):
|
||||
item.append(
|
||||
{
|
||||
k: json.dumps(v) if isinstance(v, dict) else str(v),
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"columns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"disabled": True,
|
||||
"value": v,
|
||||
"inpType": "datepicker",
|
||||
"id": f"datepicker-ban-{k}-{id}".replace("_", "-"),
|
||||
"name": f"datepicker-ban-{k}-{id}".replace("_", "-"),
|
||||
"label": f"datepicker-ban-{k}-{id}".replace("_", "-"),
|
||||
"hideLabel": True,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
item.append(
|
||||
{
|
||||
k: json.dumps(v) if isinstance(v, dict) else str(v),
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": json.dumps(v) if isinstance(v, dict) else str(v),
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
data.append(item)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def bans_builder(bans):
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "void",
|
||||
"widgets": [{"type": "Button", "data": {"text": "bans_not_found"}}],
|
||||
},
|
||||
]
|
||||
|
||||
if not bans:
|
||||
builder.append(
|
||||
{
|
||||
"type": "void",
|
||||
"widgets": [
|
||||
{"type": "MessageUnmatch", "data": {"text": "bans_not_found"}}
|
||||
],
|
||||
}
|
||||
)
|
||||
return builder
|
||||
|
||||
filters = get_bans_filter(bans)
|
||||
bans_list = get_bans_list(bans)
|
||||
|
||||
bans_table = {
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {"title": "bans_title"},
|
||||
},
|
||||
{
|
||||
"type": "Table",
|
||||
"data": {
|
||||
"title": "bans_table_title",
|
||||
"minWidth": "xl",
|
||||
"header": [
|
||||
"bans_table_select",
|
||||
"bans_table_ip",
|
||||
"bans_table_reason",
|
||||
"bans_table_ban_start",
|
||||
"bans_table_ban_end",
|
||||
"bans_table_remain",
|
||||
"bans_table_term",
|
||||
],
|
||||
"positions": [1, 1, 1, 3, 3, 2, 1],
|
||||
"items": bans_list,
|
||||
"filters": filters,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
builder.append(bans_table)
|
||||
|
||||
return builder
|
||||
|
||||
|
||||
output = bans_builder(bans)
|
||||
# output = bans_builder(no_bans)
|
||||
|
||||
# store on a file
|
||||
with open("bans.json", "w") as f:
|
||||
json.dump(output, f, indent=4)
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
from .utils.form import get_forms, get_service_settings
|
||||
|
||||
|
||||
def advanced_mode_builder(templates: list[dict], plugins: list, global_config: dict, total_config: dict, service_name: str, is_new: bool = False) -> str:
|
||||
"""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).
|
||||
"""
|
||||
settings = get_service_settings(service_name, global_config, total_config)
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": service_name,
|
||||
"type": "container",
|
||||
"lowercase": True,
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Subtitle",
|
||||
"data": {"subtitle": "services_manage_subtitle", "type": "container"},
|
||||
},
|
||||
{
|
||||
"type": "Templates",
|
||||
"data": {
|
||||
"templates": get_forms(templates, plugins, settings, ("advanced",), is_new, True),
|
||||
"operation": "new" if is_new else "edit",
|
||||
"oldServerName": service_name if service_name else "",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
from .utils.form import get_forms, get_service_settings
|
||||
|
||||
|
||||
def easy_mode_builder(templates: list[dict], plugins: list, global_config: dict, total_config: dict, service_name: str, is_new: bool = False) -> str:
|
||||
"""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).
|
||||
"""
|
||||
|
||||
# We need
|
||||
settings = get_service_settings(service_name, global_config, total_config)
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": service_name,
|
||||
"type": "container",
|
||||
"lowercase": True,
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Subtitle",
|
||||
"data": {"subtitle": "services_manage_subtitle", "type": "container"},
|
||||
},
|
||||
{
|
||||
"type": "Templates",
|
||||
"data": {
|
||||
"templates": get_forms(templates, plugins, settings, ("easy",), is_new, True),
|
||||
"operation": "new" if is_new else "edit",
|
||||
"oldServerName": service_name if service_name else "",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
from .utils.form import get_forms
|
||||
|
||||
|
||||
def global_config_builder(templates: list[dict], plugins: list, settings: dict) -> str:
|
||||
"""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).
|
||||
"""
|
||||
|
||||
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, ("advanced", "raw")),
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
from .utils.widgets import stat_widget
|
||||
|
||||
|
||||
def home_builder(data: dict) -> str:
|
||||
"""
|
||||
It returns the needed format from data to render the home page in JSON format for the Vue.js builder
|
||||
"""
|
||||
version_card = stat_widget(
|
||||
link="https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui#pro",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
title="home_version",
|
||||
subtitle=(
|
||||
"home_all_features_available"
|
||||
if data.get("is_pro_version")
|
||||
else (
|
||||
"home_awaiting_compliance"
|
||||
if data.get("pro_status") == "active" and data.get("pro_overlapped")
|
||||
else (
|
||||
"home_renew_license"
|
||||
if data.get("pro_status") == "expired"
|
||||
else "home_talk_to_team" if data.get("pro_status") == "suspended" else "home_upgrade_to_pro"
|
||||
)
|
||||
)
|
||||
),
|
||||
subtitle_color="success" if data.get("is_pro_version") else "warning",
|
||||
stat=(
|
||||
"home_pro"
|
||||
if data.get("is_pro_version")
|
||||
else (
|
||||
"home_pro_locked"
|
||||
if data.get("pro_status") == "active" and data.get("pro_overlapped")
|
||||
else "home_expired" if data.get("pro_status") == "expired" else "home_suspended" if data.get("pro_status") == "suspended" else "home_free"
|
||||
)
|
||||
),
|
||||
icon_name="crown" if data.get("is_pro_version") else "key",
|
||||
)
|
||||
|
||||
version_num_card = stat_widget(
|
||||
link="https://github.com/bunkerity/bunkerweb",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
title="home_version_number",
|
||||
subtitle=(
|
||||
"home_couldnt_find_remote"
|
||||
if not data.get("remote_version")
|
||||
else "home_latest_version" if data.get("remote_version") and data.get("check_version") else "home_update_available"
|
||||
),
|
||||
subtitle_color=("error" if not data.get("remote_version") else "success" if data.get("remote_version") and data.get("check_version") else "warning"),
|
||||
stat=data.get("version"),
|
||||
icon_name="wire",
|
||||
)
|
||||
|
||||
instances_card = stat_widget(
|
||||
link="instances",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
title="home_instances",
|
||||
subtitle="home_total_number",
|
||||
subtitle_color="info",
|
||||
stat=data.get("instances_number"),
|
||||
icon_name="box",
|
||||
)
|
||||
|
||||
services_card = stat_widget(
|
||||
link="services",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
title="home_services",
|
||||
subtitle="home_all_methods_included",
|
||||
subtitle_color="info",
|
||||
stat=data.get("services_number"),
|
||||
icon_name="disk",
|
||||
)
|
||||
|
||||
plugins_card = stat_widget(
|
||||
link="plugins",
|
||||
containerColums={"pc": 4, "tablet": 6, "mobile": 12},
|
||||
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=data.get("plugins_number"),
|
||||
icon_name="puzzle",
|
||||
)
|
||||
|
||||
builder = [version_card, version_num_card, instances_card, services_card, plugins_card]
|
||||
|
||||
return builder
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
from .utils.widgets import instance_widget
|
||||
|
||||
|
||||
def instances_builder(instances) -> str:
|
||||
"""
|
||||
It returns the needed format from data to render the instances page in JSON format for the Vue.js builder
|
||||
"""
|
||||
builder = []
|
||||
|
||||
for instance in instances:
|
||||
# setup actions buttons
|
||||
actions = ["reload", "stop"] if instance.status == "up" else ["start"]
|
||||
|
||||
buttons = [
|
||||
{
|
||||
"attrs": {
|
||||
"data-submit-form": f"""{{"INSTANCE_ID" : "{instance.hostname}", "operation" : "{action}" }}""",
|
||||
},
|
||||
"text": f"action_{action}",
|
||||
"color": "success" if action == "start" else "error" if action == "stop" else "warning",
|
||||
}
|
||||
for action in actions
|
||||
]
|
||||
|
||||
instance = instance_widget(
|
||||
containerColumns={"pc": 6, "tablet": 6, "mobile": 12},
|
||||
pairs=[
|
||||
{"key": "instances_name", "value": instance.name},
|
||||
{"key": "instances_hostname", "value": instance.hostname},
|
||||
{"key": "instances_type", "value": instance.type},
|
||||
{"key": "instances_method", "value": instance.method},
|
||||
{"key": "instances_creation_date", "value": instance.creation_date.strftime("%d-%m-%Y %H:%M:%S")},
|
||||
{"key": "instances_last_seen", "value": instance.last_seen.strftime("%d-%m-%Y %H:%M:%S")},
|
||||
],
|
||||
status="success" if instance.status == "up" else "error",
|
||||
title=instance.hostname,
|
||||
buttons=buttons,
|
||||
)
|
||||
|
||||
builder.append(instance)
|
||||
|
||||
return builder
|
||||
|
|
@ -1,290 +0,0 @@
|
|||
from .utils.widgets import title_widget, table_widget
|
||||
|
||||
|
||||
def jobs_builder(jobs):
|
||||
|
||||
jobs_list = get_jobs_list(jobs)
|
||||
|
||||
intervals = ["all"]
|
||||
|
||||
# loop on each job
|
||||
for job in jobs_list:
|
||||
# loop on each item
|
||||
for item in job:
|
||||
# get the interval if not already in intervals
|
||||
if item.get("every") and item.get("every") not in intervals:
|
||||
intervals.append(item.get("every"))
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
title_widget("jobs_title"),
|
||||
table_widget(
|
||||
positions=[3, 2, 1, 1, 1, 1, 3],
|
||||
header=[
|
||||
"jobs_table_name",
|
||||
"jobs_table_plugin_id",
|
||||
"jobs_table_interval",
|
||||
"jobs_table_reload",
|
||||
"jobs_table_success",
|
||||
"jobs_table_history",
|
||||
"jobs_table_cache_downloadable",
|
||||
],
|
||||
items=jobs_list,
|
||||
filters=[
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "keyword",
|
||||
"type": "keyword",
|
||||
"value": "",
|
||||
"keys": ["name", "plugin_id"],
|
||||
"field": {
|
||||
"id": "jobs-keyword",
|
||||
"value": "",
|
||||
"type": "text",
|
||||
"name": "jobs-keyword",
|
||||
"label": "jobs_search",
|
||||
"placeholder": "inp_keyword",
|
||||
"isClipboard": False,
|
||||
"popovers": [
|
||||
{
|
||||
"text": "jobs_search_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "every",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["every"],
|
||||
"field": {
|
||||
"id": "jobs-every",
|
||||
"value": "all",
|
||||
"values": intervals,
|
||||
"name": "jobs-every",
|
||||
"onlyDown": True,
|
||||
"label": "jobs_interval",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "jobs_interval_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "reload",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["reload"],
|
||||
"field": {
|
||||
"id": "jobs-last-run",
|
||||
"value": "all",
|
||||
"values": ["all", "success", "failed"],
|
||||
"name": "jobs-last-run",
|
||||
"onlyDown": True,
|
||||
"label": "jobs_reload",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "jobs_reload_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "success",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["success"],
|
||||
"field": {
|
||||
"id": "jobs-success",
|
||||
"value": "all",
|
||||
"values": ["all", "success", "failed"],
|
||||
"name": "jobs-success",
|
||||
"onlyDown": True,
|
||||
"label": "jobs_success",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "jobs_success_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
],
|
||||
minWidth="lg",
|
||||
title="jobs_table_title",
|
||||
),
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
return builder
|
||||
|
||||
|
||||
def get_jobs_list(jobs):
|
||||
data = []
|
||||
# loop on each dict
|
||||
for key, value in jobs.items():
|
||||
item = []
|
||||
item.append({"name": key, "type": "Text", "data": {"text": key}})
|
||||
# loop on each value
|
||||
for k, v in value.items():
|
||||
# override widget type for some keys
|
||||
if k in ("reload", "history"):
|
||||
is_success = v if k == "reload" else v[0].get("success")
|
||||
item.append(
|
||||
{
|
||||
k: "success" if is_success else "failed",
|
||||
"type": "Icons",
|
||||
"data": {
|
||||
"iconName": "check" if is_success else "cross",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if k not in ("history"):
|
||||
continue
|
||||
|
||||
if k in ("plugin_id", "every"):
|
||||
item.append({k: v, "type": "Text", "data": {"text": v}})
|
||||
continue
|
||||
|
||||
if k in ("history"):
|
||||
items = []
|
||||
for hist in v:
|
||||
items.append(
|
||||
[
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": hist["start_date"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": hist["end_date"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Icons",
|
||||
"data": {
|
||||
"iconName": "check" if hist["success"] else "cross",
|
||||
},
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
item.append(
|
||||
{
|
||||
"type": "Button",
|
||||
"data": {
|
||||
"id": f"open-modal-history-{k}",
|
||||
"text": "jobs_history",
|
||||
"hideText": True,
|
||||
"color": "blue",
|
||||
"size": "normal",
|
||||
"iconName": "document",
|
||||
"iconColor": "white",
|
||||
"modal": {
|
||||
"widgets": [
|
||||
{"type": "Title", "data": {"title": key}},
|
||||
{"type": "Subtitle", "data": {"subtitle": "jobs_history_subtitle"}},
|
||||
{
|
||||
"type": "Table",
|
||||
"data": {
|
||||
"title": "jobs_history_table_title",
|
||||
"minWidth": "",
|
||||
"header": [
|
||||
"jobs_table_start_run",
|
||||
"jobs_table_end_run",
|
||||
"jobs_table_success",
|
||||
],
|
||||
"positions": [5, 5, 2],
|
||||
"items": items,
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "ButtonGroup",
|
||||
"data": {
|
||||
"buttons": [
|
||||
{
|
||||
"id": f"close-history-{k}",
|
||||
"text": "action_close",
|
||||
"color": "close",
|
||||
"size": "normal",
|
||||
"attrs": {"data-close-modal": ""},
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if k in ("cache") and len(v) <= 0:
|
||||
item.append({k: v, "type": "Text", "data": {"text": ""}})
|
||||
continue
|
||||
|
||||
if k in ("cache") and len(v) > 0:
|
||||
files = []
|
||||
# loop on each cache item
|
||||
for cache in v:
|
||||
file_name = f"{cache['file_name']} [{cache['service_id']}]" if cache["service_id"] else f"{cache['file_name']}"
|
||||
files.append(file_name)
|
||||
|
||||
item.append(
|
||||
{
|
||||
k: " ".join(files),
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"attrs": {
|
||||
"data-plugin-id": value.get("plugin_id", ""),
|
||||
"data-job-name": key,
|
||||
},
|
||||
"id": f"{key}_cache",
|
||||
"label": f"{key}_cache",
|
||||
"hideLabel": True,
|
||||
"inpType": "select",
|
||||
"name": f"{key}_cache",
|
||||
"value": "download file",
|
||||
"values": files,
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12,
|
||||
},
|
||||
"overflowAttrEl": "data-table-body",
|
||||
"containerClass": "table download-cache-file",
|
||||
"maxBtnChars": 16,
|
||||
"popovers": [
|
||||
{
|
||||
"iconName": "info",
|
||||
"text": "jobs_download_cache_file",
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
data.append(item)
|
||||
|
||||
return data
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
from .utils.widgets import title_widget
|
||||
|
||||
|
||||
def logs_builder(files: list[str] = [], current_file: str = "", raw_data: str = "") -> str:
|
||||
|
||||
if not files:
|
||||
builder = [
|
||||
{
|
||||
"type": "void",
|
||||
"widgets": [{"type": "MessageUnmatch", "data": {"text": "logs_no_files_found"}}],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
||||
file_select = {
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"id": "logs-select-file",
|
||||
"label": "logs_log_file",
|
||||
"inpType": "select",
|
||||
"name": "logs-select-file",
|
||||
"onlyDown": True,
|
||||
"value": current_file or "Select a file",
|
||||
"values": files,
|
||||
"columns": {
|
||||
"pc": 4,
|
||||
"tablet": 6,
|
||||
"mobile": 12,
|
||||
},
|
||||
"maxBtnChars": 20,
|
||||
"attrs": {
|
||||
"data-log": "true",
|
||||
},
|
||||
"popovers": [
|
||||
{
|
||||
"iconName": "info",
|
||||
"text": "logs_select_file_info",
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
if not raw_data:
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [title_widget("logs_title"), file_select, {"type": "MessageUnmatch", "data": {"text": "logs_not_selected_or_not_found"}}],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
||||
editor = {
|
||||
"type": "Fields",
|
||||
"data": {
|
||||
"setting": {
|
||||
"containerClass": "mt-4",
|
||||
"id": "logs-file-content",
|
||||
"label": "logs_file_content",
|
||||
"inpType": "editor",
|
||||
"name": "logs-file-content",
|
||||
"value": raw_data,
|
||||
"columns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12,
|
||||
},
|
||||
"editorClass" : "min-h-[500px]",
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [title_widget("logs_title"), file_select, editor],
|
||||
}
|
||||
]
|
||||
|
||||
return builder
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
from .utils.form import get_forms, get_service_settings
|
||||
|
||||
|
||||
def raw_mode_builder(templates: list[dict], plugins: list, global_config: dict, total_config: dict, service_name: str, is_new: bool = False) -> str:
|
||||
"""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).
|
||||
"""
|
||||
|
||||
# We need
|
||||
settings = get_service_settings(service_name, global_config, total_config)
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": service_name,
|
||||
"type": "container",
|
||||
"lowercase": True,
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "Subtitle",
|
||||
"data": {"subtitle": "services_manage_subtitle", "type": "container"},
|
||||
},
|
||||
{
|
||||
"type": "Templates",
|
||||
"data": {
|
||||
"templates": get_forms(templates, plugins, settings, ("raw",), is_new, True),
|
||||
"operation": "new" if is_new else "edit",
|
||||
"oldServerName": service_name if service_name else "",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
return builder
|
||||
|
|
@ -1,379 +0,0 @@
|
|||
from typing import Union
|
||||
|
||||
from .utils.widgets import title_widget, table_widget
|
||||
|
||||
|
||||
def services_builder(services):
|
||||
# get method for each service["SERVER_NAME"]["method"]
|
||||
methods = list(set([service["SERVER_NAME"]["method"] for service in services]))
|
||||
|
||||
services_list = get_services_list(services)
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
title_widget("services_title"),
|
||||
{
|
||||
"type": "Button",
|
||||
"data": {
|
||||
"id": "services-new",
|
||||
"text": "services_new",
|
||||
"color": "success",
|
||||
"size": "normal",
|
||||
"iconName": "plus",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(server_name="new", operation="new", title="services_new_title", subtitle="services_new_subtitle"),
|
||||
"containerClass": "col-span-12 flex justify-center",
|
||||
},
|
||||
},
|
||||
table_widget(
|
||||
positions=[4, 4, 4],
|
||||
header=[
|
||||
"services_table_name",
|
||||
"services_table_method",
|
||||
"services_table_actions",
|
||||
],
|
||||
items=services_list,
|
||||
filters=[
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "keyword",
|
||||
"type": "keyword",
|
||||
"value": "",
|
||||
"keys": ["name"],
|
||||
"field": {
|
||||
"id": "services-keyword",
|
||||
"value": "",
|
||||
"type": "text",
|
||||
"name": "services-keyword",
|
||||
"label": "services_search",
|
||||
"placeholder": "inp_keyword",
|
||||
"isClipboard": False,
|
||||
"popovers": [
|
||||
{
|
||||
"text": "services_search_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "method",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["method"],
|
||||
"field": {
|
||||
"id": "services-methods",
|
||||
"value": "all",
|
||||
"values": methods,
|
||||
"name": "services-methods",
|
||||
"onlyDown": True,
|
||||
"label": "services_methods",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "services_methods_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "draft",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["draft"],
|
||||
"field": {
|
||||
"id": "services-draft",
|
||||
"value": "all",
|
||||
"values": ["all", "online", "draft"],
|
||||
"name": "services-draft",
|
||||
"onlyDown": True,
|
||||
"label": "services_draft",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "services_draft_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
],
|
||||
minWidth="md",
|
||||
title="services_table_title",
|
||||
),
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
return builder
|
||||
|
||||
|
||||
def services_settings(settings: dict) -> dict:
|
||||
# deep copy settings dict
|
||||
settings = settings.copy()
|
||||
# remove "SERVER_NAME" and "IS_DRAFT" key
|
||||
settings.pop("SERVER_NAME", None)
|
||||
settings.pop("IS_DRAFT", None)
|
||||
# Create table with settings remaining keys
|
||||
settings_table_items = []
|
||||
for key, value in settings.items():
|
||||
format_key = key.replace("USE_", "").replace("_", " ")
|
||||
settings_table_items.append(
|
||||
[
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {"text": format_key},
|
||||
},
|
||||
{
|
||||
"type": "Icons",
|
||||
"data": {
|
||||
"iconName": "check" if value.get("value") == "yes" else "cross",
|
||||
},
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
table = table_widget(
|
||||
positions=[8, 4],
|
||||
header=["services_settings_table_name", "services_settings_table_status"],
|
||||
items=settings_table_items,
|
||||
filters=[],
|
||||
minWidth="",
|
||||
title="services_settings_table_title",
|
||||
)
|
||||
|
||||
return table
|
||||
|
||||
|
||||
def services_action(
|
||||
server_name: str = "",
|
||||
operation: str = "",
|
||||
title: str = "",
|
||||
subtitle: str = "",
|
||||
additional: str = "",
|
||||
is_draft: Union[bool, None] = None,
|
||||
service: dict = None,
|
||||
) -> dict:
|
||||
|
||||
buttons = [
|
||||
{
|
||||
"id": f"close-service-btn-{server_name}",
|
||||
"text": "action_close",
|
||||
"disabled": False,
|
||||
"color": "close",
|
||||
"size": "normal",
|
||||
"attrs": {"data-close-modal": ""},
|
||||
},
|
||||
]
|
||||
|
||||
if operation == "delete":
|
||||
buttons.append(
|
||||
{
|
||||
"id": f"{operation}-service-btn-{server_name}",
|
||||
"text": f"action_{operation}",
|
||||
"disabled": False,
|
||||
"color": "delete",
|
||||
"size": "normal",
|
||||
"attrs": {
|
||||
"data-submit-form": f"""{{"SERVER_NAME" : "{server_name}", "operation" : "{operation}" }}""",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if operation == "draft":
|
||||
draft_value = "yes" if is_draft else "no"
|
||||
buttons.append(
|
||||
{
|
||||
"id": f"{operation}-service-btn-{server_name}",
|
||||
"text": "action_switch",
|
||||
"disabled": False,
|
||||
"color": "success",
|
||||
"size": "normal",
|
||||
"attrs": {
|
||||
"data-submit-form": f"""{{"SERVER_NAME" : "{server_name}", "OLD_SERVER_NAME" : "{server_name}", "operation" : "edit", "IS_DRAFT" : "{draft_value}" }}""",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
content = [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": title,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
if subtitle:
|
||||
content.append(
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": subtitle,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if additional:
|
||||
content.append(
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"bold": True,
|
||||
"text": additional,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if operation == "plugins":
|
||||
settings = services_settings(service)
|
||||
content.append(settings)
|
||||
|
||||
if operation == "delete":
|
||||
content.append(
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "",
|
||||
"bold": True,
|
||||
"text": server_name,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if operation == "edit" or operation == "new":
|
||||
modes = ("easy", "advanced", "raw")
|
||||
mode_buttons = []
|
||||
for mode in modes:
|
||||
mode_buttons.append(
|
||||
{
|
||||
"id": f"{operation}-service-btn-{server_name}",
|
||||
"text": f"services_mode_{mode}",
|
||||
"disabled": False,
|
||||
"color": "info",
|
||||
"size": "normal",
|
||||
"attrs": {
|
||||
"role": "link",
|
||||
"data-link": f"modes?service_name={server_name}&mode={mode}" if operation != "new" else f"modes?mode={mode}",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
content.append(
|
||||
{
|
||||
"type": "ButtonGroup",
|
||||
"data": {"buttons": mode_buttons},
|
||||
}
|
||||
)
|
||||
|
||||
content.append(
|
||||
{
|
||||
"type": "ButtonGroup",
|
||||
"data": {"buttons": buttons},
|
||||
},
|
||||
)
|
||||
|
||||
modal = {
|
||||
"widgets": content,
|
||||
}
|
||||
|
||||
return modal
|
||||
|
||||
|
||||
def get_services_list(services):
|
||||
data = []
|
||||
for index, service in enumerate(services):
|
||||
server_name = service["SERVER_NAME"]["value"]
|
||||
server_method = service["SERVER_NAME"]["method"]
|
||||
is_draft = True if service["IS_DRAFT"]["value"] == "yes" else False
|
||||
is_deletable = False if server_method in ("autoconf", "scheduler") else True
|
||||
|
||||
item = []
|
||||
# Get name
|
||||
item.append({"name": server_name, "type": "Text", "data": {"text": server_name}})
|
||||
item.append({"method": server_method, "type": "Text", "data": {"text": server_method}})
|
||||
item.append(
|
||||
{
|
||||
"type": "ButtonGroup",
|
||||
"data": {
|
||||
"buttons": [
|
||||
{
|
||||
"id": f"open-modal-plugins-{index}",
|
||||
"text": "plugins",
|
||||
"hideText": True,
|
||||
"color": "success",
|
||||
"size": "normal",
|
||||
"iconName": "eye",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(
|
||||
server_name=server_name,
|
||||
operation="plugins",
|
||||
title="services_plugins_title",
|
||||
subtitle="",
|
||||
service=service,
|
||||
),
|
||||
},
|
||||
{
|
||||
"attrs": {"data-server-name": server_name},
|
||||
"id": f"open-modal-manage-{index}",
|
||||
"text": "manage",
|
||||
"hideText": True,
|
||||
"color": "edit",
|
||||
"size": "normal",
|
||||
"iconName": "pen",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(
|
||||
server_name=server_name,
|
||||
operation="edit",
|
||||
title="services_edit_title",
|
||||
subtitle="services_edit_subtitle",
|
||||
additional=server_name,
|
||||
),
|
||||
},
|
||||
{
|
||||
"attrs": {"data-server-name": server_name, "data-is-draft": "yes" if is_draft else "no"},
|
||||
"id": f"open-modal-draft-{index}",
|
||||
"text": "draft" if is_draft else "online",
|
||||
"hideText": True,
|
||||
"color": "blue",
|
||||
"size": "normal",
|
||||
"iconName": "document" if is_draft else "globe",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(
|
||||
server_name=server_name,
|
||||
operation="draft",
|
||||
title="services_draft_title",
|
||||
subtitle="services_draft_subtitle" if is_draft else "services_online_subtitle",
|
||||
additional="services_draft_switch_subtitle" if is_draft else "services_online_switch_subtitle",
|
||||
is_draft=is_draft,
|
||||
),
|
||||
},
|
||||
{
|
||||
"attrs": {"data-server-name": server_name},
|
||||
"id": f"open-modal-delete-{index}",
|
||||
"text": "delete",
|
||||
"disabled": not is_deletable,
|
||||
"hideText": True,
|
||||
"color": "red",
|
||||
"size": "normal",
|
||||
"iconName": "trash",
|
||||
"iconColor": "white",
|
||||
"modal": services_action(
|
||||
server_name=server_name, operation="delete", title="services_delete_title", subtitle="services_delete_subtitle"
|
||||
),
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
data.append(item)
|
||||
|
||||
return data
|
||||
|
|
@ -1,494 +0,0 @@
|
|||
import copy
|
||||
from typing import Union
|
||||
|
||||
|
||||
def get_setting_data(template_settings: dict, settings: dict, setting: str, value: dict, is_multiple_setting: bool = False, is_new: bool = False) -> tuple:
|
||||
template_value = template_settings.get(setting, None)
|
||||
current_value = settings[setting].get("value", None) if setting in settings else None
|
||||
default_value = value.get("default")
|
||||
is_disabled_method = (
|
||||
True if settings.get(setting, {}).get("method", "ui") not in ("ui", "default", "manual") and not is_new and not is_multiple_setting else False
|
||||
)
|
||||
is_current_from_template = True if settings.get(setting, {}).get("template", None) is not None and template_value is not None else False
|
||||
is_current_default = current_value is not None and current_value == default_value
|
||||
setting_value = current_value if current_value is not None and not is_new and not is_multiple_setting else default_value
|
||||
return template_value, current_value, default_value, is_disabled_method, is_current_from_template, is_current_default, setting_value
|
||||
|
||||
|
||||
def get_service_settings(service_name: str, global_config: dict, total_config: dict) -> dict:
|
||||
"""
|
||||
total_config is a dict that contains global settings and services settings (format SERVICE_NAME_SETTING - www.example.com_USE_ANTIBOT for example -).
|
||||
We will only keep settings that are related to the service_name (with prefix SERVICE_NAME_).
|
||||
Then we will loop on global key and override value from global config by service config if exists.
|
||||
"""
|
||||
|
||||
# Get service settings
|
||||
service_settings = {}
|
||||
for key, value in total_config.items():
|
||||
if not key.startswith(f"{service_name}_"):
|
||||
continue
|
||||
|
||||
service_settings[key.replace(f"{service_name}_", "")] = value
|
||||
|
||||
# Loop on global settings to override by service settings
|
||||
for key, value in service_settings.items():
|
||||
global_config[key] = value
|
||||
|
||||
return global_config
|
||||
|
||||
|
||||
def get_plugins_multisite(plugins: list) -> list:
|
||||
# loop on plugins with list index
|
||||
plugins_multisite = []
|
||||
for index, plugin in enumerate(plugins):
|
||||
multisite_settings = {}
|
||||
# loop on settings
|
||||
for setting, value in plugin.get("settings").items():
|
||||
# check if setting is multisite
|
||||
if value.get("context") != "multisite":
|
||||
continue
|
||||
# add multisite key to plugin
|
||||
multisite_settings[setting] = value
|
||||
|
||||
# add multisite settings to plugin
|
||||
if len(multisite_settings):
|
||||
plugin_multisite = copy.deepcopy(plugin)
|
||||
plugin_multisite["settings"] = multisite_settings
|
||||
plugins_multisite.append(plugin_multisite)
|
||||
|
||||
return plugins_multisite
|
||||
|
||||
|
||||
def get_forms(
|
||||
templates_ui: list = [],
|
||||
plugins: list = [],
|
||||
settings: dict = {},
|
||||
render_forms: tuple = ("advanced", "easy", "raw"),
|
||||
is_new: bool = False,
|
||||
only_multisite: bool = False,
|
||||
) -> dict:
|
||||
"""
|
||||
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) in case
|
||||
"""
|
||||
# Copy of the plugins, and get the plugins by context if needed
|
||||
# In services page, we want only multisite settings, but in global config we want both
|
||||
plugins_base = get_plugins_multisite(plugins) if only_multisite else plugins
|
||||
|
||||
# This template will be used to show default value or value if exists
|
||||
templates = [
|
||||
{
|
||||
"name": "default",
|
||||
"steps": [],
|
||||
"configs": {},
|
||||
"settings": {},
|
||||
}
|
||||
]
|
||||
|
||||
for key, value in templates_ui.items():
|
||||
value["label"] = value["name"]
|
||||
value["name"] = key
|
||||
templates.append(value)
|
||||
|
||||
# Update SERVER_NAME to be empty if new
|
||||
if is_new and "SERVER_NAME" in settings:
|
||||
settings["SERVER_NAME"]["value"] = ""
|
||||
|
||||
if is_new and not "SERVER_NAME" in settings:
|
||||
settings["SERVER_NAME"] = {"value": "", "method": "ui", "global": False}
|
||||
|
||||
forms = {}
|
||||
for form in render_forms:
|
||||
forms[form] = {}
|
||||
|
||||
for template in templates:
|
||||
if "advanced" in forms:
|
||||
forms["advanced"][template.get("name")] = set_advanced(template, plugins_base, settings, is_new)
|
||||
|
||||
if "raw" in forms:
|
||||
forms["raw"][template.get("name")] = set_raw(template, plugins_base, settings, is_new)
|
||||
|
||||
if "easy" in forms:
|
||||
forms["easy"][template.get("name")] = set_easy(template, plugins_base, settings, is_new)
|
||||
|
||||
return forms
|
||||
|
||||
|
||||
def set_easy(template: list, plugins_base: list, settings: dict, is_new: bool) -> dict:
|
||||
"""
|
||||
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)
|
||||
# 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, is_new)
|
||||
|
||||
set_multiples(template, plugins, settings)
|
||||
|
||||
steps = template.get("steps")
|
||||
for step in steps:
|
||||
step_settings = step.get("settings", {})
|
||||
|
||||
for plugin in plugins:
|
||||
step_settings_output = {}
|
||||
for setting, value in plugin.get("settings").items():
|
||||
if setting not in step_settings:
|
||||
continue
|
||||
|
||||
step_settings_output[setting] = value
|
||||
|
||||
# Case at least one key in step settings, we can add the plugin settings to the step
|
||||
if len(step_settings_output) and not "plugins" in step:
|
||||
step["plugins"] = []
|
||||
|
||||
if len(step_settings_output):
|
||||
step_plugin = copy.deepcopy(plugin)
|
||||
step_plugin["settings"] = step_settings_output
|
||||
step["plugins"].append(step_plugin)
|
||||
|
||||
# remove settings key form step
|
||||
step.pop("settings", None)
|
||||
return steps
|
||||
|
||||
|
||||
def set_raw(template: list, plugins_base: list, settings: dict, is_new: bool = False) -> dict:
|
||||
"""
|
||||
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():
|
||||
|
||||
is_multiple_setting = "multiple" in value
|
||||
|
||||
# By default, we will loop on one setting (not multiple)
|
||||
total_settings = {setting: value}
|
||||
|
||||
# Case multiple, retrieve all settings that start with setting name
|
||||
if is_multiple_setting:
|
||||
# get all settings that start with setting name
|
||||
total_settings = {k: v for k, v in settings.items() if k.startswith(f"{setting}")}
|
||||
|
||||
# Loop in a same way it is a multiple or regular setting
|
||||
for mult_setting, mult_value in total_settings.items():
|
||||
|
||||
# Get setting data
|
||||
# We need to send setting and not mult_setting because mult_setting is unknown on plugin side
|
||||
template_value, current_value, default_value, is_disabled_method, is_current_from_template, is_current_default, setting_value = (
|
||||
get_setting_data(template_settings, settings, mult_setting, mult_value)
|
||||
)
|
||||
|
||||
if current_value is not None:
|
||||
raw_settings[mult_setting] = current_value
|
||||
continue
|
||||
|
||||
if template_value is not None:
|
||||
raw_settings[mult_setting] = template_value
|
||||
continue
|
||||
|
||||
return raw_settings
|
||||
|
||||
|
||||
def set_advanced(template: list, plugins_base: list, settings: dict, is_new: bool) -> dict:
|
||||
"""
|
||||
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, is_new)
|
||||
|
||||
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 setting is matching a multiple setting
|
||||
if not format_setting in mult_settings:
|
||||
continue
|
||||
|
||||
# Case we have at least one multiple setting, we can check if multiple name exists or create it
|
||||
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
|
||||
multiple_template[mult_name][prefix][setting]["prev_value"] = value
|
||||
multiple_template[mult_name][prefix][setting]["method"] = "default"
|
||||
|
||||
# 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 setting is matching a multiple setting
|
||||
if not format_setting in mult_settings:
|
||||
continue
|
||||
|
||||
# Case we have at least one multiple setting, we can check if multiple name exists or create it
|
||||
if not mult_name in multiple_settings:
|
||||
multiple_settings[mult_name] = {}
|
||||
# Now check if prefix exist for this mult
|
||||
if not prefix in multiple_settings[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_settings[mult_name][prefix] = new_multiple_group
|
||||
|
||||
# Update multiple template with real data
|
||||
multiple_settings[mult_name][prefix][setting]["value"] = value.get("value", multiple_settings[mult_name][prefix][setting]["value"])
|
||||
multiple_settings[mult_name][prefix][setting]["prev_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
|
||||
|
||||
# Add popovers if setting is disabled else stop
|
||||
if not multiple_settings[mult_name][prefix][setting].get("disabled", False):
|
||||
continue
|
||||
|
||||
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, 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(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(
|
||||
name: str,
|
||||
value: Union[str, int],
|
||||
total_settings: Union[str, int],
|
||||
loop_id: Union[str, int],
|
||||
template_settings: dict,
|
||||
settings: dict,
|
||||
is_new: bool = False,
|
||||
) -> dict:
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
|
||||
is_multiple_setting = value.get("multiple", False)
|
||||
|
||||
template_value, current_value, default_value, is_disabled_method, is_current_from_template, is_current_default, setting_value = get_setting_data(
|
||||
template_settings, settings, name, value, is_multiple_setting, is_new
|
||||
) # regex by pattern
|
||||
|
||||
value["pattern"] = value.get("regex", "")
|
||||
|
||||
# set inpType based on type define for each settings
|
||||
inpType = (
|
||||
"checkbox"
|
||||
if value.get("type") == "check"
|
||||
else ("select" if value.get("type") == "select" else "datepicker" if value.get("type") == "date" else "input")
|
||||
)
|
||||
value["inpType"] = inpType
|
||||
|
||||
if inpType == "select":
|
||||
# replace "select" key by "values"
|
||||
value["values"] = value.pop("select")
|
||||
|
||||
value["columns"] = {"pc": 4, "tablet": 6, "mobile": 12}
|
||||
value["disabled"] = is_disabled_method
|
||||
value["value"] = default_value
|
||||
value["name"] = value.get("label")
|
||||
value["prev_value"] = value.get("value")
|
||||
|
||||
# Prepare popover checking "help", "context"
|
||||
popovers = []
|
||||
|
||||
if is_disabled_method:
|
||||
popovers.append(
|
||||
{
|
||||
"iconName": "trespass",
|
||||
"text": "inp_popover_method_disabled",
|
||||
}
|
||||
)
|
||||
|
||||
if value.get("context"):
|
||||
popovers.append(
|
||||
{
|
||||
"iconName": ("disk" if value.get("context") == "multisite" else "globe"),
|
||||
"text": ("inp_popover_multisite" if value.get("context") == "multisite" else "inp_popover_global"),
|
||||
}
|
||||
)
|
||||
|
||||
if value.get("help"):
|
||||
popovers.append(
|
||||
{
|
||||
"iconName": "info",
|
||||
"text": value.get("help"),
|
||||
}
|
||||
)
|
||||
|
||||
value["popovers"] = popovers
|
||||
|
||||
# Case multiple, stop here
|
||||
if "multiple" in value:
|
||||
return value
|
||||
|
||||
# Else, we can add additional final data
|
||||
value["method"] = settings.get(name, {}).get("method", "ui")
|
||||
value["containerClass"] = f"z-{total_settings - loop_id}"
|
||||
|
||||
if current_value is not None and not is_current_default:
|
||||
value["value"] = current_value
|
||||
elif template_value is not None:
|
||||
value["value"] = template_value
|
||||
else:
|
||||
value["value"] = setting_value
|
||||
|
||||
return value
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
from typing import Union
|
||||
|
||||
|
||||
def title_widget(title: str) -> dict:
|
||||
return {
|
||||
"type": "Title",
|
||||
"data": {"title": title},
|
||||
}
|
||||
|
||||
|
||||
def table_widget(positions: list[int], header: list[str], items: list[dict], filters: list[dict], minWidth: str, title: str) -> dict:
|
||||
return {
|
||||
"type": "Table",
|
||||
"data": {
|
||||
"title": title,
|
||||
"minWidth": minWidth,
|
||||
"header": header,
|
||||
"positions": positions,
|
||||
"items": items,
|
||||
"filters": filters,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def stat_widget(
|
||||
link: str, containerColums: dict, title: Union[str, int], subtitle: Union[str, int], subtitle_color: str, stat: Union[str, int], icon_name: str
|
||||
) -> dict:
|
||||
"""Return a valid format to render a Stat widget"""
|
||||
return {
|
||||
"type": "card",
|
||||
"link": link,
|
||||
"containerColumns": containerColums,
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": title,
|
||||
"subtitle": subtitle,
|
||||
"subtitleColor": subtitle_color,
|
||||
"stat": stat,
|
||||
"iconName": icon_name,
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def instance_widget(containerColumns: dict, pairs: list[dict], status: str, title: Union[str, int], buttons: list[dict]) -> dict:
|
||||
"""Return a valid format to render an Instance widget"""
|
||||
return {
|
||||
"type": "card",
|
||||
"containerColumns": containerColumns,
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Instance",
|
||||
"data": {
|
||||
"pairs": pairs,
|
||||
"status": status,
|
||||
"title": title,
|
||||
"buttons": buttons,
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -1,107 +0,0 @@
|
|||
[
|
||||
{
|
||||
"type": "card",
|
||||
"link": "https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui#pro",
|
||||
"containerColumns": {
|
||||
"pc": 4,
|
||||
"tablet": 6,
|
||||
"mobile": 12
|
||||
},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_version",
|
||||
"subtitle": "home_upgrade_to_pro",
|
||||
"subtitleColor": "warning",
|
||||
"stat": "home_free",
|
||||
"iconName": "key"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"link": "https://github.com/bunkerity/bunkerweb",
|
||||
"containerColumns": {
|
||||
"pc": 4,
|
||||
"tablet": 6,
|
||||
"mobile": 12
|
||||
},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_version_number",
|
||||
"subtitle": "home_update_available",
|
||||
"subtitleColor": "warning",
|
||||
"stat": "1.5.8",
|
||||
"iconName": "wire"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"link": "/instances",
|
||||
"containerColumns": {
|
||||
"pc": 4,
|
||||
"tablet": 6,
|
||||
"mobile": 12
|
||||
},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_instances",
|
||||
"subtitle": "home_total_number",
|
||||
"subtitleColor": "info",
|
||||
"stat": 1,
|
||||
"iconName": "box"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"link": "/services",
|
||||
"containerColumns": {
|
||||
"pc": 4,
|
||||
"tablet": 6,
|
||||
"mobile": 12
|
||||
},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_services",
|
||||
"subtitle": "home_all_methods_included",
|
||||
"subtitleColor": "info",
|
||||
"stat": 2,
|
||||
"iconName": "disk"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"link": "/plugins",
|
||||
"containerColumns": {
|
||||
"pc": 4,
|
||||
"tablet": 6,
|
||||
"mobile": 12
|
||||
},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_plugins",
|
||||
"subtitle": "home_no_error",
|
||||
"subtitleColor": "success",
|
||||
"stat": "42",
|
||||
"iconName": "puzzle"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
import json
|
||||
import base64
|
||||
|
||||
home = [
|
||||
{
|
||||
"type": "card",
|
||||
"link": "https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui#pro",
|
||||
"containerColumns": {"pc": 4, "tablet": 6, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_version",
|
||||
"subtitle": "home_upgrade_to_pro",
|
||||
"subtitleColor": "warning",
|
||||
"stat": "home_free",
|
||||
"iconName": "key",
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"link": "https://github.com/bunkerity/bunkerweb",
|
||||
"containerColumns": {"pc": 4, "tablet": 6, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_version_number",
|
||||
"subtitle": "home_update_available",
|
||||
"subtitleColor": "warning",
|
||||
"stat": "1.5.8",
|
||||
"iconName": "wire",
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"link": "/instances",
|
||||
"containerColumns": {"pc": 4, "tablet": 6, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_instances",
|
||||
"subtitle": "home_total_number",
|
||||
"subtitleColor": "info",
|
||||
"stat": 1,
|
||||
"iconName": "box",
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"link": "/services",
|
||||
"containerColumns": {"pc": 4, "tablet": 6, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_services",
|
||||
"subtitle": "home_all_methods_included",
|
||||
"subtitleColor": "info",
|
||||
"stat": 2,
|
||||
"iconName": "disk",
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"link": "/plugins",
|
||||
"containerColumns": {"pc": 4, "tablet": 6, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Stat",
|
||||
"data": {
|
||||
"title": "home_plugins",
|
||||
"subtitle": "home_no_error",
|
||||
"subtitleColor": "success",
|
||||
"stat": "42",
|
||||
"iconName": "puzzle",
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
# store on a file
|
||||
with open("home.json", "w") as f:
|
||||
json.dump(home, f, indent=4)
|
||||
output_base64_bytes = base64.b64encode(bytes(json.dumps(home), "utf-8"))
|
||||
output_base64_string = output_base64_bytes.decode("ascii")
|
||||
|
||||
with open("home.txt", "w") as f:
|
||||
f.write(output_base64_string)
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import json
|
||||
import base64
|
||||
|
||||
from builder.instances import instances_builder
|
||||
|
||||
|
||||
# Create instance class using keys from the instances list
|
||||
class Instance:
|
||||
def __init__(self, _type, health, _id, hostname, name):
|
||||
self._type = _type
|
||||
self.health = health
|
||||
self._id = _id
|
||||
self.hostname = hostname
|
||||
self.name = name
|
||||
|
||||
|
||||
instances = [
|
||||
Instance("manual", True, "bunkerweb", "bunkerweb", "bunkerweb"),
|
||||
Instance("manual", True, "bunkerweb", "bunkerweb", "bunkerweb"),
|
||||
]
|
||||
|
||||
|
||||
builder = instances_builder(instances)
|
||||
|
||||
# store on a file
|
||||
with open("instances.json", "w") as f:
|
||||
json.dump(builder, f)
|
||||
|
||||
output_base64_bytes = base64.b64encode(bytes(json.dumps(builder), "utf-8"))
|
||||
output_base64_string = output_base64_bytes.decode("ascii")
|
||||
|
||||
with open("instances.txt", "w") as f:
|
||||
f.write(output_base64_string)
|
||||
|
|
@ -1,226 +0,0 @@
|
|||
import json
|
||||
import base64
|
||||
|
||||
from builder.jobs import jobs_builder
|
||||
|
||||
|
||||
jobs = {
|
||||
"anonymous-report": {
|
||||
"plugin_id": "misc",
|
||||
"every": "day",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:03 PM", "end_date": "07/08/2024, 01:10:04 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"backup-data": {
|
||||
"plugin_id": "backup",
|
||||
"every": "day",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"blacklist-download": {
|
||||
"plugin_id": "blacklist",
|
||||
"every": "hour",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:01 PM", "end_date": "07/08/2024, 01:10:02 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"bunkernet-data": {
|
||||
"plugin_id": "bunkernet",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"bunkernet-register": {
|
||||
"plugin_id": "bunkernet",
|
||||
"every": "hour",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:02 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"certbot-new": {
|
||||
"plugin_id": "letsencrypt",
|
||||
"every": "once",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"certbot-renew": {
|
||||
"plugin_id": "letsencrypt",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:03 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"cleanup-excess-jobs-runs": {
|
||||
"plugin_id": "db",
|
||||
"every": "day",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"coreruleset-nightly": {
|
||||
"plugin_id": "modsecurity",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:01 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"custom-cert": {
|
||||
"plugin_id": "customcert",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"default-server-cert": {
|
||||
"plugin_id": "misc",
|
||||
"every": "once",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [
|
||||
{
|
||||
"service_id": None,
|
||||
"file_name": "default-server-cert.pem",
|
||||
"last_update": "07/08/2024, 01:10:03 PM",
|
||||
"checksum": "203da9e16dabe522a3080c3b9efc5c2dc8054f47e98d995fe1812f4c498b4feb519ef080b7dfeaba0095c1393793815c23f22072daf5703b02762504b211db20",
|
||||
},
|
||||
{
|
||||
"service_id": None,
|
||||
"file_name": "default-server-cert.key",
|
||||
"last_update": "07/08/2024, 01:10:03 PM",
|
||||
"checksum": "7f86b1fffb8fe2011365d76e5a0955344a03c3bdb7b04aff13f8ad5b6178804290c0cd6c8f29dda9e981e3193cf5acda2a92f72312d514514305b8485667d573",
|
||||
},
|
||||
],
|
||||
},
|
||||
"download-crs-plugins": {
|
||||
"plugin_id": "modsecurity",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:03 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"download-plugins": {
|
||||
"plugin_id": "misc",
|
||||
"every": "once",
|
||||
"reload": False,
|
||||
"history": [
|
||||
{"start_date": "07/08/2024, 01:10:04 PM", "end_date": "07/08/2024, 01:10:05 PM", "success": True},
|
||||
{"start_date": "07/08/2024, 01:09:59 PM", "end_date": "07/08/2024, 01:10:00 PM", "success": True},
|
||||
],
|
||||
"cache": [],
|
||||
},
|
||||
"download-pro-plugins": {
|
||||
"plugin_id": "pro",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [
|
||||
{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:04 PM", "success": True},
|
||||
{"start_date": "07/08/2024, 01:10:00 PM", "end_date": "07/08/2024, 01:10:01 PM", "success": False},
|
||||
],
|
||||
"cache": [],
|
||||
},
|
||||
"failover-backup": {
|
||||
"plugin_id": "jobs",
|
||||
"every": "once",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:07 PM", "end_date": "07/08/2024, 01:10:08 PM", "success": True}],
|
||||
"cache": [
|
||||
{
|
||||
"service_id": None,
|
||||
"file_name": "folder:/var/tmp/bunkerweb/failover.tgz",
|
||||
"last_update": "07/08/2024, 01:10:14 PM",
|
||||
"checksum": "d22a7a696d4b44bcef6a3ac06b2d7e2b2de128243000f58202c0e82b0bf54510ade7329eca14ca478a28d46201410ea1fd8002349b7b9aa51dd0d07d2fb2f51e",
|
||||
}
|
||||
],
|
||||
},
|
||||
"greylist-download": {
|
||||
"plugin_id": "greylist",
|
||||
"every": "hour",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"mmdb-asn": {
|
||||
"plugin_id": "jobs",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:04 PM", "end_date": "07/08/2024, 01:10:06 PM", "success": True}],
|
||||
"cache": [
|
||||
{
|
||||
"service_id": None,
|
||||
"file_name": "asn.mmdb",
|
||||
"last_update": "07/08/2024, 01:10:05 PM",
|
||||
"checksum": "0beed65a84e63cf5dd6753ecc1aa6399dddaf5eb24fb22839f4cd72cbc9805cddf72be068649d111a3c21e2ac7de4a6f930c859286a25a7e937da017406d2596",
|
||||
}
|
||||
],
|
||||
},
|
||||
"mmdb-country": {
|
||||
"plugin_id": "jobs",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:04 PM", "success": True}],
|
||||
"cache": [
|
||||
{
|
||||
"service_id": None,
|
||||
"file_name": "country.mmdb",
|
||||
"last_update": "07/08/2024, 01:10:03 PM",
|
||||
"checksum": "5f0d2e2c92840747886924adc1e6ff3668882990e0cd8a4d60750fe1bddb66c3e175c8717d073b48ebda41cce4c505d434dc2a6a469823fcd41c62c4f875b212",
|
||||
}
|
||||
],
|
||||
},
|
||||
"realip-download": {
|
||||
"plugin_id": "realip",
|
||||
"every": "hour",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"self-signed": {
|
||||
"plugin_id": "selfsigned",
|
||||
"every": "day",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:03 PM", "success": True}],
|
||||
"cache": [
|
||||
{
|
||||
"service_id": "www.example.com",
|
||||
"file_name": "cert.pem",
|
||||
"last_update": "07/08/2024, 01:10:03 PM",
|
||||
"checksum": "fc33700719f6a58336e3c3b735ad3fdf0b15ebd0afbe6b4a3b02a4a92e0ab4f1761409a7a1d1ca965d59b4196a81c1d150a12ae0170f7bb3a1bc7cf02300fbe9",
|
||||
},
|
||||
{
|
||||
"service_id": "www.example.com",
|
||||
"file_name": "key.pem",
|
||||
"last_update": "07/08/2024, 01:10:03 PM",
|
||||
"checksum": "0e6eee34ab7b2a41cb21e49ebd35ce29a1b8d12b55aad3911b6357c73792eef7084fbb4eeba8bff73eb7a8789b5f486f6edb6d4b1c38a54bd0dcee1bf438f23d",
|
||||
},
|
||||
],
|
||||
},
|
||||
"update-check": {
|
||||
"plugin_id": "jobs",
|
||||
"every": "day",
|
||||
"reload": False,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:06 PM", "end_date": "07/08/2024, 01:10:07 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
"whitelist-download": {
|
||||
"plugin_id": "whitelist",
|
||||
"every": "hour",
|
||||
"reload": True,
|
||||
"history": [{"start_date": "07/08/2024, 01:10:02 PM", "end_date": "07/08/2024, 01:10:02 PM", "success": True}],
|
||||
"cache": [],
|
||||
},
|
||||
}
|
||||
|
||||
output = jobs_builder(jobs)
|
||||
|
||||
# store on a file
|
||||
with open("jobs.json", "w") as f:
|
||||
json.dump(output, f, indent=4)
|
||||
output_base64_bytes = base64.b64encode(bytes(json.dumps(output), "utf-8"))
|
||||
output_base64_string = output_base64_bytes.decode("ascii")
|
||||
|
||||
with open("jobs.txt", "w") as f:
|
||||
f.write(output_base64_string)
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
import json
|
||||
import base64
|
||||
|
||||
from builder.logs import logs_builder
|
||||
|
||||
files = ["file1", "file2"]
|
||||
current_file = ""
|
||||
raw_data = "gefesfesfsefes"
|
||||
output = logs_builder(files, current_file, raw_data)
|
||||
|
||||
with open("logs.json", "w") as f:
|
||||
json.dump(output, f, indent=4)
|
||||
|
||||
output_base64_bytes = base64.b64encode(bytes(json.dumps(output), "utf-8"))
|
||||
output_base64_string = output_base64_bytes.decode("ascii")
|
||||
with open("logs.txt", "w") as f:
|
||||
f.write(output_base64_string)
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
import json
|
||||
import base64
|
||||
from typing import Union
|
||||
|
||||
from builder.services import services_builder
|
||||
|
||||
services = [
|
||||
{
|
||||
"USE_REVERSE_PROXY": {"value": "yes", "method": "scheduler", "global": False},
|
||||
"IS_DRAFT": {"value": "no", "method": "default", "global": False},
|
||||
"SERVE_FILES": {"value": "no", "method": "scheduler", "global": True},
|
||||
"REMOTE_PHP": {"value": "", "method": "default", "global": True},
|
||||
"AUTO_LETS_ENCRYPT": {"value": "no", "method": "default", "global": True},
|
||||
"USE_CUSTOM_SSL": {"value": "no", "method": "default", "global": True},
|
||||
"USE_MODSECURITY": {"value": "yes", "method": "default", "global": True},
|
||||
"USE_BAD_BEHAVIOR": {"value": "yes", "method": "default", "global": True},
|
||||
"USE_LIMIT_REQ": {"value": "yes", "method": "default", "global": True},
|
||||
"USE_DNSBL": {"value": "yes", "method": "default", "global": True},
|
||||
"SERVER_NAME": {"value": "app1.example.com", "method": "scheduler", "global": False},
|
||||
},
|
||||
{
|
||||
"USE_REVERSE_PROXY": {"value": "yes", "method": "scheduler", "global": False},
|
||||
"IS_DRAFT": {"value": "yes", "method": "default", "global": False},
|
||||
"SERVE_FILES": {"value": "no", "method": "scheduler", "global": True},
|
||||
"REMOTE_PHP": {"value": "", "method": "default", "global": True},
|
||||
"AUTO_LETS_ENCRYPT": {"value": "no", "method": "default", "global": True},
|
||||
"USE_CUSTOM_SSL": {"value": "no", "method": "default", "global": True},
|
||||
"USE_MODSECURITY": {"value": "yes", "method": "default", "global": True},
|
||||
"USE_BAD_BEHAVIOR": {"value": "yes", "method": "default", "global": True},
|
||||
"USE_LIMIT_REQ": {"value": "yes", "method": "default", "global": True},
|
||||
"USE_DNSBL": {"value": "yes", "method": "default", "global": True},
|
||||
"SERVER_NAME": {"value": "www.example.com", "method": "ui", "global": False},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
output = services_builder(services)
|
||||
|
||||
# store on a file
|
||||
with open("services.json", "w") as f:
|
||||
json.dump(output, f, indent=4)
|
||||
output_base64_bytes = base64.b64encode(bytes(json.dumps(output), "utf-8"))
|
||||
output_base64_string = output_base64_bytes.decode("ascii")
|
||||
|
||||
with open("services.txt", "w") as f:
|
||||
f.write(output_base64_string)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from os import cpu_count
|
||||
from os import cpu_count, getpid
|
||||
from os.path import abspath
|
||||
from pathlib import Path
|
||||
from threading import Semaphore, Thread
|
||||
|
|
@ -73,15 +73,23 @@ def js2md():
|
|||
|
||||
def convert_json_to_md(file: Path):
|
||||
semaphore.acquire()
|
||||
# Run the command
|
||||
output = run_command(["documentation", "build", file.as_posix(), "-f", "md"], with_output=True)
|
||||
if output == 1:
|
||||
print("Error while running command", flush=True)
|
||||
exit(1)
|
||||
print(f"Acquiring Semaphore for: {getpid()} (file {file})", flush=True)
|
||||
try:
|
||||
# Run the command
|
||||
output = run_command(["documentation", "build", file.as_posix(), "-f", "md"], with_output=True)
|
||||
if output == 1:
|
||||
print("Error while running command", flush=True)
|
||||
exit(1)
|
||||
|
||||
# Create a new file with the same name but with .md extension
|
||||
file.with_suffix(".md").write_text(output)
|
||||
semaphore.release()
|
||||
# Create a new file with the same name but with .md extension
|
||||
file.with_suffix(".md").write_text(output)
|
||||
except BaseException:
|
||||
print(format_exc(), flush=True)
|
||||
print("Error while running documentation", str(file.name), flush=True)
|
||||
exit(1)
|
||||
finally:
|
||||
print(f"Releasing Semaphore for: {getpid()} (file {file})", flush=True)
|
||||
semaphore.release()
|
||||
|
||||
threads = []
|
||||
# Create a markdown file for each JS file
|
||||
|
|
|
|||
Loading…
Reference in a new issue