mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Merge pull request #687 from bunkerity/dev
Merge branch "dev" into branch "staging"
This commit is contained in:
commit
565f4e3f7c
16 changed files with 69 additions and 54 deletions
|
|
@ -9,6 +9,8 @@
|
|||
- [BUGFIX] Fix UI using the wrong database when generating the new config when using an external database
|
||||
- [BUGFIX] Small fixes on linux paths creating unnecessary folders
|
||||
- [BUGFIX] Fix ACME renewal fails on redirection enabled Service
|
||||
- [BUGFIX] Fix errors when using a server name with multiple values in web UI
|
||||
- [BUGFIX] Fix error when deleting a service that have custom configs on web UI
|
||||
- [MISC] Updated core dependencies
|
||||
- [MISC] Updated self-signed job to regenerate the cert if the subject or the expiration date has changed
|
||||
- [MISC] Jobs that download files from urls will now remove old cached files if urls are empty
|
||||
|
|
|
|||
|
|
@ -178,10 +178,10 @@ api.global.GET["^/bans$"] = function(self)
|
|||
local data = {}
|
||||
for i, k in ipairs(self.datastore:keys()) do
|
||||
if k:find("^bans_ip_") then
|
||||
local ret, reason = self.datastore:get(k)
|
||||
if not ret then
|
||||
local reason, err = self.datastore:get(k)
|
||||
if err then
|
||||
return self:response(ngx.HTTP_INTERNAL_SERVER_ERROR, "error",
|
||||
"can't access " .. k .. " from datastore : " + reason)
|
||||
"can't access " .. k .. " from datastore : " .. reason)
|
||||
end
|
||||
local ok, ttl = self.datastore:ttl(k)
|
||||
if not ok then
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -113,6 +113,11 @@ if __name__ == "__main__":
|
|||
type=str,
|
||||
help="The method that is used to save the config",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-check-changes",
|
||||
action="store_true",
|
||||
help="Set the changes to checked in the database",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
settings_path = Path(normpath(args.settings))
|
||||
|
|
@ -361,10 +366,11 @@ if __name__ == "__main__":
|
|||
changes.append("instances")
|
||||
logger.info("Instance 127.0.0.1 successfully saved to database")
|
||||
|
||||
# update changes in db
|
||||
ret = db.checked_changes(changes, value=True)
|
||||
if ret:
|
||||
logger.error(f"An error occurred when setting the changes to checked in the database : {ret}")
|
||||
if not args.no_check_changes:
|
||||
# update changes in db
|
||||
ret = db.checked_changes(changes, value=True)
|
||||
if ret:
|
||||
logger.error(f"An error occurred when setting the changes to checked in the database : {ret}")
|
||||
except SystemExit as e:
|
||||
sys_exit(e.code)
|
||||
except:
|
||||
|
|
|
|||
|
|
@ -15,3 +15,4 @@ worker_class = "gthread"
|
|||
threads = 1
|
||||
workers = 1
|
||||
graceful_timeout = 0
|
||||
secure_scheme_headers = {}
|
||||
|
|
|
|||
|
|
@ -232,43 +232,42 @@ def manage_bunkerweb(method: str, *args, operation: str = "reloads"):
|
|||
# Do the operation
|
||||
error = False
|
||||
if method == "services":
|
||||
editing = operation == "edit"
|
||||
service_custom_confs = glob(join(sep, "etc", "bunkerweb", "configs", "*", args[1]))
|
||||
service_custom_confs = glob(join(sep, "etc", "bunkerweb", "configs", "*", args[1].split(" ")[0]))
|
||||
moved = False
|
||||
deleted = False
|
||||
|
||||
if operation == "new":
|
||||
operation, error = app.config["CONFIG"].new_service(args[0])
|
||||
elif operation == "edit":
|
||||
if args[1] != args[2] and service_custom_confs:
|
||||
if args[1].split(" ")[0] != args[2].split(" ")[0] and service_custom_confs:
|
||||
for service_custom_conf in service_custom_confs:
|
||||
if listdir(service_custom_conf):
|
||||
move(
|
||||
service_custom_conf,
|
||||
service_custom_conf.replace(f"{sep}{args[1]}", f"{sep}{args[2]}").replace(join(sep, "etc"), join(sep, "var", "tmp")),
|
||||
)
|
||||
move(service_custom_conf, service_custom_conf.replace(f"{sep}{args[1].split(' ')[0]}", f"{sep}{args[2].split(' ')[0]}"))
|
||||
moved = True
|
||||
operation, error = app.config["CONFIG"].edit_service(args[1], args[0])
|
||||
operation, error = app.config["CONFIG"].edit_service(args[1], args[0], check_changes=not moved)
|
||||
elif operation == "delete":
|
||||
operation, error = app.config["CONFIG"].delete_service(args[2])
|
||||
for service_custom_conf in glob(join(sep, "etc", "bunkerweb", "configs", "*", args[2].split(" ")[0])):
|
||||
if listdir(service_custom_conf):
|
||||
rmtree(service_custom_conf, ignore_errors=True)
|
||||
deleted = True
|
||||
operation, error = app.config["CONFIG"].delete_service(args[2], check_changes=not deleted)
|
||||
|
||||
if error:
|
||||
app.config["TO_FLASH"].append({"content": operation, "type": "error"})
|
||||
else:
|
||||
app.config["TO_FLASH"].append({"content": operation, "type": "success"})
|
||||
|
||||
if editing and moved and args[1] != args[2] and service_custom_confs:
|
||||
for tmp_service_custom_conf in glob(join(sep, "var", "tmp", "bunkerweb", "configs", "*", args[2])):
|
||||
move(
|
||||
tmp_service_custom_conf,
|
||||
tmp_service_custom_conf.replace(
|
||||
join(sep, "var", "tmp"),
|
||||
join(sep, "etc"),
|
||||
),
|
||||
)
|
||||
error = app.config["CONFIGFILES"].save_configs()
|
||||
if moved or deleted:
|
||||
changes = ["config", "custom_configs"]
|
||||
error = app.config["CONFIGFILES"].save_configs(check_changes=False)
|
||||
if error:
|
||||
app.config["TO_FLASH"].append({"content": error, "type": "error"})
|
||||
rmtree(join(sep, "var", "tmp", "bunkerweb", "configs"), ignore_errors=True)
|
||||
changes.pop()
|
||||
|
||||
# update changes in db
|
||||
ret = db.checked_changes(changes, value=True)
|
||||
if ret:
|
||||
app.config["TO_FLASH"].append({"content": f"An error occurred when setting the changes to checked in the database : {ret}", "type": "error"})
|
||||
if method == "global_config":
|
||||
operation = app.config["CONFIG"].edit_global_conf(args[0])
|
||||
elif method == "plugins":
|
||||
|
|
@ -526,12 +525,7 @@ def services():
|
|||
Thread(
|
||||
target=manage_bunkerweb,
|
||||
name="Reloading instances",
|
||||
args=(
|
||||
"services",
|
||||
variables,
|
||||
request.form.get("OLD_SERVER_NAME", "").split(" ")[0],
|
||||
variables.get("SERVER_NAME", "").split(" ")[0],
|
||||
),
|
||||
args=("services", variables, request.form.get("OLD_SERVER_NAME", ""), variables.get("SERVER_NAME", "")),
|
||||
kwargs={"operation": request.form["operation"]},
|
||||
).start()
|
||||
|
||||
|
|
@ -554,6 +548,7 @@ def services():
|
|||
{
|
||||
"SERVER_NAME": {
|
||||
"value": service["SERVER_NAME"]["value"].split(" ")[0],
|
||||
"full_value": service["SERVER_NAME"]["value"],
|
||||
"method": service["SERVER_NAME"]["method"],
|
||||
},
|
||||
"USE_REVERSE_PROXY": service["USE_REVERSE_PROXY"],
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class Config:
|
|||
self.__settings = json_loads(Path(sep, "usr", "share", "bunkerweb", "settings.json").read_text(encoding="utf-8"))
|
||||
self.__db = db
|
||||
|
||||
def __gen_conf(self, global_conf: dict, services_conf: list[dict]) -> None:
|
||||
def __gen_conf(self, global_conf: dict, services_conf: list[dict], *, check_changes: bool = True) -> None:
|
||||
"""Generates the nginx configuration file from the given configuration
|
||||
|
||||
Parameters
|
||||
|
|
@ -62,7 +62,8 @@ class Config:
|
|||
str(env_file),
|
||||
"--method",
|
||||
"ui",
|
||||
],
|
||||
]
|
||||
+ (["--no-check-changes"] if not check_changes else []),
|
||||
stdin=DEVNULL,
|
||||
stderr=STDOUT,
|
||||
check=False,
|
||||
|
|
@ -196,7 +197,7 @@ class Config:
|
|||
0,
|
||||
)
|
||||
|
||||
def edit_service(self, old_server_name: str, variables: dict) -> Tuple[str, int]:
|
||||
def edit_service(self, old_server_name: str, variables: dict, *, check_changes: bool = True) -> Tuple[str, int]:
|
||||
"""Edits a service
|
||||
|
||||
Parameters
|
||||
|
|
@ -231,12 +232,12 @@ class Config:
|
|||
|
||||
if changed_server_name:
|
||||
for k in deepcopy(config):
|
||||
if k.startswith(old_server_name):
|
||||
if k.startswith(old_server_name_splitted[0]):
|
||||
config.pop(k)
|
||||
|
||||
self.__gen_conf(config, services)
|
||||
self.__gen_conf(config, services, check_changes=check_changes)
|
||||
return (
|
||||
f"Configuration for {old_server_name.split(' ')[0]} has been edited.",
|
||||
f"Configuration for {old_server_name_splitted[0]} has been edited.",
|
||||
0,
|
||||
)
|
||||
|
||||
|
|
@ -256,7 +257,7 @@ class Config:
|
|||
self.__gen_conf(self.get_config(methods=False) | variables, self.get_services(methods=False))
|
||||
return "The global configuration has been edited."
|
||||
|
||||
def delete_service(self, service_name: str) -> Tuple[str, int]:
|
||||
def delete_service(self, service_name: str, *, check_changes: bool = True) -> Tuple[str, int]:
|
||||
"""Deletes a service
|
||||
|
||||
Parameters
|
||||
|
|
@ -301,5 +302,5 @@ class Config:
|
|||
if k in service:
|
||||
service.pop(k)
|
||||
|
||||
self.__gen_conf(new_env, new_services)
|
||||
self.__gen_conf(new_env, new_services, check_changes=check_changes)
|
||||
return f"Configuration for {service_name} has been deleted.", 0
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class ConfigFiles:
|
|||
generate_custom_configs(custom_configs)
|
||||
self.__logger.info("Custom configs refreshed successfully")
|
||||
|
||||
def save_configs(self) -> str:
|
||||
def save_configs(self, *, check_changes: bool = True) -> str:
|
||||
custom_configs = []
|
||||
configs_path = join(sep, "etc", "bunkerweb", "configs")
|
||||
root_dirs = listdir(configs_path)
|
||||
|
|
@ -70,7 +70,7 @@ class ConfigFiles:
|
|||
}
|
||||
)
|
||||
|
||||
err = self.__db.save_custom_configs(custom_configs, "ui")
|
||||
err = self.__db.save_custom_configs(custom_configs, "ui", changed=check_changes)
|
||||
if err:
|
||||
self.__logger.error(f"Could not save custom configs: {err}")
|
||||
return "Couldn't save custom configs to database"
|
||||
|
|
|
|||
|
|
@ -64,7 +64,11 @@ class ServiceModal {
|
|||
) {
|
||||
//set form info and right form
|
||||
const [action, serviceName] = this.getActionAndServName(e.target);
|
||||
this.setForm(action, serviceName, this.formNewEdit);
|
||||
const oldServName = e.target
|
||||
.closest("[data-services-service]")
|
||||
.querySelector("[data-old-service-name]")
|
||||
.getAttribute("data-value");
|
||||
this.setForm(action, serviceName, oldServName, this.formNewEdit);
|
||||
//get service data and parse it
|
||||
//multiple type logic is launch at same time on relate class
|
||||
const servicesSettings = e.target
|
||||
|
|
@ -87,7 +91,7 @@ class ServiceModal {
|
|||
) {
|
||||
//set form info and right form
|
||||
const [action, serviceName] = this.getActionAndServName(e.target);
|
||||
this.setForm(action, serviceName, this.formNewEdit);
|
||||
this.setForm(action, serviceName, serviceName, this.formNewEdit);
|
||||
//set default value with method default
|
||||
this.setSettingsDefault();
|
||||
//server name is unset
|
||||
|
|
@ -110,7 +114,7 @@ class ServiceModal {
|
|||
) {
|
||||
//set form info and right form
|
||||
const [action, serviceName] = this.getActionAndServName(e.target);
|
||||
this.setForm(action, serviceName, this.formDelete);
|
||||
this.setForm(action, serviceName, serviceName, this.formDelete);
|
||||
//show modal
|
||||
this.openModal();
|
||||
}
|
||||
|
|
@ -202,7 +206,7 @@ class ServiceModal {
|
|||
}
|
||||
}
|
||||
|
||||
setForm(action, serviceName, formEl) {
|
||||
setForm(action, serviceName, oldServName, formEl) {
|
||||
this.modalTitle.textContent = `${action} ${serviceName}`;
|
||||
formEl.setAttribute("id", `form-${action}-${serviceName}`);
|
||||
const opeInp = formEl.querySelector(`input[name="operation"]`);
|
||||
|
|
@ -212,8 +216,8 @@ class ServiceModal {
|
|||
if (action === "edit" || action === "new") {
|
||||
this.showNewEditForm();
|
||||
const oldNameInp = formEl.querySelector(`input[name="OLD_SERVER_NAME"]`);
|
||||
oldNameInp.setAttribute("value", serviceName);
|
||||
oldNameInp.value = serviceName;
|
||||
oldNameInp.setAttribute("value", oldServName);
|
||||
oldNameInp.value = oldServName;
|
||||
}
|
||||
|
||||
if (action === "delete") {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
<script type="module" src="./js/global.js"></script>
|
||||
|
||||
<script async src="./js/utils/purify/purify.min.js"></script>
|
||||
<script async src="./js/editor/ace.js"></script>
|
||||
<script src="./js/editor/ace.js"></script>
|
||||
|
||||
{% if current_endpoint == "global_config" %}
|
||||
<script type="module" src="./js/global_config.js"></script>
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
class="dark:brightness-110 overflow-hidden hover:scale-102 transition col-span-12 lg:col-span-6 3xl:col-span-4 p-4 w-full shadow-md break-words bg-white dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border"
|
||||
>
|
||||
<div data-services-settings class="hidden" data-value="{{service['settings']}}"></div>
|
||||
<div data-old-service-name class="hidden" data-value="{{service['SERVER_NAME']['full_value']}}"></div>
|
||||
<h5 class="transition duration-300 ease-in-out text-center sm:text-left mb-1 font-bold dark:text-white/90">
|
||||
{{ service["SERVER_NAME"]['value'] }}
|
||||
</h5>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ class AutoconfTest(Test):
|
|||
}
|
||||
self._check_domains()
|
||||
|
||||
@staticmethod
|
||||
def init():
|
||||
try:
|
||||
if not Test.init():
|
||||
|
|
@ -100,6 +101,7 @@ class AutoconfTest(Test):
|
|||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def end():
|
||||
ret = True
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ class DockerTest(Test):
|
|||
}
|
||||
self._check_domains()
|
||||
|
||||
@staticmethod
|
||||
def init():
|
||||
try:
|
||||
if not Test.init():
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ class KubernetesTest(Test):
|
|||
r"app3\.example\.com": f"{Test.random_string(6)}.{getenv('TEST_DOMAIN3')}",
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def init():
|
||||
try:
|
||||
if not Test.init():
|
||||
|
|
@ -143,6 +144,7 @@ class KubernetesTest(Test):
|
|||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def end():
|
||||
ret = True
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ class Test(ABC):
|
|||
f"instiantiated with {len(tests)} tests and timeout of {timeout}s for {self._name}",
|
||||
)
|
||||
|
||||
# Class method
|
||||
# called once before running all the different tests for a given integration
|
||||
def init(self):
|
||||
@staticmethod
|
||||
def init():
|
||||
try:
|
||||
if not isdir("/tmp/bw-data"):
|
||||
mkdir("/tmp/bw-data")
|
||||
|
|
@ -46,8 +46,8 @@ class Test(ABC):
|
|||
return True
|
||||
|
||||
# Class method
|
||||
# called once all tests ended
|
||||
def end(self):
|
||||
@staticmethod
|
||||
def end():
|
||||
return True
|
||||
|
||||
# helper to check domains
|
||||
|
|
|
|||
Loading…
Reference in a new issue