mirror of https://github.com/Aidaho12/haproxy-wi
v8.2.1: Refactor JS and Python models, remove unused functions, and improve form validation
Updated JavaScript to refine option selection logic and remove redundant functions (`showCompare`, `showCompareConfigs`). Enhanced Python models with validators to enforce non-empty inputs for critical fields (`port`, `maxconn`, etc.). Optimized configuration diff logic for better performance and readability. Added file lock checks before database migrations.master
parent
44ddae6dd1
commit
f749f7366e
|
@ -5,6 +5,7 @@ from flask_apscheduler import APScheduler
|
||||||
|
|
||||||
from app.modules.common.common import set_correct_owner
|
from app.modules.common.common import set_correct_owner
|
||||||
from app.modules.roxywi import logger
|
from app.modules.roxywi import logger
|
||||||
|
from app.modules.common.lock_utils import acquire_file_lock
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.config.from_object('app.config.Configuration')
|
app.config.from_object('app.config.Configuration')
|
||||||
|
@ -33,9 +34,10 @@ from app.modules.db.db_model import create_tables
|
||||||
from app.create_db import default_values
|
from app.create_db import default_values
|
||||||
from app.modules.db.migration_manager import migrate
|
from app.modules.db.migration_manager import migrate
|
||||||
|
|
||||||
create_tables()
|
if not acquire_file_lock():
|
||||||
default_values()
|
create_tables()
|
||||||
migrate()
|
default_values()
|
||||||
|
migrate()
|
||||||
|
|
||||||
set_correct_owner('/var/lib/roxy-wi')
|
set_correct_owner('/var/lib/roxy-wi')
|
||||||
|
|
||||||
|
|
|
@ -359,13 +359,10 @@ def diff_config(old_cfg, cfg) -> str:
|
||||||
:param cfg: Path to the new configuration file to compare.
|
:param cfg: Path to the new configuration file to compare.
|
||||||
:return: Unified diff output showing the differences between `old_cfg` and `cfg`.
|
:return: Unified diff output showing the differences between `old_cfg` and `cfg`.
|
||||||
"""
|
"""
|
||||||
diff = ""
|
|
||||||
cmd = f"/bin/diff -ub {old_cfg} {cfg}"
|
cmd = f"/bin/diff -ub {old_cfg} {cfg}"
|
||||||
output, stderr = server_mod.subprocess_execute(cmd)
|
output, stderr = server_mod.subprocess_execute(cmd)
|
||||||
|
output = '\n'.join(output)
|
||||||
for line in output:
|
return output
|
||||||
diff += line + "\n"
|
|
||||||
return diff
|
|
||||||
|
|
||||||
|
|
||||||
def _classify_line(line: str) -> str:
|
def _classify_line(line: str) -> str:
|
||||||
|
@ -429,12 +426,9 @@ def compare_config(service: str, left: str, right: str) -> str:
|
||||||
:param right: The name of the right configuration file.
|
:param right: The name of the right configuration file.
|
||||||
:return: The rendered template with the diff output and the user language for Flask.
|
:return: The rendered template with the diff output and the user language for Flask.
|
||||||
"""
|
"""
|
||||||
lang = roxywi_common.get_user_lang_for_flask()
|
|
||||||
config_dir = config_common.get_config_dir(service)
|
config_dir = config_common.get_config_dir(service)
|
||||||
cmd = f'diff -pub {config_dir}{left} {config_dir}{right}'
|
output = diff_config(f'{config_dir}{left}', f'{config_dir}{right}')
|
||||||
output, stderr = server_mod.subprocess_execute(cmd)
|
return output
|
||||||
|
|
||||||
return render_template('ajax/compare.html', stdout=output, lang=lang)
|
|
||||||
|
|
||||||
|
|
||||||
def show_config(server_ip: str, service: str, config_file_name: str, configver: str, claims: dict, edit_section: str) -> str:
|
def show_config(server_ip: str, service: str, config_file_name: str, configver: str, claims: dict, edit_section: str) -> str:
|
||||||
|
|
|
@ -388,6 +388,20 @@ class HaproxyBackendServer(BaseModel):
|
||||||
send_proxy: Optional[bool] = 0
|
send_proxy: Optional[bool] = 0
|
||||||
backup: Optional[bool] = 0
|
backup: Optional[bool] = 0
|
||||||
|
|
||||||
|
@model_validator(mode='before')
|
||||||
|
@classmethod
|
||||||
|
def int_cannot_be_empty(cls, values):
|
||||||
|
if 'port' in values:
|
||||||
|
if values['port'] == '':
|
||||||
|
raise ValueError('Port cannot be empty')
|
||||||
|
if 'port_check' in values:
|
||||||
|
if values['port_check'] == '':
|
||||||
|
raise ValueError('Port check cannot be empty')
|
||||||
|
if 'maxconn' in values:
|
||||||
|
if values['maxconn'] == '':
|
||||||
|
raise ValueError('Maxconn cannot be empty')
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
class HaproxyCookie(BaseModel):
|
class HaproxyCookie(BaseModel):
|
||||||
dynamic: str
|
dynamic: str
|
||||||
|
@ -559,6 +573,21 @@ class NginxBackendServer(BaseModel):
|
||||||
fail_timeout: int
|
fail_timeout: int
|
||||||
|
|
||||||
|
|
||||||
|
@model_validator(mode='before')
|
||||||
|
@classmethod
|
||||||
|
def int_cannot_be_empty(cls, values):
|
||||||
|
if 'port' in values:
|
||||||
|
if values['port'] == '':
|
||||||
|
raise ValueError('Port cannot be empty')
|
||||||
|
if 'max_fails' in values:
|
||||||
|
if values['max_fails'] == '':
|
||||||
|
raise ValueError('max_fails cannot be empty')
|
||||||
|
if 'fail_timeout' in values:
|
||||||
|
if values['fail_timeout'] == '':
|
||||||
|
raise ValueError('fail_timeout cannot be empty')
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
class NginxUpstreamRequest(BaseModel):
|
class NginxUpstreamRequest(BaseModel):
|
||||||
name: EscapedString
|
name: EscapedString
|
||||||
balance: Optional[Literal['ip_hash', 'least_conn', 'random', 'round_robin']]
|
balance: Optional[Literal['ip_hash', 'least_conn', 'random', 'round_robin']]
|
||||||
|
@ -619,6 +648,7 @@ class NginxLocationRequest(BaseModel):
|
||||||
class NginxProxyPassRequest(BaseModel):
|
class NginxProxyPassRequest(BaseModel):
|
||||||
locations: List[NginxLocationRequest]
|
locations: List[NginxLocationRequest]
|
||||||
name: Union[IPvAnyAddress, DomainName]
|
name: Union[IPvAnyAddress, DomainName]
|
||||||
|
name_aliases: List[Union[IPvAnyAddress, DomainName]] = None
|
||||||
port: Annotated[int, Gt(1), Le(65535)]
|
port: Annotated[int, Gt(1), Le(65535)]
|
||||||
type: Literal['proxy_pass'] = 'proxy_pass'
|
type: Literal['proxy_pass'] = 'proxy_pass'
|
||||||
scheme: Literal['http', 'https'] = 'http'
|
scheme: Literal['http', 'https'] = 'http'
|
||||||
|
|
|
@ -98,15 +98,15 @@ function showStats() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function openStats() {
|
function openStats() {
|
||||||
let serv = $("#serv").val();
|
let serv = $("#serv option:selected").val();
|
||||||
let service_url = cur_url[4];
|
let service_url = $('#service').val();
|
||||||
let url = "/stats/"+service_url+"/"+serv
|
let url = "/stats/"+service_url+"/"+serv
|
||||||
let win = window.open(url, '_blank');
|
let win = window.open(url, '_blank');
|
||||||
win.focus();
|
win.focus();
|
||||||
}
|
}
|
||||||
function openVersions() {
|
function openVersions() {
|
||||||
let serv = $("#serv").val();
|
let serv = $("#serv option:selected").val();
|
||||||
let service_url = cur_url[4];
|
let service_url = $('#service').val();
|
||||||
let url = "/config/versions/"+service_url+"/"+serv
|
let url = "/config/versions/"+service_url+"/"+serv
|
||||||
let win = window.open(url,"_self");
|
let win = window.open(url,"_self");
|
||||||
win.focus();
|
win.focus();
|
||||||
|
@ -230,43 +230,6 @@ function showMap() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function showCompare() {
|
|
||||||
$.ajax({
|
|
||||||
url: "/config/compare/" + $("#service").val() + "/" + $("#serv").val() + "/show",
|
|
||||||
data: {
|
|
||||||
left: $('#left').val(),
|
|
||||||
right: $("#right").val(),
|
|
||||||
},
|
|
||||||
type: "POST",
|
|
||||||
success: function (data) {
|
|
||||||
if (data.indexOf('error:') != '-1') {
|
|
||||||
toastr.error(data);
|
|
||||||
} else {
|
|
||||||
toastr.clear();
|
|
||||||
$("#ajax").html(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function showCompareConfigs() {
|
|
||||||
clearAllAjaxFields();
|
|
||||||
$('#ajax-config_file_name').empty();
|
|
||||||
$.ajax({
|
|
||||||
url: "/config/compare/" + $("#service").val() + "/" + $("#serv").val() + "/files",
|
|
||||||
type: "GET",
|
|
||||||
success: function (data) {
|
|
||||||
if (data.indexOf('error:') != '-1') {
|
|
||||||
toastr.error(data);
|
|
||||||
} else {
|
|
||||||
toastr.clear();
|
|
||||||
$("#ajax-compare").html(data);
|
|
||||||
$("input[type=submit], button").button();
|
|
||||||
$("select").selectmenu();
|
|
||||||
window.history.pushState("Show compare config", "Show compare config", '/config/compare/' + $("#service").val() + '/' + $("#serv").val());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function showConfig() {
|
function showConfig() {
|
||||||
let edit_section = '';
|
let edit_section = '';
|
||||||
let edit_section_uri = '';
|
let edit_section_uri = '';
|
||||||
|
|
Loading…
Reference in New Issue