79 lines
3.1 KiB
Python
79 lines
3.1 KiB
Python
"""Access control and logging models."""
|
|
|
|
from datetime import datetime
|
|
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
|
|
from sqlalchemy.orm import relationship
|
|
from ..database import Base
|
|
|
|
|
|
class UserGatewayAccess(Base):
|
|
"""User access to gateways."""
|
|
|
|
__tablename__ = "user_gateway_access"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
|
gateway_id = Column(Integer, ForeignKey("gateways.id"), nullable=False)
|
|
granted_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
granted_by_id = Column(Integer, ForeignKey("users.id"), nullable=True)
|
|
|
|
# Relationships
|
|
user = relationship("User", foreign_keys=[user_id], back_populates="gateway_access")
|
|
gateway = relationship("Gateway", back_populates="user_access")
|
|
granted_by = relationship("User", foreign_keys=[granted_by_id])
|
|
|
|
def __repr__(self):
|
|
return f"<UserGatewayAccess(user_id={self.user_id}, gateway_id={self.gateway_id})>"
|
|
|
|
|
|
class UserEndpointAccess(Base):
|
|
"""User access to specific endpoints (optional fine-grained control)."""
|
|
|
|
__tablename__ = "user_endpoint_access"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
|
endpoint_id = Column(Integer, ForeignKey("endpoints.id"), nullable=False)
|
|
granted_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
granted_by_id = Column(Integer, ForeignKey("users.id"), nullable=True)
|
|
|
|
# Relationships
|
|
user = relationship("User", foreign_keys=[user_id], back_populates="endpoint_access")
|
|
endpoint = relationship("Endpoint", back_populates="user_access")
|
|
granted_by = relationship("User", foreign_keys=[granted_by_id])
|
|
|
|
def __repr__(self):
|
|
return f"<UserEndpointAccess(user_id={self.user_id}, endpoint_id={self.endpoint_id})>"
|
|
|
|
|
|
class ConnectionLog(Base):
|
|
"""Log of VPN connections for auditing."""
|
|
|
|
__tablename__ = "connection_logs"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
|
gateway_id = Column(Integer, ForeignKey("gateways.id"), nullable=False)
|
|
endpoint_id = Column(Integer, ForeignKey("endpoints.id"), nullable=True)
|
|
|
|
# Connection details
|
|
client_ip = Column(String(45), nullable=True) # Client's real IP
|
|
vpn_ip = Column(String(45), nullable=True) # Assigned VPN IP
|
|
connected_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
disconnected_at = Column(DateTime, nullable=True)
|
|
|
|
# Relationships
|
|
user = relationship("User", back_populates="connection_logs")
|
|
gateway = relationship("Gateway", back_populates="connection_logs")
|
|
endpoint = relationship("Endpoint", back_populates="connection_logs")
|
|
|
|
def __repr__(self):
|
|
return f"<ConnectionLog(user={self.user_id}, gateway={self.gateway_id}, connected={self.connected_at})>"
|
|
|
|
@property
|
|
def duration_seconds(self) -> int | None:
|
|
"""Get connection duration in seconds."""
|
|
if self.disconnected_at:
|
|
return int((self.disconnected_at - self.connected_at).total_seconds())
|
|
return None
|