readme refreshed
This commit is contained in:
@@ -8,6 +8,7 @@ from .access import UserGatewayAccess, UserEndpointAccess, ConnectionLog
|
||||
from .certificate_authority import CertificateAuthority, CAStatus, CAAlgorithm
|
||||
from .vpn_server import VPNServer, VPNProtocol, VPNCipher, VPNAuth, VPNCompression, VPNServerStatus
|
||||
from .vpn_profile import VPNProfile, VPNProfileStatus
|
||||
from .client_vpn_profile import ClientVPNProfile, ClientVPNProfileStatus
|
||||
from .vpn_connection_log import VPNConnectionLog
|
||||
|
||||
__all__ = [
|
||||
@@ -32,5 +33,7 @@ __all__ = [
|
||||
"VPNServerStatus",
|
||||
"VPNProfile",
|
||||
"VPNProfileStatus",
|
||||
"ClientVPNProfile",
|
||||
"ClientVPNProfileStatus",
|
||||
"VPNConnectionLog",
|
||||
]
|
||||
|
||||
@@ -69,6 +69,7 @@ class CertificateAuthority(Base):
|
||||
created_by = relationship("User", foreign_keys=[created_by_id])
|
||||
vpn_servers = relationship("VPNServer", back_populates="certificate_authority")
|
||||
vpn_profiles = relationship("VPNProfile", back_populates="certificate_authority")
|
||||
client_vpn_profiles = relationship("ClientVPNProfile", back_populates="certificate_authority")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<CertificateAuthority(id={self.id}, name='{self.name}', status='{self.status}')>"
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
"""Client VPN Profile model for user/technician VPN connections."""
|
||||
|
||||
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 ClientVPNProfileStatus(str, PyEnum):
|
||||
"""Client VPN Profile status."""
|
||||
PENDING = "pending" # Certificate being generated
|
||||
ACTIVE = "active" # Ready to use
|
||||
EXPIRED = "expired" # Certificate expired
|
||||
REVOKED = "revoked" # Certificate revoked
|
||||
|
||||
|
||||
class ClientVPNProfile(Base):
|
||||
"""VPN Profile for a user/technician to connect to the VPN server."""
|
||||
|
||||
__tablename__ = "client_vpn_profiles"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
vpn_server_id = Column(Integer, ForeignKey("vpn_servers.id"), nullable=False)
|
||||
ca_id = Column(Integer, ForeignKey("certificate_authorities.id"), nullable=False)
|
||||
|
||||
# Certificate data
|
||||
cert_cn = Column(String(255), nullable=False, unique=True) # Common Name
|
||||
client_cert = Column(Text, nullable=True) # Client certificate PEM
|
||||
client_key = Column(Text, nullable=True) # Client private key PEM
|
||||
|
||||
# Status
|
||||
status = Column(Enum(ClientVPNProfileStatus), default=ClientVPNProfileStatus.PENDING)
|
||||
is_active = Column(Boolean, default=True)
|
||||
|
||||
# Validity
|
||||
valid_from = Column(DateTime, nullable=True)
|
||||
valid_until = Column(DateTime, nullable=True)
|
||||
|
||||
# VPN IP assigned (updated when connected)
|
||||
vpn_ip = Column(String(15), nullable=True)
|
||||
|
||||
# Tracking
|
||||
last_connection = Column(DateTime, nullable=True)
|
||||
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
# Relationships
|
||||
user = relationship("User", back_populates="client_vpn_profile")
|
||||
vpn_server = relationship("VPNServer", back_populates="client_vpn_profiles")
|
||||
certificate_authority = relationship("CertificateAuthority", back_populates="client_vpn_profiles")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ClientVPNProfile(id={self.id}, user_id={self.user_id}, cert_cn='{self.cert_cn}')>"
|
||||
|
||||
@property
|
||||
def is_ready(self) -> bool:
|
||||
"""Check if profile is ready for use."""
|
||||
return (
|
||||
self.status == ClientVPNProfileStatus.ACTIVE and
|
||||
self.client_cert is not None and
|
||||
self.client_key is not None
|
||||
)
|
||||
|
||||
@property
|
||||
def is_expired(self) -> bool:
|
||||
"""Check if certificate is expired."""
|
||||
if self.valid_until:
|
||||
return datetime.utcnow() > self.valid_until
|
||||
return False
|
||||
@@ -47,6 +47,12 @@ class User(Base):
|
||||
primaryjoin="User.id == UserEndpointAccess.user_id"
|
||||
)
|
||||
connection_logs = relationship("ConnectionLog", back_populates="user")
|
||||
client_vpn_profile = relationship(
|
||||
"ClientVPNProfile",
|
||||
back_populates="user",
|
||||
uselist=False, # One-to-one relationship
|
||||
cascade="all, delete-orphan"
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<User(id={self.id}, username='{self.username}', role='{self.role}')>"
|
||||
|
||||
@@ -106,6 +106,7 @@ class VPNServer(Base):
|
||||
tenant = relationship("Tenant", back_populates="vpn_servers")
|
||||
certificate_authority = relationship("CertificateAuthority", back_populates="vpn_servers")
|
||||
vpn_profiles = relationship("VPNProfile", back_populates="vpn_server")
|
||||
client_vpn_profiles = relationship("ClientVPNProfile", back_populates="vpn_server")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<VPNServer(id={self.id}, name='{self.name}', {self.hostname}:{self.port}/{self.protocol.value})>"
|
||||
|
||||
Reference in New Issue
Block a user