feat: Support recording system operation logs (#651)

This commit is contained in:
王嘉豪
2025-12-22 17:34:01 +08:00
committed by GitHub
parent cefd74da86
commit f1cdbc9a00
5 changed files with 99 additions and 1 deletions
@@ -0,0 +1,43 @@
"""empty message
Revision ID: 3d4bd2d673dc
Revises: 24e961f6326b
Create Date: 2025-12-19 13:30:54.743171
"""
from alembic import op
import sqlalchemy as sa
import sqlmodel.sql.sqltypes
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = '3d4bd2d673dc'
down_revision = '24e961f6326b'
branch_labels = None
depends_on = None
def upgrade():
op.create_table('sys_logs',
sa.Column('id', sa.BIGINT(), autoincrement=True, nullable=False),
sa.Column('operation_type', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('operation_detail', sa.TEXT(), autoincrement=False, nullable=True),
sa.Column('user_id', sa.BIGINT(), autoincrement=False, nullable=True),
sa.Column('operation_status', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('oid', sa.BIGINT(), autoincrement=False, nullable=True),
sa.Column('ip_address', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('user_agent', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('execution_time', sa.BIGINT(), autoincrement=False, nullable=True),
sa.Column('error_message', sa.TEXT(), autoincrement=False, nullable=True),
sa.Column('create_time', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
sa.Column('module', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('remark', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('resource_id',sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('request_method', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('request_path', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.PrimaryKeyConstraint('id', name=op.f('sys_logs_pkey'))
)
def downgrade():
op.drop_table('sys_logs')
+14
View File
@@ -21,6 +21,8 @@ from apps.system.schemas.permission import SqlbotPermission, require_permissions
from common.core.deps import CurrentAssistant, SessionDep, CurrentUser, Trans
from common.utils.command_utils import parse_quick_command
from common.utils.data_format import DataFormat
from sqlbot_xpack.audit.models.log_model import OperationType, OperationDetails, OperationModules
from sqlbot_xpack.audit.schemas.logger_decorator import system_log, LogConfig
router = APIRouter(tags=["Data Q&A"], prefix="/chat")
@@ -80,6 +82,12 @@ async def rename(session: SessionDep, chat: RenameChat):
@router.delete("/{chart_id}", response_model=str, summary=f"{PLACEHOLDER_PREFIX}delete_chat")
@system_log(LogConfig(
operation_type=OperationType.DELETE_QA,
operation_detail=OperationDetails.DELETE_QA_DETAILS,
module=OperationModules.QA,
resource_id_expr="chart_id"
))
async def delete(session: SessionDep, chart_id: int):
try:
return delete_chat(session=session, chart_id=chart_id)
@@ -92,6 +100,12 @@ async def delete(session: SessionDep, chart_id: int):
@router.post("/start", response_model=ChatInfo, summary=f"{PLACEHOLDER_PREFIX}start_chat")
@require_permissions(permission=SqlbotPermission(type='ds', keyExpression="create_chat_obj.datasource"))
@system_log(LogConfig(
operation_type=OperationType.CREATE_QA,
operation_detail=OperationDetails.CREATE_QA_DETAILS,
module=OperationModules.QA,
result_id_expr="id"
))
async def start_chat(session: SessionDep, current_user: CurrentUser, create_chat_obj: CreateChat):
try:
return create_chat(session, current_user, create_chat_obj)
@@ -3,6 +3,8 @@ from fastapi import APIRouter, File, UploadFile, HTTPException
from apps.dashboard.crud.dashboard_service import list_resource, load_resource, \
create_resource, create_canvas, validate_name, delete_resource, update_resource, update_canvas
from apps.dashboard.models.dashboard_model import CreateDashboard, BaseDashboard, QueryDashboard, DashboardResponse
from sqlbot_xpack.audit.models.log_model import OperationType, OperationDetails, OperationModules
from sqlbot_xpack.audit.schemas.logger_decorator import system_log, LogConfig
from common.core.deps import SessionDep, CurrentUser
router = APIRouter(tags=["dashboard"], prefix="/dashboard")
@@ -29,16 +31,34 @@ async def update_resource_api(session: SessionDep, user: CurrentUser, dashboard:
@router.delete("/delete_resource/{resource_id}")
@system_log(LogConfig(
operation_type=OperationType.DELETE_DASHBOARD,
operation_detail=OperationDetails.DELETE_DASHBOARD_DETAILS,
module=OperationModules.DASHBOARD,
resource_id_expr="resource_id"
))
async def delete_resource_api(session: SessionDep, resource_id: str):
return delete_resource(session, resource_id)
@router.post("/create_canvas", response_model=BaseDashboard)
@system_log(LogConfig(
operation_type=OperationType.CREATE_DASHBOARD,
operation_detail=OperationDetails.CREATE_DASHBOARD_DETAILS,
module=OperationModules.DASHBOARD,
result_id_expr="id"
))
async def create_canvas_api(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
return create_canvas(session, user, dashboard)
@router.post("/update_canvas", response_model=BaseDashboard)
@system_log(LogConfig(
operation_type=OperationType.UPDATE_DASHBOARD,
operation_detail=OperationDetails.UPDATE_DASHBOARD_DETAILS,
module=OperationModules.DASHBOARD,
resource_id_expr="dashboard.id"
))
async def update_canvas_api(session: SessionDep, user: CurrentUser, dashboard: CreateDashboard):
return update_canvas(session, user, dashboard)
+20 -1
View File
@@ -28,7 +28,8 @@ from ..crud.field import get_fields_by_table_id
from ..crud.table import get_tables_by_ds_id
from ..models.datasource import CoreDatasource, CreateDatasource, TableObj, CoreTable, CoreField, FieldObj, \
TableSchemaResponse, ColumnSchemaResponse, PreviewResponse
from sqlbot_xpack.audit.models.log_model import OperationType, OperationDetails, OperationModules
from sqlbot_xpack.audit.schemas.logger_decorator import system_log, LogConfig
router = APIRouter(tags=["Datasource"], prefix="/datasource")
path = settings.EXCEL_PATH
@@ -69,6 +70,12 @@ async def check_by_id(session: SessionDep, trans: Trans,
@router.post("/add", response_model=CoreDatasource, summary=f"{PLACEHOLDER_PREFIX}ds_add")
@system_log(LogConfig(
operation_type=OperationType.CREATE_DATASOURCE,
operation_detail=OperationDetails.CREATE_DATASOURCE_DETAILS,
module=OperationModules.DATASOURCE,
result_id_expr="id"
))
async def add(session: SessionDep, trans: Trans, user: CurrentUser, ds: CreateDatasource):
def inner():
return create_ds(session, trans, user, ds)
@@ -87,6 +94,12 @@ async def choose_tables(session: SessionDep, trans: Trans, tables: List[CoreTabl
@router.post("/update", response_model=CoreDatasource, summary=f"{PLACEHOLDER_PREFIX}ds_update")
@require_permissions(permission=SqlbotPermission(type='ds', keyExpression="ds.id"))
@system_log(LogConfig(
operation_type=OperationType.UPDATE_DATASOURCE,
operation_detail=OperationDetails.UPDATE_DATASOURCE_DETAILS,
module=OperationModules.DATASOURCE,
resource_id_expr="ds.id"
))
async def update(session: SessionDep, trans: Trans, user: CurrentUser, ds: CoreDatasource):
def inner():
return update_ds(session, trans, user, ds)
@@ -96,6 +109,12 @@ async def update(session: SessionDep, trans: Trans, user: CurrentUser, ds: CoreD
@router.post("/delete/{id}", response_model=None, summary=f"{PLACEHOLDER_PREFIX}ds_delete")
@require_permissions(permission=SqlbotPermission(type='ds', keyExpression="id"))
@system_log(LogConfig(
operation_type=OperationType.DELETE_DATASOURCE,
operation_detail=OperationDetails.DELETE_DATASOURCE_DETAILS,
module=OperationModules.DATASOURCE,
resource_id_expr="id"
))
async def delete(session: SessionDep, id: int = Path(..., description=f"{PLACEHOLDER_PREFIX}ds_id")):
return delete_ds(session, id)
+2
View File
@@ -21,6 +21,7 @@ from apps.system.crud.aimodel_manage import async_model_info
from apps.system.crud.assistant import init_dynamic_cors
from apps.system.middleware.auth import TokenMiddleware
from apps.system.schemas.permission import RequestContextMiddleware
from sqlbot_xpack.audit.schemas.request_context import RequestContextMiddlewareCommon
from common.core.config import settings
from common.core.response_middleware import ResponseMiddleware, exception_handler
from common.core.sqlbot_cache import init_sqlbot_cache
@@ -201,6 +202,7 @@ if settings.all_cors_origins:
app.add_middleware(TokenMiddleware)
app.add_middleware(ResponseMiddleware)
app.add_middleware(RequestContextMiddleware)
app.add_middleware(RequestContextMiddlewareCommon)
app.include_router(api_router, prefix=settings.API_V1_STR)
# Register exception handlers