fix: clarify unavailable legacy blocker resolution
This commit is contained in:
@@ -15,6 +15,11 @@ WORKFLOW_SCOPES = {"PRODUCT", "GROUP", "COMPANY"}
|
||||
ENTRY_FIELDS = {"scope", "scope_key", "key", "value", "reason"}
|
||||
MAX_VALUE_LENGTH = 512
|
||||
MAX_REASON_LENGTH = 2000
|
||||
MAX_COMPANY_KEY_LENGTH = 64
|
||||
|
||||
|
||||
class BlockerResolutionUnavailable(LookupError):
|
||||
"""The blocker exists, but has no proven installation to target safely."""
|
||||
|
||||
|
||||
def validate_resolution_input(payload):
|
||||
@@ -87,12 +92,16 @@ def resolve_blocker_with_context(session, blocker_id, admin, payload, request_ip
|
||||
if agent.tenant_id != blocker.tenant_id:
|
||||
raise LookupError("blocker agent tenant mismatch")
|
||||
else:
|
||||
raise LookupError("blocker installation is required")
|
||||
raise BlockerResolutionUnavailable(
|
||||
"Blocker legado de empresa sem vínculo comprovado com um servidor; não é possível oferecer o reprocessamento de contexto com segurança."
|
||||
)
|
||||
|
||||
tenant = session.get(Tenant, blocker.tenant_id)
|
||||
company_key = _company_key(blocker, installation, tenant)
|
||||
if not company_key:
|
||||
raise ValueError("company context is unavailable")
|
||||
if len(company_key) > MAX_COMPANY_KEY_LENGTH:
|
||||
raise ValueError(f"company key must be at most {MAX_COMPANY_KEY_LENGTH} characters")
|
||||
if normalized["scope"] == "PRODUCT" and normalized["scope_key"] != blocker.product_code:
|
||||
raise ValueError("PRODUCT scope_key must match the blocker product code")
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
from sqlalchemy import select
|
||||
|
||||
from .audit import record_audit
|
||||
from .blocker_resolution import resolve_blocker_with_context
|
||||
from .blocker_resolution import BlockerResolutionUnavailable, resolve_blocker_with_context
|
||||
from .control_plane import dashboard_summary, installation_view, list_blockers, list_installations, list_jobs, list_panel_events
|
||||
from .human_auth import require_csrf, require_human
|
||||
from .models import Agent, AgentSnapshot, BlockedProduct, Installation, Job, Tenant
|
||||
@@ -119,6 +119,8 @@ def router(session_factory):
|
||||
entry_payload = {key: payload.get(key) for key in ("scope", "scope_key", "key", "value", "reason")}
|
||||
try:
|
||||
return resolve_blocker_with_context(session, blocker_id, admin, entry_payload, request_ip=request.client.host if request.client else None)
|
||||
except BlockerResolutionUnavailable as error:
|
||||
raise HTTPException(409, str(error)) from error
|
||||
except LookupError as error:
|
||||
raise HTTPException(404, str(error)) from error
|
||||
except ValueError as error:
|
||||
|
||||
+11
-4
@@ -9,7 +9,7 @@ from fastapi.templating import Jinja2Templates
|
||||
from sqlalchemy import select
|
||||
|
||||
from .config import settings
|
||||
from .blocker_resolution import _company_key, resolve_blocker_with_context
|
||||
from .blocker_resolution import BlockerResolutionUnavailable, _company_key, resolve_blocker_with_context
|
||||
from .context_keys import ALLOWED_KEYS, ENUMS
|
||||
from .control_plane import blocker_detail, blocker_filter_summary, dashboard_summary, installation_view, list_blockers, list_installations, list_jobs, list_panel_events
|
||||
from .human_auth import create_session, current_session, require_csrf, verify_password
|
||||
@@ -167,9 +167,9 @@ def router(session_factory):
|
||||
installation = session.get(Installation, blocker.installation_id) if blocker.installation_id else None
|
||||
tenant = session.get(Tenant, blocker.tenant_id)
|
||||
company_key = _company_key(blocker, installation, tenant)
|
||||
current_context = session.scalars(select(FiscalContextEntry).where(FiscalContextEntry.tenant_id == blocker.tenant_id, FiscalContextEntry.company_key == company_key)).all()
|
||||
current_context = session.scalars(select(FiscalContextEntry).where(FiscalContextEntry.tenant_id == blocker.tenant_id, FiscalContextEntry.company_key == company_key)).all() if installation else []
|
||||
value_choices = sorted({value for values in ENUMS.values() for value in values})
|
||||
return render(request, "blocker_detail.html", {"detail": detail, "auth": auth_data, "context_entries": current_context, "context_keys": sorted(ALLOWED_KEYS), "value_choices": value_choices, "error": None})
|
||||
return render(request, "blocker_detail.html", {"detail": detail, "auth": auth_data, "context_entries": current_context, "context_keys": sorted(ALLOWED_KEYS), "value_choices": value_choices, "error": None, "resolution_available": installation is not None, "resolution_values": {}})
|
||||
finally: session.close()
|
||||
|
||||
@routes.post("/blockers/{blocker_id}/resolve-context")
|
||||
@@ -182,11 +182,18 @@ def router(session_factory):
|
||||
payload = {key: values.get(key) for key in ("scope", "scope_key", "key", "value", "reason")}
|
||||
try:
|
||||
resolve_blocker_with_context(session, blocker_id, admin, payload, request_ip=request.client.host if request.client else None)
|
||||
except BlockerResolutionUnavailable as error:
|
||||
return HTMLResponse(str(error), status_code=409)
|
||||
except LookupError:
|
||||
return HTMLResponse("Blocker not found", status_code=404)
|
||||
except ValueError as error:
|
||||
detail = blocker_detail(session, blocker_id)
|
||||
return render(request, "blocker_detail.html", {"detail": detail, "auth": auth_data, "context_entries": [], "context_keys": sorted(ALLOWED_KEYS), "value_choices": sorted({value for values in ENUMS.values() for value in values}), "error": str(error)}, 422)
|
||||
blocker = session.get(BlockedProduct, blocker_id)
|
||||
installation = session.get(Installation, blocker.installation_id) if blocker and blocker.installation_id else None
|
||||
tenant = session.get(Tenant, blocker.tenant_id) if blocker else None
|
||||
company_key = _company_key(blocker, installation, tenant) if blocker else ""
|
||||
current_context = session.scalars(select(FiscalContextEntry).where(FiscalContextEntry.tenant_id == blocker.tenant_id, FiscalContextEntry.company_key == company_key)).all() if blocker and installation else []
|
||||
return render(request, "blocker_detail.html", {"detail": detail, "auth": auth_data, "context_entries": current_context, "context_keys": sorted(ALLOWED_KEYS), "value_choices": sorted({value for values in ENUMS.values() for value in values}), "error": str(error), "resolution_available": installation is not None, "resolution_values": payload}, 422)
|
||||
return RedirectResponse(f"/blockers/{blocker_id}", status_code=303)
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
Reference in New Issue
Block a user