Добавить статистику и очистку аудита; доработать UI расшифровки.

- Страница /admin/stats: MinIO, pending/consumed, загрузки, audit-метрики
- Кнопка «Очистить» в аудите с подтверждением
- Красивые callout’ы и ошибки пароля; пустой пароль не тратит попытку
- Убрать автоопределение языка; «Расшифруй» в RU UI
This commit is contained in:
Sergey Antropoff
2026-07-18 23:50:44 +03:00
parent 91719740b9
commit 8361b8e3f2
17 changed files with 1007 additions and 258 deletions
+23
View File
@@ -85,5 +85,28 @@ class ObjectStorage:
token = resp.get("NextContinuationToken")
return deleted
async def prefix_stats(self, prefix: str = "wraps/") -> dict[str, int]:
"""Count objects and total bytes under prefix."""
objects = 0
total_bytes = 0
async with self.client() as client:
token: str | None = None
while True:
kwargs: dict[str, Any] = {
"Bucket": self.settings.s3_bucket,
"Prefix": prefix,
"MaxKeys": 1000,
}
if token:
kwargs["ContinuationToken"] = token
resp = await client.list_objects_v2(**kwargs)
for obj in resp.get("Contents") or []:
objects += 1
total_bytes += int(obj.get("Size") or 0)
if not resp.get("IsTruncated"):
break
token = resp.get("NextContinuationToken")
return {"objects": objects, "bytes": total_bytes}
storage = ObjectStorage()