import secrets import json import os from datetime import datetime KEYS_FILE = "api_keys.json" def load_keys(): if os.path.exists(KEYS_FILE): with open(KEYS_FILE, "r") as f: return json.load(f) return {} def save_keys(keys): with open(KEYS_FILE, "w") as f: json.dump(keys, f, indent=2) def generate_api_key(label: str) -> str: keys = load_keys() new_key = "pii_sk_" + secrets.token_urlsafe(32) keys[new_key] = { "label": label, "active": True, "usage": 0, "created_at": datetime.utcnow().isoformat() } save_keys(keys) return new_key def validate_key(api_key: str) -> dict | None: keys = load_keys() entry = keys.get(api_key) if entry and entry["active"]: return entry return None def increment_usage(api_key: str): keys = load_keys() if api_key in keys: keys[api_key]["usage"] += 1 save_keys(keys) def revoke_key(api_key: str): keys = load_keys() if api_key in keys: keys[api_key]["active"] = False save_keys(keys) def delete_key(api_key: str): keys = load_keys() keys.pop(api_key, None) save_keys(keys) def list_keys() -> list[dict]: keys = load_keys() rows = [] for k, v in keys.items(): rows.append({ "key_preview": k[:14] + "••••••••", "label": v["label"], "status": "Active" if v["active"] else "Revoked", "usage": v["usage"], "created_at": v["created_at"][:10], "full_key": k # used internally for revoke/delete }) return rows