Initial YakPanel commit
This commit is contained in:
12
class_v2/overviewV2/__init__.py
Normal file
12
class_v2/overviewV2/__init__.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# YakPanel
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2014-2099 YakPanel(www.yakpanel.com) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: yakpanel
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# ------------------------------
|
||||
# xxx app
|
||||
# ------------------------------
|
||||
389
class_v2/overviewV2/api.py
Normal file
389
class_v2/overviewV2/api.py
Normal file
@@ -0,0 +1,389 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# YakPanel
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2014-2099 YakPanel(www.yakpanel.com) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: yakpanel
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# ------------------------------
|
||||
# overview app
|
||||
# ------------------------------
|
||||
import json
|
||||
import os
|
||||
from typing import Callable
|
||||
|
||||
import public
|
||||
from overviewV2.base import OverViewBase, DISPLAY
|
||||
from public.exceptions import HintException
|
||||
from public.validate import Param
|
||||
|
||||
public.sys_path_append("class_v2/")
|
||||
|
||||
PANEL_PATH = public.get_panel_path()
|
||||
|
||||
|
||||
class OverViewApi(OverViewBase):
|
||||
PLUGIN_DIR = os.path.join(PANEL_PATH, "plugin")
|
||||
TEMPLATE = os.path.join(PANEL_PATH, "config/overview_template.json")
|
||||
SETTING = os.path.join(PANEL_PATH, "config/overview_setting.json")
|
||||
|
||||
def __init__(self):
|
||||
overview_setting = []
|
||||
if not os.path.isfile(self.SETTING):
|
||||
try:
|
||||
temp_data = json.loads(public.readFile(self.TEMPLATE))
|
||||
except Exception as e:
|
||||
public.print_log(f"error read overview template: {e}")
|
||||
temp_data = []
|
||||
id = 0
|
||||
for temp in temp_data:
|
||||
for option in temp.get("option", []):
|
||||
if option.get("name") in [
|
||||
"sites", "ftps", "databases", "security",
|
||||
]:
|
||||
option["id"] = id
|
||||
option["template"] = temp["template"]
|
||||
option["params"] = [
|
||||
p["option"][0] for p in option.get("params", []) if p.get("option")
|
||||
]
|
||||
id += 1
|
||||
overview_setting.append(option)
|
||||
public.writeFile(self.SETTING, json.dumps(overview_setting))
|
||||
|
||||
def _check_plugin_install(self, overview: dict):
|
||||
if overview.get("type") == "plugin":
|
||||
if not overview.get("name"):
|
||||
pass
|
||||
if not os.path.exists(os.path.join(self.PLUGIN_DIR, overview["name"])):
|
||||
raise HintException(f"[{overview.get('name')}] Plugin Not Installed!")
|
||||
|
||||
def _dynamic_info(self, overview: dict, replace_title: bool = True) -> dict:
|
||||
# icon desc
|
||||
if DISPLAY.get(overview["name"]):
|
||||
overview["icon"] = DISPLAY[overview["name"]]["icon"]
|
||||
overview["desc"] = DISPLAY[overview["name"]]["desc"]
|
||||
# route
|
||||
router_inplace = ["sites", "databases"]
|
||||
try:
|
||||
if overview.get("name") in router_inplace and len(overview.get("params", [])) == 1:
|
||||
point = overview["params"][0].get("source")
|
||||
if not point:
|
||||
return overview
|
||||
if point == "mongodb":
|
||||
point = "mongo"
|
||||
|
||||
if point == "all":
|
||||
if overview["name"] == "sites":
|
||||
point = "php"
|
||||
elif overview["name"] == "databases":
|
||||
point = "mysql"
|
||||
|
||||
overview["source"]["href"] = f'{overview["source"]["href"]}/{point}'
|
||||
except Exception:
|
||||
import traceback
|
||||
public.print_log(traceback.format_exc())
|
||||
|
||||
# replace Title
|
||||
try:
|
||||
if replace_title and overview.get("name") == "monitor":
|
||||
params = overview.get("params", [])
|
||||
act = params[-1].get("name", "monitor")
|
||||
overview["title"] = f"Monitor - {act}"
|
||||
|
||||
if replace_title and overview.get("name") == "sites":
|
||||
params = overview.get("params", [])
|
||||
act = params[-1].get("name", "php")
|
||||
overview["title"] = f"Site - {act}"
|
||||
except Exception:
|
||||
import traceback
|
||||
public.print_log(traceback.format_exc())
|
||||
|
||||
return overview
|
||||
|
||||
def overview_template(self, get):
|
||||
"""
|
||||
@name 获取概览模板
|
||||
"""
|
||||
try:
|
||||
temp_data = json.loads(public.readFile(self.TEMPLATE))
|
||||
except Exception as e:
|
||||
raise HintException(e)
|
||||
|
||||
select_option_dict = {
|
||||
"site_all": public.M("sites").field("name").select()
|
||||
}
|
||||
for template in temp_data:
|
||||
template_option = template.get("option", [])
|
||||
for i in range(len(template_option) - 1, -1, -1):
|
||||
option = template_option[i]
|
||||
# display
|
||||
option = self._dynamic_info(option, replace_title=False)
|
||||
|
||||
if not option.get("status", False):
|
||||
if option.get("type") == "plugin": # 插件
|
||||
plugin_path = os.path.join(self.PLUGIN_DIR, option["name"])
|
||||
option["status"] = os.path.exists(plugin_path)
|
||||
|
||||
# 填充参数选项数据
|
||||
option_params = option.get("params", [])
|
||||
for params in option_params:
|
||||
# select_option 监控报表, 提供选择站点
|
||||
select_option = params.get("select_option")
|
||||
if select_option is not None and select_option_dict.get(select_option) is not None:
|
||||
params["option"] = select_option_dict.get(select_option)
|
||||
for site in params["option"]:
|
||||
site["source"] = site["name"]
|
||||
|
||||
return public.success_v2(temp_data)
|
||||
|
||||
def get_overview(self, get):
|
||||
"""
|
||||
@name 获取概览
|
||||
"""
|
||||
try:
|
||||
overview_setting = public.readFile(self.SETTING) or "[]"
|
||||
overview_setting = json.loads(overview_setting)
|
||||
if not isinstance(overview_setting, list):
|
||||
raise Exception("overview_setting format error")
|
||||
if len(overview_setting) == 0:
|
||||
raise Exception("overview_setting is empty")
|
||||
except Exception as ex:
|
||||
public.print_log("get_overview error info: {}".format(ex))
|
||||
public.ExecShell("rm -f {}".format(self.SETTING))
|
||||
overview_setting = []
|
||||
|
||||
func_dict = {
|
||||
"sites": self._base,
|
||||
"ftps": self._base,
|
||||
"databases": self._base,
|
||||
"security": self._security,
|
||||
"ssh_log": self._ssh_log,
|
||||
"ssl": self._ssl,
|
||||
"corn": self._corn,
|
||||
"btwaf": self._btwaf,
|
||||
"monitor": self._monitor,
|
||||
"tamper_core": self._tamper_core,
|
||||
"alarm_logs": self._alarm_logs,
|
||||
}
|
||||
|
||||
nlist = []
|
||||
for overview in overview_setting:
|
||||
overview["value"] = []
|
||||
# display
|
||||
overview = self._dynamic_info(overview)
|
||||
params_list = overview.get("params", [])
|
||||
|
||||
if overview.get("status", False):
|
||||
func: Callable[[str, list], list] = func_dict.get(overview["name"])
|
||||
if func is not None:
|
||||
overview["value"] = func(overview["name"], params_list)
|
||||
|
||||
nlist.append(overview)
|
||||
return public.success_v2(overview_setting)
|
||||
|
||||
def get_overview_window(self, get):
|
||||
"""
|
||||
params = {
|
||||
"model": "ssl",
|
||||
"source": "all"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
get.validate([
|
||||
Param("model").String().Require(),
|
||||
Param("source").String().Require(),
|
||||
], [
|
||||
public.validate.trim_filter(),
|
||||
])
|
||||
|
||||
if get.model == "ssl" and get.source not in [
|
||||
"all", "normal", "renew_fail", "expirin_soon"
|
||||
]:
|
||||
return public.fail_v2(
|
||||
"[ssl] source value mustbe one of 'all', 'normal', 'renew_fail', 'expirin_soon'"
|
||||
)
|
||||
|
||||
if get.model == "alarm_log" and get.source not in [
|
||||
"all", "handled", "unhandled"
|
||||
]:
|
||||
return public.fail_v2(
|
||||
"[alarm_log] source value mustbe one of 'all', 'handled', 'unhandled'"
|
||||
)
|
||||
except Exception as ex:
|
||||
public.print_log("get_overview_window error info: {}".format(ex))
|
||||
return public.fail_v2(str(ex))
|
||||
|
||||
data = []
|
||||
if get.model == "ssl":
|
||||
if get.source != "all":
|
||||
data = self._base_ssl(get.source)
|
||||
else:
|
||||
data = []
|
||||
for tag in ["expirin_soon", "renew_fail", "normal"]:
|
||||
data.extend(self._base_ssl(tag))
|
||||
sorted(data, key=lambda x: x.get("id", 0))
|
||||
return public.success_v2(data)
|
||||
|
||||
def add_overview(self, get):
|
||||
try:
|
||||
get.validate([
|
||||
Param("overview").String().Require(),
|
||||
], [
|
||||
public.validate.trim_filter(),
|
||||
])
|
||||
overview = json.loads(get.overview)
|
||||
overview_setting = public.readFile(self.SETTING) or "[]"
|
||||
except Exception as ex:
|
||||
public.print_log("add_overview error info: {}".format(ex))
|
||||
return public.fail_v2(str(ex))
|
||||
self._check_plugin_install(overview)
|
||||
try:
|
||||
overview_setting = json.loads(overview_setting)
|
||||
except json.JSONDecodeError:
|
||||
overview_setting = []
|
||||
|
||||
if len(overview_setting) >= 6:
|
||||
return public.fail_v2("Overview Full, Max 6 Items!")
|
||||
|
||||
if overview.get("value") is not None:
|
||||
del overview["value"]
|
||||
|
||||
max_id = 0
|
||||
for over in overview_setting:
|
||||
if over["name"] == overview["name"]:
|
||||
return public.success_v2(public.lang("Overview Exist!"))
|
||||
|
||||
if int(over["id"]) > max_id:
|
||||
max_id = int(over["id"])
|
||||
|
||||
overview["id"] = max_id + 1
|
||||
overview_setting.append(overview)
|
||||
|
||||
public.writeFile(self.SETTING, json.dumps(overview_setting))
|
||||
return public.success_v2(public.lang("Overview Add Successfully!"))
|
||||
|
||||
def set_overview(self, get):
|
||||
try:
|
||||
get.validate([
|
||||
Param("overview").String().Require(),
|
||||
], [
|
||||
public.validate.trim_filter(),
|
||||
])
|
||||
overview = json.loads(get.overview)
|
||||
except Exception as ex:
|
||||
public.print_log("set_overview error info: {}".format(ex))
|
||||
return public.fail_v2(str(ex))
|
||||
self._check_plugin_install(overview)
|
||||
overview_setting = []
|
||||
if isinstance(overview, list):
|
||||
overview_setting = overview
|
||||
elif isinstance(overview, dict):
|
||||
try:
|
||||
overview_setting = public.readFile(self.SETTING)
|
||||
overview_setting = json.loads(overview_setting)
|
||||
except Exception as err:
|
||||
public.print_log("set_overview readFile error info: {}".format(err))
|
||||
overview_setting = []
|
||||
|
||||
if overview.get("value") is not None:
|
||||
del overview["value"]
|
||||
|
||||
for idx in range(len(overview_setting)):
|
||||
over = overview_setting[idx]
|
||||
if int(over["id"]) == int(overview["id"]):
|
||||
overview_setting[idx] = overview
|
||||
break
|
||||
else:
|
||||
return public.fail_v2("Overview Not Found!")
|
||||
|
||||
public.writeFile(self.SETTING, json.dumps(overview_setting))
|
||||
return public.success_v2(public.lang("Overview Set Successfully!"))
|
||||
|
||||
def del_overview(self, get):
|
||||
try:
|
||||
get.validate([
|
||||
Param("overview_id").Integer().Require(),
|
||||
], [
|
||||
public.validate.trim_filter(),
|
||||
])
|
||||
overview_setting = public.readFile(self.SETTING)
|
||||
overview_setting = json.loads(overview_setting)
|
||||
except Exception as ex:
|
||||
public.print_log("del_overview error info: {}".format(ex))
|
||||
return public.fail_v2(str(ex))
|
||||
|
||||
if len(overview_setting) <= 1:
|
||||
return public.fail_v2("Overview At Least One Item!")
|
||||
|
||||
overview_id = int(get.overview_id)
|
||||
for idx in range(len(overview_setting) - 1, -1, -1):
|
||||
over = overview_setting[idx]
|
||||
if int(over["id"]) == overview_id:
|
||||
del overview_setting[idx]
|
||||
break
|
||||
|
||||
public.writeFile(self.SETTING, json.dumps(overview_setting))
|
||||
return public.success_v2(public.lang("Overview Delete Successfully!"))
|
||||
|
||||
def sort_overview(self, get):
|
||||
try:
|
||||
get.validate([
|
||||
Param("sort_ids").String().Require(),
|
||||
], [
|
||||
public.validate.trim_filter(),
|
||||
])
|
||||
sort_ids = json.loads(get.sort_ids)
|
||||
overview_setting = public.readFile(self.SETTING)
|
||||
overview_setting = json.loads(overview_setting)
|
||||
except Exception as ex:
|
||||
public.print_log("sort_overview error info: {}".format(ex))
|
||||
return public.fail_v2(str(ex))
|
||||
|
||||
new_overview_setting = []
|
||||
for pk in sort_ids:
|
||||
for over in overview_setting:
|
||||
if int(over["id"]) == int(pk):
|
||||
new_overview_setting.append(over)
|
||||
break
|
||||
|
||||
public.writeFile(self.SETTING, json.dumps(new_overview_setting))
|
||||
return public.success_v2(public.lang("Successfully!"))
|
||||
|
||||
|
||||
def update_overview():
|
||||
# 同步模板中的更新, 同时移除不存在的项
|
||||
try:
|
||||
api = OverViewApi()
|
||||
template_data = json.loads(public.readFile(api.TEMPLATE))
|
||||
settings = json.loads(public.readFile(api.SETTING))
|
||||
new_settings = []
|
||||
for setting in settings:
|
||||
for template in template_data:
|
||||
for op in template.get("option", []):
|
||||
if setting["name"] == op["name"]:
|
||||
try:
|
||||
new_settings.append(
|
||||
{
|
||||
"title": op["title"],
|
||||
"name": setting["name"],
|
||||
"status": setting.get("status", False),
|
||||
"type": op["type"],
|
||||
"source": op.get("source", {}),
|
||||
"params": setting["params"],
|
||||
"icon": op.get("icon", ""),
|
||||
"desc": op.get("desc", ""),
|
||||
"id": setting["id"],
|
||||
"template": op.get("template", ""),
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
public.print_log("update_overview item error:".format(str(e)))
|
||||
continue
|
||||
public.writeFile(OverViewApi.SETTING, json.dumps(new_settings))
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
update_overview()
|
||||
506
class_v2/overviewV2/base.py
Normal file
506
class_v2/overviewV2/base.py
Normal file
@@ -0,0 +1,506 @@
|
||||
# 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 []
|
||||
Reference in New Issue
Block a user