Initial commit: AegisSight-Monitor (OSINT-Monitoringsystem)

Dieser Commit ist enthalten in:
claude-dev
2026-03-04 17:53:18 +01:00
Commit 8312d24912
51 geänderte Dateien mit 19355 neuen und 0 gelöschten Zeilen

0
src/migration/__init__.py Normale Datei
Datei anzeigen

Datei anzeigen

@@ -0,0 +1,177 @@
"""Einmalige Datenmigration zu Multi-Tenancy.
Dieses Script:
1. Erstellt die AegisSight-Organisation
2. Erstellt eine permanente Lizenz fuer AegisSight
3. Weist bestehende Nutzer (rac00n, ch33tah) der AegisSight-Org zu
4. Setzt tenant_id auf alle bestehenden Daten
5. Erstellt Portal-Admin-Zugaenge
"""
import asyncio
import os
import sys
import shutil
from datetime import datetime
# Pfade fuer Imports
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from config import DB_PATH, TIMEZONE
from database import init_db, get_db
from auth import hash_password
# E-Mail-Adressen fuer bestehende Nutzer
USER_EMAILS = {
"rac00n": os.environ.get("RACOON_EMAIL", "momohomma@googlemail.com"),
"ch33tah": os.environ.get("CHEETAH_EMAIL", "hendrik_gebhardt@gmx.de"),
}
async def migrate():
"""Fuehrt die Multi-Tenancy-Migration durch."""
# 1. Backup erstellen
if os.path.exists(DB_PATH):
backup_path = DB_PATH + f".backup-{datetime.now().strftime('%Y%m%d_%H%M%S')}"
shutil.copy2(DB_PATH, backup_path)
print(f"Backup erstellt: {backup_path}")
else:
print("Keine bestehende Datenbank gefunden. Frische Installation.")
# 2. Schema-Migration (init_db erstellt neue Tabellen und fuegt Spalten hinzu)
await init_db()
print("Schema-Migration abgeschlossen.")
db = await get_db()
try:
# 3. Pruefen ob Migration bereits gelaufen ist
cursor = await db.execute("SELECT COUNT(*) as cnt FROM organizations")
org_count = (await cursor.fetchone())["cnt"]
if org_count > 0:
print("Migration wurde bereits durchgefuehrt. Abbruch.")
return
# 4. AegisSight-Organisation anlegen
now = datetime.now(TIMEZONE).isoformat()
cursor = await db.execute(
"""INSERT INTO organizations (name, slug, is_active, created_at, updated_at)
VALUES (?, ?, 1, ?, ?)""",
("AegisSight", "aegissight", now, now),
)
aegis_org_id = cursor.lastrowid
print(f"Organisation AegisSight angelegt (ID: {aegis_org_id})")
# 5. Permanente Lizenz fuer AegisSight
await db.execute(
"""INSERT INTO licenses (organization_id, license_type, max_users, valid_from, valid_until, status, notes)
VALUES (?, 'permanent', 50, ?, NULL, 'active', 'Interne AegisSight-Lizenz')""",
(aegis_org_id, now),
)
print("Permanente Lizenz fuer AegisSight erstellt")
# 6. Bestehende Nutzer der AegisSight-Org zuweisen
cursor = await db.execute("SELECT id, username FROM users")
users = await cursor.fetchall()
for user in users:
username = user["username"]
email = USER_EMAILS.get(username, f"{username}@aegis-sight.de")
await db.execute(
"""UPDATE users SET
organization_id = ?,
role = 'org_admin',
is_active = 1,
email = ?
WHERE id = ?""",
(aegis_org_id, email, user["id"]),
)
print(f"Nutzer '{username}' -> AegisSight (org_admin, email: {email})")
# 7. tenant_id auf alle bestehenden Incidents setzen
await db.execute(
"UPDATE incidents SET tenant_id = ? WHERE tenant_id IS NULL",
(aegis_org_id,),
)
cursor = await db.execute("SELECT changes()")
changes = (await cursor.fetchone())[0]
print(f"{changes} Incidents mit tenant_id versehen")
# 8. tenant_id auf alle bestehenden Articles setzen
await db.execute(
"UPDATE articles SET tenant_id = ? WHERE tenant_id IS NULL",
(aegis_org_id,),
)
cursor = await db.execute("SELECT changes()")
changes = (await cursor.fetchone())[0]
print(f"{changes} Articles mit tenant_id versehen")
# 9. tenant_id auf alle bestehenden fact_checks setzen
await db.execute(
"UPDATE fact_checks SET tenant_id = ? WHERE tenant_id IS NULL",
(aegis_org_id,),
)
# 10. tenant_id auf alle bestehenden refresh_log setzen
await db.execute(
"UPDATE refresh_log SET tenant_id = ? WHERE tenant_id IS NULL",
(aegis_org_id,),
)
# 11. tenant_id auf alle bestehenden incident_snapshots setzen
await db.execute(
"UPDATE incident_snapshots SET tenant_id = ? WHERE tenant_id IS NULL",
(aegis_org_id,),
)
# 12. tenant_id auf alle bestehenden notifications setzen
await db.execute(
"UPDATE notifications SET tenant_id = ? WHERE tenant_id IS NULL",
(aegis_org_id,),
)
# 13. System-Quellen bleiben global (tenant_id=NULL)
# Nur nutzer-erstellte Quellen bekommen tenant_id
await db.execute(
"UPDATE sources SET tenant_id = ? WHERE added_by != 'system' AND tenant_id IS NULL",
(aegis_org_id,),
)
print("Nutzer-Quellen mit tenant_id versehen (System-Quellen bleiben global)")
# 14. Portal-Admin-Zugaenge anlegen
print("\n--- Portal-Admin-Zugaenge ---")
portal_users = ["rac00n", "ch33tah"]
for pu in portal_users:
# Pruefen ob schon existiert
cursor = await db.execute(
"SELECT id FROM portal_admins WHERE username = ?", (pu,)
)
if await cursor.fetchone():
print(f"Portal-Admin '{pu}' existiert bereits")
continue
# Passwort generieren
import secrets
import string
password = ''.join(secrets.choice(string.ascii_letters + string.digits + "!@#$%&*") for _ in range(16))
pw_hash = hash_password(password)
await db.execute(
"INSERT INTO portal_admins (username, password_hash) VALUES (?, ?)",
(pu, pw_hash),
)
print(f"Portal-Admin '{pu}' erstellt - Passwort: {password}")
await db.commit()
print("\nMigration erfolgreich abgeschlossen!")
except Exception as e:
print(f"\nFEHLER bei Migration: {e}")
raise
finally:
await db.close()
if __name__ == "__main__":
asyncio.run(migrate())