mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-15 14:22:55 +08:00
feat✨: webui新增数据库api
This commit is contained in:
parent
25af1802af
commit
c146df3d25
@ -16,9 +16,7 @@ from utils.manager import plugins2settings_manager
|
|||||||
# from .api.group import router as group_routes
|
# from .api.group import router as group_routes
|
||||||
from .api.logs import router as ws_log_routes
|
from .api.logs import router as ws_log_routes
|
||||||
from .api.logs.log_manager import LOG_STORAGE
|
from .api.logs.log_manager import LOG_STORAGE
|
||||||
|
from .api.tabs.database import router as database_router
|
||||||
# from .api.plugins import router as plugin_routes
|
|
||||||
from .api.request import router as request_routes
|
|
||||||
|
|
||||||
# from .api.system import router as system_routes
|
# from .api.system import router as system_routes
|
||||||
from .api.tabs.main import router as main_router
|
from .api.tabs.main import router as main_router
|
||||||
@ -28,6 +26,10 @@ from .api.tabs.manage import router as manage_router
|
|||||||
# from .api.g import *
|
# from .api.g import *
|
||||||
from .auth import router as auth_router
|
from .auth import router as auth_router
|
||||||
|
|
||||||
|
# from .api.plugins import router as plugin_routes
|
||||||
|
# from .api.request import router as request_routes
|
||||||
|
|
||||||
|
|
||||||
driver = nonebot.get_driver()
|
driver = nonebot.get_driver()
|
||||||
|
|
||||||
gConfig.add_plugin_config("web-ui", "username", "admin", name="web-ui", help_="前端管理用户名")
|
gConfig.add_plugin_config("web-ui", "username", "admin", name="web-ui", help_="前端管理用户名")
|
||||||
@ -40,10 +42,11 @@ BaseApiRouter = APIRouter(prefix="/zhenxun/api")
|
|||||||
BaseApiRouter.include_router(auth_router)
|
BaseApiRouter.include_router(auth_router)
|
||||||
# BaseApiRouter.include_router(plugin_routes)
|
# BaseApiRouter.include_router(plugin_routes)
|
||||||
# BaseApiRouter.include_router(group_routes)
|
# BaseApiRouter.include_router(group_routes)
|
||||||
BaseApiRouter.include_router(request_routes)
|
# BaseApiRouter.include_router(request_routes)
|
||||||
# BaseApiRouter.include_router(system_routes)
|
# BaseApiRouter.include_router(system_routes)
|
||||||
BaseApiRouter.include_router(main_router)
|
BaseApiRouter.include_router(main_router)
|
||||||
BaseApiRouter.include_router(manage_router)
|
BaseApiRouter.include_router(manage_router)
|
||||||
|
BaseApiRouter.include_router(database_router)
|
||||||
|
|
||||||
|
|
||||||
@driver.on_startup
|
@driver.on_startup
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
|
from .database import *
|
||||||
from .main import *
|
from .main import *
|
||||||
from .manage import *
|
from .manage import *
|
||||||
|
|||||||
76
plugins/web_ui/api/tabs/database/__init__.py
Normal file
76
plugins/web_ui/api/tabs/database/__init__.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
from os import name
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import nonebot
|
||||||
|
from fastapi import APIRouter, Request
|
||||||
|
from nonebot.drivers import Driver
|
||||||
|
from tortoise import Tortoise
|
||||||
|
from tortoise.exceptions import OperationalError
|
||||||
|
|
||||||
|
from configs.config import NICKNAME
|
||||||
|
from services.db_context import TestSQL
|
||||||
|
from utils.utils import get_matchers
|
||||||
|
|
||||||
|
from ....base_model import QueryModel, Result
|
||||||
|
from ....config import QueryDateType
|
||||||
|
from ....utils import authentication
|
||||||
|
from .models.model import SqlModel, SqlText
|
||||||
|
from .models.sql_log import SqlLog
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
driver: Driver = nonebot.get_driver()
|
||||||
|
|
||||||
|
|
||||||
|
SQL_DICT = {}
|
||||||
|
|
||||||
|
|
||||||
|
@driver.on_startup
|
||||||
|
async def _():
|
||||||
|
for matcher in get_matchers(True):
|
||||||
|
if _plugin := matcher.plugin:
|
||||||
|
try:
|
||||||
|
_module = _plugin.module
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
plugin_name = matcher.plugin_name
|
||||||
|
if plugin_name in SQL_DICT:
|
||||||
|
raise ValueError(f"{plugin_name} 常用SQL plugin_name 重复")
|
||||||
|
SqlModel(
|
||||||
|
name=getattr(_module, "__plugin_name__", None) or plugin_name or "",
|
||||||
|
plugin_name=plugin_name or "",
|
||||||
|
sql_list=getattr(_module, "sql_list", []),
|
||||||
|
)
|
||||||
|
SQL_DICT[plugin_name] = SqlModel
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/exec_sql", dependencies=[authentication()], description="执行sql")
|
||||||
|
async def _(sql: SqlText, request: Request) -> Result:
|
||||||
|
ip = request.client.host if request.client else "unknown"
|
||||||
|
try:
|
||||||
|
if sql.sql.lower().startswith("select"):
|
||||||
|
db = Tortoise.get_connection("default")
|
||||||
|
res = await db.execute_query_dict(sql.sql)
|
||||||
|
return Result.ok(res, "执行成功啦!")
|
||||||
|
else:
|
||||||
|
result = await TestSQL.raw(sql.sql)
|
||||||
|
await SqlLog.add(ip or "0.0.0.0", sql.sql, str(result))
|
||||||
|
return Result.ok(info="执行成功啦!")
|
||||||
|
except OperationalError as e:
|
||||||
|
await SqlLog.add(ip or "0.0.0.0", sql.sql, str(e), False)
|
||||||
|
return Result.warning_(f"sql执行错误: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/get_sql_log", dependencies=[authentication()], description="sql日志列表")
|
||||||
|
async def _(query: QueryModel) -> Result:
|
||||||
|
data = await SqlLog.all().offset((query.index - 1) * query.size).limit(query.size)
|
||||||
|
return Result.ok(data)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/get_sql", dependencies=[authentication()], description="常用sql")
|
||||||
|
async def _(plugin_name: Optional[str] = None) -> Result:
|
||||||
|
if plugin_name:
|
||||||
|
return Result.ok(SQL_DICT.get(plugin_name))
|
||||||
|
return Result.ok(SQL_DICT)
|
||||||
23
plugins/web_ui/api/tabs/database/models/model.py
Normal file
23
plugins/web_ui/api/tabs/database/models/model.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from utils.models import CommonSql
|
||||||
|
|
||||||
|
|
||||||
|
class SqlText(BaseModel):
|
||||||
|
"""
|
||||||
|
sql语句
|
||||||
|
"""
|
||||||
|
|
||||||
|
sql: str
|
||||||
|
|
||||||
|
|
||||||
|
class SqlModel(BaseModel):
|
||||||
|
|
||||||
|
name: str
|
||||||
|
"""插件中文名称"""
|
||||||
|
plugin_name: str
|
||||||
|
"""插件名称"""
|
||||||
|
sql_list: List[CommonSql]
|
||||||
|
"""插件列表"""
|
||||||
40
plugins/web_ui/api/tabs/database/models/sql_log.py
Normal file
40
plugins/web_ui/api/tabs/database/models/sql_log.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
from typing import Optional, Union
|
||||||
|
|
||||||
|
from tortoise import fields
|
||||||
|
|
||||||
|
from services.db_context import Model
|
||||||
|
|
||||||
|
|
||||||
|
class SqlLog(Model):
|
||||||
|
|
||||||
|
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||||
|
"""自增id"""
|
||||||
|
ip = fields.CharField(255)
|
||||||
|
"""ip"""
|
||||||
|
sql = fields.CharField(255)
|
||||||
|
"""sql"""
|
||||||
|
result = fields.CharField(255, null=True)
|
||||||
|
"""结果"""
|
||||||
|
is_suc = fields.BooleanField(default=True)
|
||||||
|
"""是否成功"""
|
||||||
|
create_time = fields.DatetimeField(auto_now_add=True)
|
||||||
|
"""创建时间"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
table = "sql_log"
|
||||||
|
table_description = "sql执行日志"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def add(
|
||||||
|
cls, ip: str, sql: str, result: Optional[str] = None, is_suc: bool = True
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
说明:
|
||||||
|
获取用户在群内的等级
|
||||||
|
参数:
|
||||||
|
:param ip: ip
|
||||||
|
:param sql: sql
|
||||||
|
:param result: 返回结果
|
||||||
|
:param is_suc: 是否成功
|
||||||
|
"""
|
||||||
|
await cls.create(ip=ip, sql=sql, result=result, is_suc=is_suc)
|
||||||
@ -1,14 +1,16 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from logging import warning
|
from logging import warning
|
||||||
from typing import Any, Dict, List, Optional, TypeVar, Union
|
from typing import Any, Dict, Generic, List, Optional, TypeVar, Union
|
||||||
|
|
||||||
from nonebot.adapters.onebot.v11 import Bot
|
from nonebot.adapters.onebot.v11 import Bot
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel, validator
|
||||||
|
|
||||||
from configs.utils import Config
|
from configs.utils import Config
|
||||||
from utils.manager.models import Plugin as PluginManager
|
from utils.manager.models import Plugin as PluginManager
|
||||||
from utils.manager.models import PluginBlock, PluginCd, PluginCount, PluginSetting
|
from utils.manager.models import PluginBlock, PluginCd, PluginCount, PluginSetting
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
class User(BaseModel):
|
class User(BaseModel):
|
||||||
username: str
|
username: str
|
||||||
@ -49,6 +51,31 @@ class Result(BaseModel):
|
|||||||
return cls(suc=True, info=info, code=code, data=data)
|
return cls(suc=True, info=info, code=code, data=data)
|
||||||
|
|
||||||
|
|
||||||
|
class QueryModel(BaseModel, Generic[T]):
|
||||||
|
"""
|
||||||
|
基本查询条件
|
||||||
|
"""
|
||||||
|
|
||||||
|
index: int
|
||||||
|
"""页数"""
|
||||||
|
size: int
|
||||||
|
"""每页数量"""
|
||||||
|
data: T
|
||||||
|
"""携带数据"""
|
||||||
|
|
||||||
|
@validator("index")
|
||||||
|
def index_validator(cls, index):
|
||||||
|
if index < 1:
|
||||||
|
raise ValueError("查询下标小于1...")
|
||||||
|
return index
|
||||||
|
|
||||||
|
@validator("size")
|
||||||
|
def size_validator(cls, size):
|
||||||
|
if size < 1:
|
||||||
|
raise ValueError("每页数量小于1...")
|
||||||
|
return size
|
||||||
|
|
||||||
|
|
||||||
# class PluginConfig(BaseModel):
|
# class PluginConfig(BaseModel):
|
||||||
# """
|
# """
|
||||||
# 插件配置项
|
# 插件配置项
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user