"""Name the thing each audit entry is about. An audit row stores an entity type and id; the page shows the entity's current name, linked to its page, in one query per type for the whole page. An entity deleted since keeps whatever name the entry's own detail recorded. """ from __future__ import annotations from sqlalchemy import select from steward.ansible.inventory_gen import run_title, scope_labels from steward.models.alerts import AlertRule, MaintenanceWindow from steward.models.ansible import AnsibleRun from steward.models.ansible_inventory import AnsibleGroup, AnsibleTarget from steward.models.ansible_schedule import AnsibleSchedule from steward.models.api_tokens import ApiToken from steward.models.hosts import Host from steward.models.monitors import Monitor # entity_type -> (model, its page for an id). A type named by a value rather # than a row (plugin, ansible_playbook) is its own label. _NAMED = { "host": (Host, "/hosts/{}"), "monitor": (Monitor, "/monitors/{}"), "alert_rule": (AlertRule, "/alerts/history?rule={}"), "maintenance_window": (MaintenanceWindow, "/alerts/maintenance"), "ansible_target": (AnsibleTarget, "/ansible/inventory/targets/{}"), "ansible_group": (AnsibleGroup, "/ansible/inventory/groups/{}"), "ansible_schedule": (AnsibleSchedule, "/ansible/schedules"), "api_token": (ApiToken, "/ai-access/"), } _SELF_NAMED = {"plugin": "/settings/plugins/", "ansible_playbook": None} def _recorded_name(detail: dict) -> str | None: """A name the entry recorded when it was written, for a deleted entity.""" for key in ("name", "new_name", "username", "playbook"): if detail.get(key): return str(detail[key]) return None async def entity_labels(db, items: list[dict]) -> dict[tuple[str, str], dict]: """{(entity_type, entity_id): {"label", "url", "gone"}} for the audit rows in `items` ({"event", "detail"}), batched one query per type.""" ids: dict[str, set[str]] = {} for it in items: e = it["event"] if e.entity_type and e.entity_id: ids.setdefault(e.entity_type, set()).add(str(e.entity_id)) labels: dict[tuple[str, str], dict] = {} for etype, wanted in ids.items(): if etype in _NAMED: model, page = _NAMED[etype] key_col = model.id keys = [int(i) for i in wanted if i.isdigit()] if etype == "api_token" else list(wanted) if not keys: continue for row_id, name in (await db.execute( select(key_col, model.name).where(key_col.in_(keys)))).all(): labels[(etype, str(row_id))] = {"label": name, "url": page.format(row_id), "gone": False} elif etype == "ansible_run": runs = (await db.execute( select(AnsibleRun).where(AnsibleRun.id.in_(list(wanted))))).scalars().all() scopes = await scope_labels(db, [r.inventory_scope for r in runs]) for r in runs: labels[(etype, r.id)] = { "label": run_title(r.playbook_path, scopes.get(r.inventory_scope, r.inventory_scope)), "url": f"/ansible/runs/{r.id}", "gone": False} elif etype in _SELF_NAMED: for i in wanted: labels[(etype, i)] = {"label": i, "url": _SELF_NAMED[etype], "gone": False} # What a lookup did not find was deleted since: keep the name the entry recorded. for it in items: e = it["event"] if not (e.entity_type and e.entity_id): continue key = (e.entity_type, str(e.entity_id)) if key not in labels: recorded = _recorded_name(it["detail"] or {}) labels[key] = {"label": recorded or f"{str(e.entity_id)[:8]}", "url": None, "gone": True} return labels