TUI: 菜单 9注册 10登录 11注销 12重新生成密钥; 密钥导出/导入路径改系统位置

This commit is contained in:
lou
2026-08-10 15:27:48 +08:00
parent e1baf21be5
commit 66dc81952e
2 changed files with 104 additions and 3 deletions
+4
View File
@@ -12,6 +12,10 @@
6. 删除文件 (先 ls 再选 file_id)
7. 密钥导出 (红色风险警告 + 二次确认, 导出权限 600)
8. 密钥导入 (红色风险警告 + 二次确认, 自动备份 keyring.json.bak)
9. 注册账号 (用户名+密码, 成功即登录)
10. 登录 (token 自动保存)
11. 注销 (token 失效)
12. 重新生成密钥 (红色警告 + 二次确认, 旧密文永久不可解)
q. 退出
```
+100 -3
View File
@@ -136,6 +136,75 @@ def config_edit() -> None:
config_show()
def auth_register() -> None:
"""注册账号 (成功即登录)"""
print("--- 注册账号 ---")
user = _clean(input("用户名 (3-32 位字母数字或下划线): "))
pw = input("密码 (至少 6 位): ")
if not user or not pw:
print("[错误] 用户名/密码不能为空")
return
server = _clean(input(f"服务器 [{_default_server()}]: ")) or _default_server()
if not server.startswith(("http://", "https://")):
server = "http://" + server
code = run(["transfer.py", "--server", server, "--register", user, pw])
print("[完成]" if code == 0 else "[失败] 注册出错")
def auth_login() -> None:
"""登录账号"""
print("--- 登录 ---")
user = _clean(input("用户名: "))
pw = input("密码: ")
if not user or not pw:
print("[错误] 用户名/密码不能为空")
return
server = _clean(input(f"服务器 [{_default_server()}]: ")) or _default_server()
if not server.startswith(("http://", "https://")):
server = "http://" + server
code = run(["transfer.py", "--server", server, "--login", user, pw])
print("[完成]" if code == 0 else "[失败] 登录出错")
def auth_logout() -> None:
"""注销当前账号 (token 失效)"""
print("--- 注销 ---")
c = input("确认退出当前账号? (输入 yes): ").strip().lower()
if c != "yes":
print("[取消]")
return
server = _clean(input(f"服务器 [{_default_server()}]: ")) or _default_server()
if not server.startswith(("http://", "https://")):
server = "http://" + server
code = run(["transfer.py", "--server", server, "--logout"])
print("[完成] 已注销" if code == 0 else "[失败] 注销出错")
def regenerate_key() -> None:
"""重新生成密钥: 红色风险警告 + 二次确认 (旧密文全废)"""
print("--- 重新生成密钥 ---")
print()
print("\033[91m" + "" * 52 + "\033[0m")
print("\033[91m ⚠ 危险操作警告\033[0m")
print()
print("\033[91m 重新生成密钥 = 丢弃当前密钥!\033[0m")
print("\033[91m · 当前密钥加密的已上传文件将永久无法解密\033[0m")
print("\033[91m · 建议先导出旧密钥备份 (菜单 7)\033[0m")
print("\033[91m · 执行后仅新上传的文件可用新密钥解密\033[0m")
print("\033[91m" + "" * 52 + "\033[0m")
print()
c1 = input("是否了解风险并继续? (输入 yes 继续): ").strip().lower()
if c1 != "yes":
print("[取消] 未重新生成")
return
c2 = input("再次确认: 输入 CONFIRM 才执行: ").strip()
if c2 != "CONFIRM":
print("[取消] 未重新生成")
return
code = run(["config.py", "--regenerate-key", "--yes"])
print("[完成]" if code == 0 else "[失败] 重新生成出错")
def files_list() -> None:
"""ls: 列出服务端文件 + 空间配额"""
print("--- 文件列表 ---")
@@ -187,6 +256,22 @@ def delete_file() -> None:
print("[完成]" if code == 0 else "[失败] 删除出错")
def _keyring_path() -> Path:
"""密钥库路径: config.json 显式指定用指定, 否则系统默认 (SZ_KEYRING env/XDG)"""
try:
cfg = json.loads(Path(f"{CLIENT_DIR}/config/config.json").read_text(encoding="utf-8"))
raw = cfg.get("crypto", {}).get("keyring_path", "")
if raw:
return Path(raw)
except (OSError, json.JSONDecodeError):
pass
env = os.environ.get("SZ_KEYRING")
if env:
return Path(env)
xdg = os.environ.get("XDG_DATA_HOME") or str(Path.home() / ".local" / "share")
return Path(xdg) / "7z-encrypt" / "keyring.json"
def export_key() -> None:
"""密钥导出: 红色风险警告 + 二次确认 (防误操作)"""
print("--- 密钥导出 ---")
@@ -210,9 +295,9 @@ def export_key() -> None:
if c2 != "CONFIRM":
print("[取消] 未导出")
return
keyring = Path(f"{CLIENT_DIR}/config/keyring.json")
keyring = _keyring_path()
if not keyring.exists():
print("[错误] 密钥文件不存在, 无法导出")
print(f"[错误] 密钥文件不存在: {keyring}")
return
out = _clean(input(f"导出到路径 [~/keyring-export.json]: "))
out = out or str(Path.home() / "keyring-export.json")
@@ -243,7 +328,7 @@ def import_key() -> None:
print(f"[错误] 无法读取密钥文件: {e}")
return
keyring = Path(f"{CLIENT_DIR}/config/keyring.json")
keyring = _keyring_path()
print()
print("\033[91m" + "" * 52 + "\033[0m")
print("\033[91m ⚠ 危险操作警告\033[0m")
@@ -288,6 +373,10 @@ def main() -> int:
print(" 6. 删除文件")
print(" 7. 密钥导出")
print(" 8. 密钥导入")
print(" 9. 注册账号")
print(" 10. 登录")
print(" 11. 注销")
print(" 12. 重新生成密钥")
print(" q. 退出")
choice = input("> ").strip().lower()
if choice == "1":
@@ -309,6 +398,14 @@ def main() -> int:
export_key()
elif choice == "8":
import_key()
elif choice == "9":
auth_register()
elif choice == "10":
auth_login()
elif choice == "11":
auth_logout()
elif choice == "12":
regenerate_key()
elif choice == "q":
print("再见")
return 0