Files
ipam/backend/app/api/v1/ips.py
T
Your Name 1e1e5957e8 fix(ipam): 修复IP管理页面网段筛选不生效及下拉框过窄
- Ips.vue: el-select 添加 width: 280px,修复网段下拉框过窄
- Ips.vue: query 参数 networkId → network_id(与 FastAPI snake_case 一致)
- Scan.vue: el-select 用 network.id 代替整个 network 对象作为 value,修复切换网段不生效
- enhanced_scan_service.py: 替换失效的 scapy ARP 扫描为 arp-scan 命令;扫描结果自动创建缺失 IP 记录
2026-07-18 09:45:30 +08:00

162 lines
5.0 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy.orm import Session
from typing import Optional
from app.core.database import get_db
from app.core.security import get_current_user
from app.models.auth import User
from app.schemas.network import IPAddressListResponse, IPAddressUpdate, IPAddress
from app.models.network import IPStatus
from app.services.ip_service import IPService
from app.services.audit_service import AuditService, AuditAction
router = APIRouter(
prefix="/ips",
tags=["IP地址管理"],
dependencies=[Depends(get_current_user)],
)
def _client_info(request: Request) -> tuple[str, str]:
return (
request.client.host if request.client else "",
(request.headers.get("user-agent") or "")[:500],
)
@router.get("", response_model=IPAddressListResponse, summary="获取IP列表")
def get_ips(
network_id: Optional[int] = None,
status: Optional[IPStatus] = None,
search: Optional[str] = None,
skip: int = 0,
limit: int = 100,
db: Session = Depends(get_db)
):
"""获取IP地址列表,支持过滤和搜索"""
total, items = IPService.get_list(
db,
network_id=network_id,
status=status,
skip=skip,
limit=limit,
search=search
)
return {"total": total, "items": items}
@router.get("/{ip_id}", response_model=IPAddress, summary="获取IP详情")
def get_ip(ip_id: int, db: Session = Depends(get_db)):
"""根据ID获取IP详情"""
ip = IPService.get_by_id(db, ip_id)
if not ip:
raise HTTPException(status_code=404, detail="IP不存在")
return ip
@router.get("/address/{ip_address}", response_model=IPAddress, summary="根据IP地址查询")
def get_ip_by_address(ip_address: str, db: Session = Depends(get_db)):
"""根据IP地址查询详细信息"""
ip = IPService.get_by_ip(db, ip_address)
if not ip:
raise HTTPException(status_code=404, detail="IP不存在")
return ip
@router.put("/{ip_id}", response_model=IPAddress, summary="更新IP信息")
def update_ip(
ip_id: int,
ip_in: IPAddressUpdate,
request: Request,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""更新IP地址的属性信息"""
old = IPService.get_by_id(db, ip_id)
if not old:
raise HTTPException(status_code=404, detail="IP不存在")
ip = IPService.update(db, ip_id, ip_in)
if not ip:
raise HTTPException(status_code=404, detail="IP不存在")
c, u = _client_info(request)
AuditService.record(
db,
action=AuditAction.IP_UPDATE,
user=current_user,
resource_type="ip",
resource_id=str(ip.id),
resource_name=ip.ip_address,
method="PUT",
path=str(request.url.path),
ip_address=c,
user_agent=u,
detail={
"before": {
"owner": old.owner, "hostname": old.hostname, "mac_address": old.mac_address,
"vendor": old.vendor, "status": old.status.value if old.status else None,
"notes": old.notes, "switch_name": old.switch_name, "switch_port": old.switch_port,
},
"after": {
"owner": ip.owner, "hostname": ip.hostname, "mac_address": ip.mac_address,
"vendor": ip.vendor, "status": ip.status.value if ip.status else None,
"notes": ip.notes, "switch_name": ip.switch_name, "switch_port": ip.switch_port,
},
},
)
return ip
@router.post("/{ip_id}/reserve", response_model=IPAddress, summary="标记为保留IP")
def reserve_ip(
ip_id: int,
request: Request,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""将IP标记为保留状态,禁止分配"""
ip = IPService.set_reserved(db, ip_id, reserved=True)
if not ip:
raise HTTPException(status_code=404, detail="IP不存在")
c, u = _client_info(request)
AuditService.record(
db,
action=AuditAction.IP_RESERVE,
user=current_user,
resource_type="ip",
resource_id=str(ip.id),
resource_name=ip.ip_address,
method="POST",
path=str(request.url.path),
ip_address=c,
user_agent=u,
)
return ip
@router.post("/{ip_id}/unreserve", response_model=IPAddress, summary="取消保留IP")
def unreserve_ip(
ip_id: int,
request: Request,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""取消IP的保留状态"""
ip = IPService.set_reserved(db, ip_id, reserved=False)
if not ip:
raise HTTPException(status_code=404, detail="IP不存在")
c, u = _client_info(request)
AuditService.record(
db,
action=AuditAction.IP_UNRESERVE,
user=current_user,
resource_type="ip",
resource_id=str(ip.id),
resource_name=ip.ip_address,
method="POST",
path=str(request.url.path),
ip_address=c,
user_agent=u,
)
return ip