# coding: utf-8 # ------------------------------------------------------------------- # YakPanel # ------------------------------------------------------------------- # Copyright (c) 2014-2099 YakPanel(www.yakpanel.com) All rights reserved. # ------------------------------------------------------------------- # Author: yakpanel # ------------------------------------------------------------------- # ------------------------------ # overview app base # ------------------------------ import json import os import time from datetime import datetime, timedelta, date import public public.sys_path_append("class_v2/") COLORS = { "red": "text-error", "gray": "text-desc", "green": "text-primary", "orange": "text-warning", } DISPLAY = { "sites": { "icon": "i-dashicons:admin-site-alt3", "desc": public.lang("Manage and monitor the status of your website") }, "ftps": { "icon": "i-carbon:ibm-cloud-direct-link-1-dedicated", "desc": public.lang("Monitor FTP accounts and transfer status") }, "databases": { "icon": "i-carbon:data-base", "desc": public.lang("Monitor database operation and performance metrics") }, "security": { "icon": "i-carbon:security", "desc": public.lang("View the current security threats and risks of the system") }, "monitor": { "icon": "i-carbon:meter", "desc": public.lang("Comprehensive resource usage monitoring overview") }, "btwaf": { "icon": " i-hugeicons:firewall", "desc": public.lang("WAF firewall interception and protection details") }, "tamper_core": { "icon": "i-carbon:locked", "desc": public.lang("Prevent core operation and protection status") }, "ssh_log": { "icon": "i-carbon:terminal", "desc": public.lang("Monitor SSH login attempts and security status") }, "ssl": { "icon": "i-carbon:certificate", "desc": public.lang("SSL certificate status") }, "cron": { "icon": "i-carbon:time", "desc": public.lang("Scheduled task status") }, "alarm_logs": { "icon": "i-carbon:reminder", "desc": public.lang("Real-time monitoring and alarm tasks") }, } # noinspection PyUnusedLocal class OverViewBase: __db_objs = {} def _base(self, name: str, params_list: list) -> list: if not params_list: params_list = [] value_list = [] if name == "sites": for params in params_list: where = "" if params["source"] != "all": where = "LOWER(project_type)=LOWER('{}')".format(params["source"]) if where: start_num = public.M("sites").where(where + " and status='1'", ()).count() stop_num = public.M("sites").where(where + " and status='0'", ()).count() else: start_num = public.M("sites").where("status='1'", ()).count() stop_num = public.M("sites").where("status='0'", ()).count() value_list = [ { "desc": public.lang("Running"), "data": start_num, "color": COLORS["green"] }, { "desc": public.lang("Stopped"), "data": stop_num, "color": COLORS["red"] }, { "desc": public.lang("ALL"), "data": public.M("sites").where(where, ()).count(), "color": COLORS["gray"] } ] elif name == "ftps": data = public.M("ftps").count() if not isinstance(data, int): data = 0 value_list = [{ "desc": public.lang("Accounts"), "data": data, "color": COLORS["green"] }] elif name == "databases": for params in params_list: if params["source"] != "redis": if params["source"] == "all": data = public.M("databases").count() else: data = public.M("databases").where( "LOWER(type)=LOWER(?)", (params["source"],) ).count() else: from databaseModelV2.redisModel import panelRedisDB data = panelRedisDB().get_options(None).get("databases", 16) value_list = [ { "desc": params["name"], "data": data, "color": COLORS["green"] } ] else: value_list = [] return value_list def _corn(self, name: str, params_list: list) -> list: return [] def _security(self, name: str, params_list: list) -> list: from projectModelV2.safecloudModel import main cloud_safe_info = main().get_pending_alarm_trend(None) if cloud_safe_info.get("status") != 0: return [] trend_list = public.find_value_by_key( cloud_safe_info, "trend_list", default=[] ) last_scan_ts = "" if trend_list: last_scan_ts = trend_list[-1].get("timestamp", "") last_scan_time = time.strftime( "%Y/%m/%d %H:%M:%S", time.localtime(last_scan_ts) ) if last_scan_ts else public.lang("Never Scanned") try: last_total = public.find_value_by_key(cloud_safe_info, "total", default=0) except: last_total = 0 return [ { "desc": public.lang("Security Risk"), "data": last_total, "color": COLORS["gray"] if last_total == 0 else COLORS["red"] }, { "desc": public.lang("Last Scan"), "data": last_scan_time, "color": COLORS["gray"] } ] def _btwaf(self, name: str, params_list: list) -> list: default = [ { "desc": public.lang("Today Intercept"), "data": 0, "color": COLORS["orange"] }, {}, { "desc": public.lang("Yesterday Intercept"), "data": 0, "color": COLORS["orange"] } ] waf_db_path = "/www/server/btwaf/totla_db/totla_db.db" if not os.path.exists(waf_db_path): return default today_time = int(datetime.now().replace(hour=0, minute=0, second=0, microsecond=0).timestamp()) yesterday_time = today_time - 86400 result = [] try: today_data = public.M("totla_log").dbfile(waf_db_path).field('time').where( "time>=?", (today_time,) ).order('id desc').count() if not isinstance(today_data, int): raise Exception except Exception as e: public.print_log("Failed to get WAF today intercept data") today_data = 0 result.append({ "desc": public.lang("Today Intercept"), "data": 0, "color": COLORS["orange"] }) result.append({}) try: yesterday_data = public.M("totla_log").dbfile(waf_db_path).field('time').where( "time>=? and time<=?", (yesterday_time, today_time) ).order('id desc').count() if not isinstance(yesterday_data, int): raise Exception except Exception: yesterday_data = 0 result.append({ "desc": public.lang("Yesterday Intercept"), "data": yesterday_data, "color": COLORS["orange"] }) return result if result else default def _tamper_core(self, name: str, params_list: list) -> list: tamper_core_dir = "/www/server/tamper/total" default = [ { "desc": public.lang("Today Intercept"), "data": 0, "color": COLORS["gray"] }, {}, { "desc": public.lang("Yesterday Intercept"), "data": 0, "color": COLORS["gray"] } ] if not os.path.exists(tamper_core_dir): return default result = [] today_time = date.today() yesterday_time = today_time - timedelta(days=1) listdirs = os.listdir(tamper_core_dir) if not listdirs: return default for p_name in os.listdir(tamper_core_dir): dir_path = os.path.join(tamper_core_dir, str(p_name)) today_path = os.path.join(dir_path, "{}.json".format(today_time)) if os.path.isfile(today_path): today_info = public.readFile(today_path) today_info = json.loads(today_info) for info in today_info.values(): result.append({ "desc": public.lang("Today Intercept"), "data": sum(info.values()), "color": COLORS["orange"] }) else: result.append({ "desc": public.lang("Today Intercept"), "data": 0, "color": COLORS["gray"] }) result.append({}) yesterday_path = os.path.join(dir_path, "{}.json".format(yesterday_time)) if os.path.isfile(yesterday_path): yesterday_info = public.readFile(yesterday_path) yesterday_info = json.loads(yesterday_info) for info in yesterday_info.values(): result.append({ "desc": public.lang("Yesterday Intercept"), "data": sum(info.values()), "color": COLORS["orange"] }) else: result.append({ "desc": public.lang("Yesterday Intercept"), "data": 0, "color": COLORS["gray"] }) for r in result: if int(r.get("data", 0)) > 0: r["color"] = COLORS["orange"] elif int(r.get("data", 0)) == 0: r["color"] = COLORS["gray"] return result if result else default def _ssh_log(self, name: str, params_list: list) -> list: try: params_map = { "all": "all", "Accepted": "success", "Failed": "error" } from mod.project.ssh.comMod import main params = public.find_value_by_key(params_list, "source", default="all") params = params_map.get(params, "all") ssh_info = main().get_ssh_intrusion(None) if ssh_info.get("status") != 0: return [] ssh = ssh_info.get("message", {}) error = int(ssh.get("today_error", 0)) success = int(ssh.get("today_success", 0)) if params == "error": return [ { "desc": public.lang("Failed"), "data": error, "color": COLORS["gray"] if error == 0 else COLORS["red"] } ] elif params == "success": return [ { "desc": public.lang("Success"), "data": success, "color": COLORS["green"] } ] else: return [ { "desc": public.lang("Success"), "data": success, "color": COLORS["green"] }, { "desc": public.lang("Failed"), "data": error, "color": COLORS["gray"] if error == 0 else COLORS["red"] }, { "desc": public.lang("ALL"), "data": error + success, "color": COLORS["gray"] } ] except Exception: public.print_log("Failed to get SSH log information") return [] def _monitor(self, name: str, params_list: list) -> list: try: params_data = { "pv": "SUM(pv_number) as pv", "uv": "SUM(uv_number) as uv", "ip": "SUM(ip_number) as ip", "spider": "SUM(spider_count) as spider", } params_desc = { "pv": public.lang("Page Views"), "uv": public.lang("Visitors"), "ip": public.lang("IPs"), "spider": public.lang("Spiders"), } site_name = params_list[0]['source'] param = params_list[1]['source'] run_path = "{}/monitor".format(public.get_setup_path()) db_file = "{}/data/dbs/{}/{}.db".format(run_path, site_name, "request_total") if db_file not in self.__db_objs: if not os.path.exists(db_file) or os.path.getsize(db_file) == 0: return [ { "desc": site_name, }, {}, { "desc": f'{public.lang("Today")}', "data": 0, "color": COLORS["gray"] }, { "desc": f'{public.lang("Yesterday")}', "data": 0, "color": COLORS["gray"] } ] else: import db db_obj = db.Sql() db_obj._Sql__DB_FILE = db_file self.__db_objs[db_file] = db_obj else: db_obj = self.__db_objs[db_file] now_time = datetime.now().strftime('%Y%m%d') last_time = (datetime.now() - timedelta(days=1)).strftime('%Y%m%d') result = [ { "desc": site_name, }, {}, ] for i in [now_time, last_time]: sql = f'select {params_data[param]} from request_total where date="{i}";' data = db_obj.table("request_total").query(sql) try: data = data[0][0] if data is None: data = 0 except: data = 0 desc = public.lang("Today") if i == now_time else public.lang("Yesterday") result.append( { "desc": f"{desc}", "data": data, "color": COLORS["gray"] } ) return result except Exception as e: import traceback public.print_log(traceback.format_exc()) return [] def _alarm_logs(self, name: str, params_list: list) -> list: today = datetime.now().strftime("%Y-%m-%d 00:00:00") task_logs = public.M("logs").where( "type=? AND addtime >=?", ("Alarm notification", today) ).count() return [ { "desc": public.lang("Today"), "data": task_logs, "color": COLORS["gray"] if task_logs == 0 else COLORS["orange"] } ] def _base_ssl(self, select: str) -> list: from ssl_domainModelV2.model import DnsDomainSSL, Q f_fields = ("hash", "subject", "not_after", "not_after_ts") data = [] now = round((time.time() + 86400 * 30) * 1000) ip_ts = round((time.time() + 86400 * 3) * 1000) ip = public.GetLocalIp() if select == "normal": # 上次续签为成功, 且证书未过期 data = DnsDomainSSL.objects.filter( Q(renew_status=1) & ( Q(subject__ne=ip, not_after_ts__gt=now) | Q(subject=ip, not_after_ts__gt=ip_ts) ) ).fields(*f_fields).as_list() elif select == "expirin_soon": # 上次续签为成功, 但证书即将过期 data = DnsDomainSSL.objects.filter( Q(renew_status=1) & ( Q(subject__ne=ip, not_after_ts__lte=now) | Q(subject=ip, not_after_ts__lte=ip_ts) ) ).fields(*f_fields).as_list() elif select == "renew_fail": # 上次续签为失败 data = DnsDomainSSL.objects.filter( renew_status=0 ).fields(*f_fields).as_list() data = [{**d, "tag": select} for d in data] return data def _ssl(self, name: str, params_list: list) -> list: try: from ssl_domainModelV2.model import DnsDomainSSL expirin_soon = len(self._base_ssl("expirin_soon")) or 0 renew_fail = len(self._base_ssl("renew_fail")) or 0 return [ { "desc": public.lang("Expirin Soon"), "data": expirin_soon, "color": COLORS["orange"] if expirin_soon > 0 else COLORS["gray"] }, { "desc": public.lang("Renew Fail"), "data": renew_fail, "color": COLORS["red"] if renew_fail > 0 else COLORS["gray"] }, { "desc": public.lang("ALL"), "data": DnsDomainSSL.objects.all().count() or 0, "color": COLORS["gray"] } ] except Exception: import traceback public.print_log("Failed to get SSL information: {}".format(traceback.format_exc())) return []