feat: 增加操作审计与受控下载
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
"""操作审计日志。"""
|
||||
import json
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from ..models import OperationLog
|
||||
|
||||
|
||||
def record_operation(db, user: dict, action: str, *, request=None, task=None,
|
||||
resource_type: str = "", resource_name: str = "", detail: dict | None = None):
|
||||
"""将已登录用户的关键操作写入当前数据库事务。"""
|
||||
client_ip = request.client.host if request and request.client else ""
|
||||
user_agent = request.headers.get("user-agent", "")[:500] if request else ""
|
||||
db.add(OperationLog(
|
||||
id=str(uuid.uuid4()), created_at=datetime.utcnow(), username=user.get("username", ""),
|
||||
is_admin=bool(user.get("is_admin")), action=action,
|
||||
task_id=task.id if task else None,
|
||||
app_id=task.app_id if task else None,
|
||||
app_name=task.app_name if task else None,
|
||||
resource_type=resource_type, resource_name=resource_name,
|
||||
detail_json=json.dumps(detail or {}, ensure_ascii=False),
|
||||
client_ip=client_ip, user_agent=user_agent,
|
||||
))
|
||||
@@ -9,6 +9,8 @@ from urllib.parse import quote, unquote, urlparse
|
||||
|
||||
import httpx
|
||||
|
||||
from ..config import DOWNLOAD_URL_EXPIRE_SECONDS
|
||||
|
||||
|
||||
class DistributionError(Exception):
|
||||
"""分发配置或上传过程失败。"""
|
||||
@@ -167,6 +169,30 @@ def delete_published_artifacts(
|
||||
deleter(upload_config, remote_paths)
|
||||
|
||||
|
||||
def get_published_download_url(build_config: dict, upload_config: dict, published_url: str) -> str:
|
||||
"""返回用于受控下载的短时链接;WebDAV 保持原公开链接。"""
|
||||
if upload_config.get("mode") != "oss":
|
||||
return published_url
|
||||
|
||||
remote_paths = _remote_paths_from_published_url(build_config, upload_config, published_url)
|
||||
if not remote_paths:
|
||||
raise DistributionError("无法识别 OSS 文件路径,无法生成受控下载链接")
|
||||
oss = upload_config.get("oss", {})
|
||||
required = ["access_key_id", "access_key_secret", "endpoint", "bucket_name"]
|
||||
if any(not oss.get(key) for key in required):
|
||||
raise DistributionError("OSS 配置不完整")
|
||||
try:
|
||||
import oss2
|
||||
except ImportError as exc:
|
||||
raise DistributionError("未安装 oss2,请重新执行 ./deploy.sh build") from exc
|
||||
|
||||
bucket = oss2.Bucket(
|
||||
oss2.Auth(oss["access_key_id"], oss["access_key_secret"]),
|
||||
oss["endpoint"], oss["bucket_name"], connect_timeout=30,
|
||||
)
|
||||
return bucket.sign_url("GET", remote_paths[0], DOWNLOAD_URL_EXPIRE_SECONDS, slash_safe=True)
|
||||
|
||||
|
||||
def _ensure_webdav_dirs(client: httpx.Client, server_url: str, remote_path: str):
|
||||
path = ""
|
||||
for segment in remote_path.strip("/").split("/")[:-1]:
|
||||
|
||||
Reference in New Issue
Block a user