File: traffic_route.py

package info (click to toggle)
python-aiounifi 79-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 660 kB
  • sloc: python: 11,124; sh: 5; makefile: 5
file content (168 lines) | stat: -rw-r--r-- 4,313 bytes parent folder | download
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"]