```
feat(auth): 添加用户权限获取接口并完善JWT令牌角色信息 - 在JWT令牌中添加用户角色信息 - 新增get_my_permissions接口用于获取当前用户权限码列表 - 重构认证回调逻辑,增加错误日志记录 - 更新用户信息获取接口使用Authorization头验证 ```
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
"""审计日志 Celery 任务"""
|
||||
import traceback
|
||||
from app.core.celery_app import celery_app
|
||||
from app.core.database import SessionLocal
|
||||
|
||||
|
||||
@celery_app.task(queue='h3c_onu_ms', ignore_result=True)
|
||||
def create_audit_log_task(
|
||||
user_id: str,
|
||||
username: str,
|
||||
user_role: str,
|
||||
method: str,
|
||||
path: str,
|
||||
ip_address: str,
|
||||
user_agent: str,
|
||||
status_code: int,
|
||||
request_params: dict = None,
|
||||
response_data: dict = None,
|
||||
error_message: str = None,
|
||||
description: str = None,
|
||||
resource_id: str = None,
|
||||
resource_name: str = None,
|
||||
):
|
||||
"""异步写入审计日志,不阻塞主请求流程"""
|
||||
from app.services.audit_service import write_audit_log
|
||||
db = SessionLocal()
|
||||
try:
|
||||
write_audit_log(
|
||||
db,
|
||||
user_id=user_id,
|
||||
username=username,
|
||||
user_role=user_role,
|
||||
method=method,
|
||||
path=path,
|
||||
ip_address=ip_address,
|
||||
user_agent=user_agent,
|
||||
status_code=status_code,
|
||||
request_params=request_params,
|
||||
response_data=response_data,
|
||||
error_message=error_message,
|
||||
description=description,
|
||||
resource_id=resource_id,
|
||||
resource_name=resource_name,
|
||||
)
|
||||
except Exception:
|
||||
pass # 审计日志失败不影响主业务
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
@celery_app.task(queue='h3c_onu_ms')
|
||||
def cleanup_audit_logs_task():
|
||||
"""清理90天前的审计日志(每天执行)"""
|
||||
from app.services.audit_service import cleanup_old_logs
|
||||
db = SessionLocal()
|
||||
try:
|
||||
deleted = cleanup_old_logs(db)
|
||||
return {'success': True, 'deleted': deleted}
|
||||
except Exception as e:
|
||||
return {'success': False, 'error': str(e), 'traceback': traceback.format_exc()}
|
||||
finally:
|
||||
db.close()
|
||||
@@ -1,13 +1,56 @@
|
||||
"""状态检查任务"""
|
||||
import time
|
||||
import traceback
|
||||
import redis as redis_lib
|
||||
from datetime import datetime, timedelta
|
||||
from sqlalchemy import func, case
|
||||
from app.core.celery_app import celery_app
|
||||
from app.core.database import SessionLocal
|
||||
from app.core.config import settings
|
||||
from app.services.check_service import CheckService
|
||||
|
||||
_LAST_RUN_KEY = "check_all_devices:last_run"
|
||||
_RUNNING_KEY = "check_all_devices:running"
|
||||
_INTERVAL_REDIS_KEY = "system:check_interval_seconds"
|
||||
|
||||
|
||||
def _get_redis():
|
||||
return redis_lib.from_url(settings.REDIS_URL, decode_responses=True)
|
||||
|
||||
|
||||
def _get_check_interval(r) -> int:
|
||||
"""从 Redis 读取配置间隔,回退到 DB,再回退到默认值"""
|
||||
cached = r.get(_INTERVAL_REDIS_KEY)
|
||||
if cached:
|
||||
return int(cached)
|
||||
# 从 DB 读取并缓存
|
||||
db = SessionLocal()
|
||||
try:
|
||||
from app.models.setting import SystemSetting
|
||||
setting = db.query(SystemSetting).filter_by(key='check_interval_seconds').first()
|
||||
interval = int(setting.value) if setting else settings.CHECK_INTERVAL
|
||||
r.set(_INTERVAL_REDIS_KEY, str(interval))
|
||||
return interval
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
@celery_app.task(bind=True)
|
||||
def check_all_devices(self):
|
||||
"""检查所有设备状态"""
|
||||
"""检查所有设备状态(支持可配置间隔,最小5分钟)"""
|
||||
r = _get_redis()
|
||||
interval = _get_check_interval(r)
|
||||
|
||||
# Redis 节流:检查距上次运行是否已超过配置间隔
|
||||
last_run = r.get(_LAST_RUN_KEY)
|
||||
now = time.time()
|
||||
if last_run and (now - float(last_run)) < interval:
|
||||
remaining = int(interval - (now - float(last_run)))
|
||||
return {'skipped': True, 'reason': f'间隔未到,还需等待 {remaining} 秒', 'interval': interval}
|
||||
|
||||
# 标记正在运行(TTL 10分钟防止异常时永久卡住)
|
||||
r.set(_RUNNING_KEY, '1', ex=600)
|
||||
|
||||
db = SessionLocal()
|
||||
self.update_state(state='PROGRESS', meta={'current': 0, 'total': 0, 'status': '获取OLT列表...'})
|
||||
try:
|
||||
@@ -68,5 +111,66 @@ def check_all_devices(self):
|
||||
'error': str(e),
|
||||
'traceback': traceback.format_exc()
|
||||
}
|
||||
finally:
|
||||
# 任务完成后记录时间、清除运行标记
|
||||
r.set(_LAST_RUN_KEY, str(time.time()))
|
||||
r.delete(_RUNNING_KEY)
|
||||
db.close()
|
||||
|
||||
|
||||
@celery_app.task
|
||||
def aggregate_daily_snapshot():
|
||||
"""聚合昨日设备状态快照(每天凌晨执行)"""
|
||||
from app.models.device import DeviceStatusHistory, DeviceDailySnapshot, ONUDevice
|
||||
db = SessionLocal()
|
||||
try:
|
||||
yesterday = (datetime.utcnow() - timedelta(days=1)).date()
|
||||
date_str = yesterday.strftime('%Y-%m-%d')
|
||||
|
||||
# 如果已存在则跳过(幂等)
|
||||
exists = db.query(DeviceDailySnapshot).filter_by(snapshot_date=date_str).first()
|
||||
if exists:
|
||||
return {'skipped': True, 'date': date_str}
|
||||
|
||||
# 昨天每台设备的最后一次检查状态
|
||||
day_start = datetime.combine(yesterday, datetime.min.time())
|
||||
day_end = datetime.combine(yesterday, datetime.max.time())
|
||||
|
||||
daily_latest_subq = (
|
||||
db.query(
|
||||
DeviceStatusHistory.onu_device_id,
|
||||
func.max(DeviceStatusHistory.checked_at).label("max_checked_at"),
|
||||
)
|
||||
.filter(DeviceStatusHistory.checked_at.between(day_start, day_end))
|
||||
.group_by(DeviceStatusHistory.onu_device_id)
|
||||
.subquery()
|
||||
)
|
||||
|
||||
row = (
|
||||
db.query(
|
||||
func.count().label("total"),
|
||||
func.sum(case((DeviceStatusHistory.status == 'online', 1), else_=0)).label("online"),
|
||||
func.sum(case((DeviceStatusHistory.status == 'offline', 1), else_=0)).label("offline"),
|
||||
)
|
||||
.join(
|
||||
daily_latest_subq,
|
||||
(DeviceStatusHistory.onu_device_id == daily_latest_subq.c.onu_device_id) &
|
||||
(DeviceStatusHistory.checked_at == daily_latest_subq.c.max_checked_at)
|
||||
)
|
||||
.one()
|
||||
)
|
||||
|
||||
snapshot = DeviceDailySnapshot(
|
||||
snapshot_date=date_str,
|
||||
total=int(row.total or 0),
|
||||
online=int(row.online or 0),
|
||||
offline=int(row.offline or 0),
|
||||
)
|
||||
db.add(snapshot)
|
||||
db.commit()
|
||||
return {'success': True, 'date': date_str, 'total': snapshot.total, 'online': snapshot.online}
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
return {'success': False, 'error': str(e), 'traceback': traceback.format_exc()}
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
Reference in New Issue
Block a user