Files
sentinel/app/schemas/binding.py

68 lines
1.9 KiB
Python
Raw Permalink Normal View History

from __future__ import annotations
from datetime import datetime
from ipaddress import ip_address, ip_network
from pydantic import BaseModel, ConfigDict, Field, model_validator
from app.models.token_binding import BINDING_MODE_ALL, BINDING_MODE_MULTIPLE, BINDING_MODE_SINGLE
class BindingItem(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
token_display: str
bound_ip: str
binding_mode: str
allowed_ips: list[str]
status: int
status_label: str
first_used_at: datetime
last_used_at: datetime
created_at: datetime
class BindingListResponse(BaseModel):
items: list[BindingItem]
total: int
page: int
page_size: int
class BindingActionRequest(BaseModel):
id: int = Field(gt=0)
class BindingIPUpdateRequest(BaseModel):
id: int = Field(gt=0)
binding_mode: str = Field(default=BINDING_MODE_SINGLE)
allowed_ips: list[str] = Field(default_factory=list)
@model_validator(mode="after")
def validate_binding_rule(self):
allowed_ips = [item.strip() for item in self.allowed_ips if item.strip()]
if self.binding_mode == BINDING_MODE_ALL:
self.allowed_ips = []
return self
if self.binding_mode == BINDING_MODE_SINGLE:
if len(allowed_ips) != 1:
raise ValueError("Single binding mode requires exactly one IP or CIDR.")
ip_network(allowed_ips[0], strict=False)
self.allowed_ips = allowed_ips
return self
if self.binding_mode == BINDING_MODE_MULTIPLE:
if not allowed_ips:
raise ValueError("Multiple binding mode requires at least one IP.")
normalized: list[str] = []
for item in allowed_ips:
ip_address(item)
normalized.append(item)
self.allowed_ips = normalized
return self
raise ValueError("Unsupported binding mode.")