88 lines
2.9 KiB
Python
88 lines
2.9 KiB
Python
"""
|
|
Запись .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)
|