@@ -0,0 +1,87 @@
|
||||
"""
|
||||
Запись .secret/gitea_secrets.json из админки (без CLI).
|
||||
|
||||
Шифрование совместимо с update.SecretEncryption: пароль — SECRET_KEY приложения
|
||||
или WESP_MASTER_PASSWORD / keyring при расшифровке в update.py.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
_SECRET_KEYS = frozenset({"gitea_token", "gitea_username", "gitea_password"})
|
||||
|
||||
|
||||
def gitea_secrets_path(base_dir: str) -> Path:
|
||||
return Path(base_dir).resolve() / ".secret" / "gitea_secrets.json"
|
||||
|
||||
|
||||
def read_gitea_secrets_raw(base_dir: str) -> Dict[str, Any]:
|
||||
path = gitea_secrets_path(base_dir)
|
||||
if not path.is_file():
|
||||
return {}
|
||||
try:
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
return data if isinstance(data, dict) else {}
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
|
||||
def gitea_file_secret_flags(base_dir: str) -> Dict[str, bool]:
|
||||
raw = read_gitea_secrets_raw(base_dir)
|
||||
has_user = bool(raw.get("gitea_username"))
|
||||
has_pass = bool(raw.get("gitea_password"))
|
||||
return {
|
||||
"gitea_file_has_token": bool(raw.get("gitea_token")),
|
||||
"gitea_file_has_password_auth": has_user and has_pass,
|
||||
}
|
||||
|
||||
|
||||
def patch_gitea_secrets_file(
|
||||
base_dir: str,
|
||||
encryption_password: str,
|
||||
*,
|
||||
gitea_token: Optional[str] = None,
|
||||
gitea_username: Optional[str] = None,
|
||||
gitea_password: Optional[str] = None,
|
||||
clear_secrets: bool = False,
|
||||
) -> None:
|
||||
"""
|
||||
Обновить зашифрованные поля в gitea_secrets.json.
|
||||
Пустые строки в аргументах = не менять поле.
|
||||
"""
|
||||
from update import SecretEncryption
|
||||
|
||||
if not isinstance(encryption_password, str) or len(encryption_password) < 8:
|
||||
raise ValueError("Секретный ключ приложения слишком короткий — задайте WESP_SECRET_KEY")
|
||||
|
||||
path = gitea_secrets_path(base_dir)
|
||||
data = read_gitea_secrets_raw(base_dir)
|
||||
|
||||
if clear_secrets:
|
||||
for k in _SECRET_KEYS:
|
||||
data.pop(k, None)
|
||||
|
||||
def _enc(val: str) -> str:
|
||||
return SecretEncryption.encrypt_secret(val.strip(), encryption_password)
|
||||
|
||||
if gitea_token is not None and gitea_token.strip():
|
||||
data["gitea_token"] = _enc(gitea_token)
|
||||
if gitea_username is not None and gitea_username.strip():
|
||||
data["gitea_username"] = _enc(gitea_username)
|
||||
if gitea_password is not None and gitea_password.strip():
|
||||
data["gitea_password"] = _enc(gitea_password)
|
||||
|
||||
if not any(k in data for k in _SECRET_KEYS):
|
||||
if path.is_file():
|
||||
path.unlink()
|
||||
return
|
||||
|
||||
secret_dir = path.parent
|
||||
secret_dir.mkdir(mode=0o700, exist_ok=True)
|
||||
path.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
if os.name != "nt":
|
||||
os.chmod(path, 0o600)
|
||||
Reference in New Issue
Block a user