```
feat(auth): 添加用户权限获取接口并完善JWT令牌角色信息 - 在JWT令牌中添加用户角色信息 - 新增get_my_permissions接口用于获取当前用户权限码列表 - 重构认证回调逻辑,增加错误日志记录 - 更新用户信息获取接口使用Authorization头验证 ```
This commit is contained in:
+163
-12
@@ -5,7 +5,8 @@ from sqlalchemy import asc, desc, distinct, or_
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
from app.core.database import get_db
|
||||
from app.models.device import ONUDevice, DeviceStatusHistory, OLTDevice
|
||||
from app.middleware.permission_middleware import require_permission
|
||||
from app.models.device import ONUDevice, DeviceStatusHistory, OLTDevice, DeviceReplacement
|
||||
from app.schemas.device import DeviceListResponse, ONUDeviceResponse
|
||||
|
||||
router = APIRouter(prefix="/api/devices", tags=["设备管理"])
|
||||
@@ -18,8 +19,9 @@ def get_devices(
|
||||
region: str = None,
|
||||
school_name: str = None,
|
||||
keyword: str = None,
|
||||
status: str = None, # online / offline
|
||||
db: Session = Depends(get_db)
|
||||
status: str = None,
|
||||
db: Session = Depends(get_db),
|
||||
current: dict = Depends(require_permission('device.view')),
|
||||
):
|
||||
"""获取设备列表"""
|
||||
# 子查询:每台设备最新一条状态记录
|
||||
@@ -44,6 +46,24 @@ def get_devices(
|
||||
|
||||
query = db.query(ONUDevice)
|
||||
|
||||
# 数据范围过滤:区域管理员只能看自己分配的区域,学校管理员只能看自己分配的学校
|
||||
role = current.get('role', 'user')
|
||||
if role == 'area_admin':
|
||||
assigned = current.get('assigned_area') or ''
|
||||
areas = [a.strip() for a in assigned.split(',') if a.strip()]
|
||||
if areas:
|
||||
query = query.filter(ONUDevice.region.in_(areas))
|
||||
else:
|
||||
# 未分配区域则看不到任何设备
|
||||
query = query.filter(False)
|
||||
elif role == 'school_admin':
|
||||
assigned = current.get('assigned_school') or ''
|
||||
schools = [s.strip() for s in assigned.split(',') if s.strip()]
|
||||
if schools:
|
||||
query = query.filter(ONUDevice.school_name.in_(schools))
|
||||
else:
|
||||
query = query.filter(False)
|
||||
|
||||
if region:
|
||||
query = query.filter(ONUDevice.region == region)
|
||||
if school_name:
|
||||
@@ -141,17 +161,55 @@ def get_devices(
|
||||
|
||||
|
||||
@router.get("/regions")
|
||||
def get_regions(db: Session = Depends(get_db)):
|
||||
"""获取所有区域列表"""
|
||||
regions = db.query(distinct(ONUDevice.region)).filter(
|
||||
def get_regions(
|
||||
db: Session = Depends(get_db),
|
||||
current: dict = Depends(require_permission('device.view')),
|
||||
):
|
||||
"""获取所有区域列表(受角色数据范围限制)"""
|
||||
role = current.get('role', 'user')
|
||||
query = db.query(distinct(ONUDevice.region)).filter(
|
||||
ONUDevice.region.isnot(None),
|
||||
ONUDevice.region != ''
|
||||
).order_by(ONUDevice.region).all()
|
||||
return [r[0] for r in regions]
|
||||
)
|
||||
if role == 'area_admin':
|
||||
assigned = current.get('assigned_area') or ''
|
||||
areas = [a.strip() for a in assigned.split(',') if a.strip()]
|
||||
if areas:
|
||||
query = query.filter(ONUDevice.region.in_(areas))
|
||||
else:
|
||||
return []
|
||||
elif role == 'school_admin':
|
||||
assigned = current.get('assigned_school') or ''
|
||||
schools = [s.strip() for s in assigned.split(',') if s.strip()]
|
||||
if schools:
|
||||
query = query.filter(ONUDevice.school_name.in_(schools))
|
||||
else:
|
||||
return []
|
||||
return [r[0] for r in query.order_by(ONUDevice.region).all()]
|
||||
|
||||
|
||||
@router.get("/schools")
|
||||
def get_schools(
|
||||
region: str = None,
|
||||
db: Session = Depends(get_db),
|
||||
_: dict = Depends(require_permission('device.view')),
|
||||
):
|
||||
"""获取所有学校列表(可按区域筛选)"""
|
||||
query = db.query(distinct(ONUDevice.school_name)).filter(
|
||||
ONUDevice.school_name.isnot(None),
|
||||
ONUDevice.school_name != ''
|
||||
)
|
||||
if region:
|
||||
query = query.filter(ONUDevice.region == region)
|
||||
return [r[0] for r in query.order_by(ONUDevice.school_name).all()]
|
||||
|
||||
|
||||
@router.get("/{device_id}", response_model=ONUDeviceResponse)
|
||||
def get_device(device_id: int, db: Session = Depends(get_db)):
|
||||
def get_device(
|
||||
device_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
_: dict = Depends(require_permission('device.view')),
|
||||
):
|
||||
"""获取设备详情"""
|
||||
device = db.query(ONUDevice).filter(ONUDevice.id == device_id).first()
|
||||
if not device:
|
||||
@@ -186,7 +244,11 @@ def get_device(device_id: int, db: Session = Depends(get_db)):
|
||||
|
||||
|
||||
@router.post("/{device_id}/refresh")
|
||||
def refresh_device_status(device_id: int, db: Session = Depends(get_db)):
|
||||
def refresh_device_status(
|
||||
device_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
_: dict = Depends(require_permission('device.check')),
|
||||
):
|
||||
"""通过 SSH 单独更新一台设备的状态和距离"""
|
||||
from app.services.check_service import CheckService
|
||||
try:
|
||||
@@ -206,8 +268,16 @@ class DeviceUpdate(BaseModel):
|
||||
notes: Optional[str] = None
|
||||
|
||||
|
||||
class DeviceReplaceRequest(BaseModel):
|
||||
new_mac: str
|
||||
reason: Optional[str] = None
|
||||
|
||||
|
||||
@router.delete("/status/all")
|
||||
def clear_all_status(db: Session = Depends(get_db)):
|
||||
def clear_all_status(
|
||||
db: Session = Depends(get_db),
|
||||
_: dict = Depends(require_permission('device.delete')),
|
||||
):
|
||||
"""清空所有设备状态历史记录"""
|
||||
db.query(DeviceStatusHistory).delete()
|
||||
db.commit()
|
||||
@@ -215,7 +285,12 @@ def clear_all_status(db: Session = Depends(get_db)):
|
||||
|
||||
|
||||
@router.put("/{device_id}")
|
||||
def update_device(device_id: int, body: DeviceUpdate, db: Session = Depends(get_db)):
|
||||
def update_device(
|
||||
device_id: int,
|
||||
body: DeviceUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
_: dict = Depends(require_permission('device.edit')),
|
||||
):
|
||||
"""更新设备信息(区域、学校、楼宇、房间号、备注)"""
|
||||
device = db.query(ONUDevice).filter(ONUDevice.id == device_id).first()
|
||||
if not device:
|
||||
@@ -229,3 +304,79 @@ def update_device(device_id: int, body: DeviceUpdate, db: Session = Depends(get_
|
||||
return {"message": "更新成功"}
|
||||
|
||||
|
||||
@router.post("/{device_id}/replace")
|
||||
def replace_device(
|
||||
device_id: int,
|
||||
body: DeviceReplaceRequest,
|
||||
db: Session = Depends(get_db),
|
||||
current: dict = Depends(require_permission('device.edit')),
|
||||
):
|
||||
"""更换设备 MAC 地址,并记录更换历史"""
|
||||
from datetime import datetime
|
||||
device = db.query(ONUDevice).filter(ONUDevice.id == device_id).first()
|
||||
if not device:
|
||||
raise HTTPException(status_code=404, detail="设备不存在")
|
||||
|
||||
new_mac = body.new_mac.upper().strip()
|
||||
# 校验 MAC 格式(允许 XX:XX:XX:XX:XX:XX 或 XXXXXXXXXXXX)
|
||||
import re
|
||||
if not re.match(r'^([0-9A-F]{2}[:-]){5}[0-9A-F]{2}$|^[0-9A-F]{12}$', new_mac):
|
||||
raise HTTPException(status_code=400, detail="MAC 地址格式不正确")
|
||||
|
||||
# 检查新 MAC 是否已被其他设备使用
|
||||
existing = db.query(ONUDevice).filter(
|
||||
ONUDevice.mac_address == new_mac,
|
||||
ONUDevice.id != device_id
|
||||
).first()
|
||||
if existing:
|
||||
raise HTTPException(status_code=400, detail="该 MAC 地址已被其他设备使用")
|
||||
|
||||
# 同步更新库存序列号设备的 onu_device_id 关联(如有)
|
||||
from app.models.inventory import SerialDevice
|
||||
old_serial = db.query(SerialDevice).filter(SerialDevice.onu_device_id == device_id).first()
|
||||
if old_serial:
|
||||
old_serial.onu_device_id = None
|
||||
old_serial.status = "returned"
|
||||
new_serial = db.query(SerialDevice).filter(SerialDevice.mac_address == new_mac).first()
|
||||
if new_serial:
|
||||
new_serial.onu_device_id = device_id
|
||||
new_serial.status = "in_use"
|
||||
|
||||
record = DeviceReplacement(
|
||||
onu_device_id=device_id,
|
||||
old_mac=device.mac_address,
|
||||
new_mac=new_mac,
|
||||
reason=body.reason or None,
|
||||
operator_id=current.get("sub", ""),
|
||||
operator_name=current.get("username", ""),
|
||||
replaced_at=datetime.utcnow(),
|
||||
)
|
||||
db.add(record)
|
||||
device.mac_address = new_mac
|
||||
db.commit()
|
||||
return {"message": "更换成功", "old_mac": record.old_mac, "new_mac": new_mac}
|
||||
|
||||
|
||||
@router.get("/{device_id}/replacements")
|
||||
def get_device_replacements(
|
||||
device_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
_: dict = Depends(require_permission('device.view')),
|
||||
):
|
||||
"""获取设备更换历史"""
|
||||
records = db.query(DeviceReplacement).filter(
|
||||
DeviceReplacement.onu_device_id == device_id
|
||||
).order_by(DeviceReplacement.replaced_at.desc()).all()
|
||||
return [
|
||||
{
|
||||
"id": r.id,
|
||||
"old_mac": r.old_mac,
|
||||
"new_mac": r.new_mac,
|
||||
"reason": r.reason,
|
||||
"operator_name": r.operator_name,
|
||||
"replaced_at": r.replaced_at,
|
||||
}
|
||||
for r in records
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user