Files
Task_Reporter/app/modules/file_storage/models.py
egg 92834dbe0e feat: Migrate to MySQL and add unified environment configuration
## Database Migration (SQLite → MySQL)
- Add Alembic migration framework
- Add 'tr_' prefix to all tables to avoid conflicts in shared database
- Remove SQLite support, use MySQL exclusively
- Add pymysql driver dependency
- Change ad_token column to Text type for long JWT tokens

## Unified Environment Configuration
- Centralize all hardcoded settings to environment variables
- Backend: Extend Settings class in app/core/config.py
- Frontend: Use Vite environment variables (import.meta.env)
- Docker: Move credentials to environment variables
- Update .env.example files with comprehensive documentation

## Test Organization
- Move root-level test files to tests/ directory:
  - test_chat_room.py → tests/test_chat_room.py
  - test_websocket.py → tests/test_websocket.py
  - test_realtime_implementation.py → tests/test_realtime_implementation.py
- Fix path references in test_realtime_implementation.py

Breaking Changes:
- CORS now requires explicit origins (no more wildcard)
- All database tables renamed with 'tr_' prefix
- SQLite no longer supported

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 14:15:11 +08:00

45 lines
1.6 KiB
Python

"""Database models for file storage"""
from sqlalchemy import Column, String, BigInteger, DateTime, Index, ForeignKey
from sqlalchemy.orm import relationship
from datetime import datetime
from app.core.database import Base
class RoomFile(Base):
"""File uploaded to an incident room"""
__tablename__ = "tr_room_files"
# Primary key
file_id = Column(String(36), primary_key=True)
# Foreign key to incident room (CASCADE delete when room is permanently deleted)
room_id = Column(String(36), ForeignKey("tr_incident_rooms.room_id", ondelete="CASCADE"), nullable=False)
# File metadata
uploader_id = Column(String(255), nullable=False)
filename = Column(String(255), nullable=False)
file_type = Column(String(20), nullable=False) # 'image', 'document', 'log'
mime_type = Column(String(100), nullable=False)
file_size = Column(BigInteger, nullable=False) # bytes
# MinIO storage information
minio_bucket = Column(String(100), nullable=False)
minio_object_path = Column(String(500), nullable=False)
# Timestamps
uploaded_at = Column(DateTime, default=datetime.utcnow, nullable=False)
deleted_at = Column(DateTime, nullable=True) # soft delete
# Relationships
room = relationship("IncidentRoom", back_populates="files")
# Indexes
__table_args__ = (
Index("ix_tr_room_files_room_uploaded", "room_id", "uploaded_at"),
Index("ix_tr_room_files_uploader", "uploader_id"),
)
def __repr__(self):
return f"<RoomFile(file_id={self.file_id}, filename={self.filename}, room_id={self.room_id})>"