1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
"""Traffic routes as part of a UniFi network."""
from dataclasses import dataclass
from enum import StrEnum
from typing import NotRequired, Self, TypedDict
from .api import ApiItem, ApiRequestV2
class MatchingTarget(StrEnum):
"""Possible matching targets for a traffic rule."""
DOMAIN = "DOMAIN"
IP = "IP"
INTERNET = "INTERNET"
REGION = "REGION"
class PortRange(TypedDict):
"""Port range type definition."""
port_start: int
port_stop: int
class IPAddress(TypedDict):
"""IP Address for which traffic route is applicable type definition."""
ip_or_subnet: str
ip_version: str
port_ranges: list[PortRange]
ports: list[int]
class IPRange(TypedDict):
"""IP Range type definition."""
ip_start: str
ip_stop: str
ip_version: str
class TargetDevice(TypedDict):
"""Target device to which the traffic route applies."""
client_mac: NotRequired[str]
network_id: NotRequired[str]
type: str
class Domain(TypedDict):
"""A target domain for a traffic route."""
domain: str
port_ranges: list[PortRange]
ports: list[int]
class TypedTrafficRoute(TypedDict):
"""Traffic route type definition."""
_id: str
description: str
domains: list[Domain]
enabled: bool
ip_addresses: list[IPAddress]
ip_ranges: list[IPRange]
matching_target: MatchingTarget
network_id: str
next_hop: str
regions: list[str]
target_devices: list[TargetDevice]
@dataclass
class TrafficRouteListRequest(ApiRequestV2):
"""Request object for traffic route list."""
@classmethod
def create(cls) -> Self:
"""Create traffic route request."""
return cls(method="get", path="/trafficroutes", data=None)
@dataclass
class TrafficRouteSaveRequest(ApiRequestV2):
"""Request object for saving a traffic route.
To modify a route, you must make sure the `raw` attribute of the TypedTrafficRoute is modified.
The properties provide convient access for reading, however do not provide means of setting values.
"""
@classmethod
def create(
cls, traffic_route: TypedTrafficRoute, enable: bool | None = None
) -> Self:
"""Create traffic route save request."""
if enable is not None:
traffic_route["enabled"] = enable
return cls(
method="put",
path=f"/trafficroutes/{traffic_route['_id']}",
data=traffic_route,
)
class TrafficRoute(ApiItem):
"""Represent a traffic route configuration."""
raw: TypedTrafficRoute
@property
def id(self) -> str:
"""ID of traffic route."""
return self.raw["_id"]
@property
def description(self) -> str:
"""Description given by user to traffic route."""
return self.raw["description"]
@property
def domains(self) -> list[Domain]:
"""What IP addresses are matched against by this traffic route.
Note: Domain matching requires the client devices to use the UniFi gateway as the DNS server.
"""
return self.raw["domains"]
@property
def enabled(self) -> bool:
"""Is traffic route enabled."""
return self.raw["enabled"]
@property
def ip_addresses(self) -> list[IPAddress]:
"""What IP addresses are matched against by this traffic route."""
return self.raw["ip_addresses"]
@property
def ip_ranges(self) -> list[IPRange]:
"""What IP addresses are matched against by this traffic route."""
return self.raw["ip_ranges"]
@property
def matching_target(self) -> MatchingTarget:
"""What target is matched by this traffic route."""
return self.raw["matching_target"]
@property
def network_id(self) -> str:
"""Network ID that this rule applies to."""
return self.raw["network_id"]
@property
def next_hop(self) -> str:
"""Used for defining a static route."""
return self.raw["next_hop"]
@property
def regions(self) -> list[str]:
"""Regions that the rule applies to."""
return self.raw["regions"]
@property
def target_devices(self) -> list[TargetDevice]:
"""What target devices are affected by this traffic route."""
return self.raw["target_devices"]
|