|
1 | 1 | from __future__ import annotations |
2 | 2 | import hashlib |
| 3 | +import json |
| 4 | +import os |
3 | 5 |
|
4 | 6 | from PySide6.QtCore import Qt |
5 | 7 | from PySide6.QtWidgets import ( |
6 | 8 | QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, |
7 | 9 | QCheckBox, |
8 | 10 | ) |
9 | 11 |
|
| 12 | +from ...utils import paths |
| 13 | + |
10 | 14 |
|
11 | | -_PASSWORD_SHA256 = "30fa18a448f91d5558499fcf9e5c8fccf9f736b31d874629f38cd65f8feedcee" |
12 | 15 | _MAX_ATTEMPTS = 5 |
| 16 | +_AUTH_FILE = "auth.json" |
| 17 | + |
| 18 | + |
| 19 | +def _load_password_hash() -> str: |
| 20 | + """Load the expected SHA-256 hash from (in order): |
| 21 | + 1. env var AUTH_PASSWORD_HASH (for CI) |
| 22 | + 2. bundled / dev-tree auth.json (gitignored) |
| 23 | + Returns empty string if missing -> verify() will always fail.""" |
| 24 | + env = os.environ.get("AUTH_PASSWORD_HASH", "").strip().lower() |
| 25 | + if env: |
| 26 | + return env |
| 27 | + try: |
| 28 | + path = paths.find_resource(_AUTH_FILE) |
| 29 | + if path and path.exists(): |
| 30 | + with open(path, "r", encoding="utf-8") as f: |
| 31 | + data = json.load(f) |
| 32 | + return str(data.get("password_sha256", "")).strip().lower() |
| 33 | + except Exception: |
| 34 | + pass |
| 35 | + return "" |
13 | 36 |
|
14 | 37 |
|
15 | 38 | def verify(password: str) -> bool: |
16 | | - # strip leading/trailing whitespace defensively (full-width spaces too) |
| 39 | + expected = _load_password_hash() |
| 40 | + if not expected: |
| 41 | + return False |
17 | 42 | cleaned = password.strip().strip(" ") |
18 | | - return hashlib.sha256(cleaned.encode("utf-8")).hexdigest() == _PASSWORD_SHA256 |
| 43 | + return hashlib.sha256(cleaned.encode("utf-8")).hexdigest().lower() == expected |
19 | 44 |
|
20 | 45 |
|
21 | 46 | class AuthDialog(QDialog): |
|
0 commit comments