openvpn-endpoint-server/server/app/models/access.py

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