123 lines
3.0 KiB
Python
Executable File
123 lines
3.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""Helper SQLite pour l’extension Password Applet.
|
||
|
||
Commandes :
|
||
- init : initialise la base
|
||
- list : renvoie les entrées
|
||
- add : ajoute une entrée
|
||
|
||
Note :
|
||
Le champ password_enc stocke le mot de passe en clair (MVP).
|
||
"""
|
||
|
||
import json
|
||
import os
|
||
import sqlite3
|
||
import sys
|
||
from datetime import datetime
|
||
|
||
APP_DATA_DIR = os.path.join(
|
||
os.path.expanduser('~'),
|
||
'.local', 'share', 'gnome-shell', 'password-applet'
|
||
)
|
||
DB_PATH = os.path.join(APP_DATA_DIR, 'passwords.db')
|
||
|
||
SCHEMA = """
|
||
CREATE TABLE IF NOT EXISTS entries (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
label TEXT NOT NULL,
|
||
username TEXT NOT NULL,
|
||
password_enc TEXT NOT NULL,
|
||
url TEXT,
|
||
notes TEXT,
|
||
is_favorite INTEGER NOT NULL DEFAULT 0,
|
||
created_at TEXT NOT NULL,
|
||
updated_at TEXT NOT NULL
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS settings (
|
||
key TEXT PRIMARY KEY,
|
||
value TEXT NOT NULL
|
||
);
|
||
"""
|
||
|
||
def ensure_db():
|
||
os.makedirs(APP_DATA_DIR, exist_ok=True)
|
||
conn = sqlite3.connect(DB_PATH)
|
||
try:
|
||
conn.executescript(SCHEMA)
|
||
conn.commit()
|
||
finally:
|
||
conn.close()
|
||
|
||
def encrypt_password(plain: str) -> str:
|
||
return plain # Pour le MVP, rien
|
||
|
||
def cmd_init():
|
||
ensure_db()
|
||
|
||
def cmd_list():
|
||
ensure_db()
|
||
conn = sqlite3.connect(DB_PATH)
|
||
conn.row_factory = sqlite3.Row
|
||
try:
|
||
cur = conn.execute(
|
||
"SELECT id, label, username, password_enc, url, notes, "
|
||
"is_favorite, created_at, updated_at "
|
||
"FROM entries ORDER BY created_at DESC"
|
||
)
|
||
rows = [dict(row) for row in cur.fetchall()]
|
||
finally:
|
||
conn.close()
|
||
|
||
print(json.dumps(rows))
|
||
|
||
def cmd_add():
|
||
ensure_db()
|
||
raw = sys.stdin.read()
|
||
data = json.loads(raw or '{}')
|
||
|
||
label = (data.get('label') or '').strip()
|
||
username = (data.get('username') or '').strip()
|
||
password = (data.get('password') or '').strip()
|
||
url = (data.get('url') or '').strip() or None
|
||
notes = (data.get('notes') or '').strip() or None
|
||
|
||
if not label or not username or not password:
|
||
print('Missing required fields', file=sys.stderr)
|
||
sys.exit(1)
|
||
|
||
password_enc = encrypt_password(password)
|
||
now = datetime.utcnow().isoformat(timespec='seconds') + 'Z'
|
||
|
||
conn = sqlite3.connect(DB_PATH)
|
||
try:
|
||
conn.execute(
|
||
"INSERT INTO entries (label, username, password_enc, url, notes, "
|
||
"is_favorite, created_at, updated_at) VALUES (?, ?, ?, ?, ?, 0, ?, ?)",
|
||
(label, username, password_enc, url, notes, now, now)
|
||
)
|
||
conn.commit()
|
||
finally:
|
||
conn.close()
|
||
|
||
def main(argv):
|
||
if len(argv) < 2:
|
||
print("Usage: password_db.py [init|list|add]")
|
||
return 1
|
||
|
||
cmd = argv[1]
|
||
|
||
if cmd == "init":
|
||
cmd_init()
|
||
elif cmd == "list":
|
||
cmd_list()
|
||
elif cmd == "add":
|
||
cmd_add()
|
||
else:
|
||
print(f"Unknown command: {cmd}", file=sys.stderr)
|
||
return 1
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(main(sys.argv))
|