 59a59f8869
			
		
	
	59a59f8869
	
	
	
		
			
			Major architectural improvement to replace in-memory task storage with database-backed persistence while maintaining backward compatibility. Changes: - Created Task SQLAlchemy model matching database schema - Added Workflow and Execution SQLAlchemy models - Created TaskService for database CRUD operations - Updated UnifiedCoordinator to use database persistence - Modified task APIs to leverage database storage - Added task loading from database on coordinator initialization - Implemented status change persistence during task execution - Enhanced task cleanup with database support - Added comprehensive task statistics from database Benefits: - Tasks persist across application restarts - Better scalability and reliability - Historical task data retention - Comprehensive task filtering and querying - Maintains in-memory cache for performance 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			86 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """
 | |
| Unified User model for Hive platform.
 | |
| Combines authentication and basic user functionality with UUID support.
 | |
| """
 | |
| 
 | |
| from datetime import datetime
 | |
| from typing import Optional, List
 | |
| import uuid
 | |
| from sqlalchemy import Column, String, DateTime, Boolean, Text, ForeignKey
 | |
| from sqlalchemy.dialects.postgresql import UUID
 | |
| from sqlalchemy.orm import relationship
 | |
| from sqlalchemy.sql import func
 | |
| from passlib.context import CryptContext
 | |
| from ..core.database import Base
 | |
| 
 | |
| # Password hashing context
 | |
| pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
 | |
| 
 | |
| class User(Base):
 | |
|     """Unified user model with authentication and authorization support."""
 | |
|     
 | |
|     __tablename__ = "users"
 | |
|     
 | |
|     # Use UUID to match existing database schema
 | |
|     id = Column(UUID(as_uuid=True), primary_key=True, index=True, default=uuid.uuid4)
 | |
|     username = Column(String(50), unique=True, index=True, nullable=True)  # Made nullable for compatibility
 | |
|     email = Column(String(255), unique=True, index=True, nullable=False)
 | |
|     hashed_password = Column(String(255), nullable=False)
 | |
|     
 | |
|     # Extended user information (for backward compatibility)
 | |
|     full_name = Column(String(255), nullable=True)
 | |
|     role = Column(String(50), nullable=True)  # For backward compatibility with existing code
 | |
|     
 | |
|     # User status and permissions
 | |
|     is_active = Column(Boolean, default=True)
 | |
|     is_superuser = Column(Boolean, default=False)
 | |
|     is_verified = Column(Boolean, default=False)
 | |
|     
 | |
|     # Timestamps (match existing database schema)
 | |
|     created_at = Column(DateTime(timezone=True), server_default=func.now())
 | |
|     updated_at = Column(DateTime(timezone=True), onupdate=func.now())
 | |
|     last_login = Column(DateTime(timezone=True), nullable=True)
 | |
|     
 | |
|     # Relationships for authentication features
 | |
|     api_keys = relationship("APIKey", back_populates="user", cascade="all, delete-orphan")
 | |
|     refresh_tokens = relationship("RefreshToken", back_populates="user", cascade="all, delete-orphan")
 | |
|     workflows = relationship("Workflow", back_populates="creator")
 | |
|     
 | |
|     def verify_password(self, password: str) -> bool:
 | |
|         """Verify a password against the hashed password."""
 | |
|         return pwd_context.verify(password, self.hashed_password)
 | |
|     
 | |
|     @classmethod
 | |
|     def hash_password(cls, password: str) -> str:
 | |
|         """Hash a password for storage."""
 | |
|         return pwd_context.hash(password)
 | |
|     
 | |
|     def set_password(self, password: str) -> None:
 | |
|         """Set a new password for the user."""
 | |
|         self.hashed_password = self.hash_password(password)
 | |
|     
 | |
|     def update_last_login(self) -> None:
 | |
|         """Update the last login timestamp."""
 | |
|         self.last_login = datetime.utcnow()
 | |
|     
 | |
|     @property
 | |
|     def name(self) -> str:
 | |
|         """Backward compatibility property for 'name' field."""
 | |
|         return self.full_name or self.username or self.email.split('@')[0]
 | |
|     
 | |
|     def to_dict(self) -> dict:
 | |
|         """Convert user to dictionary (excluding sensitive data)."""
 | |
|         return {
 | |
|             "id": str(self.id),  # Convert UUID to string for JSON serialization
 | |
|             "username": self.username,
 | |
|             "email": self.email,
 | |
|             "full_name": self.full_name,
 | |
|             "name": self.name,  # Backward compatibility
 | |
|             "role": self.role,
 | |
|             "is_active": self.is_active,
 | |
|             "is_superuser": self.is_superuser,
 | |
|             "is_verified": self.is_verified,
 | |
|             "created_at": self.created_at.isoformat() if self.created_at else None,
 | |
|             "updated_at": self.updated_at.isoformat() if self.updated_at else None,
 | |
|             "last_login": self.last_login.isoformat() if self.last_login else None,
 | |
|         } |