Files
app-service/backend/app/models/api_key.py
matteoscrugli 8c4a555b88 Add comprehensive backend features and mobile UI improvements
Backend:
- Add 2FA authentication with TOTP support
- Add API keys management system
- Add audit logging for security events
- Add file upload/management system
- Add notifications system with preferences
- Add session management
- Add webhooks integration
- Add analytics endpoints
- Add export functionality
- Add password policy enforcement
- Add new database migrations for core tables

Frontend:
- Add module position system (top/bottom sidebar sections)
- Add search and notifications module configuration tabs
- Add mobile logo replacing hamburger menu
- Center page title absolutely when no tabs present
- Align sidebar footer toggles with navigation items
- Add lighter icon color in dark theme for mobile
- Add API keys management page
- Add notifications page with context
- Add admin analytics and audit logs pages

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 22:27:32 +01:00

70 lines
2.2 KiB
Python

"""API Key database model for programmatic access."""
import uuid
import secrets
from datetime import datetime
from sqlalchemy import Column, String, Boolean, ForeignKey, Text
from sqlalchemy.sql import func
from sqlalchemy.types import DateTime
from app.db.base import Base
def generate_api_key() -> str:
"""Generate a secure API key."""
return f"sk_{secrets.token_urlsafe(32)}"
def generate_key_prefix(key: str) -> str:
"""Generate a display prefix for the key (first 8 chars after sk_)."""
return key[:11] + "..." if len(key) > 11 else key
class APIKey(Base):
"""API Key model for programmatic authentication."""
__tablename__ = "api_keys"
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
# Owner
user_id = Column(String(36), ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True)
# Key info
name = Column(String(100), nullable=False) # User-friendly name
key_hash = Column(String(255), nullable=False, unique=True) # Hashed key (for lookup)
key_prefix = Column(String(20), nullable=False) # First chars for display (sk_xxx...)
# Permissions & scope
scopes = Column(Text, nullable=True) # JSON array of allowed scopes/permissions
# Status
is_active = Column(Boolean, default=True, nullable=False)
# Usage tracking
last_used_at = Column(DateTime, nullable=True)
last_used_ip = Column(String(45), nullable=True)
usage_count = Column(String(20), default="0") # String for SQLite compatibility
# Expiration
expires_at = Column(DateTime, nullable=True) # null = never expires
# Timestamps
created_at = Column(DateTime, server_default=func.now(), nullable=False)
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), nullable=False)
def __repr__(self):
return f"<APIKey(id={self.id}, name='{self.name}', prefix='{self.key_prefix}')>"
@property
def is_expired(self) -> bool:
"""Check if key is expired."""
if self.expires_at is None:
return False
return datetime.utcnow() > self.expires_at
@property
def is_valid(self) -> bool:
"""Check if key is valid (active and not expired)."""
return self.is_active and not self.is_expired