apac-ops-bot/backend/app/models/message.py
SamoilenkoVadym b284cadb86 Add test user authentication and RBAC admin panel
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>
2026-01-27 20:05:54 +00:00

58 lines
1.7 KiB
Python

"""
Message model for storing individual chat messages
"""
from sqlalchemy import Column, String, Text, Integer, DateTime, JSON, ForeignKey, CheckConstraint
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
import uuid
from app.database import Base
class Message(Base):
"""
Message model representing a single message in a conversation
"""
__tablename__ = "messages"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
conversation_id = Column(
UUID(as_uuid=True),
ForeignKey("conversations.id", ondelete="CASCADE"),
nullable=False,
index=True
)
# OpenAI Responses API response_id
openai_response_id = Column(String(255), index=True)
# Message content
role = Column(String(50), nullable=False) # user, assistant, system
content = Column(Text, nullable=False)
# Token count for this message
token_count = Column(Integer, default=0)
# Timestamp
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False, index=True)
# JSON field for metadata (file_search_results, etc.)
meta_data = Column(JSON, default=dict, nullable=False)
# Relationships
conversation = relationship("Conversation", back_populates="messages")
token_usage_records = relationship("TokenUsage", back_populates="message")
# Constraints
__table_args__ = (
CheckConstraint(
"role IN ('user', 'assistant', 'system')",
name="check_message_role"
),
)
def __repr__(self):
return f"<Message {self.id} - {self.role}>"