llm / scripts /reset_password.py
Aswin480
feat: initial commit for PABOT Personal Operating System
34b54ad
Raw History Blame Contribute Delete
2.13 kB
"""
Local Terminal Recovery Script — Reset Master Password.
Security Invariant:
• Executes ONLY on the local host via terminal/CLI.
• Directly modifies the local SQLite app.db — never exposed over HTTP/network.
"""
from __future__ import annotations
import argparse
import getpass
import sqlite3
import sys
from datetime import UTC, datetime
from pathlib import Path
import bcrypt
ROOT_DIR = Path(__file__).resolve().parents[1]
APP_DB = ROOT_DIR / "app.db"
def reset_password(new_password: str) -> None:
if len(new_password) < 8:
print("Error: Password must be at least 8 characters.", file=sys.stderr)
sys.exit(1)
APP_DB.parent.mkdir(parents=True, exist_ok=True)
conn = sqlite3.connect(str(APP_DB))
cur = conn.cursor()
cur.execute(
"""CREATE TABLE IF NOT EXISTS auth_config (
key TEXT PRIMARY KEY,
value TEXT NOT NULL,
updated_at TEXT NOT NULL
)"""
)
pw_bytes = new_password.encode("utf-8")[:72]
pw_hash = bcrypt.hashpw(pw_bytes, bcrypt.gensalt()).decode("utf-8")
now = datetime.now(UTC).isoformat()
cur.execute(
"""INSERT INTO auth_config(key, value, updated_at) VALUES (?,?,?)
ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at""",
("master_password_hash", pw_hash, now),
)
conn.commit()
conn.close()
print("[OK] Master password reset successfully in app.db.")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Reset PA/POS master password locally from the server console.")
parser.add_argument("--password", type=str, help="New master password (optional; prompted securely if omitted)")
args = parser.parse_args()
password = args.password
if not password:
password = getpass.getpass("Enter new master password (min 8 chars): ")
confirm = getpass.getpass("Confirm new master password: ")
if password != confirm:
print("Error: Passwords do not match.", file=sys.stderr)
sys.exit(1)
reset_password(password)