"""Gateway model for mGuard routers.""" from datetime import datetime from enum import Enum as PyEnum from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, Enum, Text from sqlalchemy.orm import relationship from ..database import Base class RouterType(str, PyEnum): """Supported mGuard router types.""" FL_MGUARD_2000 = "FL_MGUARD_2000" FL_MGUARD_4000 = "FL_MGUARD_4000" FL_MGUARD_RS4000 = "FL_MGUARD_RS4000" FL_MGUARD_1000 = "FL_MGUARD_1000" class ProvisioningMethod(str, PyEnum): """Method used to provision the gateway.""" REST_API = "rest_api" # For firmware 10.5.x+ SSH = "ssh" # For older firmware ATV_FILE = "atv_file" # Offline via config file class Gateway(Base): """Gateway model representing an mGuard router.""" __tablename__ = "gateways" id = Column(Integer, primary_key=True, index=True) tenant_id = Column(Integer, ForeignKey("tenants.id"), nullable=False) # Basic info name = Column(String(255), nullable=False) description = Column(Text, nullable=True) location = Column(String(255), nullable=True) # Physical location # Router details serial_number = Column(String(100), nullable=True, unique=True) router_type = Column(Enum(RouterType), nullable=False) firmware_version = Column(String(50), nullable=True) provisioning_method = Column(Enum(ProvisioningMethod), default=ProvisioningMethod.ATV_FILE) # VPN configuration vpn_ip = Column(String(45), nullable=True, unique=True) # IPv4/IPv6 vpn_cert_cn = Column(String(255), nullable=True, unique=True) # Certificate Common Name vpn_subnet = Column(String(50), nullable=True) # Network behind gateway, e.g., "10.0.0.0/24" # Status is_online = Column(Boolean, default=False, nullable=False) is_provisioned = Column(Boolean, default=False, nullable=False) last_seen = Column(DateTime, nullable=True) last_config_update = Column(DateTime, nullable=True) # Timestamps created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) # Relationships tenant = relationship("Tenant", back_populates="gateways") endpoints = relationship("Endpoint", back_populates="gateway", cascade="all, delete-orphan") user_access = relationship("UserGatewayAccess", back_populates="gateway", cascade="all, delete-orphan") connection_logs = relationship("ConnectionLog", back_populates="gateway") vpn_profiles = relationship("VPNProfile", back_populates="gateway", cascade="all, delete-orphan", order_by="VPNProfile.priority") def __repr__(self): return f"" @property def supports_rest_api(self) -> bool: """Check if gateway supports REST API (firmware 10.x+).""" if not self.firmware_version: return False try: major_version = int(self.firmware_version.split('.')[0]) return major_version >= 10 except (ValueError, IndexError): return False @property def primary_profile(self): """Get the primary VPN profile (highest priority).""" active_profiles = [p for p in self.vpn_profiles if p.is_active] if active_profiles: return min(active_profiles, key=lambda p: p.priority) return None @property def has_vpn_profiles(self) -> bool: """Check if gateway has any VPN profiles.""" return len(self.vpn_profiles) > 0