updates
This commit is contained in:
parent
147f0ae329
commit
d24854483f
2 changed files with 481 additions and 43 deletions
462
poweron/appdoc/app_keymanagement.html
Normal file
462
poweron/appdoc/app_keymanagement.html
Normal file
|
|
@ -0,0 +1,462 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Key Management - Praktische Umsetzung & Werkzeuge</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
h1 {
|
||||
color: #2c3e50;
|
||||
border-bottom: 3px solid #3498db;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
h2 {
|
||||
color: #34495e;
|
||||
margin-top: 30px;
|
||||
border-bottom: 2px solid #ecf0f1;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
h3 {
|
||||
color: #7f8c8d;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.architecture-box {
|
||||
background: white;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
.highlight {
|
||||
background: #fff3cd;
|
||||
padding: 15px;
|
||||
border-left: 4px solid #ffc107;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.info-box {
|
||||
background: #d1ecf1;
|
||||
border: 1px solid #bee5eb;
|
||||
border-radius: 5px;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.security-note {
|
||||
background: #f8d7da;
|
||||
border: 1px solid #f5c6cb;
|
||||
border-radius: 5px;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.process-flow {
|
||||
background: #e7f3ff;
|
||||
border: 1px solid #b3d9ff;
|
||||
border-radius: 5px;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.warning-box {
|
||||
background: #fff3cd;
|
||||
border: 1px solid #ffeeba;
|
||||
border-radius: 5px;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
border-left: 4px solid #ffc107;
|
||||
}
|
||||
.success-box {
|
||||
background: #d4edda;
|
||||
border: 1px solid #c3e6cb;
|
||||
border-radius: 5px;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.workflow-step {
|
||||
background: #f8f9fa;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 5px;
|
||||
padding: 15px;
|
||||
margin: 15px 0;
|
||||
border-left: 4px solid #6c757d;
|
||||
}
|
||||
.workflow-step h4 {
|
||||
margin-top: 0;
|
||||
color: #495057;
|
||||
}
|
||||
ul, ol {
|
||||
margin: 10px 0;
|
||||
padding-left: 30px;
|
||||
}
|
||||
li {
|
||||
margin: 5px 0;
|
||||
}
|
||||
.file-structure {
|
||||
background: #f8f9fa;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 5px;
|
||||
padding: 15px;
|
||||
margin: 15px 0;
|
||||
font-family: monospace;
|
||||
}
|
||||
.tool-description {
|
||||
background: #e8f5e8;
|
||||
border: 1px solid #c3e6cb;
|
||||
border-radius: 5px;
|
||||
padding: 15px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
.tool-description h4 {
|
||||
margin-top: 0;
|
||||
color: #155724;
|
||||
}
|
||||
.code-example {
|
||||
background: #2c3e50;
|
||||
color: #ecf0f1;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
overflow-x: auto;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Key Management - Praktische Umsetzung & Werkzeuge</h1>
|
||||
|
||||
<div class="architecture-box">
|
||||
<h2>1. Kern-Anforderungen & Prinzipien</h2>
|
||||
|
||||
<div class="security-note">
|
||||
<h3>🔒 Grundprinzipien</h3>
|
||||
<ul>
|
||||
<li><strong>Keine Plain-Text Keys im Code:</strong> Keys werden nur verschlüsselt gespeichert</li>
|
||||
<li><strong>Lokale Entwicklung:</strong> Keys können lokal ohne Internetzugang entschlüsselt werden</li>
|
||||
<li><strong>Absolute Dev/Prod Trennung:</strong> Keine Überschneidung zwischen Development und Production</li>
|
||||
<li><strong>Minimaler Aufwand:</strong> Neue Keys direkt im Code erfassen können</li>
|
||||
<li><strong>Keine Provider-Abhängigkeit:</strong> Master Keys werden bei uns gespeichert</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h3>1.1 File-Struktur</h3>
|
||||
<div class="file-structure">
|
||||
repository/
|
||||
├── config.ini # Generische Konfiguration
|
||||
├── .env # Instanz-spezifische Umgebungsvariablen
|
||||
├── .env.development # Development-spezifische Keys
|
||||
├── .env.production # Production-spezifische Keys
|
||||
└── src/
|
||||
└── utils/
|
||||
└── config.py # getConfig() Funktion
|
||||
</div>
|
||||
|
||||
<h3>1.2 Key-Format</h3>
|
||||
<div class="info-box">
|
||||
<h4>Verschlüsselte Keys haben folgendes Format:</h4>
|
||||
<ul>
|
||||
<li><strong>Development Keys:</strong> <code>DEV_ENC:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...</code></li>
|
||||
<li><strong>Production Keys:</strong> <code>PROD_ENC:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...</code></li>
|
||||
<li><strong>Metadata:</strong> <code>PROD_ENC:encrypted_value|LIMIT:1000/hour|TRACK:true</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="architecture-box">
|
||||
<h2>2. Master Key Management</h2>
|
||||
|
||||
<h3>2.1 Master Key Storage - Eigene V-Domäne</h3>
|
||||
<div class="info-box">
|
||||
<h4>Master Keys werden bei uns gespeichert:</h4>
|
||||
<ul>
|
||||
<li><strong>Development Master Key:</strong> Lokal auf Entwickler-Maschine (~/.keytool/dev-master.key)</li>
|
||||
<li><strong>Production Master Key:</strong> Auf eigener V-Domäne (z.B. keys.internal.company.com)</li>
|
||||
<li><strong>Keine Cloud-Provider:</strong> Vollständige Kontrolle über Key-Storage</li>
|
||||
<li><strong>HSM-Backed:</strong> Hardware Security Module für Production Keys</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h3>2.2 Master Key Nutzung für Decryption</h3>
|
||||
<div class="process-flow">
|
||||
<h4>Workflow für Key-Decryption:</h4>
|
||||
<ol>
|
||||
<li><strong>Key-Format erkennen:</strong> DEV_ENC: oder PROD_ENC: Prefix parsen</li>
|
||||
<li><strong>Master Key laden:</strong> Entsprechenden Master Key aus Storage laden</li>
|
||||
<li><strong>Environment-Check:</strong> Sicherstellen, dass Key in richtiger Umgebung entschlüsselt wird</li>
|
||||
<li><strong>Decryption:</strong> Key mit Master Key entschlüsseln</li>
|
||||
<li><strong>Metadata parsen:</strong> Limits und Tracking-Informationen extrahieren</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<h3>2.3 Environment-Separation</h3>
|
||||
<div class="security-note">
|
||||
<h4>🔐 Strikte Trennung:</h4>
|
||||
<ul>
|
||||
<li><strong>Development:</strong> Kann nur DEV_ENC: Keys entschlüsseln</li>
|
||||
<li><strong>Production:</strong> Kann nur PROD_ENC: Keys entschlüsseln</li>
|
||||
<li><strong>Cross-Decryption:</strong> Wird blockiert - Security Feature</li>
|
||||
<li><strong>Automatische Erkennung:</strong> Environment wird automatisch erkannt</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="architecture-box">
|
||||
<h2>3. Encryption Tool - Lokale Nutzung</h2>
|
||||
|
||||
<h3>3.1 Tool-Funktionalität</h3>
|
||||
<div class="tool-description">
|
||||
<h4>Das Encryption Tool bietet:</h4>
|
||||
<ul>
|
||||
<li><strong>Lokale Nutzung:</strong> Funktioniert ohne Internetzugang</li>
|
||||
<li><strong>Automatische File-Auswahl:</strong> Repository, Instanz, Key-Name auswählen</li>
|
||||
<li><strong>Copy/Paste Integration:</strong> Key direkt einfügen und verschlüsseln</li>
|
||||
<li><strong>Automatisches Speichern:</strong> Verschlüsselter Key wird im richtigen File gespeichert</li>
|
||||
<li><strong>Environment-Aware:</strong> Erkennt automatisch ob DEV oder PROD</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h3>3.2 Tool-Workflow</h3>
|
||||
<div class="workflow-step">
|
||||
<h4>Schritt 1: Repository & Instanz auswählen</h4>
|
||||
<p>Tool zeigt verfügbare Repositories und deren Instanzen an</p>
|
||||
</div>
|
||||
|
||||
<div class="workflow-step">
|
||||
<h4>Schritt 2: Key-Name definieren</h4>
|
||||
<p>Neuen Key-Namen eingeben (z.B. API_KEY_CUSTOMER_001)</p>
|
||||
</div>
|
||||
|
||||
<div class="workflow-step">
|
||||
<h4>Schritt 3: Plain-Text Key einfügen</h4>
|
||||
<p>Key per Copy/Paste einfügen</p>
|
||||
</div>
|
||||
|
||||
<div class="workflow-step">
|
||||
<h4>Schritt 4: Automatische Verschlüsselung</h4>
|
||||
<p>Tool verschlüsselt Key und speichert ihn im richtigen File</p>
|
||||
</div>
|
||||
|
||||
<h3>3.3 Tool-Integration</h3>
|
||||
<div class="info-box">
|
||||
<h4>Integration in den Entwickler-Workflow:</h4>
|
||||
<ul>
|
||||
<li><strong>Command Line Tool:</strong> <code>keytool encrypt --repo=repo-name --instance=dev --key=API_KEY --value=plaintext</code></li>
|
||||
<li><strong>IDE Integration:</strong> Plugin für VS Code/IntelliJ</li>
|
||||
<li><strong>Git Hooks:</strong> Automatische Validierung vor Commit</li>
|
||||
<li><strong>CI/CD Integration:</strong> Automatische Key-Validierung bei Deployment</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="architecture-box">
|
||||
<h2>4. getConfig() Funktion - Praktische Umsetzung</h2>
|
||||
|
||||
<h3>4.1 Funktionalität</h3>
|
||||
<div class="info-box">
|
||||
<h4>Die getConfig() Funktion:</h4>
|
||||
<ul>
|
||||
<li><strong>Config Loading:</strong> Lädt config.ini und .env Files beim App-Start</li>
|
||||
<li><strong>Automatische Decryption:</strong> Entschlüsselt alle verschlüsselten Keys</li>
|
||||
<li><strong>Environment Detection:</strong> Erkennt automatisch Development/Production</li>
|
||||
<li><strong>Variable Access:</strong> Stellt entschlüsselte Keys als Variablen zur Verfügung</li>
|
||||
<li><strong>Metadata Handling:</strong> Verarbeitet Limits und Tracking-Informationen</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h3>4.2 Implementierungs-Logik</h3>
|
||||
<div class="process-flow">
|
||||
<h4>getConfig() Workflow:</h4>
|
||||
<ol>
|
||||
<li><strong>File Loading:</strong> config.ini und .env Files laden</li>
|
||||
<li><strong>Environment Detection:</strong> Dev/Prod automatisch erkennen</li>
|
||||
<li><strong>Master Key Loading:</strong> Entsprechenden Master Key laden</li>
|
||||
<li><strong>Key Scanning:</strong> Alle verschlüsselten Keys identifizieren</li>
|
||||
<li><strong>Decryption:</strong> Keys mit Master Key entschlüsseln</li>
|
||||
<li><strong>Metadata Parsing:</strong> Limits und Tracking-Informationen extrahieren</li>
|
||||
<li><strong>Variable Setup:</strong> Entschlüsselte Keys als Variablen verfügbar machen</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<h3>4.3 Usage im Code</h3>
|
||||
<div class="code-example">
|
||||
# In der Anwendung
|
||||
from utils.config import getConfig
|
||||
|
||||
config = getConfig()
|
||||
|
||||
# Zugriff auf entschlüsselte Keys
|
||||
api_key = config.get('API_KEY_CUSTOMER_001')
|
||||
db_password = config.get('DB_PASSWORD')
|
||||
|
||||
# Mit Customer-Context
|
||||
customer_api_key = config.get('API_KEY', customer_id='CUSTOMER_001')
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="architecture-box">
|
||||
<h2>5. Repository & Instanz Management</h2>
|
||||
|
||||
<h3>5.1 Multi-Repository Struktur</h3>
|
||||
<div class="info-box">
|
||||
<h4>Verwaltung vieler Repositories:</h4>
|
||||
<ul>
|
||||
<li><strong>Zentrale Registry:</strong> Alle Repositories und Instanzen werden zentral verwaltet</li>
|
||||
<li><strong>Instanz-spezifische .env Files:</strong> Jede Instanz hat eigene .env Datei</li>
|
||||
<li><strong>Automatische Synchronisation:</strong> Keys werden automatisch zwischen Repositories synchronisiert</li>
|
||||
<li><strong>Versionierung:</strong> Alle Key-Änderungen werden versioniert</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h3>5.2 Instanz-spezifische Konfiguration</h3>
|
||||
<div class="file-structure">
|
||||
repository/
|
||||
├── .env.development # Development Keys
|
||||
├── .env.staging # Staging Keys
|
||||
├── .env.production # Production Keys
|
||||
└── .env.local # Lokale Override Keys
|
||||
</div>
|
||||
|
||||
<h3>5.3 Deployment-Integration</h3>
|
||||
<div class="process-flow">
|
||||
<h4>Automatisches Deployment:</h4>
|
||||
<ol>
|
||||
<li><strong>Code auf GitHub main:</strong> Trigger für automatisches Deployment</li>
|
||||
<li><strong>Key-Validierung:</strong> Alle Keys werden auf Gültigkeit geprüft</li>
|
||||
<li><strong>Environment-Matching:</strong> Richtige .env Files werden für Ziel-Umgebung geladen</li>
|
||||
<li><strong>Key-Decryption:</strong> Keys werden in Ziel-Umgebung entschlüsselt</li>
|
||||
<li><strong>App-Start:</strong> Anwendung startet mit entschlüsselten Keys</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="architecture-box">
|
||||
<h2>6. Sicherheits-Features</h2>
|
||||
|
||||
<h3>6.1 Key-Validierung</h3>
|
||||
<div class="security-note">
|
||||
<h4>🔒 Automatische Sicherheits-Checks:</h4>
|
||||
<ul>
|
||||
<li><strong>Plain-Text Detection:</strong> Blockiert Commits mit unverschlüsselten Keys</li>
|
||||
<li><strong>Environment-Mismatch:</strong> Verhindert PROD Keys in DEV Umgebung</li>
|
||||
<li><strong>Key-Rotation:</strong> Automatische Warnung bei veralteten Keys</li>
|
||||
<li><strong>Usage-Tracking:</strong> Überwachung von Key-Nutzung (nur Production)</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h3>6.2 Git Integration</h2>
|
||||
<div class="info-box">
|
||||
<h4>Git Hooks und CI/CD:</h4>
|
||||
<ul>
|
||||
<li><strong>Pre-commit Hook:</strong> Prüft auf Plain-Text Keys</li>
|
||||
<li><strong>Pre-push Hook:</strong> Validiert Key-Format und Environment</li>
|
||||
<li><strong>CI/CD Pipeline:</strong> Automatische Key-Validierung bei jedem Build</li>
|
||||
<li><strong>Deployment Check:</strong> Verhindert Deployment mit ungültigen Keys</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="architecture-box">
|
||||
<h2>7. Praktische Implementierung</h2>
|
||||
|
||||
<h3>7.1 Tool-Setup</h3>
|
||||
<div class="workflow-step">
|
||||
<h4>Entwickler-Setup:</h4>
|
||||
<ol>
|
||||
<li><strong>Master Key generieren:</strong> Lokalen Development Master Key erstellen</li>
|
||||
<li><strong>Tool installieren:</strong> Encryption Tool lokal installieren</li>
|
||||
<li><strong>Repository registrieren:</strong> Lokale Repositories im Tool registrieren</li>
|
||||
<li><strong>Test-Key erstellen:</strong> Ersten verschlüsselten Key erstellen</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<h3>7.2 Täglicher Workflow</h3>
|
||||
<div class="process-flow">
|
||||
<h4>Entwickler-Alltag:</h4>
|
||||
<ol>
|
||||
<li><strong>Neuen Key benötigen:</strong> API Key für neuen Customer</li>
|
||||
<li><strong>Tool starten:</strong> Encryption Tool öffnen</li>
|
||||
<li><strong>Kontext wählen:</strong> Repository, Instanz, Key-Name auswählen</li>
|
||||
<li><strong>Key einfügen:</strong> Plain-Text Key per Copy/Paste einfügen</li>
|
||||
<li><strong>Automatische Verschlüsselung:</strong> Tool verschlüsselt und speichert</li>
|
||||
<li><strong>Code verwenden:</strong> getConfig() kann Key sofort nutzen</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<h3>7.3 Key-Rotation</h3>
|
||||
<div class="success-box">
|
||||
<h4>✨ Einfache Key-Rotation:</h4>
|
||||
<ul>
|
||||
<li><strong>Automatische Erkennung:</strong> Tool erkennt Keys die rotiert werden müssen</li>
|
||||
<li><strong>One-Command Rotation:</strong> Alle Keys einer Instanz mit einem Befehl rotieren</li>
|
||||
<li><strong>Grace Period:</strong> Alte Keys bleiben 24h gültig für Übergang</li>
|
||||
<li><strong>Automatische Benachrichtigung:</strong> Team wird über Rotation informiert</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="architecture-box">
|
||||
<h2>8. Monitoring & Alerts</h2>
|
||||
|
||||
<h3>8.1 Key-Monitoring</h3>
|
||||
<div class="info-box">
|
||||
<h4>Überwachung der Keys:</h4>
|
||||
<ul>
|
||||
<li><strong>Key-Age:</strong> Tage bis zur Rotation</li>
|
||||
<li><strong>Usage-Patterns:</strong> Wie oft werden Keys verwendet</li>
|
||||
<li><strong>Environment-Mismatches:</strong> PROD Keys in DEV Umgebung</li>
|
||||
<li><strong>Plain-Text Detection:</strong> Unverschlüsselte Keys im Code</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h3>8.2 Alert-System</h3>
|
||||
<div class="warning-box">
|
||||
<h4>Automatische Benachrichtigungen:</h4>
|
||||
<ul>
|
||||
<li><strong>Rotation Due:</strong> Key muss in 7 Tagen rotiert werden</li>
|
||||
<li><strong>Security Violation:</strong> PROD Key in DEV Umgebung</li>
|
||||
<li><strong>Plain-Text Alert:</strong> Unverschlüsselter Key im Code gefunden</li>
|
||||
<li><strong>Usage Anomaly:</strong> Ungewöhnliche Key-Nutzung</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="architecture-box">
|
||||
<h2>9. Zusammenfassung der Werkzeuge</h2>
|
||||
|
||||
<div class="tool-description">
|
||||
<h3>9.1 Encryption Tool</h3>
|
||||
<ul>
|
||||
<li><strong>Zweck:</strong> Neue Keys verschlüsseln und in richtige Files speichern</li>
|
||||
<li><strong>Input:</strong> Repository, Instanz, Key-Name, Plain-Text Key</li>
|
||||
<li><strong>Output:</strong> Verschlüsselter Key im richtigen .env File</li>
|
||||
<li><strong>Lokale Nutzung:</strong> Funktioniert ohne Internetzugang</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="tool-description">
|
||||
<h3>9.2 getConfig() Funktion</h3>
|
||||
<ul>
|
||||
<li><strong>Zweck:</strong> Config Files laden und Keys entschlüsseln</li>
|
||||
<li><strong>Input:</strong> config.ini und .env Files</li>
|
||||
<li><strong>Output:</strong> Entschlüsselte Keys als Variablen</li>
|
||||
<li><strong>Integration:</strong> Wird beim App-Start aufgerufen</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="tool-description">
|
||||
<h3>9.3 Master Key Storage</h3>
|
||||
<ul>
|
||||
<li><strong>Development:</strong> Lokal auf Entwickler-Maschine</li>
|
||||
<li><strong>Production:</strong> Auf eigener V-Domäne</li>
|
||||
<li><strong>Keine Provider:</strong> Vollständige Kontrolle</li>
|
||||
<li><strong>Environment-Separation:</strong> Absolute Trennung Dev/Prod</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -307,19 +307,19 @@ class UserConnection(BaseModel, ModelMixin):
|
|||
|
||||
<div class="warning">
|
||||
<strong>⚠️ Critical Rule:</strong> All timestamp fields MUST include "UTC timestamp in seconds" in their description
|
||||
for the automatic conversion system to work correctly.
|
||||
for consistency and documentation purposes.
|
||||
</div>
|
||||
|
||||
<h3>1.6 Automatic Timestamp Conversion</h3>
|
||||
<h3>1.6 Direct Float Storage</h3>
|
||||
|
||||
<p>The system automatically converts timestamp fields using the <code class="code-inline">ModelMixin.to_dict()</code> method:</p>
|
||||
<p>The system now stores all timestamp fields directly as float values in the database:</p>
|
||||
|
||||
<div class="code-block">
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Convert a Pydantic model to a dictionary.
|
||||
Handles both Pydantic v1 and v2.
|
||||
Properly serializes datetime fields to ISO format strings.
|
||||
All timestamp fields remain as float values.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Dictionary representation of the model
|
||||
|
|
@ -330,44 +330,20 @@ def to_dict(self) -> Dict[str, Any]:
|
|||
else:
|
||||
data: Dict[str, Any] = self.dict() # Pydantic v1
|
||||
|
||||
# Convert datetime fields to ISO format strings
|
||||
for key, value in data.items():
|
||||
if isinstance(value, datetime):
|
||||
data[key] = value.isoformat()
|
||||
elif isinstance(value, (int, float)) and self._is_timestamp_field(key):
|
||||
# Handle timestamp fields based on field metadata
|
||||
try:
|
||||
data[key] = datetime.fromtimestamp(value).isoformat()
|
||||
except (ValueError, TypeError):
|
||||
# If conversion fails, keep the original value
|
||||
pass
|
||||
|
||||
return data
|
||||
|
||||
def _is_timestamp_field(self, field_name: str) -> bool:
|
||||
"""
|
||||
Check if a field is a timestamp field based on field metadata.
|
||||
Looks for 'UTC timestamp' in the field description.
|
||||
"""
|
||||
try:
|
||||
# Get field info from Pydantic model
|
||||
if hasattr(self, 'model_fields'):
|
||||
# Pydantic v2
|
||||
field_info = self.model_fields.get(field_name)
|
||||
if field_info and field_info.description:
|
||||
return 'UTC timestamp' in field_info.description
|
||||
elif hasattr(self, '__fields__'):
|
||||
# Pydantic v1
|
||||
field_info = self.__fields__.get(field_name)
|
||||
if field_info and field_info.field_info and field_info.field_info.description:
|
||||
return 'UTC timestamp' in field_info.field_info.description
|
||||
except Exception:
|
||||
pass
|
||||
# All fields (including timestamps) remain in their original format
|
||||
# No conversions needed - timestamps are already float
|
||||
|
||||
# Fallback: return False for safety
|
||||
return False
|
||||
return data
|
||||
</div>
|
||||
|
||||
<p><strong>Key Benefits:</strong></p>
|
||||
<ul>
|
||||
<li><strong>No unnecessary conversions</strong> between float and string</li>
|
||||
<li><strong>Direct database storage</strong> as float values</li>
|
||||
<li><strong>Consistent data types</strong> across the entire system</li>
|
||||
<li><strong>Better performance</strong> without string parsing</li>
|
||||
</ul>
|
||||
|
||||
<h3>1.7 Utility Functions</h3>
|
||||
|
||||
<h4>Backend Utilities (Python)</h4>
|
||||
|
|
@ -447,7 +423,7 @@ def migrate_timestamp_field(value):
|
|||
<tr>
|
||||
<td>Backend Models</td>
|
||||
<td><span class="phase-status phase-completed">COMPLETED</span></td>
|
||||
<td>11 models, 15 timestamp fields standardized</td>
|
||||
<td>11 models, 15 timestamp fields standardized as float</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Backend APIs</td>
|
||||
|
|
@ -460,9 +436,9 @@ def migrate_timestamp_field(value):
|
|||
<td>All utilities expect float timestamps</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Database Migration</td>
|
||||
<td><span class="phase-status phase-completed">NOT REQUIRED</span></td>
|
||||
<td>Database will be cleaned before testing</td>
|
||||
<td>Database Storage</td>
|
||||
<td><span class="phase-status phase-completed">COMPLETED</span></td>
|
||||
<td>All timestamps stored as float (no string conversion)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Testing & Validation</td>
|
||||
|
|
|
|||
Loading…
Reference in a new issue