增加API鉴权

This commit is contained in:
jeremygan2021
2025-11-16 18:00:28 +08:00
parent bb04bd8fa5
commit b7a8a86e53
23 changed files with 343 additions and 52 deletions

View File

@@ -1,4 +1,4 @@
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi import APIRouter, Depends, HTTPException, status, Security
from sqlalchemy.orm import Session
from typing import List, Optional
from datetime import datetime
@@ -9,13 +9,13 @@ from schemas import Device as DeviceSchema, DeviceCreate, DeviceUpdate, Bootstra
from models import Device as DeviceModel
from database import Content as ContentModel
from mqtt_manager import mqtt_manager
from auth import get_api_key
router = APIRouter(
prefix="/api/devices",
tags=["devices"]
)
@router.post("/", response_model=DeviceSchema, status_code=status.HTTP_201_CREATED)
@router.post("/", response_model=DeviceSchema, status_code=status.HTTP_201_CREATED, dependencies=[Depends(get_api_key)])
async def create_device(device: DeviceCreate, db: Session = Depends(get_db)):
"""
注册新设备
@@ -46,7 +46,7 @@ async def create_device(device: DeviceCreate, db: Session = Depends(get_db)):
return db_device
@router.get("/", response_model=List[DeviceSchema])
@router.get("/", response_model=List[DeviceSchema], dependencies=[Depends(get_api_key)])
async def list_devices(
skip: int = 0,
limit: int = 100,
@@ -68,7 +68,7 @@ async def list_devices(
devices = query.offset(skip).limit(limit).all()
return devices
@router.get("/{device_id}", response_model=DeviceSchema)
@router.get("/{device_id}", response_model=DeviceSchema, dependencies=[Depends(get_api_key)])
async def get_device(device_id: str, db: Session = Depends(get_db)):
"""
获取设备详情
@@ -81,7 +81,7 @@ async def get_device(device_id: str, db: Session = Depends(get_db)):
)
return device
@router.put("/{device_id}", response_model=DeviceSchema)
@router.put("/{device_id}", response_model=DeviceSchema, dependencies=[Depends(get_api_key)])
async def update_device(
device_id: str,
device_update: DeviceUpdate,
@@ -108,7 +108,7 @@ async def update_device(
return device
@router.delete("/{device_id}", status_code=status.HTTP_204_NO_CONTENT)
@router.delete("/{device_id}", status_code=status.HTTP_204_NO_CONTENT, dependencies=[Depends(get_api_key)])
async def delete_device(device_id: str, db: Session = Depends(get_db)):
"""
删除设备
@@ -126,11 +126,12 @@ async def delete_device(device_id: str, db: Session = Depends(get_db)):
db.delete(device)
db.commit()
@router.get("/{device_id}/bootstrap", response_model=BootstrapResponse)
async def device_bootstrap(device_id: str, db: Session = Depends(get_db)):
@router.post("/{device_id}/bootstrap", response_model=BootstrapResponse, dependencies=[Depends(get_api_key)])
async def bootstrap_device(device_id: str, db: Session = Depends(get_db)):
"""
设备启动获取当前版本信息
设备引导 - 获取设备配置和内容
"""
# 验证设备是否存在
device = db.query(DeviceModel).filter(DeviceModel.device_id == device_id).first()
if not device:
raise HTTPException(
@@ -138,29 +139,19 @@ async def device_bootstrap(device_id: str, db: Session = Depends(get_db)):
detail="设备不存在"
)
# 更新设备最后在线时间
device.last_online = datetime.utcnow()
db.commit()
# 获取最新的活跃内容
latest_content = db.query(ContentModel).filter(
ContentModel.device_id == device_id,
ContentModel.is_active == True
).order_by(ContentModel.version.desc()).first()
# 获取设备场景的内容
contents = db.query(ContentModel).filter(ContentModel.scene == device.scene).all()
# 构建响应
response = BootstrapResponse(
device_id=device_id,
timezone=latest_content.timezone if latest_content else "Asia/Shanghai",
time_format=latest_content.time_format if latest_content else "%Y-%m-%d %H:%M"
scene=device.scene,
contents=contents
)
if latest_content:
response.content_version = latest_content.version
response.last_updated = latest_content.created_at
return response
@router.get("/{device_id}/status")
@router.get("/{device_id}/status", dependencies=[Depends(get_api_key)])
async def get_device_status(device_id: str, db: Session = Depends(get_db)):
"""
获取设备状态