feat: sap-cli skill v2.1.0 — self-contained distributable package
- assets/: sap-cli source (v2.1.0, 26 commands, 16 object types) - references/: tool constraints + error handling (self-contained) - scripts/setup.py: one-click install/config/verify - SKILL.md: full command reference + dual-platform install guide - VERSION: 2.1.0 Built from D:/Codespace/sap-cli via scripts/pack_skill.py
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
"""凭证管理模块。
|
||||
|
||||
使用 keyring 库安全存储 SAP 密码,优雅降级到 config.ini。
|
||||
服务名格式: sap-cli:{host}:{client}
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import getpass
|
||||
import logging
|
||||
|
||||
# 从独立模块导入,避免与 config 循环 import
|
||||
from sapcli.password import ( # noqa: F401 – re-export
|
||||
_KEYRING_AVAILABLE,
|
||||
_keyring,
|
||||
_keyring_mod,
|
||||
_service_name,
|
||||
get_password,
|
||||
resolve_password,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("sapcli.auth")
|
||||
|
||||
|
||||
def set_password(host: str, client: str, user: str, password: str) -> bool:
|
||||
"""存储密码到 keyring。
|
||||
|
||||
Returns:
|
||||
是否成功存储
|
||||
"""
|
||||
if not _KEYRING_AVAILABLE:
|
||||
print(" ✗ keyring 库不可用,无法安全存储密码")
|
||||
print(" 安装方法: pip install keyring")
|
||||
return False
|
||||
try:
|
||||
_keyring.set_password(_service_name(host, client), user, password)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f" ✗ 存储密码失败: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def delete_password(host: str, client: str, user: str) -> bool:
|
||||
"""从 keyring 删除密码。
|
||||
|
||||
Returns:
|
||||
是否成功删除
|
||||
"""
|
||||
if not _KEYRING_AVAILABLE:
|
||||
print(" ✗ keyring 库不可用")
|
||||
return False
|
||||
try:
|
||||
_keyring.delete_password(_service_name(host, client), user)
|
||||
return True
|
||||
except _keyring_mod.errors.PasswordDeleteError:
|
||||
print(" ℹ keyring 中未找到该密码")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f" ✗ 删除密码失败: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def cmd_auth_login(args: argparse.Namespace, client=None) -> None:
|
||||
"""auth login: 交互式保存密码到 keyring。"""
|
||||
import os
|
||||
from sapcli.config import load_config
|
||||
|
||||
try:
|
||||
cfg, _ = load_config(getattr(args, "config", None))
|
||||
except Exception as e:
|
||||
print(f" ✗ 无法加载配置: {e}")
|
||||
return
|
||||
|
||||
print("=" * 60)
|
||||
print(" sap-cli 密钥登录")
|
||||
print("=" * 60)
|
||||
print(f" 主机: {cfg.host}")
|
||||
print(f" Client: {cfg.client}")
|
||||
print(f" 用户: {cfg.user}")
|
||||
|
||||
password = getpass.getpass(" 请输入密码: ")
|
||||
if not password:
|
||||
print(" ✗ 密码不能为空")
|
||||
return
|
||||
|
||||
if set_password(cfg.host, cfg.client, cfg.user, password):
|
||||
print(f" ✓ 密码已安全存储到 keyring")
|
||||
print(f" 服务名: {_service_name(cfg.host, cfg.client)}")
|
||||
else:
|
||||
print(" ✗ 密码存储失败")
|
||||
|
||||
|
||||
def cmd_auth_logout(args: argparse.Namespace, client=None) -> None:
|
||||
"""auth logout: 从 keyring 删除密码。"""
|
||||
from sapcli.config import load_config
|
||||
|
||||
try:
|
||||
cfg, _ = load_config(getattr(args, "config", None))
|
||||
except Exception as e:
|
||||
print(f" ✗ 无法加载配置: {e}")
|
||||
return
|
||||
|
||||
if delete_password(cfg.host, cfg.client, cfg.user):
|
||||
print(" ✓ 密码已从 keyring 删除")
|
||||
else:
|
||||
print(" ✗ 删除失败")
|
||||
|
||||
|
||||
def cmd_auth_status(args: argparse.Namespace, client=None) -> None:
|
||||
"""auth status: 显示 keyring 状态。"""
|
||||
print("=" * 60)
|
||||
print(" sap-cli 密钥状态")
|
||||
print("=" * 60)
|
||||
|
||||
if _KEYRING_AVAILABLE:
|
||||
print(f" keyring: ✓ 可用")
|
||||
try:
|
||||
backend = _keyring.get_keyring().__class__.__name__
|
||||
print(f" 后端: {backend}")
|
||||
except Exception:
|
||||
logger.debug("获取 keyring 后端名称失败", exc_info=True)
|
||||
else:
|
||||
print(f" keyring: ✗ 不可用")
|
||||
print(f" 安装方法: pip install keyring")
|
||||
Reference in New Issue
Block a user