feat: add admin config diagnostics
This commit is contained in:
+163
-2
@@ -1649,8 +1649,169 @@ class ConfigService:
|
|||||||
}
|
}
|
||||||
FLOAT_FIELDS = {"opacity"}
|
FLOAT_FIELDS = {"opacity"}
|
||||||
|
|
||||||
def get_config(self):
|
def get_config(self, include_diagnostics: bool = True):
|
||||||
return dict(settings.items())
|
config = dict(settings.items())
|
||||||
|
if not include_diagnostics:
|
||||||
|
return config
|
||||||
|
|
||||||
|
diagnostics = self.build_config_diagnostics(config)
|
||||||
|
return {
|
||||||
|
**config,
|
||||||
|
"diagnostics": diagnostics,
|
||||||
|
"diagnosticItems": diagnostics["items"],
|
||||||
|
"diagnostic_items": diagnostics["items"],
|
||||||
|
"diagnosticSummary": diagnostics["summary"],
|
||||||
|
"diagnostic_summary": diagnostics["summary"],
|
||||||
|
}
|
||||||
|
|
||||||
|
def build_config_diagnostics(self, config: Optional[dict[str, Any]] = None) -> dict[str, Any]:
|
||||||
|
config = config or dict(settings.items())
|
||||||
|
items: list[dict[str, Any]] = []
|
||||||
|
|
||||||
|
def add_item(
|
||||||
|
key: str,
|
||||||
|
severity: str,
|
||||||
|
category: str,
|
||||||
|
field: Optional[str],
|
||||||
|
priority: int,
|
||||||
|
count: int = 1,
|
||||||
|
fields: Optional[list[str]] = None,
|
||||||
|
) -> None:
|
||||||
|
target_fields = fields or ([field] if field else [])
|
||||||
|
action = {
|
||||||
|
"type": "field" if field else "section",
|
||||||
|
"field": field,
|
||||||
|
"fields": target_fields,
|
||||||
|
"category": category,
|
||||||
|
}
|
||||||
|
items.append(
|
||||||
|
{
|
||||||
|
"key": key,
|
||||||
|
"severity": severity,
|
||||||
|
"category": category,
|
||||||
|
"priority": priority,
|
||||||
|
"count": max(int(count or 0), 0),
|
||||||
|
"field": field,
|
||||||
|
"fields": target_fields,
|
||||||
|
"action": action,
|
||||||
|
"actionType": action["type"],
|
||||||
|
"action_type": action["type"],
|
||||||
|
"targetField": field,
|
||||||
|
"target_field": field,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
admin_token = str(config.get("admin_token") or "")
|
||||||
|
if admin_token == settings.default_config.get("admin_token"):
|
||||||
|
add_item("default_admin_password", "danger", "security", "admin_token", 100)
|
||||||
|
|
||||||
|
file_storage = str(config.get("file_storage") or "local").strip().lower()
|
||||||
|
if file_storage == "s3":
|
||||||
|
missing_fields = [
|
||||||
|
field
|
||||||
|
for field in ["s3_access_key_id", "s3_secret_access_key", "s3_bucket_name"]
|
||||||
|
if not str(config.get(field) or "").strip()
|
||||||
|
]
|
||||||
|
if missing_fields:
|
||||||
|
add_item(
|
||||||
|
"s3_incomplete",
|
||||||
|
"danger",
|
||||||
|
"storage",
|
||||||
|
missing_fields[0],
|
||||||
|
95,
|
||||||
|
count=len(missing_fields),
|
||||||
|
fields=missing_fields,
|
||||||
|
)
|
||||||
|
elif file_storage == "webdav":
|
||||||
|
missing_fields = [
|
||||||
|
field
|
||||||
|
for field in ["webdav_url", "webdav_username", "webdav_password"]
|
||||||
|
if not str(config.get(field) or "").strip()
|
||||||
|
]
|
||||||
|
if missing_fields:
|
||||||
|
add_item(
|
||||||
|
"webdav_incomplete",
|
||||||
|
"danger",
|
||||||
|
"storage",
|
||||||
|
missing_fields[0],
|
||||||
|
95,
|
||||||
|
count=len(missing_fields),
|
||||||
|
fields=missing_fields,
|
||||||
|
)
|
||||||
|
|
||||||
|
if self._to_int(config.get("openUpload")) and self._to_int(config.get("max_save_seconds")) <= 0:
|
||||||
|
add_item("guest_upload_retention", "warning", "retention", "max_save_seconds", 80)
|
||||||
|
|
||||||
|
if (
|
||||||
|
self._to_int(config.get("uploadSize")) >= 50 * 1024 * 1024
|
||||||
|
and not self._to_int(config.get("enableChunk"))
|
||||||
|
):
|
||||||
|
add_item("chunking_recommended", "warning", "upload", "enableChunk", 70)
|
||||||
|
|
||||||
|
if self._to_int(config.get("uploadMinute")) <= 0 or self._to_int(config.get("uploadCount")) <= 0:
|
||||||
|
add_item(
|
||||||
|
"upload_guard_disabled",
|
||||||
|
"warning",
|
||||||
|
"upload",
|
||||||
|
"uploadMinute",
|
||||||
|
60,
|
||||||
|
fields=["uploadMinute", "uploadCount"],
|
||||||
|
)
|
||||||
|
|
||||||
|
if self._to_int(config.get("errorMinute")) <= 0 or self._to_int(config.get("errorCount")) <= 0:
|
||||||
|
add_item(
|
||||||
|
"access_guard_disabled",
|
||||||
|
"warning",
|
||||||
|
"security",
|
||||||
|
"errorMinute",
|
||||||
|
55,
|
||||||
|
fields=["errorMinute", "errorCount"],
|
||||||
|
)
|
||||||
|
|
||||||
|
expire_style = config.get("expireStyle")
|
||||||
|
if not isinstance(expire_style, list) or len(expire_style) == 0:
|
||||||
|
add_item("expiration_style_empty", "danger", "retention", "expireStyle", 75)
|
||||||
|
|
||||||
|
if not items:
|
||||||
|
add_item("healthy", "success", "system", None, 10, count=0)
|
||||||
|
|
||||||
|
items.sort(key=lambda item: (-item["priority"], item["key"]))
|
||||||
|
summary = self._build_config_diagnostic_summary(items)
|
||||||
|
return {
|
||||||
|
"items": items,
|
||||||
|
"diagnosticItems": items,
|
||||||
|
"diagnostic_items": items,
|
||||||
|
"summary": summary,
|
||||||
|
"diagnosticSummary": summary,
|
||||||
|
"diagnostic_summary": summary,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _build_config_diagnostic_summary(self, items: list[dict[str, Any]]) -> dict[str, Any]:
|
||||||
|
severity_order = {"danger": 3, "warning": 2, "neutral": 1, "success": 0}
|
||||||
|
strongest_severity = max(
|
||||||
|
(item["severity"] for item in items),
|
||||||
|
key=lambda severity: severity_order.get(severity, 0),
|
||||||
|
default="success",
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
"total": len(items),
|
||||||
|
"dangerCount": sum(1 for item in items if item["severity"] == "danger"),
|
||||||
|
"danger_count": sum(1 for item in items if item["severity"] == "danger"),
|
||||||
|
"warningCount": sum(1 for item in items if item["severity"] == "warning"),
|
||||||
|
"warning_count": sum(1 for item in items if item["severity"] == "warning"),
|
||||||
|
"successCount": sum(1 for item in items if item["severity"] == "success"),
|
||||||
|
"success_count": sum(1 for item in items if item["severity"] == "success"),
|
||||||
|
"neutralCount": sum(1 for item in items if item["severity"] == "neutral"),
|
||||||
|
"neutral_count": sum(1 for item in items if item["severity"] == "neutral"),
|
||||||
|
"strongestSeverity": strongest_severity,
|
||||||
|
"strongest_severity": strongest_severity,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _to_int(self, value: Any) -> int:
|
||||||
|
try:
|
||||||
|
return int(value or 0)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return 0
|
||||||
|
|
||||||
async def update_config(self, data: dict):
|
async def update_config(self, data: dict):
|
||||||
current_config = dict(settings.items())
|
current_config = dict(settings.items())
|
||||||
|
|||||||
+16
-1
@@ -494,13 +494,28 @@ async def get_config(
|
|||||||
return APIResponse(detail=config_service.get_config())
|
return APIResponse(detail=config_service.get_config())
|
||||||
|
|
||||||
|
|
||||||
|
@admin_api.get("/config/diagnostics")
|
||||||
|
async def get_config_diagnostics(
|
||||||
|
config_service: ConfigService = Depends(get_config_service),
|
||||||
|
):
|
||||||
|
return APIResponse(detail=config_service.build_config_diagnostics())
|
||||||
|
|
||||||
|
|
||||||
@admin_api.patch("/config/update")
|
@admin_api.patch("/config/update")
|
||||||
async def update_config(
|
async def update_config(
|
||||||
data: dict,
|
data: dict,
|
||||||
config_service: ConfigService = Depends(get_config_service),
|
config_service: ConfigService = Depends(get_config_service),
|
||||||
file_service: FileService = Depends(get_file_service),
|
file_service: FileService = Depends(get_file_service),
|
||||||
):
|
):
|
||||||
data.pop("themesChoices", None)
|
for field in (
|
||||||
|
"themesChoices",
|
||||||
|
"diagnostics",
|
||||||
|
"diagnosticItems",
|
||||||
|
"diagnostic_items",
|
||||||
|
"diagnosticSummary",
|
||||||
|
"diagnostic_summary",
|
||||||
|
):
|
||||||
|
data.pop(field, None)
|
||||||
await config_service.update_config(data)
|
await config_service.update_config(data)
|
||||||
await file_service.record_admin_activity(
|
await file_service.record_admin_activity(
|
||||||
action="config.update",
|
action="config.update",
|
||||||
|
|||||||
Reference in New Issue
Block a user