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

63 lines
2.3 KiB
Python

"""User model with role-based access control."""
from datetime import datetime
from enum import Enum as PyEnum
from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, Enum
from sqlalchemy.orm import relationship
from ..database import Base
class UserRole(str, PyEnum):
"""User roles for access control."""
SUPER_ADMIN = "super_admin" # Can manage all tenants
ADMIN = "admin" # Can manage own tenant
TECHNICIAN = "technician" # Can connect to assigned gateways
VIEWER = "viewer" # Read-only access
class User(Base):
"""User model with multi-tenant support."""
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
tenant_id = Column(Integer, ForeignKey("tenants.id"), nullable=True) # NULL for super_admin
username = Column(String(255), nullable=False, unique=True, index=True)
password_hash = Column(String(255), nullable=False)
email = Column(String(255), nullable=False, unique=True)
full_name = Column(String(255), nullable=True)
role = Column(Enum(UserRole), default=UserRole.TECHNICIAN, nullable=False)
is_active = Column(Boolean, default=True, nullable=False)
last_login = Column(DateTime, nullable=True)
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="users")
gateway_access = relationship(
"UserGatewayAccess",
back_populates="user",
cascade="all, delete-orphan",
primaryjoin="User.id == UserGatewayAccess.user_id"
)
endpoint_access = relationship(
"UserEndpointAccess",
back_populates="user",
cascade="all, delete-orphan",
primaryjoin="User.id == UserEndpointAccess.user_id"
)
connection_logs = relationship("ConnectionLog", back_populates="user")
def __repr__(self):
return f"<User(id={self.id}, username='{self.username}', role='{self.role}')>"
@property
def is_super_admin(self) -> bool:
"""Check if user is super admin."""
return self.role == UserRole.SUPER_ADMIN
@property
def is_admin(self) -> bool:
"""Check if user has admin privileges."""
return self.role in (UserRole.SUPER_ADMIN, UserRole.ADMIN)