diff --git a/api/api_funct.py b/api/api_funct.py index 44e047de..118b3687 100644 --- a/api/api_funct.py +++ b/api/api_funct.py @@ -785,7 +785,7 @@ def create_ssh(): token = request.headers.get('token') login, group_id, role_id = user_sql.get_username_group_id_from_api_token(token) try: - ssh_mod.create_ssh_cread_api(name, enable, group_id, username, password) + ssh_mod.create_ssh_cred_api(name, enable, group_id, username, password) data = {'status': 'done'} except Exception as e: data = {'status': f'error: {e}'} diff --git a/app/create_db.py b/app/create_db.py index ee184cc8..93a70df8 100644 --- a/app/create_db.py +++ b/app/create_db.py @@ -155,7 +155,7 @@ def default_values(): {'service_id': 3, 'service': 'Keepalived', 'slug': 'keepalived'}, {'service_id': 4, 'service': 'Apache', 'slug': 'apache'}, {'service_id': 5, 'service': 'HA cluster', 'slug': 'cluster'}, - {'service_id': 6, 'service': 'UDP balancing', 'slug': 'udp'}, + {'service_id': 6, 'service': 'UDP listener', 'slug': 'udp'}, ] try: diff --git a/app/modules/config/config.py b/app/modules/config/config.py index 79dde53a..20642f5e 100644 --- a/app/modules/config/config.py +++ b/app/modules/config/config.py @@ -66,7 +66,7 @@ def get_config(server_ip, cfg, service='haproxy', **kwargs): """ config_path = '' - if service in ('keepalived', 'haproxy'): + if service in ('keepalived', 'haproxy') and not kwargs.get("waf"): config_path = sql.get_setting(f'{service}_config_path') elif service in ('nginx', 'apache'): config_path = _replace_config_path_to_correct(kwargs.get('config_file_name')) diff --git a/app/modules/db/group.py b/app/modules/db/group.py index ddd20d33..f22b7e02 100644 --- a/app/modules/db/group.py +++ b/app/modules/db/group.py @@ -18,16 +18,14 @@ def select_groups(**kwargs): return query_res -def add_group(name, description): +def add_group(name: str, description: str) -> int: try: - last_insert = Groups.insert(name=name, description=description) - last_insert_id = last_insert.execute() + last_id = Groups.insert(name=name, description=description).execute() except Exception as e: out_error(e) - return False else: - add_setting_for_new_group(last_insert_id) - return True + add_setting_for_new_group(last_id) + return last_id def add_setting_for_new_group(group_id): diff --git a/app/modules/db/user.py b/app/modules/db/user.py index e6bbf683..f1bd7dad 100644 --- a/app/modules/db/user.py +++ b/app/modules/db/user.py @@ -6,12 +6,12 @@ from app.modules.db.common import out_error import app.modules.roxy_wi_tools as roxy_wi_tools -def add_user(user, email, password, role, activeuser, group): +def add_user(user, email, password, role, enabled, group): if password != 'aduser': try: hashed_pass = roxy_wi_tools.Tools.get_hash(password) last_id = User.insert( - username=user, email=email, password=hashed_pass, role=role, activeuser=activeuser, groups=group + username=user, email=email, password=hashed_pass, role=role, activeuser=enabled, groups=group ).execute() except Exception as e: out_error(e) @@ -20,7 +20,7 @@ def add_user(user, email, password, role, activeuser, group): else: try: last_id = User.insert( - username=user, email=email, role=role, ldap_user=1, activeuser=activeuser, groups=group + username=user, email=email, role=role, ldap_user=1, activeuser=enabled, groups=group ).execute() except Exception as e: out_error(e) diff --git a/app/modules/db/waf.py b/app/modules/db/waf.py index a2c23239..00ec124c 100644 --- a/app/modules/db/waf.py +++ b/app/modules/db/waf.py @@ -318,5 +318,3 @@ def update_waf_metrics_enable(name, enable): Waf.update(metrics=enable).where(Waf.server_id == server_id).execute() except Exception as e: out_error(e) - else: - return 'ok' diff --git a/app/modules/roxywi/common.py b/app/modules/roxywi/common.py index d5f87195..4ecb0a74 100644 --- a/app/modules/roxywi/common.py +++ b/app/modules/roxywi/common.py @@ -167,7 +167,7 @@ def keep_action_history(service: str, action: str, server_ip: str, login: str, u hostname = ha_sql.select_cluster_name(int(server_id)) except Exception as e: logging('Roxy-WI server', f'Cannot get info about cluster {server_ip} for history: {e}', roxywi=1) - elif service == 'UDP Listener': + elif service == 'UDP listener': try: server_id = int(server_ip) listener = udp_sql.get_listener(server_id) @@ -317,3 +317,8 @@ def handle_exceptions(ex: Exception, server_ip: str, message: str, **kwargs: Any """ logging(server_ip, f'error: {message}: {ex}', **kwargs) raise Exception(f'error: {message}: {ex}') + + +def handle_json_exceptions(ex: Exception, server_ip: str, message: str, **kwargs: Any) -> dict: + logging(server_ip, f'error: {message}: {ex}', roxywi=1, login=1, **kwargs) + return {'status': 'failed', 'error': f'{message}: {ex}'} diff --git a/app/modules/roxywi/group.py b/app/modules/roxywi/group.py index 04ed535c..2933a37c 100644 --- a/app/modules/roxywi/group.py +++ b/app/modules/roxywi/group.py @@ -2,16 +2,15 @@ import app.modules.db.group as group_sql import app.modules.roxywi.common as roxywi_common -def update_group(group_id: int, group_name: str, desc: str) -> str: +def update_group(group_id: int, group_name: str, desc: str) -> None: if group_name == '': return roxywi_common.return_error_message() else: try: group_sql.update_group(group_name, desc, group_id) roxywi_common.logging('Roxy-WI server', f'The {group_name} has been updated', roxywi=1, login=1) - return 'ok' except Exception as e: - return f'error: {e}' + raise Exception(e) def delete_group(group_id: int) -> str: diff --git a/app/modules/roxywi/user.py b/app/modules/roxywi/user.py index 3bae0c60..728d5efc 100644 --- a/app/modules/roxywi/user.py +++ b/app/modules/roxywi/user.py @@ -9,10 +9,9 @@ import app.modules.roxywi.common as roxywi_common import app.modules.tools.alerting as alerting -def create_user(new_user: str, email: str, password: str, role: int, activeuser: int, group: int) -> None: +def create_user(new_user: str, email: str, password: str, role: int, enabled: int, group: int) -> int: try: - user_id = user_sql.add_user(new_user, email, password, role, activeuser, group) - # user_sql.update_user_role(user_id, group, role) + user_id = user_sql.add_user(new_user, email, password, role, enabled, group) roxywi_common.logging(f'a new user {new_user}', 'has been created', roxywi=1, login=1) try: user_sql.update_user_role(user_id, group, role) @@ -32,8 +31,10 @@ def create_user(new_user: str, email: str, password: str, role: int, activeuser: except Exception as e: roxywi_common.handle_exceptions(e, 'Roxy-WI server', 'Cannot create a new user', roxywi=1, login=1) + return user_id -def delete_user(user_id: int) -> str: + +def delete_user(user_id: int): if user_sql.is_user_super_admin(user_id): count_super_admin_users = user_sql.get_super_admin_count() if count_super_admin_users < 2: @@ -45,7 +46,6 @@ def delete_user(user_id: int) -> str: if user_sql.delete_user(user_id): user_sql.delete_user_groups(user_id) roxywi_common.logging(username, ' has been deleted user ', roxywi=1, login=1) - return "ok" def update_user(email, new_user, user_id, enabled, group_id, role_id): @@ -81,7 +81,7 @@ def get_user_services(user_id: int) -> str: ) -def change_user_services(user: str, user_id: int, user_services: str) -> str: +def change_user_services(user: str, user_id: int, user_services: dict): services = '' for _k, v in user_services.items(): @@ -91,9 +91,8 @@ def change_user_services(user: str, user_id: int, user_services: str) -> str: try: user_sql.update_user_services(services=services, user_id=user_id) except Exception as e: - return f'error: Cannot save: {e}' + raise Exception(f'error: Cannot save: {e}') roxywi_common.logging('Roxy-WI server', f'Access to the services has been updated for user: {user}', roxywi=1, login=1) - return 'ok' def change_user_active_group(group_id: int, user_uuid: str) -> str: diff --git a/app/modules/roxywi/waf.py b/app/modules/roxywi/waf.py index 59bb65bf..14430208 100644 --- a/app/modules/roxywi/waf.py +++ b/app/modules/roxywi/waf.py @@ -71,7 +71,7 @@ def waf_overview(serv, waf_service) -> str: return render_template('ajax/overviewWaf.html', service_status=servers_sorted, role=role, waf_service=waf_service, lang=lang) -def change_waf_mode(waf_mode: str, server_hostname: str, service: str) -> str: +def change_waf_mode(waf_mode: str, server_hostname: str, service: str): serv = server_sql.select_server_by_name(server_hostname) if service == 'haproxy': @@ -88,10 +88,8 @@ def change_waf_mode(waf_mode: str, server_hostname: str, service: str) -> str: roxywi_common.logging(serv, f'Has been changed WAF mod to {waf_mode}', roxywi=1, login=1) - return 'ok' - -def switch_waf_rule(serv: str, enable: int, rule_id: int) -> str: +def switch_waf_rule(serv: str, enable: int, rule_id: int): haproxy_path = sql.get_setting('haproxy_dir') rule_file = waf_sql.select_waf_rule_by_id(rule_id) conf_file_path = haproxy_path + '/waf/modsecurity.conf' @@ -111,13 +109,13 @@ def switch_waf_rule(serv: str, enable: int, rule_id: int) -> str: pass waf_sql.update_enable_waf_rules(rule_id, serv, enable) - return server_mod.ssh_command(serv, cmd) + server_mod.ssh_command(serv, cmd) -def create_waf_rule(serv, service) -> str: - new_waf_rule = common.checkAjaxInput(request.form.get('new_waf_rule')) - new_rule_desc = common.checkAjaxInput(request.form.get('new_rule_description')) - rule_file = common.checkAjaxInput(request.form.get('new_rule_file')) +def create_waf_rule(serv: str, service: str, json_data: dict) -> int: + new_waf_rule = common.checkAjaxInput(json_data['new_waf_rule']) + new_rule_desc = common.checkAjaxInput(json_data['new_rule_description']) + rule_file = common.checkAjaxInput(json_data['new_rule_file']) rule_file = f'{rule_file}.conf' waf_path = '' @@ -131,7 +129,7 @@ def create_waf_rule(serv, service) -> str: cmd = f"sudo echo Include {rule_file_path} >> {conf_file_path} && sudo touch {rule_file_path}" server_mod.ssh_command(serv, cmd) - waf_sql.insert_new_waf_rule(new_waf_rule, rule_file, new_rule_desc, service, serv) + last_id = waf_sql.insert_new_waf_rule(new_waf_rule, rule_file, new_rule_desc, service, serv) try: roxywi_common.logging('WAF', f' A new rule has been created {rule_file} on the server {serv}', @@ -139,4 +137,4 @@ def create_waf_rule(serv, service) -> str: except Exception: pass - return 'ok' + return last_id diff --git a/app/modules/server/ssh.py b/app/modules/server/ssh.py index 14db2cc6..09596964 100644 --- a/app/modules/server/ssh.py +++ b/app/modules/server/ssh.py @@ -63,15 +63,13 @@ def ssh_connect(server_ip): return ssh -def create_ssh_cred() -> str: - name = common.checkAjaxInput(request.form.get('new_ssh')) - enable = common.checkAjaxInput(request.form.get('ssh_enable')) - group = common.checkAjaxInput(request.form.get('new_group')) +def create_ssh_cred(json_data: dict) -> dict: + name = common.checkAjaxInput(json_data['ssh']) + enable = int(json_data['enabled']) + group = common.checkAjaxInput(json_data['group']) group_name = group_sql.get_group_name_by_id(group) - username = common.checkAjaxInput(request.form.get('ssh_user')) - password = common.checkAjaxInput(request.form.get('ssh_pass')) - page = common.checkAjaxInput(request.form.get('page')) - page = page.split("#")[0] + username = common.checkAjaxInput(json_data['user']) + password = common.checkAjaxInput(json_data['pass']) lang = roxywi_common.get_user_lang_for_flask() name = f'{name}_{group_name}' @@ -83,16 +81,17 @@ def create_ssh_cred() -> str: if username is None or name is None: return error_mess - else: - try: - cred_sql.insert_new_ssh(name, enable, group, username, password) - except Exception as e: - roxywi_common.handle_exceptions(e, 'Roxy-WI server', 'Cannot create new SSH credentials', roxywi=1, login=1) - roxywi_common.logging('Roxy-WI server', f'New SSH credentials {name} has been created', roxywi=1, login=1) - return render_template('ajax/new_ssh.html', groups=group_sql.select_groups(), sshs=cred_sql.select_ssh(name=name), page=page, lang=lang) + + try: + last_id = cred_sql.insert_new_ssh(name, enable, group, username, password) + except Exception as e: + roxywi_common.handle_exceptions(e, 'Roxy-WI server', 'Cannot create new SSH credentials', roxywi=1, login=1) + roxywi_common.logging('Roxy-WI server', f'New SSH credentials {name} has been created', roxywi=1, login=1) + rendered_template = render_template('ajax/new_ssh.html', groups=group_sql.select_groups(), sshs=cred_sql.select_ssh(name=name), lang=lang) + return {'id': last_id, 'template': rendered_template} -def create_ssh_cread_api(name: str, enable: str, group: str, username: str, password: str) -> bool: +def create_ssh_cred_api(name: str, enable: str, group: str, username: str, password: str) -> bool: group_name = group_sql.get_group_name_by_id(group) name = common.checkAjaxInput(name) name = f'{name}_{group_name}' @@ -117,7 +116,7 @@ def create_ssh_cread_api(name: str, enable: str, group: str, username: str, pass roxywi_common.handle_exceptions(e, 'Roxy-WI server', f'Cannot create SSH credentials {name}', roxywi=1) -def upload_ssh_key(name: str, user_group: str, key: str, passphrase: str) -> str: +def upload_ssh_key(name: str, user_group: int, key: str, passphrase: str) -> str: if '..' in name: raise Exception('error: nice try') @@ -172,13 +171,13 @@ def upload_ssh_key(name: str, user_group: str, key: str, passphrase: str) -> str return f'success: SSH key has been saved into: {ssh_keys}' -def update_ssh_key() -> str: - ssh_id = common.checkAjaxInput(request.form.get('id')) - name = common.checkAjaxInput(request.form.get('name')) - enable = common.checkAjaxInput(request.form.get('ssh_enable')) - group = common.checkAjaxInput(request.form.get('group')) - username = common.checkAjaxInput(request.form.get('ssh_user')) - password = common.checkAjaxInput(request.form.get('ssh_pass')) +def update_ssh_key(json_data: dict): + ssh_id = int(json_data['id']) + name = common.checkAjaxInput(json_data['name']) + enable = common.checkAjaxInput(json_data['ssh_enable']) + group = int(json_data['group']) + username = common.checkAjaxInput(json_data['ssh_user']) + password = common.checkAjaxInput(json_data['ssh_pass']) new_ssh_key_name = '' ssh_key_name = '' ssh_enable = 0 @@ -206,8 +205,6 @@ def update_ssh_key() -> str: cred_sql.update_ssh(ssh_id, name, enable, group, username, password) roxywi_common.logging('Roxy-WI server', f'The SSH credentials {name} has been updated ', roxywi=1, login=1) - return 'ok' - def delete_ssh_key(ssh_id) -> str: lib_path = get_config.get_config_var('main', 'lib_path') diff --git a/app/routes/main/routes.py b/app/routes/main/routes.py index 98652438..1d45cbf5 100644 --- a/app/routes/main/routes.py +++ b/app/routes/main/routes.py @@ -160,11 +160,11 @@ def service_history(service, server_ip): history = '' server_ip = common.checkAjaxInput(server_ip) - if service in ('haproxy', 'nginx', 'keepalived', 'apache', 'cluster'): + if service in ('haproxy', 'nginx', 'keepalived', 'apache', 'cluster', 'udp'): service_desc = service_sql.select_service(service) if not roxywi_auth.is_access_permit_to_service(service_desc.slug): abort(403, f'You do not have needed permissions to access to {service_desc.slug.title()} service') - if service == 'cluster': + if service in ('cluster', 'udp'): server_id = server_ip else: server_id = server_sql.select_server_id_by_ip(server_ip) diff --git a/app/routes/server/routes.py b/app/routes/server/routes.py index 298fd4b9..abbb0134 100644 --- a/app/routes/server/routes.py +++ b/app/routes/server/routes.py @@ -1,6 +1,6 @@ import json -from flask import render_template, request, g +from flask import render_template, request, g, jsonify, abort from flask_login import login_required from app.routes.server import bp @@ -187,67 +187,80 @@ def delete_server(server_id): return server_mod.delete_server(server_id) -@bp.route('/group/create', methods=['POST']) +@bp.route('/group', methods=['POST', 'PUT', 'DELETE']) def create_group(): roxywi_auth.page_for_admin() - newgroup = common.checkAjaxInput(request.form.get('groupname')) - desc = common.checkAjaxInput(request.form.get('newdesc')) - if newgroup == '': - return error_mess - else: + json_data = request.get_json() + if request.method == 'POST': + name = json_data.get('name') + desc = json_data.get('desc') + if name == '': + return error_mess try: - if group_sql.add_group(newgroup, desc): - roxywi_common.logging('Roxy-WI server', f'A new group {newgroup} has been created', roxywi=1, login=1) - return render_template('ajax/new_group.html', groups=group_sql.select_groups(group=newgroup)) + last_id = group_sql.add_group(name, desc) + roxywi_common.logging('Roxy-WI server', f'A new group {name} has been created', roxywi=1, login=1) + return jsonify({ + 'status': 'created', + 'id': last_id, + 'data': render_template('ajax/new_group.html', groups=group_sql.select_groups(group=name))} + ) except Exception as e: - return str(e) + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', 'Cannot create a new group') + elif request.method == 'PUT': + name = json_data.get('name') + desc = json_data.get('desc') + group_id = json_data.get('group_id') + try: + group_mod.update_group(group_id, name, desc) + return jsonify({'status': 'updated'}) + except Exception as e: + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', f'Cannot update group {name}') + elif request.method == 'DELETE': + group_id = json_data.get('group_id') + try: + group_mod.delete_group(group_id) + 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('/group/update', methods=['POST']) -def update_group(): - roxywi_auth.page_for_admin() - name = common.checkAjaxInput(request.form.get('updategroup')) - desc = common.checkAjaxInput(request.form.get('descript')) - group_id = common.checkAjaxInput(request.form.get('id')) - - return group_mod.update_group(group_id, name, desc) - - -@bp.route('/group/delete/') -def delete_group(group_id): - roxywi_auth.page_for_admin() - return group_mod.delete_group(group_id) - - -@bp.route('/ssh/create', methods=['POST']) +@bp.route('/ssh', methods=['POST', 'PUT', 'DELETE', 'PATCH']) +@get_user_params() def create_ssh(): roxywi_auth.page_for_admin(level=2) - return ssh_mod.create_ssh_cred() + json_data = request.get_json() + if request.method == 'POST': + try: + 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') + 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') + 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') + elif request.method == 'PATCH': + user_group = roxywi_common.get_user_group() + name = common.checkAjaxInput(json_data['name']) + passphrase = common.checkAjaxInput(json_data['pass']) + key = json_data['ssh_cert'] - -@bp.route('/ssh/delete/') -def delete_ssh(ssh_id): - roxywi_auth.page_for_admin(level=2) - return ssh_mod.delete_ssh_key(ssh_id) - - -@bp.route('/ssh/update', methods=['POST']) -def update_ssh(): - roxywi_auth.page_for_admin(level=2) - return ssh_mod.update_ssh_key() - - -@bp.route('/ssh/upload', methods=['POST']) -def upload_ssh_key(): - user_group = roxywi_common.get_user_group() - name = common.checkAjaxInput(request.form.get('name')) - passphrase = common.checkAjaxInput(request.form.get('pass')) - key = request.form.get('ssh_cert') - - try: - return ssh_mod.upload_ssh_key(name, user_group, key, passphrase) - except Exception as e: - return str(e) + try: + 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') @bp.app_template_filter('string_to_dict') diff --git a/app/routes/udp/routes.py b/app/routes/udp/routes.py index c7e87740..e9872f19 100644 --- a/app/routes/udp/routes.py +++ b/app/routes/udp/routes.py @@ -38,16 +38,21 @@ def listener_funct(service): elif request.method == 'POST': json_data = request.get_json() json_data['group_id'] = g.user_params['group_id'] + listener_name = json_data['new-listener-name'] try: listener_id = udp_mod.create_listener(json_data) + roxywi_common.logging(listener_id, f'UDP listener {listener_name} has been created', roxywi=1, keep_history=1, login=1, service='UDP listener') return jsonify({'status': 'created', 'listener_id': listener_id}) except Exception as e: - return jsonify({'status': 'failed', 'error': str(e)}) + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server','Cannot create UDP listener') elif request.method == 'PUT': json_data = request.get_json() json_data['group_id'] = g.user_params['group_id'] + listener_name = json_data['new-listener-name'] + listener_id = json_data['listener_id'] try: udp_mod.update_listener(json_data) + roxywi_common.logging(listener_id, f'UDP listener {listener_name} has been updated', roxywi=1, keep_history=1, login=1, service='UDP listener') return jsonify({'status': 'updated'}), 201 except Exception as e: return jsonify({'status': 'failed', 'error': str(e)}) @@ -57,13 +62,14 @@ def listener_funct(service): try: inv, server_ips = service_mod.generate_udp_inv(listener_id, 'uninstall') service_mod.run_ansible(inv, server_ips, f'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 jsonify({'status': 'failed', 'error': str(e)}) + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server',f'Cannot create inventory for UDP listener deleting {listener_id}') try: udp_sql.delete_listener(listener_id) return jsonify({'status': 'deleted'}), 201 except Exception as e: - return jsonify({'status': 'failed', 'error': str(e)}) + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server',f'Cannot delete UDP listener {listener_id}') @bp.get('//listener/') @@ -100,6 +106,7 @@ def get_listener_settings(service, listener_id): def action_with_listener(service, listener_id, action): try: udp_mod.listener_actions(listener_id, action, g.user_params['group_id']) + roxywi_common.logging(listener_id, f'UDP listener {listener_id} has been {action}ed', roxywi=1, keep_history=1, login=1, service='UDP listener') return jsonify({'status': 'done'}) except Exception as e: - return jsonify({'status': 'failed', 'error': str(e)}) + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server',f'Cannot {action} listener') diff --git a/app/routes/user/routes.py b/app/routes/user/routes.py index 03abff6f..ea9ed84f 100644 --- a/app/routes/user/routes.py +++ b/app/routes/user/routes.py @@ -1,6 +1,6 @@ import json -from flask import render_template, request +from flask import render_template, request, jsonify, g, abort from flask_login import login_required from app.routes.user import bp @@ -21,70 +21,56 @@ def before_request(): pass -@bp.post('/create') +@bp.route('', methods=['POST', 'PUT', 'DELETE']) @get_user_params() def create_user(): roxywi_auth.page_for_admin(level=2) - email = common.checkAjaxInput(request.form.get('newemail')) - password = common.checkAjaxInput(request.form.get('newpassword')) - role = common.checkAjaxInput(request.form.get('newrole')) - new_user = common.checkAjaxInput(request.form.get('newusername')) - page = common.checkAjaxInput(request.form.get('page')) - activeuser = common.checkAjaxInput(request.form.get('activeuser')) - group = common.checkAjaxInput(request.form.get('newgroupuser')) - lang = roxywi_common.get_user_lang_for_flask() + json_data = request.get_json() - if not roxywi_common.check_user_group_for_flask(): - return 'error: Wrong group' - if page == 'servers': - if roxywi_auth.is_admin(level=2, role_id=role): - roxywi_common.logging(new_user, ' tried to privilege escalation: user creation', roxywi=1, login=1) - return 'error: Wrong role' - try: - roxywi_user.create_user(new_user, email, password, role, activeuser, group) - except Exception as e: - return str(e) - else: - return render_template( - 'ajax/new_user.html', users=user_sql.select_users(user=new_user), groups=group_sql.select_groups(), page=page, - roles=sql.select_roles(), adding=1, lang=lang - ) - - -@bp.post('/update') -def update_user(): - roxywi_auth.page_for_admin(level=2) - email = request.form.get('email') - new_user = request.form.get('updateuser') - user_id = request.form.get('id') - enabled = request.form.get('activeuser') - group_id = int(request.form.get('usergroup')) - - if roxywi_common.check_user_group_for_flask(): - if request.form.get('role'): - role_id = int(request.form.get('role')) - if roxywi_auth.is_admin(level=role_id): - roxywi_user.update_user(email, new_user, user_id, enabled, group_id, role_id) - else: - roxywi_common.logging(new_user, ' tried to privilege escalation', roxywi=1, login=1) - return 'error: dalsd' + if request.method == 'POST': + email = common.checkAjaxInput(json_data['email']) + password = common.checkAjaxInput(json_data['password']) + role = int(json_data['role']) + new_user = common.checkAjaxInput(json_data['username']) + enabled = int(json_data['enabled']) + group_id = int(json_data['user_group']) + lang = roxywi_common.get_user_lang_for_flask() + current_user_role_id = g.user_params['role'] + if not roxywi_common.check_user_group_for_flask(): + return roxywi_common.handle_json_exceptions('Wrong group', 'Roxy-WI server', '') + if current_user_role_id < role: + return roxywi_common.handle_json_exceptions('Wrong role', 'Roxy-WI server', '') + try: + user_id = roxywi_user.create_user(new_user, email, password, role, enabled, group_id) + except Exception as e: + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', 'Cannot create a new user') else: + return jsonify({'status': 'created', 'id': user_id, 'data': render_template( + 'ajax/new_user.html', users=user_sql.select_users(user=new_user), groups=group_sql.select_groups(), + roles=sql.select_roles(), adding=1, lang=lang + )}) + elif request.method == 'PUT': + user_id = int(json_data['user_id']) + user_name = common.checkAjaxInput(json_data['username']) + email = common.checkAjaxInput(json_data['email']) + enabled = int(json_data['enabled']) + if roxywi_common.check_user_group_for_flask(): try: - user_sql.update_user_from_admin_area(new_user, email, user_id, enabled) + user_sql.update_user_from_admin_area(user_name, email, user_id, enabled) except Exception as e: - return f'error: Cannot update user: {e}' - roxywi_common.logging(new_user, ' has been updated user ', roxywi=1, login=1) - - return 'ok' - - -@bp.route('/delete/') -def delete_user(user_id): - roxywi_auth.page_for_admin(level=2) - try: - return roxywi_user.delete_user(user_id) - except Exception as e: - return f'error: {e}' + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', 'Cannot update user') + roxywi_common.logging(user_name, ' has been updated user ', roxywi=1, login=1) + return jsonify({'status': 'updated'}) + elif request.method == 'DELETE': + roxywi_auth.page_for_admin(level=2) + user_id = int(json_data['user_id']) + try: + roxywi_user.delete_user(user_id) + return jsonify({'status': 'deleted'}) + except Exception as e: + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', f'Cannot delete the user {user_id}') + else: + abort(405) @bp.route('/ldap/') @@ -108,10 +94,14 @@ def show_user_services(user_id): if request.method == 'GET': return roxywi_user.get_user_services(user_id) else: - user = common.checkAjaxInput(request.form.get('changeUserServicesUser')) - user_services = json.loads(request.form.get('jsonDatas')) - - return roxywi_user.change_user_services(user, user_id, user_services) + json_data = request.get_json() + user = json_data['username'] + user_services = json_data['services'] + try: + roxywi_user.change_user_services(user, user_id, user_services) + return jsonify({'status': 'updated'}) + except Exception as e: + return roxywi_common.handle_json_exceptions(e, 'Roxy-WI server', 'Cannot change user services') @bp.route('/group', methods=['GET', 'PUT']) diff --git a/app/routes/waf/routes.py b/app/routes/waf/routes.py index 543ccac8..51e1a772 100644 --- a/app/routes/waf/routes.py +++ b/app/routes/waf/routes.py @@ -1,6 +1,6 @@ import os -from flask import render_template, request, g, abort +from flask import render_template, request, g, abort, jsonify from flask_login import login_required from app.routes.waf import bp @@ -87,6 +87,8 @@ def waf_rules(service, server_ip): @bp.route('///rule/') @get_user_params() def waf_rule_edit(service, server_ip, rule_id): + if service not in ('haproxy', 'nginx'): + abort(404) roxywi_auth.page_for_admin(level=2) if not roxywi_auth.is_access_permit_to_service(service): abort(403, f'You do not have needed permissions to access to {service.title()} service') @@ -100,17 +102,19 @@ def waf_rule_edit(service, server_ip, rule_id): get_date = roxy_wi_tools.GetDate(sql.get_setting('time_zone')) waf_rule_file = waf_sql.select_waf_rule_by_id(rule_id) configs_dir = sql.get_setting('tmp_config_path') - cfg = f"{configs_dir}{server_ip}-{get_date.return_date('config')}-{waf_rule_file}" - error = config_mod.get_config(server_ip, cfg, waf=service, waf_rule_file=waf_rule_file) + try: + cfg = f"{configs_dir}{server_ip}-{get_date.return_date('config')}-{waf_rule_file}" + config_mod.get_config(server_ip, cfg, waf=service, waf_rule_file=waf_rule_file) + except Exception as e: + pass config_file_name = common.return_nice_path(config_path) + 'waf/rules/' + waf_rule_file - config_read = '' try: conf = open(cfg, "r") config_read = conf.read() conf.close() except IOError: - print('Cannot read imported config file') + return f'error: Cannot read imported config file: {e}' kwargs = { 'title': 'Edit a WAF rule', @@ -147,8 +151,8 @@ def waf_save_config(service, server_ip, rule_id): try: with open(cfg, "a") as conf: conf.write(config) - except IOError: - print("error: Cannot read imported config file") + except IOError as e: + return f"error: Cannot read imported config file: {e}" stderr = config_mod.master_slave_upload_and_restart(server_ip, cfg, save, 'waf', oldcfg=oldcfg, config_file_name=config_file_name) @@ -169,32 +173,46 @@ def waf_save_config(service, server_ip, rule_id): def enable_rule(server_ip, rule_id, enable): server_ip = common.is_ip_or_dns(server_ip) - return roxy_waf.switch_waf_rule(server_ip, enable, rule_id) + try: + roxy_waf.switch_waf_rule(server_ip, enable, rule_id) + return jsonify({'status': 'updated'}) + except Exception as e: + return roxywi_common.handle_json_exceptions(e, server_ip, f'Cannot enable WAF rule {rule_id} on server {server_ip}') @bp.route('///rule/create', methods=['POST']) def create_rule(service, server_ip): - if service not in ('haproxy', 'nginx'): - return 'error: Wrong service' - server_ip = common.is_ip_or_dns(server_ip) + json_data = request.get_json() + if service not in ('haproxy', 'nginx'): + return roxywi_common.handle_json_exceptions('Wrong service', server_ip, '') - return roxy_waf.create_waf_rule(server_ip, service) + try: + last_id = roxy_waf.create_waf_rule(server_ip, service, json_data) + return jsonify({'status': 'created', 'id': last_id}) + except Exception as e: + return roxywi_common.handle_json_exceptions(e, server_ip, 'Cannot create WAF rule') @bp.route('//mode//') def change_waf_mode(service, server_name, waf_mode): if service not in ('haproxy', 'nginx'): - return 'error: Wrong service' + return roxywi_common.handle_json_exceptions('Wrong service', server_name, '') server_name = common.checkAjaxInput(server_name) waf_mode = common.checkAjaxInput(waf_mode) - return roxy_waf.change_waf_mode(waf_mode, server_name, service) + try: + roxy_waf.change_waf_mode(waf_mode, server_name, service) + return jsonify({'status': 'updated'}) + except Exception as e: + return roxywi_common.handle_json_exceptions(e, server_name, 'Cannot change WAF mode') @bp.route('/overview//') def overview_waf(service, server_ip): + if service not in ('haproxy', 'nginx'): + abort(404) server_ip = common.is_ip_or_dns(server_ip) if service not in ('haproxy', 'nginx'): @@ -206,4 +224,8 @@ def overview_waf(service, server_ip): @bp.route('/metric/enable//') def enable_metric(enable, server_name): server_name = common.checkAjaxInput(server_name) - return waf_sql.update_waf_metrics_enable(server_name, enable) + try: + waf_sql.update_waf_metrics_enable(server_name, enable) + return jsonify({'status': 'updated'}) + except Exception as e: + return roxywi_common.handle_json_exceptions(e, server_name, 'Cannot enable WAF metrics') diff --git a/app/static/js/admin_settings.js b/app/static/js/admin/admin_settings.js similarity index 100% rename from app/static/js/admin_settings.js rename to app/static/js/admin/admin_settings.js diff --git a/app/static/js/admin/group.js b/app/static/js/admin/group.js new file mode 100644 index 00000000..22bbff8c --- /dev/null +++ b/app/static/js/admin/group.js @@ -0,0 +1,144 @@ +$( function() { + $('#add-group-button').click(function () { + addGroupDialog.dialog('open'); + }); + let group_tabel_title = $("#group-add-table-overview").attr('title'); + let addGroupDialog = $("#group-add-table").dialog({ + autoOpen: false, + resizable: false, + height: "auto", + width: 600, + modal: true, + title: group_tabel_title, + show: { + effect: "fade", + duration: 200 + }, + hide: { + effect: "fade", + duration: 200 + }, + buttons: { + "Add": function () { + addGroup(this); + }, + Cancel: function () { + $(this).dialog("close"); + clearTips(); + } + } + }); + $("#ajax-group input").change(function () { + let id = $(this).attr('id').split('-'); + updateGroup(id[1]) + }); +}); +function addGroup(dialog_id) { + toastr.clear(); + let valid = true; + let allFields = $([]).add($('#new-group-add')); + allFields.removeClass("ui-state-error"); + valid = valid && checkLength($('#new-group-add'), "new group name", 1); + if (valid) { + let jsonData = { + 'name': $('#new-group-add').val(), + 'desc': $('#new-desc').val() + } + $.ajax({ + url: "/app/server/group", + type: 'POST', + data: JSON.stringify(jsonData), + contentType: "application/json; charset=utf-8", + success: function (data) { + if (data.status === 'failed') { + toastr.error(data); + } else { + let id = data.id; + $('select:regex(id, group)').append('').selectmenu("refresh"); + common_ajax_action_after_success(dialog_id, 'newgroup', 'ajax-group', data.data); + } + } + }); + } +} +function updateGroup(id) { + toastr.clear(); + let jsonData = { + "name": $('#name-' + id).val(), + "desc": $('#descript-' + id).val(), + "group_id": id + } + $.ajax({ + url: "/app/server/group", + type: "PUT", + data: JSON.stringify(jsonData), + contentType: "application/json; charset=utf-8", + success: function (data) { + if (data.status === 'failed') { + toastr.error(data); + } else { + toastr.clear(); + $("#group-" + id).addClass("update", 1000); + setTimeout(function () { + $("#group-" + id).removeClass("update"); + }, 2500); + $('select:regex(id, group) option[value=' + id + ']').remove(); + $('select:regex(id, group)').append('').selectmenu("refresh"); + } + } + }); +} +function confirmDeleteGroup(id) { + $( "#dialog-confirm" ).dialog({ + resizable: false, + height: "auto", + width: 400, + modal: true, + title: delete_word+ " " +$('#name-'+id).val() + "?", + buttons: [{ + text: delete_word, + click: function() { + $(this).dialog("close"); + removeGroup(id); + } + }, { + text: cancel_word, + click: function () { + $(this).dialog("close"); + } + }] + }); +} +function removeGroup(id) { + $("#group-" + id).css("background-color", "#f2dede"); + $.ajax({ + url: "/app/server/group", + type: 'DELETE', + data: JSON.stringify({'group_id': id}), + contentType: "application/json; charset=utf-8", + success: function (data) { + if (data.status === 'failed') { + toastr.error(data.error); + } else { + $("#group-" + id).remove(); + $('select:regex(id, group) option[value=' + id + ']').remove(); + $('select:regex(id, group)').selectmenu("refresh"); + } + } + }); +} +function getGroupNameById(group_id) { + let group_name = '' + $.ajax({ + url: "/app/user/group/name/" + group_id, + async: false, + success: function (data) { + if (data.indexOf('error:') != '-1') { + toastr.error(data); + } else { + group_name = data; + } + } + }); + return group_name; +} diff --git a/app/static/js/admin/ssh.js b/app/static/js/admin/ssh.js new file mode 100644 index 00000000..fbc35a01 --- /dev/null +++ b/app/static/js/admin/ssh.js @@ -0,0 +1,238 @@ +$( function() { + $('#add-ssh-button').click(function () { + addCredsDialog.dialog('open'); + }); + let ssh_tabel_title = $("#ssh-add-table-overview").attr('title'); + let addCredsDialog = $("#ssh-add-table").dialog({ + autoOpen: false, + resizable: false, + height: "auto", + width: 600, + modal: true, + title: ssh_tabel_title, + show: { + effect: "fade", + duration: 200 + }, + hide: { + effect: "fade", + duration: 200 + }, + buttons: [{ + text: add_word, + click: function () { + addCreds(this); + } + }, { + text: cancel_word, + click: function () { + $(this).dialog("close"); + clearTips(); + } + }] + }); + $( "#ssh_enable_table input" ).change(function() { + let id = $(this).attr('id').split('-'); + updateSSH(id[1]) + sshKeyEnableShow(id[1]) + }); + $( "#ssh_enable_table select" ).on('selectmenuchange',function() { + let id = $(this).attr('id').split('-'); + updateSSH(id[1]) + sshKeyEnableShow(id[1]) + }); + $('#new-ssh_enable').click(function() { + if ($('#new-ssh_enable').is(':checked')) { + $('#ssh_pass').css('display', 'none'); + } else { + $('#ssh_pass').css('display', 'block'); + } + }); + if ($('#new-ssh_enable').is(':checked')) { + $('#ssh_pass').css('display', 'none'); + } else { + $('#ssh_pass').css('display', 'block'); + } +}); +function addCreds(dialog_id) { + toastr.clear(); + let ssh_add_div = $('#new-ssh-add'); + let ssh_enable = 0; + if ($('#new-ssh_enable').is(':checked')) { + ssh_enable = '1'; + } + let valid = true; + let allFields = $([]).add(ssh_add_div).add($('#ssh_user')) + allFields.removeClass("ui-state-error"); + valid = valid && checkLength(ssh_add_div, "Name", 1); + valid = valid && checkLength($('#ssh_user'), "Credentials", 1); + if (valid) { + let jsonData = { + "ssh": ssh_add_div.val(), + "group": $('#new-sshgroup').val(), + "user": $('#ssh_user').val(), + "pass": $('#ssh_pass').val(), + "enabled": ssh_enable, + } + $.ajax({ + url: "/app/server/ssh", + type: "POST", + data: JSON.stringify(jsonData), + contentType: "application/json; charset=utf-8", + success: function (data) { + if (data.status === 'failed') { + toastr.error(data.error); + } else { + let group_name = getGroupNameById($('#new-sshgroup').val()); + let id = data.id; + common_ajax_action_after_success(dialog_id, 'ssh-table-' + id, 'ssh_enable_table', data.data); + $('select:regex(id, credentials)').append('').selectmenu("refresh"); + $('select:regex(id, ssh-key-name)').append('').selectmenu("refresh"); + $("input[type=submit], button").button(); + $("input[type=checkbox]").checkboxradio(); + $("select").selectmenu(); + } + } + }); + } +} +function sshKeyEnableShow(id) { + $('#ssh_enable-' + id).click(function () { + if ($('#ssh_enable-' + id).is(':checked')) { + $('#ssh_pass-' + id).css('display', 'none'); + } else { + $('#ssh_pass-' + id).css('display', 'block'); + } + }); + if ($('#ssh_enable-' + id).is(':checked')) { + $('#ssh_pass-' + id).css('display', 'none'); + } else { + $('#ssh_pass-' + id).css('display', 'block'); + } +} +function updateSSH(id) { + toastr.clear(); + let ssh_enable = 0; + let ssh_name_val = $('#ssh_name-' + id).val(); + if ($('#ssh_enable-' + id).is(':checked')) { + ssh_enable = '1'; + } + let group = $('#sshgroup-' + id).val(); + console.log('group' + group) + if (group === undefined || group === null) { + group = $('#new-sshgroup').val(); + } + let jsonData = { + "name": ssh_name_val, + "group": group, + "ssh_enable": ssh_enable, + "ssh_user": $('#ssh_user-' + id).val(), + "ssh_pass": $('#ssh_pass-' + id).val(), + "id": id + } + $.ajax({ + url: "/app/server/ssh", + data: JSON.stringify(jsonData), + contentType: "application/json; charset=utf-8", + type: "PUT", + success: function (data) { + if (data.status === 'failed') { + toastr.error(data.error); + } else { + toastr.clear(); + $("#ssh-table-" + id).addClass("update", 1000); + setTimeout(function () { + $("#ssh-table-" + id).removeClass("update"); + }, 2500); + $('select:regex(id, credentials) option[value=' + id + ']').remove(); + $('select:regex(id, ssh-key-name) option[value=' + ssh_name_val + ']').remove(); + $('select:regex(id, credentials)').append('').selectmenu("refresh"); + $('select:regex(id, ssh-key-name)').append('').selectmenu("refresh"); + } + } + }); +} +function confirmDeleteSsh(id) { + $( "#dialog-confirm" ).dialog({ + resizable: false, + height: "auto", + width: 400, + modal: true, + title: delete_word +" " + $('#ssh_name-' + id).val() + "?", + buttons: [{ + text: delete_word, + click: function () { + $(this).dialog("close"); + removeSsh(id); + } + },{ + text: cancel_word, + click: function () { + $(this).dialog("close"); + } + }] + }); +} +function removeSsh(id) { + $("#ssh-table-" + id).css("background-color", "#f2dede"); + $.ajax({ + url: "/app/server/ssh", + 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 { + $("#ssh-table-" + id).remove(); + $('select:regex(id, credentials) option[value=' + id + ']').remove(); + $('select:regex(id, credentials)').selectmenu("refresh"); + } + } + }); +} +function uploadSsh() { + toastr.clear(); + if ($("#ssh-key-name option:selected").val() == "------" || $('#ssh_cert').val() == '') { + toastr.error('All fields must be completed'); + } else { + let jsonData = { + "ssh_cert": $('#ssh_cert').val(), + "name": $('#ssh-key-name').val(), + "pass": $('#ssh-key-pass').val() + } + $.ajax({ + url: "/app/server/ssh", + type: "PATCH", + data: JSON.stringify(jsonData), + contentType: "application/json; charset=utf-8", + success: function (data) { + if (data.status === 'failed') { + toastr.error(data.error); + } else if (data.status === 'uploaded') { + toastr.clear(); + toastr.success(data.message) + } else { + toastr.error('Something wrong, check and try again'); + } + } + }); + } +} +function checkSshConnect(ip) { + $.ajax({ + url: "/app/server/check/ssh/" + ip, + success: function (data) { + if (data.indexOf('error:') != '-1') { + toastr.error(data) + } else if (data.indexOf('failed') != '-1') { + toastr.error(data) + } else if (data.indexOf('Errno') != '-1') { + toastr.error(data) + } else { + toastr.clear(); + toastr.success('Connect is accepted'); + } + } + }); +} diff --git a/app/static/js/overview.js b/app/static/js/overview.js index 9d275448..e4abbe52 100644 --- a/app/static/js/overview.js +++ b/app/static/js/overview.js @@ -1,4 +1,4 @@ -let cur_url = window.location.href.split('/app/').pop(); +var cur_url = window.location.href.split('/app/').pop(); cur_url = cur_url.split('/'); function showHapservers(serv, hostnamea, service) { let i; @@ -213,9 +213,9 @@ $( function() { if (cur_url[0] != 'portscanner') { try { - let service_name = id[2] + var service_name = id[2] } catch (err) { - let service_name = 'haproxy' + var service_name = 'haproxy' } updateHapWIServer(id[1], service_name) @@ -282,8 +282,7 @@ function updateHapWIServer(id, service_name) { name: $('#server-name-' + id).val(), metrics: metrics, alert_en: alert_en, - active: active, - token: $('#token').val() + active: active }, type: "POST", success: function (data) { diff --git a/app/static/js/udp.js b/app/static/js/udp.js index e5182e5e..8bc3d0ec 100644 --- a/app/static/js/udp.js +++ b/app/static/js/udp.js @@ -416,7 +416,6 @@ function clearUdpVip() { } function confirmUdpBalancerAction(action, listener_id) { let action_word = translate_div.attr('data-'+action); - console.log('#litener-name-'+listener_id); let l_name = $('#listener-name-'+listener_id).text(); $( "#dialog-confirm" ).dialog({ resizable: false, diff --git a/app/static/js/users.js b/app/static/js/users.js index d0c3ef49..3b817df7 100644 --- a/app/static/js/users.js +++ b/app/static/js/users.js @@ -1,35 +1,6 @@ var cur_url = window.location.href.split('/app/').pop(); cur_url = cur_url.split('/'); $( function() { - $('#add-group-button').click(function() { - addGroupDialog.dialog('open'); - }); - let group_tabel_title = $( "#group-add-table-overview" ).attr('title'); - let addGroupDialog = $( "#group-add-table" ).dialog({ - autoOpen: false, - resizable: false, - height: "auto", - width: 600, - modal: true, - title: group_tabel_title, - show: { - effect: "fade", - duration: 200 - }, - hide: { - effect: "fade", - duration: 200 - }, - buttons: { - "Add": function() { - addGroup(this); - }, - Cancel: function() { - $( this ).dialog( "close" ); - clearTips(); - } - } - }); $('#add-user-button').click(function() { addUserDialog.dialog('open'); }); @@ -94,38 +65,6 @@ $( function() { } }] }); - $('#add-ssh-button').click(function() { - addCredsDialog.dialog('open'); - }); - let ssh_tabel_title = $( "#ssh-add-table-overview" ).attr('title'); - let addCredsDialog = $( "#ssh-add-table" ).dialog({ - autoOpen: false, - resizable: false, - height: "auto", - width: 600, - modal: true, - title: ssh_tabel_title, - show: { - effect: "fade", - duration: 200 - }, - hide: { - effect: "fade", - duration: 200 - }, - buttons: [{ - text: add_word, - click: function () { - addCreds(this); - } - }, { - text: cancel_word, - click: function () { - $(this).dialog("close"); - clearTips(); - } - }] - }); $( "#ajax-users input" ).change(function() { let id = $(this).attr('id').split('-'); updateUser(id[1]) @@ -134,10 +73,6 @@ $( function() { let id = $(this).attr('id').split('-'); updateUser(id[1]) }); - $( "#ajax-group input" ).change(function() { - let id = $(this).attr('id').split('-'); - updateGroup(id[1]) - }); $( "#ajax-servers input" ).change(function() { let id = $(this).attr('id').split('-'); updateServer(id[1]) @@ -146,28 +81,6 @@ $( function() { let id = $(this).attr('id').split('-'); updateServer(id[1]) }); - $( "#ssh_enable_table input" ).change(function() { - let id = $(this).attr('id').split('-'); - updateSSH(id[1]) - sshKeyEnableShow(id[1]) - }); - $( "#ssh_enable_table select" ).on('selectmenuchange',function() { - let id = $(this).attr('id').split('-'); - updateSSH(id[1]) - sshKeyEnableShow(id[1]) - }); - $('#new-ssh_enable').click(function() { - if ($('#new-ssh_enable').is(':checked')) { - $('#ssh_pass').css('display', 'none'); - } else { - $('#ssh_pass').css('display', 'block'); - } - }); - if ($('#new-ssh_enable').is(':checked')) { - $('#ssh_pass').css('display', 'none'); - } else { - $('#ssh_pass').css('display', 'block'); - } $( "#scan_server" ).change(function() { if ($('#scan_server').is(':checked')) { $('.services_for_scan').hide(); @@ -176,27 +89,28 @@ $( function() { } }); $('#search_ldap_user').click(function() { - let valid = true; toastr.clear(); - allFields = $([]).add($('#new-username')); + let username_div = $('#new-username') + let valid = true; + let allFields = $([]).add(username_div); allFields.removeClass("ui-state-error"); - valid = valid && checkLength($('#new-username'), "user name", 1); - user = $('#new-username').val() + valid = valid && checkLength(username_div, "user name", 1); + let user = username_div.val() if (valid) { $.ajax({ - url: "/app/user/ldap/" + $('#new-username').val(), + url: "/app/user/ldap/" + user, success: function (data) { data = data.replace(/\s+/g, ' '); if (data.indexOf('error:') != '-1') { toastr.error(data); $('#new-email').val(''); - $('#new-password').attr('readonly', false); - $('#new-password').val(''); + username_div.attr('readonly', false); + username_div.val(''); } else { let json = $.parseJSON(data); toastr.clear(); - if (!$('#new-username').val().includes('@')) { - $('#new-username').val(user + '@' + json[1]); + if (!user.includes('@')) { + username_div.val(user + '@' + json[1]); } $('#new-email').val(json[0]); $('#new-password').val('aduser'); @@ -209,7 +123,6 @@ $( function() { }); $("#tabs ul li").click(function() { let activeTab = $(this).find("a").attr("href"); - console.log(activeTab); let activeTabClass = activeTab.replace('#', ''); $('.menu li ul li').each(function () { $(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)'); @@ -252,65 +165,35 @@ window.onload = function() { function addUser(dialog_id) { let valid = true; toastr.clear(); - allFields = $([]).add($('#new-username')).add($('#new-password')).add($('#new-email')) + let allFields = $([]).add($('#new-username')).add($('#new-password')).add($('#new-email')) allFields.removeClass("ui-state-error"); valid = valid && checkLength($('#new-username'), "user name", 1); valid = valid && checkLength($('#new-password'), "password", 1); valid = valid && checkLength($('#new-email'), "Email", 1); - let activeuser = 0; + let enabled = 0; if ($('#activeuser').is(':checked')) { - activeuser = '1'; + enabled = '1'; } if (valid) { + let jsonData = { + "username": $('#new-username').val(), + "password": $('#new-password').val(), + "email": $('#new-email').val(), + "role": $('#new-role').val(), + "enabled": enabled, + "user_group": $('#new-group').val(), + } $.ajax({ - url: "/app/user/create", - data: { - newusername: $('#new-username').val(), - newpassword: $('#new-password').val(), - newemail: $('#new-email').val(), - newrole: $('#new-role').val(), - activeuser: activeuser, - page: cur_url[0].split('#')[0], - newgroupuser: $('#new-group').val(), - token: $('#token').val() - }, + url: "/app/user", type: "POST", + data: JSON.stringify(jsonData), + contentType: "application/json; charset=utf-8", success: function (data) { - data = data.replace(/\s+/g, ' '); - if (data.indexOf('error:') != '-1') { - toastr.error(data); + if (data.status === 'failed') { + toastr.error(data.error); } else { - let getId = new RegExp('[0-9]+'); - let id = data.match(getId); - common_ajax_action_after_success(dialog_id, 'user-' + id, 'ajax-users', data); - } - } - }); - } -} -function addGroup(dialog_id) { - toastr.clear(); - let valid = true; - allFields = $([]).add($('#new-group-add')); - allFields.removeClass("ui-state-error"); - valid = valid && checkLength($('#new-group-add'), "new group name", 1); - if (valid) { - $.ajax({ - url: "/app/server/group/create", - data: { - groupname: $('#new-group-add').val(), - newdesc: $('#new-desc').val(), - token: $('#token').val() - }, - type: "POST", - success: function (data) { - if (data.indexOf('error:') != '-1') { - toastr.error(data); - } else { - let getId = new RegExp('[0-9]+'); - let id = data.match(getId); - $('select:regex(id, group)').append('').selectmenu("refresh"); - common_ajax_action_after_success(dialog_id, 'newgroup', 'ajax-group', data); + let user_id = data.id; + common_ajax_action_after_success(dialog_id, 'user-' + user_id, 'ajax-users', data.data); } } }); @@ -386,8 +269,7 @@ function addServer(dialog_id) { slave: $('#slavefor').val(), cred: cred, page: cur_url[0].split('#')[0], - desc: $('#desc').val(), - token: $('#token').val() + desc: $('#desc').val() }, type: "POST", success: function (data) { @@ -426,8 +308,7 @@ function after_server_creating(servername, newip, scan_server) { act: 'after_adding', servername: servername, newip: newip, - scan_server: scan_server, - token: $('#token').val() + scan_server: scan_server }, type: "POST", success: function (data) { @@ -440,80 +321,6 @@ function after_server_creating(servername, newip, scan_server) { } }); } -function addCreds(dialog_id) { - toastr.clear(); - let ssh_enable = 0; - if ($('#new-ssh_enable').is(':checked')) { - ssh_enable = '1'; - } - let valid = true; - allFields = $([]).add($('#new-ssh-add')).add($('#ssh_user')) - allFields.removeClass("ui-state-error"); - valid = valid && checkLength($('#new-ssh-add'), "Name", 1); - valid = valid && checkLength($('#ssh_user'), "Credentials", 1); - if (valid) { - $.ajax({ - url: "/app/server/ssh/create", - data: { - new_ssh: $('#new-ssh-add').val(), - new_group: $('#new-sshgroup').val(), - ssh_user: $('#ssh_user').val(), - ssh_pass: $('#ssh_pass').val(), - ssh_enable: ssh_enable, - page: cur_url[0].split('#')[0], - token: $('#token').val() - }, - type: "POST", - success: function (data) { - if (data.indexOf('error:') != '-1') { - toastr.error(data); - } else { - let group_name = getGroupNameById($('#new-sshgroup').val()); - let getId = new RegExp('ssh-table-[0-9]+'); - let id = data.match(getId) + ''; - id = id.split('-').pop(); - common_ajax_action_after_success(dialog_id, 'ssh-table-' + id, 'ssh_enable_table', data); - $('select:regex(id, credentials)').append('').selectmenu("refresh"); - $('select:regex(id, ssh-key-name)').append('').selectmenu("refresh"); - $("input[type=submit], button").button(); - $("input[type=checkbox]").checkboxradio(); - $("select").selectmenu(); - } - } - }); - } -} -function getGroupNameById(group_id) { - let group_name = '' - $.ajax({ - url: "/app/user/group/name/" + group_id, - async: false, - - success: function (data) { - if (data.indexOf('error:') != '-1') { - toastr.error(data); - } else { - group_name = data; - } - } - }); - return group_name; -} -function sshKeyEnableShow(id) { - $('#ssh_enable-'+id).click(function() { - if ($('#ssh_enable-'+id).is(':checked')) { - $('#ssh_pass-'+id).css('display', 'none'); - } else { - $('#ssh_pass-'+id).css('display', 'block'); - } - }); - if ($('#ssh_enable-'+id).is(':checked')) { - $('#ssh_pass-'+id).css('display', 'none'); - } else { - $('#ssh_pass-'+id).css('display', 'block'); - } -} - function confirmDeleteUser(id) { $( "#dialog-confirm" ).dialog({ resizable: false, @@ -535,27 +342,7 @@ function confirmDeleteUser(id) { }] }); } -function confirmDeleteGroup(id) { - $( "#dialog-confirm" ).dialog({ - resizable: false, - height: "auto", - width: 400, - modal: true, - title: delete_word+ " " +$('#name-'+id).val() + "?", - buttons: [{ - text: delete_word, - click: function() { - $(this).dialog("close"); - removeGroup(id); - } - }, { - text: cancel_word, - click: function () { - $(this).dialog("close"); - } - }] - }); -} + function confirmDeleteServer(id) { $( "#dialog-confirm" ).dialog({ resizable: false, @@ -577,27 +364,6 @@ function confirmDeleteServer(id) { }] }); } -function confirmDeleteSsh(id) { - $( "#dialog-confirm" ).dialog({ - resizable: false, - height: "auto", - width: 400, - modal: true, - title: delete_word +" " + $('#ssh_name-' + id).val() + "?", - buttons: [{ - text: delete_word, - click: function () { - $(this).dialog("close"); - removeSsh(id); - } - },{ - text: cancel_word, - click: function () { - $(this).dialog("close"); - } - }] - }); -} function cloneServer(id) { $( "#add-server-button" ).trigger( "click" ); if ($('#enable-'+id).is(':checked')) { @@ -640,14 +406,15 @@ function cloneServer(id) { function removeUser(id) { $("#user-" + id).css("background-color", "#f2dede"); $.ajax({ - url: "/app/user/delete/" + id, - + url: "/app/user", + data: JSON.stringify({'user_id': id}), + contentType: "application/json; charset=utf-8", + type: "DELETE", success: function (data) { - data = data.replace(/\s+/g, ' '); - if (data == "ok") { + if (data.status === 'failed') { + toastr.error(data.error); + } else { $("#user-" + id).remove(); - } else if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') { - toastr.error(data); } } }); @@ -670,70 +437,27 @@ function removeServer(id) { } }); } -function removeGroup(id) { - $("#group-" + id).css("background-color", "#f2dede"); - $.ajax({ - url: "/app/server/group/delete/" + id, - - success: function (data) { - data = data.replace(/\s+/g, ' '); - if (data == "ok") { - $("#group-" + id).remove(); - $('select:regex(id, group) option[value=' + id + ']').remove(); - $('select:regex(id, group)').selectmenu("refresh"); - } else if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') { - toastr.error(data); - } - } - }); -} -function removeSsh(id) { - $("#ssh-table-"+id).css("background-color", "#f2dede"); - $.ajax( { - url: "/app/server/ssh/delete/" + id, - - success: function( data ) { - data = data.replace(/\s+/g,' '); - if(data == "ok") { - $("#ssh-table-"+id).remove(); - $('select:regex(id, credentials) option[value='+id+']').remove(); - $('select:regex(id, credentials)').selectmenu("refresh"); - } else if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') { - toastr.error(data); - } - } - } ); -} function updateUser(id) { toastr.remove(); - cur_url[0] = cur_url[0].split('#')[0] - let usergroup = Cookies.get('group'); - let role = $('#role-' + id).val(); - let activeuser = 0; + let enabled = 0; if ($('#activeuser-' + id).is(':checked')) { - activeuser = '1'; - } - if (role == null && role !== undefined) { - toastr.warning('You cannot edit superAdmin user'); - return false; + enabled = '1'; } toastr.remove(); + let jsonData = { + "username": $('#login-' + id).val(), + "email": $('#email-' + id).val(), + "enabled": enabled, + "user_id": id + } $.ajax({ - url: "/app/user/update", - data: { - updateuser: $('#login-' + id).val(), - email: $('#email-' + id).val(), - role: role, - usergroup: usergroup, - activeuser: activeuser, - id: id, - token: $('#token').val() - }, - type: "POST", + url: "/app/user", + type: "PUT", + data: JSON.stringify(jsonData), + contentType: "application/json; charset=utf-8", success: function (data) { - data = data.replace(/\s+/g, ' '); - if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') { - toastr.error(data); + if (data.status === 'failed') { + toastr.error(data.error); } else { toastr.remove(); $("#user-" + id).addClass("update", 1000); @@ -744,33 +468,6 @@ function updateUser(id) { } }); } -function updateGroup(id) { - toastr.clear(); - $.ajax({ - url: "/app/server/group/update", - data: { - updategroup: $('#name-' + id).val(), - descript: $('#descript-' + id).val(), - id: id, - token: $('#token').val() - }, - type: "POST", - success: function (data) { - data = data.replace(/\s+/g, ' '); - if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') { - toastr.error(data); - } else { - toastr.clear(); - $("#group-" + id).addClass("update", 1000); - setTimeout(function () { - $("#group-" + id).removeClass("update"); - }, 2500); - $('select:regex(id, group) option[value=' + id + ']').remove(); - $('select:regex(id, group)').append('').selectmenu("refresh"); - } - } - }); -} function updateServer(id) { toastr.clear(); let typeip = 0; @@ -806,8 +503,7 @@ function updateServer(id) { cred: $('#credentials-' + id + ' option:selected').val(), id: id, desc: $('#desc-' + id).val(), - protected: protected_serv, - token: $('#token').val() + protected: protected_serv }, type: "POST", success: function (data) { @@ -824,74 +520,6 @@ function updateServer(id) { } }); } -function uploadSsh() { - toastr.clear(); - if ($("#ssh-key-name option:selected").val() == "------" || $('#ssh_cert').val() == '') { - toastr.error('All fields must be completed'); - } else { - $.ajax({ - url: "/app/server/ssh/upload", - data: { - ssh_cert: $('#ssh_cert').val(), - name: $('#ssh-key-name').val(), - pass: $('#ssh-key-pass').val(), - token: $('#token').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) - } else { - toastr.error('Something wrong, check and try again'); - } - } - }); - } -} -function updateSSH(id) { - toastr.clear(); - let ssh_enable = 0; - if ($('#ssh_enable-' + id).is(':checked')) { - ssh_enable = '1'; - } - let group = $('#sshgroup-' + id).val(); - if (cur_url[0].indexOf('servers') != '-1') { - group = $('#new-server-group-add').val(); - } - $.ajax({ - url: "/app/server/ssh/update", - data: { - name: $('#ssh_name-' + id).val(), - group: group, - ssh_enable: ssh_enable, - ssh_user: $('#ssh_user-' + id).val(), - ssh_pass: $('#ssh_pass-' + id).val(), - id: id, - token: $('#token').val() - }, - type: "POST", - success: function (data) { - data = data.replace(/\s+/g, ' '); - if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') { - toastr.error(data); - } else { - toastr.clear(); - $("#ssh-table-" + id).addClass("update", 1000); - setTimeout(function () { - $("#ssh-table-" + id).removeClass("update"); - }, 2500); - $('select:regex(id, credentials) option[value=' + id + ']').remove(); - $('select:regex(id, ssh-key-name) option[value=' + $('#ssh_name-' + id).val() + ']').remove(); - $('select:regex(id, credentials)').append('').selectmenu("refresh"); - $('select:regex(id, ssh-key-name)').append('').selectmenu("refresh"); - } - } - }); -} function showApacheLog(serv) { let rows = $('#rows').val(); let grep = $('#grep').val(); @@ -911,8 +539,7 @@ function showApacheLog(serv) { hour: hour, minute: minute, hour1: hour1, - minute1: minute1, - token: $('#token').val() + minute1: minute1 }, type: "POST", success: function( data ) { @@ -920,24 +547,6 @@ function showApacheLog(serv) { } } ); } -function checkSshConnect(ip) { - $.ajax({ - url: "/app/server/check/ssh/" + ip, - - success: function (data) { - if (data.indexOf('error:') != '-1') { - toastr.error(data) - } else if (data.indexOf('failed') != '-1') { - toastr.error(data) - } else if (data.indexOf('Errno') != '-1') { - toastr.error(data) - } else { - toastr.clear(); - toastr.success('Connect is accepted'); - } - } - }); -} function openChangeUserPasswordDialog(id) { changeUserPasswordDialog(id); } @@ -993,8 +602,7 @@ function changeUserPassword(id, d) { url: "/app/user/password", data: { updatepassowrd: pass, - id: id, - token: $('#token').val() + id: id }, type: "POST", success: function (data) { @@ -1024,7 +632,6 @@ function changeUserServiceDialog(id) { } $.ajax({ url: "/app/user/services/" + id, - success: function (data) { if (data.indexOf('danger') != '-1') { toastr.error(data); @@ -1056,21 +663,20 @@ function changeUserServiceDialog(id) { } function changeUserServices(user_id) { let jsonData = {}; - jsonData[user_id] = {}; + jsonData['services'] = {}; + jsonData['services'][user_id] = {}; + jsonData['username'] = $('#login-'+user_id).val(); $('#checked_services tbody tr').each(function () { let this_id = $(this).attr('id').split('-')[1]; - jsonData[user_id][this_id] = {} + jsonData['services'][user_id][this_id] = {} }); $.ajax( { url: "/app/user/services/" + user_id, - data: { - jsonDatas: JSON.stringify(jsonData), - changeUserServicesUser: $('#login-'+user_id).val(), - token: $('#token').val() - }, + data: JSON.stringify(jsonData), + contentType: "application/json; charset=utf-8", type: "POST", success: function( data ) { - if (data.indexOf('error:') != '-1' || data.indexOf('Failed') != '-1') { + if (data.status === 'failed') { toastr.error(data); } else { $("#user-" + user_id).addClass("update", 1000); @@ -1223,8 +829,7 @@ function removeOpenVpnProfile(id) { $.ajax({ url: "/app/admin/openvpn/delete", data: { - openvpndel: id, - token: $('#token').val() + openvpndel: id }, type: "POST", success: function (data) { @@ -1246,8 +851,7 @@ function uploadOvpn() { url: "/app/admin/openvpn/upload", data: { uploadovpn: $('#ovpn_upload_file').val(), - ovpnname: $('#ovpn_upload_name').val(), - token: $('#token').val() + ovpnname: $('#ovpn_upload_name').val() }, type: "POST", success: function (data) { @@ -1423,10 +1027,6 @@ function serverIsUp(server_ip, server_id) { if (cur_url.split('#')[1] == 'servers') { $.ajax({ url: "/app/server/check/server/" + server_ip, - // data: { - // token: $('#token').val() - // }, - // type: "POST", success: function (data) { data = data.replace(/^\s+|\s+$/g, ''); if (data.indexOf('up') != '-1') { @@ -1533,8 +1133,7 @@ function saveGroupsAndRoles(user_id) { url: "/app/user/groups/save", data: { changeUserGroupsUser: $('#login-' + user_id).val(), - jsonDatas: JSON.stringify(jsonData), - token: $('#token').val() + jsonDatas: JSON.stringify(jsonData) }, type: "POST", success: function (data) { @@ -1554,10 +1153,6 @@ function openChangeServerServiceDialog(server_id) { let hostname = $('#hostname-' + server_id).val(); $.ajax({ url: "/app/server/services/" + server_id, - // data: { - // token: $('#token').val() - // }, - // type: "GET", success: function (data) { $("#groups-roles").html(data); $("#groups-roles").dialog({ @@ -1623,7 +1218,6 @@ function changeServerServices(server_id) { data: { jsonDatas: JSON.stringify(jsonData), changeServerServicesServer: $('#hostname-' + server_id).val(), - token: $('#token').val() }, type: "POST", success: function (data) { diff --git a/app/static/js/waf.js b/app/static/js/waf.js index 38d111c3..046d3e68 100644 --- a/app/static/js/waf.js +++ b/app/static/js/waf.js @@ -37,11 +37,16 @@ function metrics_waf(name) { name = name.split('metrics')[1] $.ajax({ url: "/app/waf/metric/enable/" + enable + "/" + name, + contentType: "application/json; charset=utf-8", success: function (data) { - showOverviewWaf(ip, hostnamea); - setTimeout(function () { - $("#" + name).parent().parent().removeClass("update"); - }, 2500); + if (data.status === 'failed') { + toastr.error(data.error); + } else { + showOverviewWaf(ip, hostnamea); + setTimeout(function () { + $("#" + name).parent().parent().removeClass("update"); + }, 2500); + } } }); } @@ -71,17 +76,22 @@ function changeWafMode(id) { let service = cur_url[1]; $.ajax({ url: "/app/waf/" + service + "/mode/" + server_hostname + "/" + waf_mode, + contentType: "application/json; charset=utf-8", success: function (data) { - toastr.info('Do not forget restart WAF service'); - $('#' + server_hostname + '-select-line').addClass("update", 1000); - setTimeout(function () { - $('#' + server_hostname + '-select-line').removeClass("update"); - }, 2500); + if (data.status === 'failed') { + toastr.error(data.error); + } else { + toastr.info('Do not forget restart WAF service'); + $('#' + server_hostname + '-select-line').addClass("update", 1000); + setTimeout(function () { + $('#' + server_hostname + '-select-line').removeClass("update"); + }, 2500); + } } }); } $( function() { - $( "#waf_rules input" ).change(function() { + $("#waf_rules input").change(function () { let id = $(this).attr('id').split('-'); waf_rules_en(id[1]) }); @@ -94,9 +104,10 @@ function waf_rules_en(id) { let serv = cur_url[2]; $.ajax({ url: "/app/waf/" + serv + "/rule/" + id + "/" + enable, + contentType: "application/json; charset=utf-8", success: function (data) { - if (data.indexOf('sed:') != '-1' || data.indexOf('error: ') != '-1') { - toastr.error(data); + if (data.status === 'failed') { + toastr.error(data.error); } else { toastr.info('Do not forget restart WAF service'); $('#rule-' + id).addClass("update", 1000); @@ -143,21 +154,21 @@ function addNewConfig() { new_rule_description = escapeHtml(new_rule_description); new_rule_file = escapeHtml(new_rule_file); serv = escapeHtml(serv); + jsonData = { + "new_waf_rule": new_rule_name, + "new_rule_description": new_rule_description, + "new_rule_file": new_rule_file + } $.ajax({ url: "/app/waf/" + service + "/" + serv + "/rule/create", - data: { - new_waf_rule: new_rule_name, - new_rule_description: new_rule_description, - new_rule_file: new_rule_file - }, + data: JSON.stringify(jsonData), + contentType: "application/json; charset=utf-8", type: "POST", success: function (data) { - if (data.indexOf('error:') != '-1') { - toastr.error(data); + if (data.status === 'failed') { + toastr.error(data.error); } else { - let getId = new RegExp('[0-9]+'); - let id = data.match(getId) + ''; - window.location.replace('waf.py?service=' + service + '&waf_rule_id=' + id + '&serv=' + serv); + window.location.replace("/app/waf/" + service + "/" + serv + "/rule/" + data.id); } } }); diff --git a/app/templates/admin.html b/app/templates/admin.html index 39cf13da..d95627e9 100644 --- a/app/templates/admin.html +++ b/app/templates/admin.html @@ -3,7 +3,9 @@ {% 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' %} @@ -182,6 +184,7 @@ {% include 'include/intro/admin.html' %} {% else %} {% include 'include/intro/servers.html' %} + {% endif %} {% include 'include/intro/js_script.html' %} {% endblock %} diff --git a/app/templates/ajax/new_ssh.html b/app/templates/ajax/new_ssh.html index 6b77a713..49b0090e 100644 --- a/app/templates/ajax/new_ssh.html +++ b/app/templates/ajax/new_ssh.html @@ -11,7 +11,7 @@ {% endif %} - {% if page != "servers" %} + {% if g.user_params['role'] == 1 %} +

{% if ssh.enable == 1 %} @@ -36,7 +36,7 @@
- + {% endfor %} diff --git a/app/templates/include/admin_settings.html b/app/templates/include/admin_settings.html index 655c3594..8ab3af96 100644 --- a/app/templates/include/admin_settings.html +++ b/app/templates/include/admin_settings.html @@ -14,7 +14,7 @@ 'smon': 'SMON', } %} - + {% set section = namespace(section='') %} diff --git a/app/templates/include/admin_ssh.html b/app/templates/include/admin_ssh.html index 74587ab4..bbcef943 100644 --- a/app/templates/include/admin_ssh.html +++ b/app/templates/include/admin_ssh.html @@ -1,10 +1,12 @@
- - {% if g.user_params['role'] == 1 %}
- {{lang.words.name|title()}} + + {{lang.words.name|title()}} - SSH {{lang.words.key}} + + + SSH {{lang.words.key}} + {{lang.words.group|title()}}