From 112ecd5ce6844d27828926636ed46054c90829c7 Mon Sep 17 00:00:00 2001 From: Aidaho Date: Sun, 16 Jun 2024 22:54:41 +0300 Subject: [PATCH] v7.3.1.0: Refactor and optimize server applications for better error handling and accuracy The code changes focus on enhancing the server application's functionality by improving the error handling mechanism and streamlining the logic. Modifications include refining how servers get created, updated, and deleted, optimizing how ssh related actions are performed, and ensuring more accurate server scanning. The changes help reduce potential errors and make the application more efficient. --- app/jobs.py | 8 +- app/modules/common/common.py | 25 ++ app/modules/config/add.py | 24 +- app/modules/roxywi/roxy.py | 2 +- app/modules/server/server.py | 30 +- app/routes/add/routes.py | 3 +- app/routes/install/routes.py | 2 +- app/routes/main/routes.py | 2 +- app/routes/server/routes.py | 209 +++++----- app/routes/udp/routes.py | 2 +- app/routes/waf/routes.py | 2 +- app/static/js/admin/common.js | 307 ++++++++++++++ app/static/js/admin/server.js | 484 +++++++++++++++++++++++ app/static/js/admin/ssh.js | 1 - app/static/js/variables.js | 2 +- app/templates/admin.html | 6 +- app/templates/checker.html | 1 - app/templates/ha_cluster.html | 1 - app/templates/include/admin_servers.html | 4 +- app/templates/include/admin_ssh.html | 2 +- app/templates/logs.html | 2 +- app/templates/logs_internal.html | 2 +- app/templates/smon/dashboard.html | 1 - 23 files changed, 956 insertions(+), 166 deletions(-) create mode 100644 app/static/js/admin/common.js create mode 100644 app/static/js/admin/server.js diff --git a/app/jobs.py b/app/jobs.py index 9652315d..4b99ffef 100644 --- a/app/jobs.py +++ b/app/jobs.py @@ -2,14 +2,13 @@ import os import shutil import datetime -import distro - from app import scheduler import app.modules.db.sql as sql import app.modules.db.user as user_sql import app.modules.db.roxy as roxy_sql import app.modules.db.history as history_sql import app.modules.roxywi.roxy as roxy +import app.modules.common.common as common import app.modules.tools.common as tools_common import app.modules.roxy_wi_tools as roxy_wi_tools @@ -76,10 +75,7 @@ def delete_old_logs(): def update_owner_on_log(): log_path = get_config.get_config_var('main', 'log_path') try: - if distro.id() == 'ubuntu': - os.system(f'sudo chown www-data:www-data -R {log_path}') - else: - os.system(f'sudo chown apache:apache -R {log_path}') + common.set_correct_owner(log_path) except Exception: pass diff --git a/app/modules/common/common.py b/app/modules/common/common.py index 5715c624..ad588255 100644 --- a/app/modules/common/common.py +++ b/app/modules/common/common.py @@ -1,7 +1,9 @@ import re +import os import dateutil from datetime import datetime +import distro from shlex import quote from shutil import which from pytz import timezone @@ -194,7 +196,30 @@ def sanitize_input_word(word: str) -> str: def return_proxy_dict() -> dict: + """ + Return a dictionary containing proxy information for HTTP and HTTPS. + + :return: A dictionary with the following key-value pairs: + - "https": The proxy setting for HTTPS. + - "http": The proxy setting for HTTP. + If the proxy setting is None, an empty string, or "None", an empty dictionary is returned. + """ proxy = sql.get_setting('proxy') if proxy in {None, '', 'None'}: return {} return {"https": proxy, "http": proxy} + + +def set_correct_owner(path: str) -> None: + """ + Sets the correct owner of the specified path. + + :param path: The path for which to set the correct owner. + :type path: str + :return: None + :rtype: None + """ + if distro.id() == 'ubuntu': + os.system(f'sudo chown www-data:www-data -R {path}') + else: + os.system(f'sudo chown apache:apache -R {path}') diff --git a/app/modules/config/add.py b/app/modules/config/add.py index ba1f0a1e..237d9a1a 100644 --- a/app/modules/config/add.py +++ b/app/modules/config/add.py @@ -290,20 +290,18 @@ def create_map(server_ip: str, map_name: str, group: str) -> str: lib_path = get_config.get_config_var('main', 'lib_path') map_name = f"{map_name.split('.')[0]}.map" map_path = f'{lib_path}/maps/{group}/' - full_path = f'{map_path}/{map_name}' + full_path = f'{map_path}{map_name}' try: - server_mod.subprocess_execute(f'mkdir -p {map_path}') + server_mod.subprocess_execute(f'sudo mkdir -p {map_path}') + common.set_correct_owner(lib_path) except Exception as e: raise Exception(f'error: cannot create a local folder for maps: {e}') try: - open(full_path, 'a').close() - try: - roxywi_common.logging(server_ip, f'A new map {map_name} has been created', roxywi=1, login=1) - except Exception: - pass + os.mknod(full_path) + roxywi_common.logging(server_ip, f'A new map {map_name} has been created', roxywi=1, login=1) except IOError as e: - raise Exception(f'error: Cannot create a new {map_name} map. {e}, ') + raise Exception(f'error: Cannot create a new {map_name} map. {e}') else: return 'success: ' @@ -488,17 +486,17 @@ def get_ssl_cert(server_ip: str, cert_id: int) -> str: try: return server_mod.ssh_command(server_ip, command) except Exception as e: - return f'error: Cannot connect to the server {e.args[0]}' + return f'error: Cannot connect to the server {e}' -def get_ssl_raw_cert(server_ip: str, cert_id: int) -> str: +def get_ssl_raw_cert(server_ip: str, cert_id: str) -> str: cert_path = sql.get_setting('cert_path') command = f"cat {cert_path}/{cert_id}" try: return server_mod.ssh_command(server_ip, command) except Exception as e: - return f'error: Cannot connect to the server {e.args[0]}' + return f'error: Cannot connect to the server {e}' def get_ssl_certs(server_ip: str) -> str: @@ -507,7 +505,7 @@ def get_ssl_certs(server_ip: str) -> str: try: return server_mod.ssh_command(server_ip, command) except Exception as e: - return f'error: Cannot connect to the server: {e.args[0]}' + return f'error: Cannot connect to the server: {e}' def del_ssl_cert(server_ip: str, cert_id: str) -> str: @@ -517,7 +515,7 @@ def del_ssl_cert(server_ip: str, cert_id: str) -> str: try: return server_mod.ssh_command(server_ip, command) except Exception as e: - return f'error: Cannot delete the certificate {e.args[0]}' + return f'error: Cannot delete the certificate {e}' def upload_ssl_cert(server_ip: str, ssl_name: str, ssl_cont: str) -> str: diff --git a/app/modules/roxywi/roxy.py b/app/modules/roxywi/roxy.py index 68b28a8e..cd102ff0 100644 --- a/app/modules/roxywi/roxy.py +++ b/app/modules/roxywi/roxy.py @@ -83,7 +83,7 @@ def update_user_status() -> None: roxy_wi_get_plan = requests.Session() roxy_wi_get_plan.mount("https://", adapter) json_body = {'license': user_license} - roxy_wi_get_plan = requests.post(f'https://roxy-wi.org/user/license', timeout=5, proxies=proxy_dict, json=json_body) + roxy_wi_get_plan = requests.post('https://roxy-wi.org/user/license', timeout=5, proxies=proxy_dict, json=json_body) try: status = roxy_wi_get_plan.json() roxy_sql.update_user_status(status['status'], status['plan'], status['method']) diff --git a/app/modules/server/server.py b/app/modules/server/server.py index e3a8b1cc..73277dd4 100644 --- a/app/modules/server/server.py +++ b/app/modules/server/server.py @@ -414,25 +414,22 @@ def show_firewalld_rules(server_ip) -> str: return render_template('ajax/firewall_rules.html', input_chain=input_chain2, IN_public_allow=in_public_allow, output_chain=output_chain, lang=lang) -def create_server(hostname, ip, group, typeip, enable, master, cred, port, desc, haproxy, nginx, apache, firewall, **kwargs) -> bool: +def create_server(hostname, ip, group, typeip, enable, master, cred, port, desc, haproxy, nginx, apache, firewall, **kwargs) -> int: if not roxywi_auth.is_admin(level=2, role_id=kwargs.get('role_id')): raise Exception('error: not enough permission') - if server_sql.add_server(hostname, ip, group, typeip, enable, master, cred, port, desc, haproxy, nginx, apache, firewall): - return True - else: - return False + last_id = server_sql.add_server(hostname, ip, group, typeip, enable, master, cred, port, desc, haproxy, nginx, apache, firewall) + return last_id -def update_server_after_creating(hostname: str, ip: str, scan_server: int) -> str: +def update_server_after_creating(hostname: str, ip: str, scan_server: int) -> None: try: checker_sql.insert_new_checker_setting_for_server(ip) except Exception as e: - roxywi_common.logging(f'Cannot insert Checker settings for {hostname}', str(e), roxywi=1) - raise Exception(f'error: Cannot insert Checker settings for {hostname} {e}') + roxywi_common.handle_exceptions(e, ip, f'Cannot insert Checker settings for {hostname}', roxywi=1, login=1) try: - if scan_server == '1': + if scan_server: nginx_config_path = sql.get_setting('nginx_config_path') haproxy_config_path = sql.get_setting('haproxy_config_path') haproxy_dir = sql.get_setting('haproxy_dir') @@ -459,19 +456,15 @@ def update_server_after_creating(hostname: str, ip: str, scan_server: int) -> st server_sql.update_firewall(ip) except Exception as e: - roxywi_common.logging(f'Cannot scan a new server {hostname}', str(e), roxywi=1) - raise Exception(f'error: Cannot scan a new server {hostname} {e}') + roxywi_common.handle_exceptions(e, ip, f'Cannot get scan the server {hostname}', roxywi=1, login=1) try: get_system_info(ip) except Exception as e: - roxywi_common.logging(f'Cannot get information from {hostname}', str(e), roxywi=1, login=1) - raise Exception(f'error: Cannot get information from {hostname} {e}') - - return 'ok' + roxywi_common.handle_exceptions(e, ip, f'Cannot get information from {hostname}', roxywi=1, login=1) -def delete_server(server_id: int) -> str: +def delete_server(server_id: int) -> None: server = server_sql.select_servers(id=server_id) server_ip = '' hostname = '' @@ -481,9 +474,9 @@ def delete_server(server_id: int) -> str: server_ip = s[2] if backup_sql.check_exists_backup(server_ip): - return 'warning: Delete the backup first' + raise 'warning: Delete the backup first' if backup_sql.check_exists_s3_backup(server_ip): - return 'warning: Delete the S3 backup first' + raise 'warning: Delete the S3 backup first' if server_sql.delete_server(server_id): waf_sql.delete_waf_server(server_id) ps_sql.delete_port_scanner_settings(server_id) @@ -492,7 +485,6 @@ def delete_server(server_id: int) -> str: server_sql.delete_system_info(server_id) service_sql.delete_service_settings(server_id) roxywi_common.logging(server_ip, f'The server {hostname} has been deleted', roxywi=1, login=1) - return 'Ok' def server_is_up(server_ip: str) -> str: diff --git a/app/routes/add/routes.py b/app/routes/add/routes.py index a486e48d..428f2f27 100644 --- a/app/routes/add/routes.py +++ b/app/routes/add/routes.py @@ -577,9 +577,10 @@ def upload_cert(): return add_mod.upload_ssl_cert(server_ip, ssl_name, ssl_cont) -@bp.route('/cert/get/raw//') +@bp.route('/cert/get/raw//') def get_cert_raw(server_ip, cert_id): server_ip = common.is_ip_or_dns(server_ip) + cert_id = common.checkAjaxInput(cert_id) return add_mod.get_ssl_raw_cert(server_ip, cert_id) diff --git a/app/routes/install/routes.py b/app/routes/install/routes.py index 76a7c8fe..797407d3 100644 --- a/app/routes/install/routes.py +++ b/app/routes/install/routes.py @@ -147,6 +147,6 @@ def install_udp(): listener_id = int(json_data['listener_id']) try: inv, server_ips = service_mod.generate_udp_inv(listener_id, 'install') - return service_mod.run_ansible(inv, server_ips, f'udp'), 201 + return service_mod.run_ansible(inv, server_ips, 'udp'), 201 except Exception as e: return jsonify({'status': 'failed', 'error': f'Cannot create listener: {e}'}) diff --git a/app/routes/main/routes.py b/app/routes/main/routes.py index 1d45cbf5..8fd8f5f0 100644 --- a/app/routes/main/routes.py +++ b/app/routes/main/routes.py @@ -176,7 +176,7 @@ def service_history(service, server_ip): elif service == 'user': history = history_sql.select_action_history_by_user_id(server_ip) else: - abort(404, f'History not found') + abort(404, 'History not found') kwargs = { 'user_subscription': roxywi_common.return_user_subscription(), diff --git a/app/routes/server/routes.py b/app/routes/server/routes.py index abbb0134..5769c1e4 100644 --- a/app/routes/server/routes.py +++ b/app/routes/server/routes.py @@ -73,118 +73,111 @@ def show_ip(server_id): return server_mod.ssh_command(server_ip.ip, commands, ip="1") -@bp.post('/create') +@bp.route('', methods=['POST', 'PUT', 'DELETE', 'PATCH']) @get_user_params() def create_server(): roxywi_auth.page_for_admin(level=2) - hostname = common.checkAjaxInput(request.form.get('servername')) - ip = common.is_ip_or_dns(request.form.get('newip')) - group = common.checkAjaxInput(request.form.get('newservergroup')) - typeip = common.checkAjaxInput(request.form.get('typeip')) - haproxy = common.checkAjaxInput(request.form.get('haproxy')) - nginx = common.checkAjaxInput(request.form.get('nginx')) - apache = common.checkAjaxInput(request.form.get('apache')) - firewall = common.checkAjaxInput(request.form.get('firewall')) - enable = common.checkAjaxInput(request.form.get('enable')) - master = common.checkAjaxInput(request.form.get('slave')) - cred = common.checkAjaxInput(request.form.get('cred')) - page = common.checkAjaxInput(request.form.get('page')) - page = page.split("#")[0] - port = common.checkAjaxInput(request.form.get('newport')) - desc = common.checkAjaxInput(request.form.get('desc')) - add_to_smon = common.checkAjaxInput(request.form.get('add_to_smon')) + json_data = request.get_json() lang = roxywi_common.get_user_lang_for_flask() + if request.method in ('POST', 'PUT'): + hostname = common.checkAjaxInput(json_data['name']) + group = int(json_data['group']) + type_ip = int(json_data['type_ip']) + firewall = int(json_data['firewall']) + enable = int(json_data['enable']) + cred = int(json_data['cred']) + port = int(json_data['port']) + desc = common.checkAjaxInput(json_data['desc']) + master = int(json_data['slave']) + protected = int(json_data['protected']) - if ip == '': - return 'error: IP or DNS name is not valid' - try: - if server_mod.create_server(hostname, ip, group, typeip, enable, master, cred, port, desc, haproxy, nginx, - apache, firewall): + if request.method == 'POST': + ip = common.is_ip_or_dns(json_data['ip']) + haproxy = int(json_data['haproxy']) + nginx = int(json_data['nginx']) + apache = int(json_data['apache']) + add_to_smon = int(json_data['add_to_smon']) + if ip == '': + return jsonify({'status': 'failed','error': 'IP or DNS name is not valid'}) + try: + last_id = server_mod.create_server(hostname, ip, group, type_ip, enable, master, cred, port, desc, haproxy, nginx, apache, firewall) + except Exception as e: + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', 'Cannot create server') + + try: + user_subscription = roxywi_common.return_user_status() + except Exception as e: + user_subscription = roxywi_common.return_unsubscribed_user_status() + roxywi_common.logging('Roxy-WI server', f'Cannot get a user plan: {e}', roxywi=1) + + if add_to_smon: try: - user_subscription = roxywi_common.return_user_status() + user_group = roxywi_common.get_user_group(id=1) + json_data = { + "name": hostname, + "ip": ip, + "port": "0", + "enabled": "1", + "url": "", + "body": "", + "group": hostname, + "desc": f"Ping {hostname}", + "tg": "0", + "slack": "0", + "pd": "0", + "resolver": "", + "record_type": "", + "packet_size": "56", + "http_method": "", + "check_type": "ping", + "agent_id": "1", + "interval": "120", + } + smon_mod.create_smon(json_data, user_group) except Exception as e: - user_subscription = roxywi_common.return_unsubscribed_user_status() - roxywi_common.logging('Roxy-WI server', f'Cannot get a user plan: {e}', roxywi=1) + roxywi_common.logging(ip, f'error: Cannot add server {hostname} to SMON: {e}', roxywi=1) - if add_to_smon: - try: - user_group = roxywi_common.get_user_group(id=1) - json_data = { - "name": hostname, - "ip": ip, - "port": "0", - "enabled": "1", - "url": "", - "body": "", - "group": hostname, - "desc": f"Ping {hostname}", - "tg": "0", - "slack": "0", - "pd": "0", - "resolver": "", - "record_type": "", - "packet_size": "56", - "http_method": "", - "check_type": "ping", - "agent_id": "1", - "interval": "120", - } - smon_mod.create_smon(json_data, user_group) - except Exception as e: - roxywi_common.logging(ip, f'error: Cannot add server {hostname} to SMON: {e}', roxywi=1) + roxywi_common.logging(ip, f'A new server {hostname} has been created', roxywi=1, login=1, keep_history=1, service='server') - roxywi_common.logging(ip, f'A new server {hostname} has been created', roxywi=1, login=1, keep_history=1, service='server') - - return render_template( - 'ajax/new_server.html', groups=group_sql.select_groups(), servers=server_sql.select_servers(server=ip), lang=lang, - masters=server_sql.select_servers(get_master_servers=1), sshs=cred_sql.select_ssh(group=group), page=page, - user_subscription=user_subscription, adding=1 - ) - except Exception as e: - return f'{e}' - - -@bp.post('/create/after') -def after_add(): - hostname = common.checkAjaxInput(request.form.get('servername')) - ip = common.is_ip_or_dns(request.form.get('newip')) - scan_server = common.checkAjaxInput(request.form.get('scan_server')) - - try: - return server_mod.update_server_after_creating(hostname, ip, scan_server) - except Exception as e: - return str(e) - - -@bp.post('/update') -def update_server(): - roxywi_auth.page_for_admin(level=2) - name = request.form.get('updateserver') - group = request.form.get('servergroup') - typeip = request.form.get('typeip') - firewall = request.form.get('firewall') - enable = request.form.get('enable') - master = int(request.form.get('slave')) - serv_id = request.form.get('id') - cred = request.form.get('cred') - port = request.form.get('port') - protected = request.form.get('protected') - desc = request.form.get('desc') - - if name is None or port is None: - return error_mess - else: - server_sql.update_server(name, group, typeip, enable, master, serv_id, cred, port, desc, firewall, protected) - server_ip = server_sql.select_server_ip_by_id(serv_id) - roxywi_common.logging(server_ip, f'The server {name} has been update', roxywi=1, login=1, keep_history=1, service='server') - - return 'ok' - - -@bp.route('/delete/') -def delete_server(server_id): - roxywi_auth.page_for_admin(level=2) - return server_mod.delete_server(server_id) + kwargs = { + 'groups': group_sql.select_groups(), + 'servers': server_sql.select_servers(server=ip), + 'lang': lang, + 'masters': server_sql.select_servers(get_master_servers=1), + 'sshs': cred_sql.select_ssh(group=group), + 'user_subscription': user_subscription, + 'adding': 1 + } + return jsonify({'status': 'created', 'id': last_id, 'data': render_template('ajax/new_server.html', **kwargs)}) + elif request.method == 'PUT': + serv_id = int(json_data['id']) + if hostname is None or port is None: + return jsonify({'status': 'failed', 'error': 'Cannot find server ip or port'}) + else: + try: + server_sql.update_server(hostname, group, type_ip, enable, master, serv_id, cred, port, desc, firewall, protected) + except Exception as e: + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', 'Cannot update server') + server_ip = server_sql.select_server_ip_by_id(serv_id) + roxywi_common.logging(server_ip, f'The server {hostname} has been update', roxywi=1, login=1, + keep_history=1, service='server') + return jsonify({'status': 'updated'}) + elif request.method == 'DELETE': + server_id = int(json_data['id']) + try: + server_mod.delete_server(server_id) + return jsonify({'status': 'deleted'}) + except Exception as e: + roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', 'Cannot delete the server') + elif request.method == 'PATCH': + hostname = common.checkAjaxInput(json_data['name']) + ip = common.is_ip_or_dns(json_data['ip']) + scan_server = int(json_data['scan_server']) + try: + server_mod.update_server_after_creating(hostname, ip, scan_server) + return jsonify({'status': 'updated'}) + except Exception as e: + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', 'Cannot scan the server') @bp.route('/group', methods=['POST', 'PUT', 'DELETE']) @@ -222,8 +215,6 @@ def create_group(): return jsonify({'status': 'deleted'}) except Exception as e: return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', f'Cannot delete {group_id}') - else: - abort(405) @bp.route('/ssh', methods=['POST', 'PUT', 'DELETE', 'PATCH']) @@ -236,20 +227,20 @@ def create_ssh(): data = ssh_mod.create_ssh_cred(json_data) return jsonify({'status': 'created', 'id': data['id'], 'data': data['template']}) except Exception as e: - return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', f'Cannot create SSH') + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', 'Cannot create SSH') elif request.method == 'PUT': try: ssh_mod.update_ssh_key(json_data) return jsonify({'status': 'updated'}) except Exception as e: - return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', f'Cannot update SSH') + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', 'Cannot update SSH') elif request.method == 'DELETE': ssh_id = int(json_data.get('id')) try: ssh_mod.delete_ssh_key(ssh_id) return jsonify({'status': 'deleted'}) except Exception as e: - return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', f'Cannot delete SSH') + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', 'Cannot delete SSH') elif request.method == 'PATCH': user_group = roxywi_common.get_user_group() name = common.checkAjaxInput(json_data['name']) @@ -260,7 +251,7 @@ def create_ssh(): saved_path = ssh_mod.upload_ssh_key(name, user_group, key, passphrase) return jsonify({'status': 'uploaded', 'message': saved_path}) except Exception as e: - return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', f'Cannot upload ssh') + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', 'Cannot upload ssh') @bp.app_template_filter('string_to_dict') diff --git a/app/routes/udp/routes.py b/app/routes/udp/routes.py index e9872f19..01bfc31d 100644 --- a/app/routes/udp/routes.py +++ b/app/routes/udp/routes.py @@ -61,7 +61,7 @@ def listener_funct(service): listener_id = int(kwargs['listener_id']) try: inv, server_ips = service_mod.generate_udp_inv(listener_id, 'uninstall') - service_mod.run_ansible(inv, server_ips, f'udp'), 201 + service_mod.run_ansible(inv, server_ips, 'udp'), 201 roxywi_common.logging(listener_id, f'UDP listener has been deleted {listener_id}', roxywi=1, keep_history=1, login=1, service='UDP listener') except Exception as e: return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server',f'Cannot create inventory for UDP listener deleting {listener_id}') diff --git a/app/routes/waf/routes.py b/app/routes/waf/routes.py index 51e1a772..60d7caad 100644 --- a/app/routes/waf/routes.py +++ b/app/routes/waf/routes.py @@ -113,7 +113,7 @@ def waf_rule_edit(service, server_ip, rule_id): conf = open(cfg, "r") config_read = conf.read() conf.close() - except IOError: + except IOError as e: return f'error: Cannot read imported config file: {e}' kwargs = { diff --git a/app/static/js/admin/common.js b/app/static/js/admin/common.js new file mode 100644 index 00000000..4a52c6a5 --- /dev/null +++ b/app/static/js/admin/common.js @@ -0,0 +1,307 @@ +$( function() { + $("#tabs ul li").click(function () { + let activeTab = $(this).find("a").attr("href"); + let activeTabClass = activeTab.replace('#', ''); + $('.menu li ul li').each(function () { + $(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)'); + $(this).find('a').css('padding-left', '20px') + $(this).find('a').css('background-color', '#48505A'); + $(this).children("." + activeTabClass).css('padding-left', '30px'); + $(this).children("." + activeTabClass).css('border-left', '4px solid var(--right-menu-blue-rolor)'); + $(this).children("." + activeTabClass).css('background-color', 'var(--right-menu-blue-rolor)'); + }); + if (activeTab == '#tools') { + loadServices(); + } else if (activeTab == '#settings') { + loadSettings(); + } else if (activeTab == '#updatehapwi') { + loadupdatehapwi(); + } else if (activeTab == '#openvpn') { + loadopenvpn(); + } else if (activeTab == '#backup') { + loadBackup(); + } + }); +} ); +window.onload = function() { + $('#tabs').tabs(); + let activeTabIdx = $('#tabs').tabs('option','active') + if (cur_url[0].split('#')[0] == 'admin') { + if (activeTabIdx == 6) { + loadServices(); + } else if (activeTabIdx == 3) { + loadSettings(); + } else if (activeTabIdx == 4) { + loadBackup(); + } else if (activeTabIdx == 7) { + loadupdatehapwi(); + } else if (activeTabIdx == 8) { + loadopenvpn(); + } + } +} +function updateService(service, action='update') { + $("#ajax-update").html('') + $("#ajax-update").html(wait_mess); + $.ajax({ + url: "/app/admin/tools/update/" + service, + success: function (data) { + data = data.replace(/\s+/g, ' '); + if (data.indexOf('Complete!') != '-1' || data.indexOf('Unpacking') != '-1') { + toastr.clear(); + toastr.success(service + ' has been ' + action + 'ed'); + } else if (data.indexOf('Unauthorized') != '-1' || data.indexOf('Status code: 401') != '-1') { + toastr.clear(); + toastr.error('It looks like there is no authorization in the Roxy-WI repository. Your subscription may have expired or there is no subscription. How to get the subscription'); + } else if (data.indexOf('but not installed') != '-1') { + toastr.clear(); + toastr.error('There is setting for Roxy-WI repository, but Roxy-WI is installed without repository. Please reinstall with package manager'); + } else if (data.indexOf('No Match for argument') != '-1' || data.indexOf('Unable to find a match') != '-1') { + toastr.clear(); + toastr.error('It seems like Roxy-WI repository is not set. Please read docs for detail'); + } else if (data.indexOf('password for') != '-1') { + toastr.clear(); + toastr.error('It seems like apache user needs to be add to sudoers. Please read docs for detail'); + } else if (data.indexOf('No packages marked for update') != '-1') { + toastr.clear(); + toastr.info('It seems like the lastest version Roxy-WI is installed'); + } else if (data.indexOf('Connection timed out') != '-1') { + toastr.clear(); + toastr.error('Cannot connect to Roxy-WI repository. Connection timed out'); + } else if (data.indexOf('--disable') != '-1') { + toastr.clear(); + toastr.error('It seems like there is a problem with repositories'); + } else if (data.indexOf('Error: Package') != '-1') { + toastr.clear(); + toastr.error(data); + } else if (data.indexOf('conflicts with file from') != '-1') { + toastr.clear(); + toastr.error(data); + } else if (data.indexOf('error:') != '-1' || data.indexOf('Failed') != '-1') { + toastr.error(data); + } else if (data.indexOf('0 upgraded, 0 newly installed') != '-1') { + toastr.info('There is no a new version of ' + service); + } else { + toastr.clear(); + toastr.success(service + ' has been ' + action + 'ed'); + } + $("#ajax-update").html(''); + loadupdatehapwi(); + loadServices(); + show_version(); + } + }); +} +function confirmDeleteOpenVpnProfile(id) { + $( "#dialog-confirm" ).dialog({ + resizable: false, + height: "auto", + width: 400, + modal: true, + title: "Are you sure you want to delete profile " +id+ "?", + buttons: { + "Delete": function() { + $( this ).dialog( "close" ); + removeOpenVpnProfile(id); + }, + Cancel: function() { + $( this ).dialog( "close" ); + } + } + }); +} +function removeOpenVpnProfile(id) { + $("#" + id).css("background-color", "#f2dede"); + $.ajax({ + url: "/app/admin/openvpn/delete", + data: { + openvpndel: id + }, + type: "POST", + success: function (data) { + data = data.replace(/\s+/g, ' '); + if (data == "ok") { + $("#" + id).remove(); + } else if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') { + toastr.error(data); + } + } + }); +} +function uploadOvpn() { + toastr.clear(); + if ($("#ovpn_upload_name").val() == '' || $('#ovpn_upload_file').val() == '') { + toastr.error('All fields must be completed'); + } else { + $.ajax({ + url: "/app/admin/openvpn/upload", + data: { + uploadovpn: $('#ovpn_upload_file').val(), + ovpnname: $('#ovpn_upload_name').val() + }, + type: "POST", + success: function (data) { + data = data.replace(/\s+/g, ' '); + if (data.indexOf('danger') != '-1' || data.indexOf('unique') != '-1' || data.indexOf('error:') != '-1') { + toastr.error(data); + } else if (data.indexOf('success') != '-1') { + toastr.clear(); + toastr.success(data); + location.reload(); + } else { + toastr.error('Something wrong, check and try again'); + } + } + }); + } +} +function OpenVpnSess(id, action) { + $.ajax({ + url: "/app/admin/openvpn/" + action + "/" + id, + success: function (data) { + data = data.replace(/\s+/g, ' '); + if (data.indexOf('danger') != '-1' || data.indexOf('unique') != '-1' || data.indexOf('error:') != '-1') { + toastr.error(data); + } else if (data.indexOf('success') != '-1') { + toastr.clear(); + toastr.success(data) + location.reload() + } else { + toastr.error('Something wrong, check and try again'); + } + } + }); +} +function loadSettings() { + $.ajax({ + url: "/app/admin/settings", + success: function (data) { + data = data.replace(/\s+/g, ' '); + if (data.indexOf('error:') != '-1') { + toastr.error(data); + } else { + $('#settings').html(data); + $.getScript(awesome); + $( "input[type=checkbox]" ).checkboxradio(); + $( "select" ).selectmenu(); + } + } + } ); +} +function loadServices() { + $.ajax({ + url: "/app/admin/tools", + success: function (data) { + data = data.replace(/\s+/g, ' '); + if (data.indexOf('danger') != '-1' || data.indexOf('unique') != '-1' || data.indexOf('error:') != '-1') { + toastr.error(data); + } else { + $('#ajax-services-body').html(data); + $.getScript(awesome); + } + } + } ); +} +function loadupdatehapwi() { + $.ajax({ + url: "/app/admin/update", + success: function (data) { + data = data.replace(/\s+/g, ' '); + if (data.indexOf('danger') != '-1' || data.indexOf('unique') != '-1' || data.indexOf('error:') != '-1') { + toastr.error(data); + } else { + $('#ajax-updatehapwi-body').html(data); + } + } + } ); +} +function checkUpdateRoxy() { + $.ajax({ + url: "/app/admin/update/check", + success: function (data) { + loadupdatehapwi(); + } + } ); +} +function loadopenvpn() { + $.ajax({ + url: "/app/admin/openvpn", + success: function (data) { + data = data.replace(/\s+/g, ' '); + if (data.indexOf('group_error') == '-1' && data.indexOf('error:') != '-1') { + toastr.error(data); + } else { + $('#openvpn').html(data); + $.getScript(awesome); + } + } + } ); +} +function confirmAjaxServiceAction(action, service) { + let action_word = translate_div.attr('data-'+action); + $( "#dialog-confirm-services" ).dialog({ + resizable: false, + height: "auto", + width: 400, + modal: true, + title: action_word + " " + service+"?", + buttons: [{ + text: action_word, + click: function () { + $(this).dialog("close"); + ajaxActionServices(action, service); + } + }, { + text: cancel_word, + click: function() { + $( this ).dialog( "close" ); + } + }] + }); +} +function ajaxActionServices(action, service) { + $.ajax( { + url: "/app/admin/tools/action/" + service + "/" + action, + success: function( data ) { + if (data.indexOf('error:') != '-1' || data.indexOf('Failed') != '-1') { + toastr.error(data); + } else if (data.indexOf('warning: ') != '-1') { + toastr.warning(data); + } else { + window.history.pushState("services", "services", cur_url[0].split("#")[0] + "#tools"); + toastr.success('The ' + service + ' has been ' + action +'ed'); + loadServices(); + } + }, + error: function(){ + alert(w.data_error); + } + } ); +} +function showApacheLog(serv) { + let rows = $('#rows').val(); + let grep = $('#grep').val(); + let exgrep = $('#exgrep').val(); + let hour = $('#time_range_out_hour').val(); + let minute = $('#time_range_out_minut').val(); + let hour1 = $('#time_range_out_hour1').val(); + let minute1 = $('#time_range_out_minut1').val(); + let url = "/app/logs/apache_internal/" + serv + "/" + rows; + $.ajax( { + url: url, + data: { + rows: rows, + serv: serv, + grep: grep, + exgrep: exgrep, + hour: hour, + minute: minute, + hour1: hour1, + minute1: minute1 + }, + type: "POST", + success: function( data ) { + $("#ajax").html(data); + } + } ); +} diff --git a/app/static/js/admin/server.js b/app/static/js/admin/server.js new file mode 100644 index 00000000..c2e0b18d --- /dev/null +++ b/app/static/js/admin/server.js @@ -0,0 +1,484 @@ +$( function() { + $('#add-server-button').click(function() { + addServerDialog.dialog('open'); + }); + let server_tabel_title = $( "#server-add-table-overview" ).attr('title'); + let addServerDialog = $( "#server-add-table" ).dialog({ + autoOpen: false, + resizable: false, + height: "auto", + width: 600, + modal: true, + title: server_tabel_title, + show: { + effect: "fade", + duration: 200 + }, + hide: { + effect: "fade", + duration: 200 + }, + buttons: [{ + text: add_word, + click: function () { + addServer(this); + } + }, { + text: cancel_word, + click: function () { + $(this).dialog("close"); + clearTips(); + } + }] + }); + $( "#ajax-servers input" ).change(function() { + let id = $(this).attr('id').split('-'); + updateServer(id[1]) + }); + $( "#ajax-servers select" ).on('selectmenuchange',function() { + let id = $(this).attr('id').split('-'); + updateServer(id[1]) + }); + $( "#scan_server" ).change(function() { + if ($('#scan_server').is(':checked')) { + $('.services_for_scan').hide(); + } else { + $('.services_for_scan').show(); + } + }); +}); +function addServer(dialog_id) { + toastr.clear() + let valid = true; + let servername = $('#new-server-add').val(); + let ip = $('#new-ip').val(); + let server_group = $('#new-server-group-add').val(); + let cred = $('#credentials').val(); + let scan_server = 0; + let type_ip = 0; + let enable = 0; + let haproxy = 0; + let nginx = 0; + let apache = 0; + let firewall = 0; + let add_to_smon = 0; + if ($('#scan_server').is(':checked')) { + scan_server = '1'; + } + if ($('#typeip').is(':checked')) { + type_ip = '1'; + } + if ($('#enable').is(':checked')) { + enable = '1'; + } + if ($('#haproxy').is(':checked')) { + haproxy = '1'; + } + if ($('#nginx').is(':checked')) { + nginx = '1'; + } + if ($('#apache').is(':checked')) { + apache = '1'; + } + if ($('#firewall').is(':checked')) { + firewall = '1'; + } + if ($('#add_to_smon').is(':checked')) { + add_to_smon = '1'; + } + let allFields = $([]).add($('#new-server-add')).add($('#new-ip')).add($('#new-port')) + allFields.removeClass("ui-state-error"); + valid = valid && checkLength($('#new-server-add'), "Hostname", 1); + valid = valid && checkLength($('#new-ip'), "IP", 1); + valid = valid && checkLength($('#new-port'), "Port", 1); + if (cred == null) { + toastr.error('First select credentials'); + return false; + } + if (server_group === '------') { + toastr.error('First select a group'); + return false; + } + if (server_group === undefined || server_group === null) { + server_group = $('#new-sshgroup').val(); + } + if (valid) { + let json_data = { + "name": servername, + "ip": ip, + "port": $('#new-port').val(), + "group": server_group, + "type_ip": type_ip, + "haproxy": haproxy, + 'nginx': nginx, + "apache": apache, + "firewall": firewall, + "add_to_smon": add_to_smon, + "enable": enable, + "slave": $('#slavefor').val(), + "cred": cred, + "desc": $('#desc').val(), + "protected": 0 + } + $.ajax({ + url: "/app/server", + type: "POST", + data: JSON.stringify(json_data), + contentType: "application/json; charset=utf-8", + success: function (data) { + if (data.status === 'failed') { + toastr.error(data.error); + } else { + common_ajax_action_after_success(dialog_id, 'newserver', 'ajax-servers', data.data); + $("input[type=submit], button").button(); + $("input[type=checkbox]").checkboxradio(); + $(".controlgroup").controlgroup(); + $("select").selectmenu(); + let id = data.id; + $('select:regex(id, git-server)').append('').selectmenu("refresh"); + $('select:regex(id, backup-server)').append('').selectmenu("refresh"); + $('select:regex(id, haproxy_exp_addserv)').append('').selectmenu("refresh"); + $('select:regex(id, nginx_exp_addserv)').append('').selectmenu("refresh"); + $('select:regex(id, apache_exp_addserv)').append('').selectmenu("refresh"); + $('select:regex(id, node_exp_addserv)').append('').selectmenu("refresh"); + $('select:regex(id, geoipserv)').append('').selectmenu("refresh"); + $('select:regex(id, haproxyaddserv)').append('').selectmenu("refresh"); + $('select:regex(id, nginxaddserv)').append('').selectmenu("refresh"); + $('select:regex(id, apacheaddserv)').append('').selectmenu("refresh"); + after_server_creating(servername, ip, scan_server); + } + } + }); + } +} +function after_server_creating(servername, ip, scan_server) { + let json_data = { + "name": servername, + "ip": ip, + "scan_server": scan_server + } + $.ajax({ + url: "/app/server", + data: JSON.stringify(json_data), + contentType: "application/json; charset=utf-8", + type: "PATCH", + success: function (data) { + data = data.replace(/\s+/g, ' '); + if (data.indexOf('You should install lshw on the server') != '-1') { + toastr.error(data); + } else if (data.indexOf('error:') != '-1') { + toastr.error(data); + } + } + }); +} +function updateServer(id) { + toastr.clear(); + let type_ip = 0; + let enable = 0; + let firewall = 0; + let protected_serv = 0; + if ($('#typeip-' + id).is(':checked')) { + type_ip = '1'; + } + if ($('#enable-' + id).is(':checked')) { + enable = '1'; + } + if ($('#firewall-' + id).is(':checked')) { + firewall = '1'; + } + if ($('#protected-' + id).is(':checked')) { + protected_serv = '1'; + } + let group = $('#servergroup-' + id + ' option:selected').val(); + if (group === undefined || group === null) { + group = $('#new-sshgroup').val(); + } + let json_data = { + "name": $('#hostname-' + id).val(), + "port": $('#port-' + id).val(), + "group": group, + "type_ip": type_ip, + "firewall": firewall, + "enable": enable, + "slave": $('#slavefor-' + id + ' option:selected').val(), + "cred": $('#credentials-' + id + ' option:selected').val(), + "id": id, + "desc": $('#desc-' + id).val(), + "protected": protected_serv + } + $.ajax({ + url: "/app/server", + type: 'PUT', + contentType: "application/json; charset=utf-8", + data: JSON.stringify(json_data), + success: function (data) { + if (data.status === 'failed') { + toastr.error(data.error); + } else { + toastr.clear(); + $("#server-" + id).addClass("update", 1000); + setTimeout(function () { + $("#server-" + id).removeClass("update"); + }, 2500); + } + } + }); +} +function confirmDeleteServer(id) { + $( "#dialog-confirm" ).dialog({ + resizable: false, + height: "auto", + width: 400, + modal: true, + title: delete_word + " " + $('#hostname-' + id).val() + "?", + buttons: [{ + text: delete_word, + click: function () { + $(this).dialog("close"); + removeServer(id); + } + },{ + text: cancel_word, + click: function () { + $(this).dialog("close"); + } + }] + }); +} +function cloneServer(id) { + $( "#add-server-button" ).trigger( "click" ); + if ($('#enable-'+id).is(':checked')) { + $('#enable').prop('checked', true) + } else { + $('#enable').prop('checked', false) + } + if ($('#typeip-'+id).is(':checked')) { + $('#typeip').prop('checked', true) + } else { + $('#typeip').prop('checked', false) + } + if ($('#haproxy-'+id).is(':checked')) { + $('#haproxy').prop('checked', true) + } else { + $('#haproxy').prop('checked', false) + } + if ($('#nginx-'+id).is(':checked')) { + $('#nginx').prop('checked', true) + } else { + $('#nginx').prop('checked', false) + } + $('#enable').checkboxradio("refresh"); + $('#typeip').checkboxradio("refresh"); + $('#haproxy').checkboxradio("refresh"); + $('#nginx').checkboxradio("refresh"); + $('#new-server-add').val($('#hostname-'+id).val()) + $('#new-ip').val($('#ip-'+id).val()) + $('#new-port').val($('#port-'+id).val()) + $('#desc').val($('#desc-'+id).val()) + $('#slavefor').val($('#slavefor-'+id+' option:selected').val()).change() + $('#slavefor').selectmenu("refresh"); + $('#credentials').val($('#credentials-'+id+' option:selected').val()).change() + $('#credentials').selectmenu("refresh"); + if (cur_url[0].indexOf('admin') != '-1') { + $('#new-server-group-add').val($('#servergroup-'+id+' option:selected').val()).change() + $('#new-server-group-add').selectmenu("refresh"); + } +} +function removeServer(id) { + $("#server-" + id).css("background-color", "#f2dede"); + $.ajax({ + url: "/app/server", + type: "DELETE", + data: JSON.stringify({'id': id}), + contentType: "application/json; charset=utf-8", + success: function (data) { + if (data.status === 'failed') { + toastr.error(data.error); + } else { + $("#server-" + id).remove(); + } + } + }); +} +function viewFirewallRules(ip) { + $.ajax({ + url: "/app/server/firewall/" + ip, + success: function (data) { + data = data.replace(/\s+/g, ' '); + if (data.indexOf('danger') != '-1' || data.indexOf('unique') != '-1' || data.indexOf('error: ') != '-1') { + toastr.error(data); + } else { + toastr.clear(); + $("#firewall_rules_body").html(data); + $("#firewall_rules" ).dialog({ + resizable: false, + height: "auto", + width: 860, + modal: true, + title: "Firewall rules", + buttons: { + Close: function() { + $( this ).dialog( "close" ); + $("#firewall_rules_body").html(''); + } + } + }); + } + } + } ); +} +function updateServerInfo(ip, id) { + $.ajax({ + url: "/app/server/system_info/update/" + ip + "/" + id, + success: function (data) { + data = data.replace(/\s+/g, ' '); + if (data.indexOf('error:') != '-1' || data.indexOf('error_code') != '-1') { + toastr.error(data); + } else { + $("#server-info").html(data); + $('#server-info').show(); + $.getScript(awesome); + } + } + }); +} +function showServerInfo(id, ip) { + let server_info = translate_div.attr('data-server_info'); + $.ajax({ + url: "/app/server/system_info/get/" + ip + "/" +id, + success: function (data) { + data = data.replace(/\s+/g, ' '); + if (data.indexOf('error:') != '-1' || data.indexOf('error_code') != '-1') { + toastr.error(data); + } else { + $("#server-info").html(data); + $("#dialog-server-info").dialog({ + resizable: false, + height: "auto", + width: 1000, + modal: true, + title: server_info + " (" + ip + ")", + buttons: [{ + text: close_word, + click: function () { + $(this).dialog("close"); + } + }] + }); + $.getScript(awesome); + } + } + }); +} +function serverIsUp(server_ip, server_id) { + let cur_url = window.location.href.split('/').pop(); + if (cur_url.split('#')[1] == 'servers') { + $.ajax({ + url: "/app/server/check/server/" + server_ip, + success: function (data) { + data = data.replace(/^\s+|\s+$/g, ''); + if (data.indexOf('up') != '-1') { + $('#server_status-' + server_id).removeClass('serverNone'); + $('#server_status-' + server_id).removeClass('serverDown'); + $('#server_status-' + server_id).addClass('serverUp'); + $('#server_status-' + server_id).attr('title', 'Server is reachable'); + } else if (data.indexOf('down') != '-1') { + $('#server_status-' + server_id).removeClass('serverNone'); + $('#server_status-' + server_id).removeClass('serverUp'); + $('#server_status-' + server_id).addClass('serverDown'); + $('#server_status-' + server_id).attr('title', 'Server is unreachable'); + } else { + $('#server_status-' + server_id).removeClass('serverDown'); + $('#server_status-' + server_id).removeClass('serverUp'); + $('#server_status-' + server_id).addClass('serverNone'); + $('#server_status-' + server_id).attr('title', 'Cannot get server status'); + } + } + }); + } +} +function openChangeServerServiceDialog(server_id) { + let user_groups_word = translate_div.attr('data-user_groups'); + let hostname = $('#hostname-' + server_id).val(); + $.ajax({ + url: "/app/server/services/" + server_id, + success: function (data) { + $("#groups-roles").html(data); + $("#groups-roles").dialog({ + resizable: false, + height: "auto", + width: 700, + modal: true, + title: user_groups_word + ' ' + hostname, + buttons: [{ + text: save_word, + click: function () { + changeServerServices(server_id); + $(this).dialog("close"); + } + }, { + text: cancel_word, + click: function () { + $(this).dialog("close"); + } + }] + }); + } + }); +} +function addServiceToServer(service_id) { + let service_name = $('#add_service-'+service_id).attr('data-service_name'); + let length_tr = $('#checked_services tbody tr').length; + let tr_class = 'odd'; + if (length_tr % 2 != 0) { + tr_class = 'even'; + } + let html_tag = '' + + ''+service_name+'' + + '-'; + $('#add_service-'+service_id).remove(); + $("#checked_services tbody").append(html_tag); +} +function removeServiceFromServer(service_id) { + let service_name = $('#remove_service-'+service_id).attr('data-service_name'); + let length_tr = $('#all_services tbody tr').length; + let tr_class = 'odd'; + if (length_tr % 2 != 0) { + tr_class = 'even'; + } + let html_tag = '' + + ''+service_name+'' + + '+'; + $('#remove_service-'+service_id).remove(); + $("#all_services tbody").append(html_tag); +} +function changeServerServices(server_id) { + let jsonData = {}; + $('#checked_services tbody tr').each(function () { + let this_id = $(this).attr('id').split('-')[1]; + jsonData[this_id] = 1 + }); + $('#all_services tbody tr').each(function () { + let this_id = $(this).attr('id').split('-')[1]; + jsonData[this_id] = 0 + }); + $.ajax({ + url: "/app/server/services/" + server_id, + data: { + jsonDatas: JSON.stringify(jsonData), + changeServerServicesServer: $('#hostname-' + server_id).val(), + }, + type: "POST", + success: function (data) { + if (data.indexOf('error:') != '-1' || data.indexOf('Failed') != '-1') { + toastr.error(data); + } else { + $("#server-" + server_id).addClass("update", 1000); + setTimeout(function () { + $("#server-" + server_id).removeClass("update"); + }, 2500); + } + } + }); +} diff --git a/app/static/js/admin/ssh.js b/app/static/js/admin/ssh.js index fbc35a01..801bce8c 100644 --- a/app/static/js/admin/ssh.js +++ b/app/static/js/admin/ssh.js @@ -118,7 +118,6 @@ function updateSSH(id) { ssh_enable = '1'; } let group = $('#sshgroup-' + id).val(); - console.log('group' + group) if (group === undefined || group === null) { group = $('#new-sshgroup').val(); } diff --git a/app/static/js/variables.js b/app/static/js/variables.js index 46fe4e5f..3ff5b9a7 100644 --- a/app/static/js/variables.js +++ b/app/static/js/variables.js @@ -18,4 +18,4 @@ const script = `${scriptPath}/script.js`; const overview = `${scriptPath}/overview.js`; const configShow = `${scriptPath}/configshow.js`; const awesome = `${scriptPath}/fontawesome.min.js`; -const ha = `${scriptPath}/js/ha.js`; +const ha = `${scriptPath}/ha.js`; diff --git a/app/templates/admin.html b/app/templates/admin.html index d95627e9..be23a494 100644 --- a/app/templates/admin.html +++ b/app/templates/admin.html @@ -3,11 +3,13 @@ {% block h2 %}{{lang.words.admin_area|title()}}{% endblock %} {% block content %} {% from 'include/input_macros.html' import input, select, copy_to_clipboard, checkbox %} + + - + - + {% include 'include/del_confirm.html' %}
    diff --git a/app/templates/checker.html b/app/templates/checker.html index 3c4e5459..c12aa1ba 100644 --- a/app/templates/checker.html +++ b/app/templates/checker.html @@ -3,7 +3,6 @@ {% block h2 %} Checker {{ lang.words.settings }} {% endblock %} {% block content %} {% from 'include/input_macros.html' import input, select, copy_to_clipboard, checkbox %} -
    diff --git a/app/templates/ha_cluster.html b/app/templates/ha_cluster.html index 4e92c0b7..7fb74d70 100644 --- a/app/templates/ha_cluster.html +++ b/app/templates/ha_cluster.html @@ -3,7 +3,6 @@ {% block h2 %}{{ lang.ha_page.has }} {% endblock %} {% block content %} {% from 'include/input_macros.html' import input, checkbox, copy_to_clipboard %} - diff --git a/app/templates/include/admin_servers.html b/app/templates/include/admin_servers.html index 8de260dd..e1906553 100644 --- a/app/templates/include/admin_servers.html +++ b/app/templates/include/admin_servers.html @@ -61,8 +61,6 @@ {% endfor %} - {% else %} - {% endif %} {% set id = 'enable-' + server.0|string() %} @@ -134,7 +132,7 @@ {% set id = 'desc-' + server.0|string() %} {% if server.11 is not none %} - {{ input(id, value=server.11, size='20') }} + {{ input(id, value=server.11.replace("'", ''), size='20') }} {% else %} {{ input(id, size='20') }} {% endif %} diff --git a/app/templates/include/admin_ssh.html b/app/templates/include/admin_ssh.html index bbcef943..4095b55b 100644 --- a/app/templates/include/admin_ssh.html +++ b/app/templates/include/admin_ssh.html @@ -4,7 +4,7 @@ {{lang.words.name|title()}} - + SSH {{lang.words.key}} diff --git a/app/templates/logs.html b/app/templates/logs.html index 20b4c4c7..67795f74 100644 --- a/app/templates/logs.html +++ b/app/templates/logs.html @@ -3,7 +3,7 @@ {% block h2 %}{{lang.menu_links.logs.h2}} {{service_name}}{% endblock %} {% block content %} {% from 'include/input_macros.html' import input, checkbox %} - + diff --git a/app/templates/logs_internal.html b/app/templates/logs_internal.html index 3d8f5e18..abb286f8 100644 --- a/app/templates/logs_internal.html +++ b/app/templates/logs_internal.html @@ -3,7 +3,7 @@ {% block h2 %}{{lang.words.internal|title()}} {{lang.words.logs}}{% endblock %} {% block content %} {% from 'include/input_macros.html' import input, checkbox %} - +
    diff --git a/app/templates/smon/dashboard.html b/app/templates/smon/dashboard.html index a7e88a4d..93733839 100644 --- a/app/templates/smon/dashboard.html +++ b/app/templates/smon/dashboard.html @@ -4,7 +4,6 @@ {% from 'include/input_macros.html' import input, checkbox, select %} {% block content %} -