Версия 0.0.3
This commit is contained in:
parent
413e9c57be
commit
8c7d0609df
189 changed files with 52063 additions and 2769 deletions
|
|
@ -1,23 +1,62 @@
|
|||
# models.py
|
||||
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
|
||||
user: Optional[UserResponse] = None
|
||||
user: Optional[UserResponse] = None
|
||||
|
|
|
|||
|
|
@ -25,42 +25,35 @@ class FirewallZone(BaseModel):
|
|||
"""Represents a firewalld zone configuration"""
|
||||
|
||||
name: Annotated[str, StringConstraints(min_length=1)] = Field(
|
||||
..., description="Name of the zone"
|
||||
)
|
||||
target: Optional[FirewallTarget] = Field(
|
||||
default=FirewallTarget.DEFAULT, description="Zone target type"
|
||||
)
|
||||
services: List[str] = Field(
|
||||
default_factory=list, description="List of enabled services"
|
||||
)
|
||||
ports: List[str] = Field(default_factory=list, description="List of enabled ports")
|
||||
sources: List[str] = Field(
|
||||
default_factory=list, description="List of source addresses"
|
||||
)
|
||||
interfaces: List[str] = Field(
|
||||
default_factory=list, description="List of network interfaces"
|
||||
)
|
||||
..., description="Name of the zone")
|
||||
target: Optional[FirewallTarget] = Field(default=FirewallTarget.DEFAULT,
|
||||
description="Zone target type")
|
||||
services: List[str] = Field(default_factory=list,
|
||||
description="List of enabled services")
|
||||
ports: List[str] = Field(default_factory=list,
|
||||
description="List of enabled ports")
|
||||
sources: List[str] = Field(default_factory=list,
|
||||
description="List of source addresses")
|
||||
interfaces: List[str] = Field(default_factory=list,
|
||||
description="List of network interfaces")
|
||||
|
||||
|
||||
class FirewallService(BaseModel):
|
||||
"""Represents a firewalld service configuration"""
|
||||
|
||||
name: Annotated[str, StringConstraints(min_length=1)] = Field(
|
||||
..., description="Name of the service"
|
||||
)
|
||||
ports: List[str] = Field(
|
||||
default_factory=list, description="List of ports used by the service"
|
||||
)
|
||||
..., description="Name of the service")
|
||||
ports: List[str] = Field(default_factory=list,
|
||||
description="List of ports used by the service")
|
||||
protocols: List[str] = Field(
|
||||
default_factory=list, description="List of protocols used by the service"
|
||||
)
|
||||
default_factory=list,
|
||||
description="List of protocols used by the service")
|
||||
modules: List[str] = Field(
|
||||
default_factory=list,
|
||||
description="List of kernel modules required by the service",
|
||||
)
|
||||
timeout: Optional[int] = Field(
|
||||
default=0, ge=0, description="Timeout in seconds (0 for permanent)"
|
||||
)
|
||||
default=0, ge=0, description="Timeout in seconds (0 for permanent)")
|
||||
|
||||
|
||||
class FirewallPort(BaseModel):
|
||||
|
|
@ -69,8 +62,7 @@ class FirewallPort(BaseModel):
|
|||
port: int = Field(..., ge=1, le=65535, description="Port number (1-65535)")
|
||||
protocol: Protocol = Field(..., description="Network protocol (tcp/udp)")
|
||||
timeout: Optional[int] = Field(
|
||||
default=0, ge=0, description="Timeout in seconds (0 for permanent)"
|
||||
)
|
||||
default=0, ge=0, description="Timeout in seconds (0 for permanent)")
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.port}/{self.protocol.value}"
|
||||
|
|
@ -81,9 +73,11 @@ class FirewallSource(BaseModel):
|
|||
|
||||
address: Annotated[
|
||||
str,
|
||||
StringConstraints(pattern=r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}(?:/[0-9]{1,2})?$"),
|
||||
StringConstraints(
|
||||
pattern=r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}(?:/[0-9]{1,2})?$"),
|
||||
] = Field(..., description="IP address or network in CIDR notation")
|
||||
zone: Optional[str] = Field(default=None, description="Zone name for the source")
|
||||
zone: Optional[str] = Field(default=None,
|
||||
description="Zone name for the source")
|
||||
|
||||
@field_validator("address")
|
||||
def validate_ip_address(cls, v):
|
||||
|
|
@ -106,10 +100,10 @@ class FirewallRule(BaseModel):
|
|||
|
||||
zone: str = Field(..., description="Zone name")
|
||||
source: Optional[FirewallSource] = Field(
|
||||
default=None, description="Source configuration"
|
||||
)
|
||||
port: Optional[FirewallPort] = Field(default=None, description="Port configuration")
|
||||
default=None, description="Source configuration")
|
||||
port: Optional[FirewallPort] = Field(default=None,
|
||||
description="Port configuration")
|
||||
service: Optional[str] = Field(default=None, description="Service name")
|
||||
timeout: Optional[int] = Field(
|
||||
default=0, ge=0, description="Rule timeout in seconds"
|
||||
)
|
||||
timeout: Optional[int] = Field(default=0,
|
||||
ge=0,
|
||||
description="Rule timeout in seconds")
|
||||
|
|
|
|||
|
|
@ -2,34 +2,87 @@ 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 +94,20 @@ 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 +115,53 @@ 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
|
||||
|
|
|
|||
32
SRV/models/request.py
Normal file
32
SRV/models/request.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class NoteRequest(BaseModel):
|
||||
"""
|
||||
Модель добавления заметки к просканированному устройству
|
||||
|
||||
Атрибуты:
|
||||
note (str): Заметка устройства
|
||||
"""
|
||||
|
||||
note: str
|
||||
|
||||
class WifiConnectRequest(BaseModel):
|
||||
"""
|
||||
Модель для подключения к точке доступа Wi-Fi
|
||||
|
||||
Атрибуты:
|
||||
ssid (str): Название точки доступа Wi-Fi
|
||||
password (str): Пароль точки доступа Wi-Fi
|
||||
"""
|
||||
ssid: str
|
||||
password: str
|
||||
|
||||
class WifiDisconnectRequest(BaseModel):
|
||||
"""
|
||||
Модель для отключения от точки доступа Wi-Fi
|
||||
|
||||
Атрибуты:
|
||||
ssid (str): Название точки доступа Wi-Fi
|
||||
"""
|
||||
ssid: str
|
||||
38
SRV/models/subnet.py
Normal file
38
SRV/models/subnet.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
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
|
||||
vendor: Optional[str] = None
|
||||
open_ports: List[str] = []
|
||||
status: str
|
||||
last_seen: Optional[str] = None
|
||||
note: Optional[str] = None
|
||||
|
||||
|
||||
class SubnetScanResult(BaseModel):
|
||||
"""
|
||||
Результат сканирования устройств в подсети
|
||||
|
||||
Атрибуты:
|
||||
devices (List[Device]): Список просканированных устройств
|
||||
"""
|
||||
|
||||
devices: List[Device] = []
|
||||
|
|
@ -8,6 +8,7 @@ class Protocol(str, Enum):
|
|||
"""
|
||||
Enum для сетевых протоколов UFW.
|
||||
"""
|
||||
|
||||
TCP = "tcp"
|
||||
UDP = "udp"
|
||||
BOTH = "both"
|
||||
|
|
@ -21,12 +22,13 @@ class Protocol(str, Enum):
|
|||
class Action(str, Enum):
|
||||
"""
|
||||
Enum для действий UFW.
|
||||
|
||||
|
||||
Attributes:
|
||||
ALLOW: Разрешить трафик
|
||||
DENY: Запретить трафик без уведомления
|
||||
REJECT: Запретить трафик с уведомлением отправителю
|
||||
"""
|
||||
|
||||
ALLOW = "allow"
|
||||
DENY = "deny"
|
||||
REJECT = "reject"
|
||||
|
|
@ -35,17 +37,19 @@ class Action(str, Enum):
|
|||
class Direction(str, Enum):
|
||||
"""
|
||||
Enum для направления трафика UFW.
|
||||
|
||||
|
||||
Attributes:
|
||||
IN: Входящий трафик
|
||||
OUT: Исходящий трафик
|
||||
"""
|
||||
|
||||
IN = "in"
|
||||
OUT = "out"
|
||||
|
||||
|
||||
class UFWRule(BaseModel):
|
||||
"""Модель правила UFW"""
|
||||
|
||||
action: Action
|
||||
direction: Direction
|
||||
from_ip: str
|
||||
|
|
@ -58,30 +62,35 @@ class UFWRule(BaseModel):
|
|||
def validate_port(cls, v):
|
||||
"""
|
||||
Проверяет корректность порта или диапазона портов.
|
||||
|
||||
|
||||
Args:
|
||||
v: Порт (число) или диапазон портов (строка вида "3000:3999")
|
||||
|
||||
|
||||
Returns:
|
||||
Union[int, str]: Валидированное значение порта
|
||||
|
||||
|
||||
Raises:
|
||||
ValueError: Если порт или диапазон портов некорректен
|
||||
"""
|
||||
if isinstance(v, int):
|
||||
if not (1 <= v <= 65535):
|
||||
raise ValueError(f"Порт должен быть в диапазоне 1-65535, получено: {v}")
|
||||
raise ValueError(
|
||||
f"Порт должен быть в диапазоне 1-65535, получено: {v}")
|
||||
return v
|
||||
elif isinstance(v, str):
|
||||
try:
|
||||
start, end = map(int, v.split(':'))
|
||||
start, end = map(int, v.split(":"))
|
||||
if not (1 <= start <= end <= 65535):
|
||||
raise ValueError
|
||||
return v
|
||||
except (ValueError, TypeError):
|
||||
raise ValueError(f"Некорректный диапазон портов: {v}. Формат: start:end, где 1 <= start <= end <= 65535")
|
||||
raise ValueError(
|
||||
f"Некорректный диапазон портов: {v}. Формат: start:end, где 1 <= start <= end <= 65535"
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Порт должен быть числом или строкой с диапазоном, получено: {type(v)}")
|
||||
raise ValueError(
|
||||
f"Порт должен быть числом или строкой с диапазоном, получено: {type(v)}"
|
||||
)
|
||||
|
||||
@validator("from_ip", "to_ip")
|
||||
def validate_ip(cls, v):
|
||||
|
|
@ -98,14 +107,17 @@ class UFWRule(BaseModel):
|
|||
"""Проверяет совместимость версий IP адресов"""
|
||||
if "from_ip" not in values:
|
||||
return v
|
||||
|
||||
|
||||
# Определяем версии IP
|
||||
from_ip = ipaddress.ip_network(values["from_ip"], strict=False)
|
||||
to_ip = ipaddress.ip_network(v, strict=False)
|
||||
|
||||
if isinstance(from_ip, ipaddress.IPv6Network) != isinstance(to_ip, ipaddress.IPv6Network):
|
||||
raise ValueError("Несовместимые версии IP: нельзя смешивать IPv4 и IPv6 в одном правиле")
|
||||
|
||||
|
||||
if isinstance(from_ip, ipaddress.IPv6Network) != isinstance(
|
||||
to_ip, ipaddress.IPv6Network):
|
||||
raise ValueError(
|
||||
"Несовместимые версии IP: нельзя смешивать IPv4 и IPv6 в одном правиле"
|
||||
)
|
||||
|
||||
return v
|
||||
|
||||
@validator("action", pre=True)
|
||||
|
|
@ -125,44 +137,45 @@ class UFWRule(BaseModel):
|
|||
def to_ufw_command(self) -> str:
|
||||
"""Преобразует правило в команду UFW."""
|
||||
cmd_parts = ["ufw"]
|
||||
|
||||
|
||||
# Добавляем действие
|
||||
cmd_parts.append(self.action.value)
|
||||
|
||||
|
||||
# Добавляем направление
|
||||
cmd_parts.append(self.direction.value)
|
||||
|
||||
|
||||
# Добавляем from с IP
|
||||
cmd_parts.extend(["from", self.from_ip])
|
||||
|
||||
|
||||
# Добавляем to с IP
|
||||
cmd_parts.extend(["to", self.to_ip])
|
||||
|
||||
|
||||
# Добавляем порт и протокол
|
||||
port_str = str(self.port) # Работает как с числами, так и с диапазонами
|
||||
port_str = str(
|
||||
self.port) # Работает как с числами, так и с диапазонами
|
||||
cmd_parts.extend(["port", port_str])
|
||||
|
||||
|
||||
# Добавляем протокол
|
||||
proto = self.protocol.value
|
||||
if proto == "both":
|
||||
cmd_parts.append("proto tcp/udp")
|
||||
else:
|
||||
cmd_parts.extend(["proto", proto])
|
||||
|
||||
|
||||
# Добавляем комментарий если есть
|
||||
if self.comment:
|
||||
cmd_parts.extend(["comment", f"'{self.comment}'"])
|
||||
|
||||
|
||||
return " ".join(cmd_parts)
|
||||
|
||||
@classmethod
|
||||
def from_ufw_output(cls, line: str) -> "UFWRule":
|
||||
"""
|
||||
Создает экземпляр UFWRule из строки вывода команды 'ufw status numbered'.
|
||||
|
||||
|
||||
Args:
|
||||
line: Строка вывода UFW (например, "[1] 80/tcp ALLOW IN 192.168.1.0/24 # Web Server")
|
||||
|
||||
|
||||
Returns:
|
||||
UFWRule: Новый экземпляр правила
|
||||
"""
|
||||
|
|
@ -180,47 +193,49 @@ class UFWRule(BaseModel):
|
|||
(?:\#\s*(?P<comment>.*?))?
|
||||
\s*$
|
||||
"""
|
||||
|
||||
|
||||
match = re.match(pattern, line, re.VERBOSE | re.IGNORECASE)
|
||||
if not match:
|
||||
raise ValueError(f"Невозможно разобрать строку правила UFW: {line}")
|
||||
|
||||
raise ValueError(
|
||||
f"Невозможно разобрать строку правила UFW: {line}")
|
||||
|
||||
groups = match.groupdict()
|
||||
|
||||
|
||||
# Преобразуем протокол в enum
|
||||
proto_str = groups['protocol'].lower()
|
||||
protocol = Protocol.BOTH if proto_str == "tcp/udp" else \
|
||||
Protocol.UDP if proto_str == "udp" else Protocol.TCP
|
||||
|
||||
proto_str = groups["protocol"].lower()
|
||||
protocol = (Protocol.BOTH if proto_str == "tcp/udp" else
|
||||
Protocol.UDP if proto_str == "udp" else Protocol.TCP)
|
||||
|
||||
# Преобразуем действие в enum (игнорируем регистр)
|
||||
action_str = groups['action'].lower()
|
||||
action = Action.ALLOW if action_str == "allow" else \
|
||||
Action.DENY if action_str == "deny" else Action.REJECT
|
||||
|
||||
action_str = groups["action"].lower()
|
||||
action = (Action.ALLOW if action_str == "allow" else
|
||||
Action.DENY if action_str == "deny" else Action.REJECT)
|
||||
|
||||
# Преобразуем направление в enum
|
||||
direction_str = groups['direction'].lower()
|
||||
direction_str = groups["direction"].lower()
|
||||
direction = Direction.IN if direction_str == "in" else Direction.OUT
|
||||
|
||||
|
||||
# Обрабатываем IP адреса
|
||||
from_ip = groups['from_ip'].strip()
|
||||
from_ip = groups["from_ip"].strip()
|
||||
if from_ip.lower() == "anywhere":
|
||||
from_ip = "0.0.0.0/0"
|
||||
|
||||
|
||||
# Для исходящих правил меняем местами from и to
|
||||
to_ip = "0.0.0.0/0" # По умолчанию anywhere
|
||||
|
||||
|
||||
# Обрабатываем порт
|
||||
port = groups['port']
|
||||
if ':' in port:
|
||||
port = groups["port"]
|
||||
if ":" in port:
|
||||
# Оставляем как строку для диапазона
|
||||
port = port.strip()
|
||||
else:
|
||||
# Преобразуем в число для одиночного порта
|
||||
port = int(port)
|
||||
|
||||
|
||||
# Обрабатываем комментарий
|
||||
comment = groups.get('comment', '').strip() if groups.get('comment') else None
|
||||
|
||||
comment = groups.get("comment",
|
||||
"").strip() if groups.get("comment") else None
|
||||
|
||||
return cls(
|
||||
action=action,
|
||||
direction=direction,
|
||||
|
|
@ -228,22 +243,24 @@ class UFWRule(BaseModel):
|
|||
to_ip=to_ip,
|
||||
port=port,
|
||||
protocol=protocol,
|
||||
comment=comment
|
||||
comment=comment,
|
||||
)
|
||||
|
||||
|
||||
class UFWRulesResponse(BaseModel):
|
||||
"""
|
||||
Модель для представления списка правил UFW.
|
||||
|
||||
|
||||
Attributes:
|
||||
enabled: Включен ли UFW
|
||||
rules: Список правил UFW
|
||||
total_rules: Общее количество правил
|
||||
"""
|
||||
|
||||
enabled: bool = Field(..., description="Включен ли UFW")
|
||||
rules: List[UFWRule] = Field(default_factory=list, description="Список правил UFW")
|
||||
|
||||
rules: List[UFWRule] = Field(default_factory=list,
|
||||
description="Список правил UFW")
|
||||
|
||||
@property
|
||||
def total_rules(self) -> int:
|
||||
"""Возвращает общее количество правил."""
|
||||
|
|
@ -253,11 +270,12 @@ class UFWRulesResponse(BaseModel):
|
|||
class UFWStatus(BaseModel):
|
||||
"""
|
||||
Модель для представления статуса UFW.
|
||||
|
||||
|
||||
Attributes:
|
||||
enabled: Включен ли UFW
|
||||
message: Сообщение о статусе
|
||||
last_checked: Время последней проверки статуса
|
||||
"""
|
||||
|
||||
enabled: bool = Field(..., description="Включен ли UFW")
|
||||
message: str = Field(..., description="Сообщение о статусе")
|
||||
|
|
|
|||
40
SRV/models/wifi.py
Normal file
40
SRV/models/wifi.py
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
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)
|
||||
note (Optional[str]): Заметка для точки доступа
|
||||
"""
|
||||
|
||||
ssid: Optional[str] = None
|
||||
bssid: str
|
||||
channel: Optional[int] = None
|
||||
signal: Optional[int] = None
|
||||
encryption: Optional[str] = None
|
||||
frequency: Optional[str] = None
|
||||
vendor: Optional[str] = None
|
||||
hidden: bool = False
|
||||
note: Optional[str] = None
|
||||
|
||||
|
||||
class WifiScanResult(BaseModel):
|
||||
"""
|
||||
Результат сканирования Wi-Fi
|
||||
|
||||
Атрибуты:
|
||||
access_points (List[WifiAccessPoint]): Список найденных Wi-Fi точек доступа
|
||||
"""
|
||||
|
||||
access_points: List[WifiAccessPoint]
|
||||
Loading…
Add table
Add a link
Reference in a new issue