ALM-2 / backend /db_models /api_key.py
ACA050's picture
Upload 520 files
2ed8996 verified
"""
API Key model for AegisLM SaaS Backend.
Production-ready SQLAlchemy model for secure
API key management and usage tracking.
"""
from datetime import datetime, timedelta
from sqlalchemy import Column, Integer, String, DateTime, Boolean, Text, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from core.database import Base
class ApiKey(Base):
"""API Key model for programmatic access."""
__tablename__ = "api_keys"
# Primary key
id = Column(Integer, primary_key=True, index=True)
# Foreign key
user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
# Key fields
key = Column(String(255), unique=True, index=True, nullable=False)
name = Column(String(255), nullable=False)
description = Column(Text, nullable=True)
# Status and permissions
is_active = Column(Boolean, default=True, nullable=False)
expires_at = Column(DateTime(timezone=True), nullable=True)
# Usage tracking
last_used_at = Column(DateTime(timezone=True), nullable=True)
usage_count = Column(Integer, default=0, nullable=False)
# Audit fields
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False, index=True)
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)
# Relationships
user = relationship("User", back_populates="api_keys")
def __repr__(self):
return f"<ApiKey(id={self.id}, name={self.name}, user_id={self.user_id})>"
def to_dict(self, include_key: bool = False):
"""Convert API key to dictionary."""
data = {
"id": self.id,
"user_id": self.user_id,
"name": self.name,
"description": self.description,
"is_active": self.is_active,
"expires_at": self.expires_at.isoformat() if self.expires_at else None,
"last_used_at": self.last_used_at.isoformat() if self.last_used_at else None,
"usage_count": self.usage_count,
"created_at": self.created_at.isoformat() if self.created_at else None,
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
}
if include_key:
data["key"] = self.key
return data
def is_expired(self) -> bool:
"""Check if API key is expired."""
if self.expires_at is None:
return False
return datetime.utcnow() > self.expires_at
def is_valid(self) -> bool:
"""Check if API key is valid and active."""
return (
self.is_active
and not self.is_expired()
)
def update_usage(self):
"""Update usage tracking."""
self.last_used_at = datetime.utcnow()
self.usage_count += 1
self.updated_at = datetime.utcnow()
@classmethod
def create_expiration_date(cls, days: int = 365) -> datetime:
"""Create expiration date for API key."""
return datetime.utcnow() + timedelta(days=days)