diff --git a/backend/create_admin.py b/backend/create_admin.py index c2d3dcb..c38db25 100644 --- a/backend/create_admin.py +++ b/backend/create_admin.py @@ -1,64 +1,82 @@ """ -TEE OFF ADMIN GENERATOR v1.9 (DEBUG & BULLETPROOF) +TEE OFF ADMIN GENERATOR --------------------------------------------------------------------------- -FUNKSJON: Genererer SQL-kommando for administrator. -STATUS: Beholder TRUNCATE for feilsøking, men sikrer SQL-innsendingen. +FUNKSJON: Oppretter eller erstatter administrator direkte i databasen uten + å skrive ut SQL, passordhash eller andre hemmeligheter. +STATUS: Nullstiller admins-tabellen og lager en ny 2FA-hemmelighet. --------------------------------------------------------------------------- """ -import pyotp -from passlib.hash import pbkdf2_sha256 +import asyncio import getpass import sys -def generate_admin(): - print("\n" + "="*50) - print(" TEE OFF ADMIN GENERATOR v1.9 (DEBUG MODE)") - print("="*50) - - username = input("Brukernavn (f.eks Envide Webutvikling): ").strip() +import asyncpg +import pyotp +from passlib.hash import pbkdf2_sha256 + +from env_config import get_database_url + +DB_URL = get_database_url() + + +async def generate_admin() -> None: + print("\n" + "=" * 50) + print(" TEE OFF ADMIN GENERATOR") + print("=" * 50) + + username = input("Brukernavn (f.eks Brukeren Leif): ").strip() email = input("E-post: ").strip() - - # Sikre mot SQL-feil hvis navnet/eposten inneholder apostrof - safe_username = username.replace("'", "''") - safe_email = email.replace("'", "''") - - # Passord-verifisering + while True: password = getpass.getpass("Skriv inn passord: ") password_confirm = getpass.getpass("Gjenta passord: ") - - if password == password_confirm: - if len(password) < 8: - print("⚠️ Advarsel: Passordet bør være minst 8 tegn.") - print(f"\n[DEBUG] Passord akseptert. Lengde: {len(password)} tegn.") - break - else: - print("❌ Passordene er ikke like. Prøv igjen.\n") - otp_secret = pyotp.random_base32() - - print("⏳ Genererer PBKDF2-hash...") + if password != password_confirm: + print("❌ Passordene er ikke like. Prøv igjen.\n") + continue + + if len(password) < 8: + print("⚠️ Advarsel: Passordet bør være minst 8 tegn.") + break + password_hash = pbkdf2_sha256.hash(password) - print(f"[DEBUG] Hash generert. Lengde: {len(password_hash)} tegn.") - - print("\n✅ GENERERING VELLYKKET!") + otp_secret = pyotp.random_base32() + + conn = None + try: + conn = await asyncpg.connect(DB_URL) + async with conn.transaction(): + await conn.execute("TRUNCATE admins") + await conn.execute( + """ + INSERT INTO admins (username, email, password_hash, otp_secret) + VALUES ($1, $2, $3, $4) + """, + username, + email, + password_hash, + otp_secret, + ) + except Exception as exc: + print(f"❌ Kunne ikke opprette admin-brukeren: {type(exc).__name__}") + sys.exit(1) + finally: + if conn is not None: + await conn.close() + + print("\n✅ ADMIN BRUKER OPPRETTET") print("-" * 50) - print("SLIK LEGGER DU INN BRUKEREN TRYGT:") + print("Brukeren er lagret direkte i databasen.") + print("2FA-hemmeligheten vises nedenfor kun denne ene gangen.") + print("Lagre den i authenticator-appen din før du lukker terminalen.") print("-" * 50) - print("1. Gå inn i databasen:") - print(" docker exec -it teeoff_db psql -U teeoff_admin -d teeoff") - print("\n2. Lim inn disse to linjene nøyaktig slik de står:") - print("TRUNCATE admins;") - print(f"INSERT INTO admins (username, email, password_hash, otp_secret) VALUES ('{safe_username}', '{safe_email}', '{password_hash}', '{otp_secret}');") - print("\n3. Skriv 'exit' for å gå ut.") - print("-" * 50) - print("4. KONFIGURER 2FA I GOOGLE AUTHENTICATOR:") - print(f"Bruk denne nøkkelen: {otp_secret}") + print(f"2FA-nøkkel: {otp_secret}") print("-" * 50 + "\n") + if __name__ == "__main__": try: - generate_admin() + asyncio.run(generate_admin()) except KeyboardInterrupt: print("\nAvbrutt.") - sys.exit(0) \ No newline at end of file + sys.exit(0) diff --git a/backend/test_login.py b/backend/test_login.py index 93606f9..b134236 100644 --- a/backend/test_login.py +++ b/backend/test_login.py @@ -1,6 +1,7 @@ import asyncio import asyncpg import os +import sys from passlib.context import CryptContext from env_config import get_database_url, get_required_env @@ -16,23 +17,23 @@ async def test_sannheten(): username = os.getenv("TEST_ADMIN_USERNAME", "Envide Webutvikling").strip() test_password = get_required_env("TEST_ADMIN_PASSWORD") - + + conn = None try: conn = await asyncpg.connect(DB_URL) row = await conn.fetchrow("SELECT password_hash FROM admins WHERE username = $1", username) - + if not row: print("❌ FEIL: Fant ikke brukeren i det hele tatt!") return - + db_hash = row['password_hash'] - print(f"1. Hash funnet i databasen: {db_hash[:30]}...") - - print(f"2. Tester mot passordet: '{test_password}'") - + print("1. Hash funnet i databasen.") + print("2. Tester om oppgitt TEST_ADMIN_PASSWORD matcher.") + # Den magiske testen is_valid = pwd_context.verify(test_password, db_hash) - + print("-" * 50) if is_valid: print("✅ SUKSESS! Passordet og hashen stemmer 100% overens.") @@ -40,9 +41,12 @@ async def test_sannheten(): else: print("❌ FEIL! Passordet stemmer IKKE med hashen i databasen.") print("➡️ KONKLUSJON: Scriptet som oppdaterer passordet gjør en feil (f.eks. legger til usynlige tegn), eller lagringen i databasen blir korrupt.") - + except Exception as exc: + print(f"❌ Kunne ikke teste admin-login: {type(exc).__name__}") + sys.exit(1) finally: - await conn.close() + if conn is not None: + await conn.close() if __name__ == "__main__": asyncio.run(test_sannheten()) diff --git a/backend/update_admin.py b/backend/update_admin.py index 6b4d697..2a9386f 100644 --- a/backend/update_admin.py +++ b/backend/update_admin.py @@ -8,7 +8,6 @@ STATUS: Påvirker IKKE tofaktor (2FA). Gjør jobben fra start til slutt. """ import asyncio import asyncpg -import os import sys import getpass from passlib.hash import pbkdf2_sha256 @@ -23,10 +22,11 @@ async def update_admin_password(): print("="*50) # Kobler til databasen på ekte backend-vis + conn = None try: conn = await asyncpg.connect(DB_URL) - except Exception as e: - print(f"❌ Kunne ikke koble til databasen: {e}") + except Exception as exc: + print(f"❌ Kunne ikke koble til databasen: {type(exc).__name__}") sys.exit(1) try: @@ -55,7 +55,6 @@ async def update_admin_password(): if password == password_confirm: if len(password) < 8: print("⚠️ Advarsel: Passordet bør være minst 8 tegn.") - print(f"\n[DEBUG] Passord akseptert.") break else: print("❌ Passordene er ikke like. Prøv igjen.\n") @@ -75,7 +74,8 @@ async def update_admin_password(): finally: # Lukk tilkoblingen pent - await conn.close() + if conn is not None: + await conn.close() if __name__ == "__main__": try: