Implemented simple authentication for testing and admin panel for user management: Backend: - Add simple email/password login for test users (admin@test.local, user@test.local) - Implement RBAC (Role-Based Access Control) with Permission enum - Create admin endpoints for user management and system analytics - Add bcrypt password hashing for test users - Create script to generate test users in database Frontend: - Add SimpleLogin component for test authentication - Create AdminPanel with user management and system analytics - Add role-based navigation (Admin tab visible only for admins) - Update AuthContext to support both MSAL and simple login - Add API methods for admin operations Features: - Admins can view all users, manage roles, activate/deactivate accounts - Admins can view system-wide analytics (users, conversations, tokens, costs) - Regular users only see their own chats and usage - Role badges in UI show user role (user/admin/superadmin) Note: Simple authentication is for testing only. Production uses Azure AD MSAL. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
45 lines
1.6 KiB
Python
45 lines
1.6 KiB
Python
"""
|
|
Conversation model for storing chat conversations
|
|
"""
|
|
|
|
from sqlalchemy import Column, String, Boolean, DateTime, JSON, ForeignKey
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
from sqlalchemy.orm import relationship
|
|
from sqlalchemy.sql import func
|
|
import uuid
|
|
|
|
from app.database import Base
|
|
|
|
|
|
class Conversation(Base):
|
|
"""
|
|
Conversation model representing a chat conversation between user and bot
|
|
"""
|
|
|
|
__tablename__ = "conversations"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
|
|
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True)
|
|
|
|
# OpenAI Responses API response_id for multi-turn conversations
|
|
last_response_id = Column(String(255), index=True)
|
|
|
|
# Conversation metadata
|
|
title = Column(String(500)) # Auto-generated or user-defined
|
|
is_archived = Column(Boolean, default=False, nullable=False)
|
|
|
|
# Timestamps
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
|
|
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), index=True)
|
|
last_message_at = Column(DateTime(timezone=True))
|
|
|
|
# JSON field for additional metadata
|
|
meta_data = Column(JSON, default=dict, nullable=False)
|
|
|
|
# Relationships
|
|
user = relationship("User", back_populates="conversations")
|
|
messages = relationship("Message", back_populates="conversation", cascade="all, delete-orphan", order_by="Message.created_at")
|
|
token_usage = relationship("TokenUsage", back_populates="conversation")
|
|
|
|
def __repr__(self):
|
|
return f"<Conversation {self.id} - {self.title}>"
|