diff --git a/SRV/api/v1/subnet.py b/SRV/api/v1/subnet.py index 8884256..1942c62 100644 --- a/SRV/api/v1/subnet.py +++ b/SRV/api/v1/subnet.py @@ -1,16 +1,13 @@ from fastapi import APIRouter, HTTPException -from typing import List -from pydantic import BaseModel +from typing import List, Dict from models.subnet import SubnetScanResult from models.wifi import WifiScanResult +from models.request import NoteRequest from services.subnet_service import SubnetService from services.wifi_service import WifiService router = APIRouter() -class NoteRequest(BaseModel): - note: str - @router.get("/scan", response_model=SubnetScanResult) def scan_subnet(subnet: str = "192.168.1.0/24", ports: List[int] = None): """Сканирует локальную подсеть и возвращает данные об устройствах""" diff --git a/SRV/models/auth.py b/SRV/models/auth.py index 479f967..805a5b2 100644 --- a/SRV/models/auth.py +++ b/SRV/models/auth.py @@ -2,20 +2,52 @@ from pydantic import BaseModel from typing import Optional class UserCreate(BaseModel): + """ + Модель созданного пользователя + + Атрибуты: + username (str): Имя пользователя + password (str): Пароль пользователя + is_admin (bool): Административный доступ + """ username: str password: str is_admin: bool = False class UserLogin(BaseModel): + """ + Модель авторизации пользователя + + Атрибуты: + username (str): Имя пользователя + password (str): Пароль пользователя + """ username: str password: str class UserResponse(BaseModel): + """ + Модель проверки наличия пользователя + + Атрибуты: + id (int): Идентификатор + username (str): Имя пользователя + is_admin (bool): Административный доступ + """ id: int username: str is_admin: bool class Token(BaseModel): + """ + Токен пользователя + + Атрибуты: + access_token (str): Токен пользователя (захэширован) + token_type (str): Тип токена + session_id (Optional[str]): Идентификатор сессии + user (Optional[UserResponse]): Пользователь на основе проверки наличия пользователя + """ access_token: str token_type: str session_id: Optional[str] = None diff --git a/SRV/models/network.py b/SRV/models/network.py index 2dbc442..9589215 100644 --- a/SRV/models/network.py +++ b/SRV/models/network.py @@ -2,34 +2,82 @@ from typing import List, Optional, Union from pydantic import BaseModel -# Класс для маршрутов IPv4 class IPv4Route(BaseModel): + """ + Модель маршрута IPv4 + + Атрибуты: + destination (str): IP-адрес назначения + prefix (int): Префикс подсети в формате CIDR + next_hop (str): Адрес следующего узла (маршрутизатор) + metric (int): Метрика маршрута + """ destination: str prefix: int next_hop: str metric: int -# Класс для маршрутов IPv6 + class IPv6Route(BaseModel): + """ + Модель маршрута IPv6 + + Атрибуты: + destination (str): IP-адрес назначения + prefix (int): Префикс подсети (CIDR) + next_hop (str): Адрес следующего узла (маршрутизатор) + metric (int): Метрика маршрута + """ destination: str prefix: int next_hop: str metric: int -# Класс для индивидуальной конфигурации IP + class IndividualIPConfig(BaseModel): + """ + Модель индивидуальной конфигурации IP-адреса + + Атрибуты: + address (str): IP-адрес интерфейса + routes (List[Union[IPv4Route, IPv6Route]]): Список маршрутов (IPv4/IPv6) + method (Optional[str]): Метод назначения IP + gateway (str): Основной шлюз по умолчанию + dns (List[str]): Список DNS-серверов + """ address: str routes: List[Union[IPv4Route, IPv6Route]] method: Optional[str] gateway: str dns: List[str] -# Класс для конфигурации IP + class IPConfig(BaseModel): + """ + Модель конфигурации IP (IPv4/IPv6) + + Атрибуты: + configurations (List[IndividualIPConfig]): Список индивидуальных IP-конфигураций + """ configurations: List[IndividualIPConfig] -# Класс для сетевого интерфейса + class NetworkInterface(BaseModel): + """ + Модель базового сетевого интерфейса + + Атрибуты: + name (str): Название интерфейса + type (str): Тип интерфейса + mac_address (str): MAC-адрес устройства + device_state (str): Состояние устройства + active_connection (str): Название активного соединения + device_mtu (str): MTU устройства + ipv4 (IPConfig): Конфигурация IPv4 + ipv6 (IPConfig): Конфигурация IPv6 + container_x (int): Положение по X на холсте + container_y (int): Положение по Y на холсте + """ name: str type: str mac_address: str @@ -41,8 +89,19 @@ class NetworkInterface(BaseModel): container_x: int = 0 container_y: int = 0 -# Класс для WiFi устройства + class WiFiDevice(NetworkInterface): + """ + Модель Wi-Fi устройства (наследуется от NetworkInterface) + + Атрибуты: + ssid (Optional[str]): Название Wi-Fi сети + bssid (Optional[str]): MAC-адрес точки доступа + bitrate (Optional[int]): Скорость соединения + strength (Optional[int]): Уровень сигнала + frequency (Optional[float]): Частота + mode (Union[str, int]): Режим работы + """ ssid: Optional[str] = None bssid: Optional[str] = None bitrate: Optional[int] = None @@ -50,19 +109,50 @@ class WiFiDevice(NetworkInterface): frequency: Optional[float] = None mode: Union[str, int] = None + class NetworkInterfacesContainer(BaseModel): + """ + Контейнер для группы сетевых интерфейсов с координатами + + Атрибуты: + interfaces (List[Union[NetworkInterface, WiFiDevice]]): Список интерфейсов + container_x (int): Положение по оси X + container_y (int): Положение по оси Y + """ interfaces: List[Union[NetworkInterface, WiFiDevice]] container_x: int container_y: int + class Activation(BaseModel): + """ + Модель активированных интерфейсов + + Атрибуты: + id (int): Идентификатор ноды активированных интерфейсов + interfaces (List[Union[NetworkInterface, WiFiDevice]]): Активированные интерфейсы + container_x (int): Положение по X на холсте + container_y (int): Положение по Y на холсте + isOpen (bool): Флаг скрытия ноды на холсте + """ id: int interfaces: List[Union[NetworkInterface, WiFiDevice]] container_x: int container_y: int isOpen: bool = True + class Deactivation(BaseModel): + """ + Модель отключенных интерфейсов + + Атрибуты: + id (int): Идентификатор ноды отключенных интерфейсов + interfaces (List[Union[NetworkInterface, WiFiDevice]]): Отключенные интерфейсы + container_x (int): Положение по X на холсте + container_y (int): Положение по Y на холсте + isOpen (bool): Флаг скрытия ноды на холсте + """ id: int interfaces: List[Union[NetworkInterface, WiFiDevice]] container_x: int diff --git a/SRV/models/request.py b/SRV/models/request.py new file mode 100644 index 0000000..4f98e7f --- /dev/null +++ b/SRV/models/request.py @@ -0,0 +1,11 @@ +from pydantic import BaseModel + + +class NoteRequest(BaseModel): + """ + Модель добавления заметки к просканированному устройству + + Атрибуты: + note (str): Заметка устройства + """ + note: str \ No newline at end of file diff --git a/SRV/models/subnet.py b/SRV/models/subnet.py index 8ea9fa3..1e22ac4 100644 --- a/SRV/models/subnet.py +++ b/SRV/models/subnet.py @@ -2,6 +2,19 @@ from pydantic import BaseModel from typing import Optional, List class Device(BaseModel): + """ + Сканируемое устройство в подсети + + Атрибуты: + ip (str): IP-адрес устройства + mac (Optional[str]): MAC-адрес устройства + hostname (Optional[str]): Имя хоста + vendor (Optional[str]): Название производителя устройства (По MAC-адресу) + open_ports (List[str]): Открытые порты устройства + status (str): Статус устройства (онлайн/оффлайн) + last_seen (Optional[str]): Последняя активность устройства + note (Optional[str]): Заметка устройства + """ ip: str mac: Optional[str] = None hostname: Optional[str] = None @@ -12,4 +25,10 @@ class Device(BaseModel): note: Optional[str] = None class SubnetScanResult(BaseModel): + """ + Результат сканирования устройств в подсети + + Атрибуты: + devices (List[Device]): Список просканированных устройств + """ devices: List[Device] = [] \ No newline at end of file diff --git a/SRV/models/wifi.py b/SRV/models/wifi.py index 753e571..ee1b7ae 100644 --- a/SRV/models/wifi.py +++ b/SRV/models/wifi.py @@ -1,7 +1,21 @@ from pydantic import BaseModel from typing import Optional, List + class WifiAccessPoint(BaseModel): + """ + Модель точки доступа Wi-Fi + + Атрибуты: + ssid (Optional[str]): Название точки доступа. Может быть скрытым + bssid (str): Уникальный идентификатор точки доступа (по типу MAC-адреса) + channel (Optional[int]): Канал, на котором работает точка доступа + signal (Optional[int]): Уровень сигнала (dBm) + encryption (Optional[str]): Тип шифрования (WPA2, WPA3, открытая и т.д.) + frequency (Optional[str]): Частота вещания (2.4GHz/5GHz) + vendor (Optional[str]): Производитель точки доступа (определяется по MAC-адресу) + hidden (bool): Флаг скрытия названия точки доступа (ssid) + """ ssid: Optional[str] = None bssid: str channel: Optional[int] = None @@ -11,5 +25,12 @@ class WifiAccessPoint(BaseModel): vendor: Optional[str] = None hidden: bool = False + class WifiScanResult(BaseModel): - access_points: List[WifiAccessPoint] \ No newline at end of file + """ + Результат сканирования Wi-Fi + + Атрибуты: + access_points (List[WifiAccessPoint]): Список найденных Wi-Fi точек доступа + """ + access_points: List[WifiAccessPoint] diff --git a/SRV/services/wifi_service.py b/SRV/services/wifi_service.py index 7a5894c..ffd2b5e 100644 --- a/SRV/services/wifi_service.py +++ b/SRV/services/wifi_service.py @@ -6,6 +6,7 @@ from functools import lru_cache from typing import List, Optional, Dict from mac_vendor_lookup import MacLookup import pywifi +from pywifi import Profile from models.wifi import WifiAccessPoint, WifiScanResult logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s") @@ -184,7 +185,7 @@ class WifiService: iw_results = self._get_iw_scan_data() iw_by_bssid = {ap['bssid']: ap for ap in iw_results if ap.get('bssid')} - best_aps_by_ssid: Dict[str, WifiAccessPoint] = {} # Сделал словарь чтобы агрегировать точки доступа у сетей для выявления лучшего + best_aps_by_ssid: Dict[str, WifiAccessPoint] = {} # Сделал словарь, чтобы агрегировать точки доступа у сетей для выявления лучшего for ap in py_results: bssid = ap.bssid.lower() if ap.bssid else None if not bssid: