- Backend: Agent model + migration 022 (creates agents table, seeds system agents, backfills conversations, adds What's New announcement) - Backend: agents CRUD API (/agents/), role-based permission matrix, agent_manager role - Backend: chat endpoint refactored to resolve agent by slug, use agent's LLM config/tools/RAG - Backend: PA CreateAgentTool + ListAgentsTool for conversational agent creation - Backend: LLMFactory extended with get_llm_from_config() + stream_completion_with_llm() - Frontend: AgentListItem/Agent types, useAgentStore, dynamic sidebar with lucide icon resolution - Frontend: Admin → Agents tab + full LibreChat-style AgentEditorModal (react-hook-form) - Frontend: AgentPickerModal (Browse Templates + Create Custom), AgentCard - Frontend: chat page reads ?agent=slug, shows dynamic header/welcome/prompts from DB Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
50 lines
1.9 KiB
Python
50 lines
1.9 KiB
Python
"""
|
|
User Model with Role-Based Access Control (RBAC)
|
|
"""
|
|
from sqlalchemy import Column, String, Boolean, DateTime, Enum, ForeignKey
|
|
from sqlalchemy.dialects.postgresql import UUID, JSONB
|
|
from sqlalchemy.orm import relationship
|
|
from app.database import Base
|
|
import uuid
|
|
from datetime import datetime
|
|
import enum
|
|
|
|
|
|
class UserRole(enum.Enum):
|
|
"""User role enum for RBAC"""
|
|
SUPER_ADMIN = "super_admin"
|
|
CONTENT_MANAGER = "content_manager"
|
|
AGENT_MANAGER = "agent_manager"
|
|
USER = "user"
|
|
|
|
|
|
class User(Base):
|
|
"""
|
|
User model with Microsoft Entra ID integration
|
|
Auto-provisioned on first login
|
|
"""
|
|
__tablename__ = "users"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
entra_id = Column(String, unique=True, nullable=False, index=True) # Azure AD object ID
|
|
email = Column(String, unique=True, nullable=False, index=True)
|
|
display_name = Column(String)
|
|
role = Column(String, default="user", nullable=False)
|
|
department_id = Column(UUID(as_uuid=True), ForeignKey("departments.id", ondelete="SET NULL"), nullable=True)
|
|
is_active = Column(Boolean, default=True, nullable=False)
|
|
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
last_login_at = Column(DateTime, nullable=True)
|
|
|
|
# Region — derived from MS Graph usageLocation at login, used for RAG filtering
|
|
region_code = Column(String(20), nullable=True, index=True)
|
|
|
|
# Access Control — features granted via AD Groups or admin override
|
|
allowed_features = Column(JSONB, default=list, nullable=False, server_default='[]')
|
|
features_override = Column(Boolean, default=False, nullable=False, server_default='false')
|
|
|
|
# Relationships
|
|
department = relationship("Department", back_populates="users")
|
|
conversations = relationship("Conversation", back_populates="user", cascade="all, delete-orphan")
|
|
|
|
def __repr__(self):
|
|
return f"<User {self.email} ({self.role})>"
|