Разделение сканирования на разные подсети. Хранение каждой из просканированных подсетей. Исправление багов с заметками и обновленные локали

This commit is contained in:
parent c326edfb9a
commit b1306ff66f
10 changed files with 1124 additions and 285 deletions

View file

@ -1,5 +1,6 @@
import os
import logging
from typing import Optional
from fastapi import APIRouter, HTTPException, Depends, Response, Request
from starlette.responses import FileResponse
from services.settings_service import SettingsService
@ -13,12 +14,14 @@ router = APIRouter()
settings_service = SettingsService()
@router.post("/clear_subnet")
def clear_subnet(translations: Translations = Depends(get_translations())):
def clear_subnet(subnet: Optional[str] = None, translations: Translations = Depends(get_translations())):
"""Очищает данные узлов подсети, сохранённые в devices.json.
Удаляет все записи об узлах подсети, оставляя файл пустым.
Args:
subnet (Optional[str]): Подсеть в формате CIDR (например, "10.1.1.0/24").
Если None, очищает все подсети.
translations: Объект переводов для текущего языка.
Returns:
@ -28,9 +31,12 @@ def clear_subnet(translations: Translations = Depends(get_translations())):
HTTPException: Если произошла ошибка очистки (status_code=500).
"""
try:
success = settings_service.clear_subnet()
success = settings_service.clear_subnet(subnet)
if success:
return {"message": translations.gettext("Данные узлов подсети успешно очищены")}
if subnet:
return {"message": translations.gettext("Данные узлов подсети {subnet} успешно очищены").format(subnet=subnet)}
else:
return {"message": translations.gettext("Данные всех подсетей успешно очищены")}
else:
raise HTTPException(status_code=500, detail=translations.gettext("Не удалось очистить данные узлов подсети"))
except Exception as e:
@ -91,26 +97,28 @@ DEVICE_PATH = "storage/devices/devices.json"
WIFI_PATH = "storage/wifi/wifi.json"
@router.get("/export_devices", response_class=FileResponse)
async def export_devices(translations: Translations = Depends(get_translations())):
async def export_devices(subnet: str, translations: Translations = Depends(get_translations())):
"""
Экспортирует файл с данными устройств в формате JSON.
Экспортирует файл с данными устройств в формате JSON для указанной подсети.
Args:
subnet (str): Подсеть в формате CIDR (например, "10.1.1.0/24").
translations: Объект переводов для текущего языка.
Returns:
FileResponse: Файл devices.json для скачивания.
FileResponse: Файл <subnet>.json для скачивания.
Raises:
HTTPException: Если файл не найден (status_code=404).
"""
if not os.path.exists(DEVICE_PATH):
logger.warning(f"Export file not found: {DEVICE_PATH}")
file_path = f"storage/subnets/{subnet.replace('/', '_')}.json"
if not os.path.exists(file_path):
logger.warning(f"Export file not found: {file_path}")
raise HTTPException(status_code=404, detail=translations.gettext("Файл не найден"))
logger.info(f"Exporting file: {DEVICE_PATH}")
logger.info(f"Exporting file: {file_path}")
return FileResponse(
path=DEVICE_PATH,
filename="devices.json",
path=file_path,
filename=f"{subnet.replace('/', '_')}.json",
media_type="application/json"
)

View file

@ -2,7 +2,7 @@ from fastapi import APIRouter, HTTPException, Body, Depends
from models.subnet import SubnetScanResult, SubnetScanRequest
from models.wifi import WifiScanResult
from models.request import NoteRequest, WifiConnectRequest, WifiDisconnectRequest
from services.subnet_service import SubnetService
from services.subnet_service import SubnetService, get_subnet_service
from services.wifi_service import WifiService
from services.connect_service import WifiConnectionService
from utils.i18n import get_translations, _
@ -14,15 +14,15 @@ router = APIRouter()
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@router.post("/devices", response_model=SubnetScanResult)
def scan_subnet(request: SubnetScanRequest = Body(...), translations: Translations = Depends(get_translations())):
def scan_subnet(request: SubnetScanRequest = Body(...), subnet_service: SubnetService = Depends(get_subnet_service), translations: Translations = Depends(get_translations())):
"""Сканирует локальную подсеть и возвращает данные об устройствах.
Выполняет сканирование указанной подсети для обнаружения активных устройств.
Args:
request (SubnetScanRequest): Объект с полем subnet.
subnet_service: Сервис сканирования подсети.
translations: Объект переводов для текущего языка.
Returns:
@ -32,17 +32,16 @@ def scan_subnet(request: SubnetScanRequest = Body(...), translations: Translatio
HTTPException: Если произошла ошибка сканирования (status_code=500).
"""
try:
subnet_service = SubnetService()
# Если subnet пустая строка, определяем автоматически
subnet = request.subnet.strip() if request.subnet else None
logger.info(f"Requested subnet scan for: {subnet or 'auto-detected'}")
result = subnet_service.scan_subnet(subnet)
if not result.devices:
if not result.devices and result.error:
logger.warning(f"No devices found in subnet {subnet or 'auto-detected'}")
return result
except Exception as e:
logger.error(f"Error in scan_subnet: {str(e)}")
raise HTTPException(status_code=500, detail=translations.gettext("Ошибка сканирования: {error}").format(error=str(e)))
raise HTTPException(status_code=500, detail=translations.gettext("Ошибка сканирования подсети: {error}").format(error=str(e)))
@router.get("/wifi", response_model=WifiScanResult)
def scan_wifi(timeout: int = 30, translations: Translations = Depends(get_translations())):
@ -68,7 +67,7 @@ def scan_wifi(timeout: int = 30, translations: Translations = Depends(get_transl
raise HTTPException(status_code=500, detail=translations.gettext("Ошибка сканирования Wi-Fi: {error}").format(error=str(e)))
@router.post("/devices/{mac}/note")
def add_note(mac: str, request: NoteRequest, translations: Translations = Depends(get_translations())):
def add_note(mac: str, request: NoteRequest, subnet_service: SubnetService = Depends(get_subnet_service), translations: Translations = Depends(get_translations())):
"""Добавляет заметку для устройства по MAC-адресу.
Привязывает заметку к устройству, идентифицируемому по MAC-адресу.
@ -76,6 +75,7 @@ def add_note(mac: str, request: NoteRequest, translations: Translations = Depend
Args:
mac (str): MAC-адрес устройства.
request (NoteRequest): Объект с полем "note" для текста заметки.
subnet_service: Сервис сканирования подсети.
translations: Объект переводов для текущего языка.
Returns:
@ -86,13 +86,14 @@ def add_note(mac: str, request: NoteRequest, translations: Translations = Depend
существует (status_code=400), или произошла внутренняя ошибка (status_code=500).
"""
try:
subnet_service = SubnetService()
success, error_message = subnet_service.add_note(mac, request.note)
success, result = subnet_service.add_note(mac, request.note, translations)
if not success:
if "не найдено" in error_message.lower():
raise HTTPException(status_code=404, detail=translations.gettext(error_message))
elif "уже существует" in error_message.lower():
raise HTTPException(status_code=400, detail=translations.gettext(error_message))
if result[0] == "not_found":
raise HTTPException(status_code=404, detail=translations.gettext("Устройство с MAC {mac} не найдено").format(mac=mac))
elif result[0] == "note_exists":
raise HTTPException(status_code=400, detail=translations.gettext("Заметка для устройства с MAC {mac} уже существует").format(mac=mac))
else:
raise HTTPException(status_code=500, detail=translations.gettext("Внутренняя ошибка сервера: {error}").format(error=result[1]["error"]))
return {"message": translations.gettext("Заметка '{note}' добавлена для устройства {mac}").format(note=request.note, mac=mac)}
except HTTPException as e:
raise e
@ -100,7 +101,7 @@ def add_note(mac: str, request: NoteRequest, translations: Translations = Depend
raise HTTPException(status_code=500, detail=translations.gettext("Ошибка добавления заметки: {error}").format(error=str(e)))
@router.put("/devices/{mac}/note")
def update_note(mac: str, request: NoteRequest, translations: Translations = Depends(get_translations())):
def update_note(mac: str, request: NoteRequest, subnet_service: SubnetService = Depends(get_subnet_service), translations: Translations = Depends(get_translations())):
"""Обновляет заметку для устройства по MAC-адресу.
Изменяет существующую заметку, привязанную к устройству.
@ -108,6 +109,7 @@ def update_note(mac: str, request: NoteRequest, translations: Translations = Dep
Args:
mac (str): MAC-адрес устройства.
request (NoteRequest): Объект с полем "note" для нового текста заметки.
subnet_service: Сервис сканирования подсети.
translations: Объект переводов для текущего языка.
Returns:
@ -118,13 +120,14 @@ def update_note(mac: str, request: NoteRequest, translations: Translations = Dep
существует (status_code=400), или произошла внутренняя ошибка (status_code=500).
"""
try:
subnet_service = SubnetService()
success, error_message = subnet_service.update_note(mac, request.note)
success, result = subnet_service.update_note(mac, request.note, translations)
if not success:
if "не найдено" in error_message.lower():
raise HTTPException(status_code=404, detail=translations.gettext(error_message))
elif "не существует" in error_message.lower():
raise HTTPException(status_code=400, detail=translations.gettext(error_message))
if result[0] == "not_found":
raise HTTPException(status_code=404, detail=translations.gettext("Устройство с MAC {mac} не найдено").format(mac=mac))
elif result[0] == "note_not_exists":
raise HTTPException(status_code=400, detail=translations.gettext("Заметка для устройства с MAC {mac} не существует").format(mac=mac))
else:
raise HTTPException(status_code=500, detail=translations.gettext("Внутренняя ошибка сервера: {error}").format(error=result[1]["error"]))
return {"message": translations.gettext("Заметка '{note}' обновлена для устройства {mac}").format(note=request.note, mac=mac)}
except HTTPException as e:
raise e
@ -132,13 +135,14 @@ def update_note(mac: str, request: NoteRequest, translations: Translations = Dep
raise HTTPException(status_code=500, detail=translations.gettext("Ошибка обновления заметки: {error}").format(error=str(e)))
@router.delete("/devices/{mac}/note")
def delete_note(mac: str, translations: Translations = Depends(get_translations())):
def delete_note(mac: str, subnet_service: SubnetService = Depends(get_subnet_service), translations: Translations = Depends(get_translations())):
"""Удаляет заметку для устройства по MAC-адресу.
Удаляет привязанную заметку для указанного устройства.
Args:
mac (str): MAC-адрес устройства.
subnet_service: Сервис сканирования подсети.
translations: Объект переводов для текущего языка.
Returns:
@ -149,13 +153,14 @@ def delete_note(mac: str, translations: Translations = Depends(get_translations(
существует (status_code=400), или произошла внутренняя ошибка (status_code=500).
"""
try:
subnet_service = SubnetService()
success, error_message = subnet_service.delete_note(mac)
success, result = subnet_service.delete_note(mac, translations)
if not success:
if "не найдено" in error_message.lower():
raise HTTPException(status_code=404, detail=translations.gettext(error_message))
elif "не существует" in error_message.lower():
raise HTTPException(status_code=400, detail=translations.gettext(error_message))
if result[0] == "not_found":
raise HTTPException(status_code=404, detail=translations.gettext("Устройство с MAC {mac} не найдено").format(mac=mac))
elif result[0] == "note_not_exists":
raise HTTPException(status_code=400, detail=translations.gettext("Заметка для устройства с MAC {mac} не существует").format(mac=mac))
else:
raise HTTPException(status_code=500, detail=translations.gettext("Внутренняя ошибка сервера: {error}").format(error=result[1]["error"]))
return {"message": translations.gettext("Заметка удалена для устройства {mac}").format(mac=mac)}
except HTTPException as e:
raise e
@ -182,12 +187,14 @@ def add_wifi_note(ssid: str, request: NoteRequest, translations: Translations =
"""
try:
wifi_service = WifiService()
success, error_message = wifi_service.add_note(ssid, request.note)
success, result = wifi_service.add_note(ssid, request.note)
if not success:
if "не найдена" in error_message.lower():
raise HTTPException(status_code=404, detail=translations.gettext(error_message))
elif "уже существует" in error_message.lower():
raise HTTPException(status_code=400, detail=translations.gettext(error_message))
if result[0] == "not_found":
raise HTTPException(status_code=404, detail=translations.gettext("Сеть с SSID {ssid} не найдена").format(ssid=ssid))
elif result[0] == "note_exists":
raise HTTPException(status_code=400, detail=translations.gettext("Заметка для сети с SSID {ssid} уже существует").format(ssid=ssid))
else:
raise HTTPException(status_code=500, detail=translations.gettext("Внутренняя ошибка сервера: {error}").format(error=result[1]["error"]))
return {"message": translations.gettext("Заметка '{note}' добавлена для сети с SSID {ssid}").format(note=request.note, ssid=ssid)}
except HTTPException as e:
raise e
@ -214,12 +221,14 @@ def update_wifi_note(ssid: str, request: NoteRequest, translations: Translations
"""
try:
wifi_service = WifiService()
success, error_message = wifi_service.update_note(ssid, request.note)
success, result = wifi_service.update_note(ssid, request.note)
if not success:
if "не найдена" in error_message.lower():
raise HTTPException(status_code=404, detail=translations.gettext(error_message))
elif "не существует" in error_message.lower():
raise HTTPException(status_code=400, detail=translations.gettext(error_message))
if result[0] == "not_found":
raise HTTPException(status_code=404, detail=translations.gettext("Сеть с SSID {ssid} не найдена").format(ssid=ssid))
elif result[0] == "note_not_exists":
raise HTTPException(status_code=400, detail=translations.gettext("Заметка для сети с SSID {ssid} не существует").format(ssid=ssid))
else:
raise HTTPException(status_code=500, detail=translations.gettext("Внутренняя ошибка сервера: {error}").format(error=result[1]["error"]))
return {"message": translations.gettext("Заметка '{note}' обновлена для сети с SSID {ssid}").format(note=request.note, ssid=ssid)}
except HTTPException as e:
raise e
@ -245,12 +254,14 @@ def delete_wifi_note(ssid: str, translations: Translations = Depends(get_transla
"""
try:
wifi_service = WifiService()
success, error_message = wifi_service.delete_note(ssid)
success, result = wifi_service.delete_note(ssid)
if not success:
if "не найдена" in error_message.lower():
raise HTTPException(status_code=404, detail=translations.gettext(error_message))
elif "не существует" in error_message.lower():
raise HTTPException(status_code=400, detail=translations.gettext(error_message))
if result[0] == "not_found":
raise HTTPException(status_code=404, detail=translations.gettext("Сеть с SSID {ssid} не найдена").format(ssid=ssid))
elif result[0] == "note_not_exists":
raise HTTPException(status_code=400, detail=translations.gettext("Заметка для сети с SSID {ssid} не существует").format(ssid=ssid))
else:
raise HTTPException(status_code=500, detail=translations.gettext("Внутренняя ошибка сервера: {error}").format(error=result[1]["error"]))
return {"message": translations.gettext("Заметка удалена для сети с SSID {ssid}").format(ssid=ssid)}
except HTTPException as e:
raise e