This commit is contained in:
parent 06a5a758a3
commit 58fa7d1ee6
19 changed files with 567 additions and 377 deletions

View file

@ -26,9 +26,8 @@ async def register(user: UserCreate):
raise e
except Exception as e:
logger.error(f"Ошибка в register: {type(e).__name__} - {str(e)}")
raise HTTPException(
status_code=500, detail="Не удалось зарегистрировать пользователя"
)
raise HTTPException(status_code=500,
detail="Не удалось зарегистрировать пользователя")
@router.post("/login", response_model=Token)
@ -46,9 +45,8 @@ async def login(user: UserLogin, request: Request):
raise e
except Exception as e:
logger.error(f"Ошибка в login: {type(e).__name__} - {str(e)}")
raise HTTPException(
status_code=500, detail="Не удалось авторизовать пользователя"
)
raise HTTPException(status_code=500,
detail="Не удалось авторизовать пользователя")
@router.get("/me")
@ -66,10 +64,10 @@ async def get_current_user(request: Request):
except HTTPException as e:
raise e
except Exception as e:
logger.error(f"Ошибка в get_current_user: {type(e).__name__} - {str(e)}")
raise HTTPException(
status_code=500, detail="Не удалось получить данные пользователя"
)
logger.error(
f"Ошибка в get_current_user: {type(e).__name__} - {str(e)}")
raise HTTPException(status_code=500,
detail="Не удалось получить данные пользователя")
@router.get("/logout")
@ -83,7 +81,8 @@ async def logout(request: Request):
raise e
except Exception as e:
logger.error(f"Ошибка в logout: {type(e).__name__} - {str(e)}")
raise HTTPException(status_code=500, detail="Не удалось выйти из системы")
raise HTTPException(status_code=500,
detail="Не удалось выйти из системы")
@router.get("/check_json")
@ -104,21 +103,28 @@ async def check_users_file():
data = storage._read_data()
has_users = len(data.get("users", [])) > 0
if has_users:
logger.info(f"Файл {file_path} существует и содержит пользователей")
logger.info(
f"Файл {file_path} существует и содержит пользователей")
return {
"exists": True,
"has_users": True,
"message": "Файл users.json существует и содержит пользователей",
"message":
"Файл users.json существует и содержит пользователей",
}
else:
logger.info(f"Файл {file_path} существует, но не содержит пользователей")
logger.info(
f"Файл {file_path} существует, но не содержит пользователей")
return {
"exists": True,
"has_users": False,
"message": "Файл users.json существует, но не содержит пользователей",
"exists":
True,
"has_users":
False,
"message":
"Файл users.json существует, но не содержит пользователей",
}
except Exception as e:
logger.error(
f"Ошибка при проверке файла users.json: {type(e).__name__} - {str(e)}"
)
raise HTTPException(status_code=500, detail="Ошибка при проверке файла")
raise HTTPException(status_code=500,
detail="Ошибка при проверке файла")

View file

@ -31,7 +31,9 @@ class SuccessResponse(BaseModel):
@router.get(
"/zones",
response_model=List[str],
responses={500: {"model": ErrorResponse}},
responses={500: {
"model": ErrorResponse
}},
summary="Get all available zones",
)
async def get_zones() -> List[str]:
@ -53,7 +55,9 @@ async def get_zones() -> List[str]:
@router.get(
"/zones/default",
response_model=str,
responses={500: {"model": ErrorResponse}},
responses={500: {
"model": ErrorResponse
}},
summary="Get default zone",
)
async def get_default_zone() -> str:
@ -75,7 +79,14 @@ async def get_default_zone() -> str:
@router.put(
"/zones/default/{zone}",
response_model=SuccessResponse,
responses={404: {"model": ErrorResponse}, 500: {"model": ErrorResponse}},
responses={
404: {
"model": ErrorResponse
},
500: {
"model": ErrorResponse
}
},
summary="Set default zone",
)
async def set_default_zone(
@ -94,9 +105,8 @@ async def set_default_zone(
firewalld.set_default_zone(zone)
return SuccessResponse(message=f"Default zone set to {zone}")
except ValueError:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=f"Zone '{zone}' not found"
)
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
detail=f"Zone '{zone}' not found")
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
@ -107,10 +117,18 @@ async def set_default_zone(
@router.get(
"/zones/{zone}",
response_model=FirewallZone,
responses={404: {"model": ErrorResponse}, 500: {"model": ErrorResponse}},
responses={
404: {
"model": ErrorResponse
},
500: {
"model": ErrorResponse
}
},
summary="Get zone configuration",
)
async def get_zone(zone: str = Path(..., description="Zone name")) -> FirewallZone:
async def get_zone(zone: str = Path(...,
description="Zone name")) -> FirewallZone:
"""
Get detailed configuration for a specific zone.
@ -122,13 +140,13 @@ async def get_zone(zone: str = Path(..., description="Zone name")) -> FirewallZo
"""
try:
zone_info = firewalld.get_zone_settings(zone)
return FirewallZone(
name=zone, target=FirewallTarget.DEFAULT, interfaces=[], **zone_info
)
return FirewallZone(name=zone,
target=FirewallTarget.DEFAULT,
interfaces=[],
**zone_info)
except ValueError:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=f"Zone '{zone}' not found"
)
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
detail=f"Zone '{zone}' not found")
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
@ -139,10 +157,13 @@ async def get_zone(zone: str = Path(..., description="Zone name")) -> FirewallZo
@router.get(
"/zones/{zone}/services",
response_model=List[str],
responses={500: {"model": ErrorResponse}},
responses={500: {
"model": ErrorResponse
}},
summary="Get services in zone",
)
async def get_services(zone: str = Path(..., description="Zone name")) -> List[str]:
async def get_services(zone: str = Path(...,
description="Zone name")) -> List[str]:
"""
Get all services in a zone.
@ -164,7 +185,14 @@ async def get_services(zone: str = Path(..., description="Zone name")) -> List[s
@router.post(
"/zones/{zone}/services",
response_model=SuccessResponse,
responses={404: {"model": ErrorResponse}, 500: {"model": ErrorResponse}},
responses={
404: {
"model": ErrorResponse
},
500: {
"model": ErrorResponse
}
},
summary="Add service to zone",
)
async def add_service(
@ -183,11 +211,11 @@ async def add_service(
"""
try:
firewalld.add_service(zone, rule.name, rule.timeout)
return SuccessResponse(message=f"Service {rule.name} added to zone {zone}")
return SuccessResponse(
message=f"Service {rule.name} added to zone {zone}")
except ValueError:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=f"Zone '{zone}' not found"
)
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
detail=f"Zone '{zone}' not found")
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
@ -198,12 +226,19 @@ async def add_service(
@router.delete(
"/zones/{zone}/services/{service}",
response_model=SuccessResponse,
responses={404: {"model": ErrorResponse}, 500: {"model": ErrorResponse}},
responses={
404: {
"model": ErrorResponse
},
500: {
"model": ErrorResponse
}
},
summary="Remove service from zone",
)
async def remove_service(
zone: str = Path(..., description="Zone name"),
service: str = Path(..., description="Service name"),
zone: str = Path(..., description="Zone name"),
service: str = Path(..., description="Service name"),
) -> SuccessResponse:
"""
Remove a service from a zone.
@ -217,7 +252,8 @@ async def remove_service(
"""
try:
firewalld.remove_service(zone, service)
return SuccessResponse(message=f"Service {service} removed from zone {zone}")
return SuccessResponse(
message=f"Service {service} removed from zone {zone}")
except ValueError:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
@ -233,10 +269,13 @@ async def remove_service(
@router.get(
"/zones/{zone}/ports",
response_model=List[str],
responses={500: {"model": ErrorResponse}},
responses={500: {
"model": ErrorResponse
}},
summary="Get ports in zone",
)
async def get_ports(zone: str = Path(..., description="Zone name")) -> List[str]:
async def get_ports(zone: str = Path(...,
description="Zone name")) -> List[str]:
"""
Get all ports in a zone.
@ -259,9 +298,15 @@ async def get_ports(zone: str = Path(..., description="Zone name")) -> List[str]
"/zones/{zone}/ports",
response_model=SuccessResponse,
responses={
400: {"model": ErrorResponse},
404: {"model": ErrorResponse},
500: {"model": ErrorResponse},
400: {
"model": ErrorResponse
},
404: {
"model": ErrorResponse
},
500: {
"model": ErrorResponse
},
},
summary="Add port to zone",
)
@ -282,10 +327,11 @@ async def add_port(
try:
firewalld.add_port(zone, rule.port, rule.protocol.value, rule.timeout)
return SuccessResponse(
message=f"Port {rule.port}/{rule.protocol.value} added to zone {zone}"
)
message=
f"Port {rule.port}/{rule.protocol.value} added to zone {zone}")
except ValueError as e:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e))
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
@ -296,7 +342,14 @@ async def add_port(
@router.delete(
"/zones/{zone}/ports",
response_model=SuccessResponse,
responses={404: {"model": ErrorResponse}, 500: {"model": ErrorResponse}},
responses={
404: {
"model": ErrorResponse
},
500: {
"model": ErrorResponse
}
},
summary="Remove port from zone",
)
async def remove_port(
@ -316,12 +369,11 @@ async def remove_port(
try:
firewalld.remove_port(zone, rule.port, rule.protocol.value)
return SuccessResponse(
message=f"Port {rule.port}/{rule.protocol.value} removed from zone {zone}"
)
message=
f"Port {rule.port}/{rule.protocol.value} removed from zone {zone}")
except ValueError:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=f"Zone '{zone}' not found"
)
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
detail=f"Zone '{zone}' not found")
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
@ -332,10 +384,13 @@ async def remove_port(
@router.get(
"/zones/{zone}/sources",
response_model=List[str],
responses={500: {"model": ErrorResponse}},
responses={500: {
"model": ErrorResponse
}},
summary="Get sources in zone",
)
async def get_sources(zone: str = Path(..., description="Zone name")) -> List[str]:
async def get_sources(zone: str = Path(...,
description="Zone name")) -> List[str]:
"""
Get all sources in a zone.
@ -357,7 +412,14 @@ async def get_sources(zone: str = Path(..., description="Zone name")) -> List[st
@router.post(
"/zones/{zone}/sources",
response_model=SuccessResponse,
responses={404: {"model": ErrorResponse}, 500: {"model": ErrorResponse}},
responses={
404: {
"model": ErrorResponse
},
500: {
"model": ErrorResponse
}
},
summary="Add source to zone",
)
async def add_source(
@ -376,11 +438,11 @@ async def add_source(
"""
try:
firewalld.add_source(zone, rule.address)
return SuccessResponse(message=f"Source {rule.address} added to zone {zone}")
return SuccessResponse(
message=f"Source {rule.address} added to zone {zone}")
except ValueError:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=f"Zone '{zone}' not found"
)
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
detail=f"Zone '{zone}' not found")
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
@ -391,7 +453,14 @@ async def add_source(
@router.delete(
"/zones/{zone}/sources/{source}",
response_model=SuccessResponse,
responses={404: {"model": ErrorResponse}, 500: {"model": ErrorResponse}},
responses={
404: {
"model": ErrorResponse
},
500: {
"model": ErrorResponse
}
},
summary="Remove source from zone",
)
async def remove_source(
@ -410,7 +479,8 @@ async def remove_source(
"""
try:
firewalld.remove_source(zone, source)
return SuccessResponse(message=f"Source {source} removed from zone {zone}")
return SuccessResponse(
message=f"Source {source} removed from zone {zone}")
except ValueError:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
@ -426,7 +496,9 @@ async def remove_source(
@router.post(
"/reload",
response_model=SuccessResponse,
responses={500: {"model": ErrorResponse}},
responses={500: {
"model": ErrorResponse
}},
summary="Reload firewall rules",
)
async def reload_firewall() -> SuccessResponse:

View file

@ -14,8 +14,8 @@ async def check_ip_config(data: Dict[str, Any] = Body(...)):
return result
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Ошибка проверки IP конфигурации: {str(e)}"
)
status_code=500,
detail=f"Ошибка проверки IP конфигурации: {str(e)}")
@router.post("/apply_ip")
@ -24,15 +24,17 @@ async def apply_ip_config(data: Dict[str, Any] = Body(...)):
try:
await ip_service.apply_ip_config(data)
return {
"success": True,
"message": f"Настройки сетевого профиля для {data['connection_id']} применены",
"success":
True,
"message":
f"Настройки сетевого профиля для {data['connection_id']} применены",
}
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Ошибка проверки IP конфигурации: {str(e)}"
)
status_code=500,
detail=f"Ошибка проверки IP конфигурации: {str(e)}")
@router.post("/save_ip")
@ -41,12 +43,14 @@ async def save_ip_config(data: Dict[str, Any] = Body(...)):
try:
await ip_service.apply_ip_config(data)
return {
"success": True,
"message": f"Настройки сетевого профиля для {data['connection_id']} применены",
"success":
True,
"message":
f"Настройки сетевого профиля для {data['connection_id']} применены",
}
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Ошибка проверки IP конфигурации: {str(e)}"
)
status_code=500,
detail=f"Ошибка проверки IP конфигурации: {str(e)}")

View file

@ -25,17 +25,27 @@ class ContainerPositionManager:
def __init__(self):
self.positions: Dict[str, Dict[str, Union[int, bool]]] = {
"activation": {"x": 0, "y": 0, "isOpen": False},
"deactivation": {"x": 0, "y": 0, "isOpen": False},
"activation": {
"x": 0,
"y": 0,
"isOpen": False
},
"deactivation": {
"x": 0,
"y": 0,
"isOpen": False
},
}
def get_position_and_state(self, container_name: str) -> Tuple[int, int, bool]:
def get_position_and_state(self,
container_name: str) -> Tuple[int, int, bool]:
container = self.positions.get(container_name)
if not container:
raise ValueError(f"Неверное имя контейнера: {container_name}")
return container["x"], container["y"], container["isOpen"]
def update_position(self, container_id: int, x: int, y: int, isOpen: bool) -> None:
def update_position(self, container_id: int, x: int, y: int,
isOpen: bool) -> None:
container_name = "activation" if container_id == 1 else "deactivation"
self.positions[container_name] = {"x": x, "y": y, "isOpen": isOpen}
@ -52,15 +62,12 @@ async def get_network_data() -> Dict[str, Dict]:
network_data = await network_service.get_network_interfaces_container()
activation_interfaces, deactivation_interfaces = _split_interfaces(
network_data.interfaces
)
network_data.interfaces)
activation_x, activation_y, activation_is_open = (
container_manager.get_position_and_state("activation")
)
container_manager.get_position_and_state("activation"))
deactivation_x, deactivation_y, deactivation_is_open = (
container_manager.get_position_and_state("deactivation")
)
container_manager.get_position_and_state("deactivation"))
activation = Activation(
id=1,
@ -83,16 +90,14 @@ async def get_network_data() -> Dict[str, Dict]:
}
except Exception as e:
logger.error(f"Ошибка в get_network_data: {e}")
raise HTTPException(
status_code=500, detail="Не удалось получить сетевые данные"
)
raise HTTPException(status_code=500,
detail="Не удалось получить сетевые данные")
def _split_interfaces(
interfaces: List[Union[NetworkInterface, WiFiDevice]],
) -> Tuple[
List[Union[NetworkInterface, WiFiDevice]], List[Union[NetworkInterface, WiFiDevice]]
]:
) -> Tuple[List[Union[NetworkInterface, WiFiDevice]], List[Union[
NetworkInterface, WiFiDevice]]]:
"""
Разделяет интерфейсы на активные и неактивные
"""
@ -107,13 +112,16 @@ def _split_interfaces(
@router.post("/update_container_position")
async def update_container_position(data: Dict[str, Union[int, bool]] = Body(...)):
async def update_container_position(data: Dict[str, Union[int,
bool]] = Body(...)):
"""
Обновляет позицию и состояние контейнера
"""
try:
required_keys = ["container_id", "container_x", "container_y", "isOpen"]
required_keys = [
"container_id", "container_x", "container_y", "isOpen"
]
if not all(key in data for key in required_keys):
raise ValueError(
"Отсутствуют обязательные поля: container_id, container_x, container_y, isOpen"
@ -125,18 +133,18 @@ async def update_container_position(data: Dict[str, Union[int, bool]] = Body(...
is_open = data["isOpen"]
# Проверка типов
if (
not isinstance(container_id, int)
or not isinstance(container_x, int)
or not isinstance(container_y, int)
or not isinstance(is_open, bool)
):
if (not isinstance(container_id, int)
or not isinstance(container_x, int)
or not isinstance(container_y, int)
or not isinstance(is_open, bool)):
raise ValueError("Неверный тип данных в запросе")
container_manager.update_position(
container_id, container_x, container_y, is_open
)
return {"success": True, "message": "Позиция и состояние контейнера обновлены"}
container_manager.update_position(container_id, container_x,
container_y, is_open)
return {
"success": True,
"message": "Позиция и состояние контейнера обновлены"
}
except Exception as e:
logger.error(f"Ошибка обновления позиции контейнера: {e}")
raise HTTPException(
@ -152,4 +160,5 @@ async def get_hostname():
return hostname_info
except Exception as e:
logger.error(f"Ошибка в get_hostname: {e}")
raise HTTPException(status_code=500, detail="Не удалось получить имя хоста")
raise HTTPException(status_code=500,
detail="Не удалось получить имя хоста")

View file

@ -17,7 +17,8 @@ def scan_subnet(subnet: str = "192.168.1.0/24", ports: List[int] = None):
result = subnet_service.scan_subnet(subnet, ports)
return result
except Exception as e:
raise HTTPException(status_code=500, detail=f"Ошибка сканирования: {str(e)}")
raise HTTPException(status_code=500,
detail=f"Ошибка сканирования: {str(e)}")
@router.get("/wifi", response_model=WifiScanResult)
@ -28,9 +29,8 @@ def scan_wifi(timeout: int = 30):
result = wifi_service.scan_wifi(timeout=timeout)
return result
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Ошибка сканирования Wi-Fi: {str(e)}"
)
raise HTTPException(status_code=500,
detail=f"Ошибка сканирования Wi-Fi: {str(e)}")
@router.post("/devices/{mac}/note")
@ -44,13 +44,15 @@ def add_note(mac: str, request: NoteRequest):
raise HTTPException(status_code=404, detail=error_message)
elif "уже существует" in error_message:
raise HTTPException(status_code=400, detail=error_message)
return {"message": f"Заметка '{request.note}' добавлена для устройства {mac}"}
return {
"message":
f"Заметка '{request.note}' добавлена для устройства {mac}"
}
except HTTPException as e:
raise e
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Ошибка добавления заметки: {str(e)}"
)
raise HTTPException(status_code=500,
detail=f"Ошибка добавления заметки: {str(e)}")
@router.put("/devices/{mac}/note")
@ -64,13 +66,15 @@ def update_note(mac: str, request: NoteRequest):
raise HTTPException(status_code=404, detail=error_message)
elif "не существует" in error_message:
raise HTTPException(status_code=400, detail=error_message)
return {"message": f"Заметка '{request.note}' обновлена для устройства {mac}"}
return {
"message":
f"Заметка '{request.note}' обновлена для устройства {mac}"
}
except HTTPException as e:
raise e
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Ошибка обновления заметки: {str(e)}"
)
raise HTTPException(status_code=500,
detail=f"Ошибка обновления заметки: {str(e)}")
@router.delete("/devices/{mac}/note")
@ -88,6 +92,5 @@ def delete_note(mac: str):
except HTTPException as e:
raise e
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Ошибка удаления заметки: {str(e)}"
)
raise HTTPException(status_code=500,
detail=f"Ошибка удаления заметки: {str(e)}")

View file

@ -9,7 +9,8 @@ router = APIRouter()
class RuleNumbers(BaseModel):
numbers: List[int] = Field(..., description="Список номеров правил для удаления")
numbers: List[int] = Field(
..., description="Список номеров правил для удаления")
@router.get("/rules", response_model=UFWRulesResponse)
@ -47,7 +48,8 @@ async def enable_ufw():
if success:
return {"status": "success", "message": "UFW успешно включен"}
else:
raise HTTPException(status_code=500, detail="Не удалось включить UFW")
raise HTTPException(status_code=500,
detail="Не удалось включить UFW")
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error: {str(e)}")
@ -63,7 +65,8 @@ async def disable_ufw():
if success:
return {"status": "success", "message": "UFW успешно выключен"}
else:
raise HTTPException(status_code=500, detail="Не удалось выключить UFW")
raise HTTPException(status_code=500,
detail="Не удалось выключить UFW")
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error: {str(e)}")
@ -85,11 +88,13 @@ async def add_ufw_in_rules(rules: List[UFWRule]):
result = ufw_service.add_rules(rules)
if result["success"]:
successful_rules = len([r for r in result["results"] if r["success"]])
successful_rules = len(
[r for r in result["results"] if r["success"]])
total_rules = len(result["results"])
return {
"status": "success",
"message": f"Добавлено {successful_rules} из {total_rules} правил",
"message":
f"Добавлено {successful_rules} из {total_rules} правил",
"details": result,
}
else:
@ -124,8 +129,8 @@ async def add_ufw_out_rules(rules: List[UFWRule]):
}
else:
raise HTTPException(
status_code=500, detail="Не удалось добавить исходящие правила UFW"
)
status_code=500,
detail="Не удалось добавить исходящие правила UFW")
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error: {str(e)}")
@ -141,7 +146,8 @@ async def delete_ufw_rules(rule_numbers: RuleNumbers):
if result["success"]:
return {
"status": "success",
"message": f"Удалено {result['successful']} из {result['total']} правил",
"message":
f"Удалено {result['successful']} из {result['total']} правил",
"details": result,
}
else:

View file

@ -56,9 +56,8 @@ async def websocket_endpoint(websocket: WebSocket):
data = await websocket.receive_json()
logger.info(f"Полученные данные: {data}")
if all(
key in data for key in ["container_id", "container_x", "container_y"]
):
if all(key in data
for key in ["container_id", "container_x", "container_y"]):
await update_container_position(data)
network_data = await get_network_data()