fix: searchable client combobox in Nova instalação
Replaces the native list with a combobox (name/code/CNPJ search, accent- and case-insensitive, keyboard + mouse, custom dropdown, hidden client_id = the Gerenciador's real CLIENTE.ID). The backend resolves client_id against the active GTI_GERENCIADOR mirror and rejects free text/unknown ids. Adds Tenant.external_cnpj (migration 0025) mirrored via the internal endpoint. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -162,7 +162,7 @@ def test_full_installation_flow_creates_a_working_agent(hub):
|
||||
release_id = publish_release(factory)
|
||||
login(client)
|
||||
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "tenant_id": tenant_id(factory),
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "client_id": tenant_id(factory),
|
||||
"display_name": "Servidor Principal", "expected_hostname": "SRV-UNIAO",
|
||||
"release_id": release_id}, follow_redirects=False)
|
||||
assert created.status_code == 303
|
||||
@@ -221,7 +221,7 @@ def test_direct_authenticated_download_does_not_need_a_link(hub):
|
||||
client, factory = hub
|
||||
release_id = publish_release(factory)
|
||||
login(client)
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "tenant_id": tenant_id(factory),
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "client_id": tenant_id(factory),
|
||||
"display_name": "Loja 2", "release_id": release_id}, follow_redirects=False)
|
||||
installation_uuid = created.headers["location"].rsplit("/", 1)[-1]
|
||||
downloaded = client.get(f"/agents/pending/{installation_uuid}/download")
|
||||
@@ -303,7 +303,7 @@ def test_revoked_installation_link_rejected(hub):
|
||||
client, factory = hub
|
||||
release_id = publish_release(factory)
|
||||
login(client)
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "tenant_id": tenant_id(factory),
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "client_id": tenant_id(factory),
|
||||
"display_name": "Teste", "release_id": release_id}, follow_redirects=False)
|
||||
uid = created.headers["location"].rsplit("/", 1)[-1]
|
||||
linked = client.post(f"/agents/pending/{uid}/link", data={"csrf_token": csrf(client)}, follow_redirects=False)
|
||||
@@ -322,7 +322,7 @@ def test_release_revoked_blocks_download(hub):
|
||||
client, factory = hub
|
||||
release_id = publish_release(factory)
|
||||
login(client)
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "tenant_id": tenant_id(factory),
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "client_id": tenant_id(factory),
|
||||
"display_name": "Teste", "release_id": release_id}, follow_redirects=False)
|
||||
uid = created.headers["location"].rsplit("/", 1)[-1]
|
||||
linked = client.post(f"/agents/pending/{uid}/link", data={"csrf_token": csrf(client)}, follow_redirects=False)
|
||||
|
||||
@@ -340,7 +340,7 @@ def test_panel_flow_code_generate_download_and_enroll_with_exe(hub, tmp_path):
|
||||
client, factory = hub
|
||||
release_id = publish_exe_release(factory, tmp_path)
|
||||
login(client)
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "tenant_id": tenant_id(factory),
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "client_id": tenant_id(factory),
|
||||
"display_name": "Servidor EXE", "release_id": release_id}, follow_redirects=False)
|
||||
assert created.status_code == 303
|
||||
installation_uuid = created.headers["location"].rsplit("/", 1)[-1]
|
||||
@@ -391,7 +391,7 @@ def test_rotation_generates_a_code_that_invalidates_the_previous(hub, tmp_path):
|
||||
client, factory = hub
|
||||
release_id = publish_exe_release(factory, tmp_path)
|
||||
login(client)
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "tenant_id": tenant_id(factory),
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "client_id": tenant_id(factory),
|
||||
"display_name": "Rotação", "release_id": release_id}, follow_redirects=False)
|
||||
installation_uuid = created.headers["location"].rsplit("/", 1)[-1]
|
||||
first = client.post(f"/agents/pending/{installation_uuid}/code", data={"csrf_token": csrf(client)}, follow_redirects=True)
|
||||
@@ -414,7 +414,7 @@ def test_revoke_clears_code_and_is_audited(hub, tmp_path):
|
||||
client, factory = hub
|
||||
release_id = publish_exe_release(factory, tmp_path)
|
||||
login(client)
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "tenant_id": tenant_id(factory),
|
||||
created = client.post("/agents/new", data={"csrf_token": csrf(client), "client_id": tenant_id(factory),
|
||||
"display_name": "Revoga", "release_id": release_id}, follow_redirects=False)
|
||||
installation_uuid = created.headers["location"].rsplit("/", 1)[-1]
|
||||
client.post(f"/agents/pending/{installation_uuid}/code", data={"csrf_token": csrf(client)})
|
||||
|
||||
@@ -23,8 +23,8 @@ def hub(tmp_path, monkeypatch):
|
||||
factory = setup_db()
|
||||
seed(factory) # tenant "Acme" (LOCAL, no source) + admin "operator"/"a-secure-password"
|
||||
with factory() as session:
|
||||
session.add(Tenant(name="Mercado Ativo", source="GTI_GERENCIADOR", external_client_id=1, active=True))
|
||||
session.add(Tenant(name="Loja Inativa", source="GTI_GERENCIADOR", external_client_id=2, active=False))
|
||||
session.add(Tenant(name="Mercado Ativo", source="GTI_GERENCIADOR", external_client_id=1, external_code="000001", external_cnpj="11222333000181", active=True))
|
||||
session.add(Tenant(name="Loja <Inativa>", source="GTI_GERENCIADOR", external_client_id=2, external_cnpj="99888777000166", active=False))
|
||||
release, _ = publish(session, write_temp_zip(make_release_zip(VERSION), VERSION), version=VERSION)
|
||||
release_id = release.id
|
||||
session.commit()
|
||||
@@ -46,7 +46,7 @@ def test_new_installation_form_lists_only_active_gerenciador_tenants(hub):
|
||||
login(client)
|
||||
body = client.get("/agents/new").text
|
||||
assert "Mercado Ativo" in body
|
||||
assert "Loja Inativa" not in body # inactive: excluded from the selector
|
||||
assert "Loja <Inativa>" not in body # inactive: excluded from the selector
|
||||
assert "Acme" not in body # LOCAL (not from GTI Gerenciador): excluded
|
||||
|
||||
|
||||
@@ -54,8 +54,8 @@ def test_cannot_create_installation_for_an_inactive_tenant(hub):
|
||||
client, factory, release_id = hub
|
||||
login(client)
|
||||
with factory() as session:
|
||||
inactive_id = session.scalar(select(Tenant).where(Tenant.name == "Loja Inativa")).id
|
||||
response = client.post("/agents/new", data={"csrf_token": csrf(client), "tenant_id": inactive_id, "display_name": "Teste", "release_id": release_id})
|
||||
inactive_id = session.scalar(select(Tenant).where(Tenant.name == "Loja <Inativa>")).external_client_id
|
||||
response = client.post("/agents/new", data={"csrf_token": csrf(client), "client_id": inactive_id, "display_name": "Teste", "release_id": release_id})
|
||||
assert response.status_code == 400 and "ativo" in response.text.lower()
|
||||
with factory() as session:
|
||||
assert session.scalar(select(AgentEnrollment)) is None
|
||||
@@ -65,8 +65,10 @@ def test_cannot_create_installation_for_a_local_tenant(hub):
|
||||
client, factory, release_id = hub
|
||||
login(client)
|
||||
with factory() as session:
|
||||
local_id = session.scalar(select(Tenant).where(Tenant.name == "Acme")).id
|
||||
response = client.post("/agents/new", data={"csrf_token": csrf(client), "tenant_id": local_id, "display_name": "Teste", "release_id": release_id})
|
||||
acme = session.scalar(select(Tenant).where(Tenant.name == "Acme"))
|
||||
assert acme.source == "LOCAL" and acme.external_client_id is None
|
||||
local_id = 987654 # a LOCAL tenant has no external id, so nothing can ever match it
|
||||
response = client.post("/agents/new", data={"csrf_token": csrf(client), "client_id": local_id, "display_name": "Teste", "release_id": release_id})
|
||||
assert response.status_code == 400
|
||||
with factory() as session:
|
||||
assert session.scalar(select(AgentEnrollment)) is None
|
||||
@@ -76,9 +78,31 @@ def test_creates_installation_for_an_active_gerenciador_tenant(hub):
|
||||
client, factory, release_id = hub
|
||||
login(client)
|
||||
with factory() as session:
|
||||
active_id = session.scalar(select(Tenant).where(Tenant.name == "Mercado Ativo")).id
|
||||
response = client.post("/agents/new", data={"csrf_token": csrf(client), "tenant_id": active_id, "display_name": "Teste", "release_id": release_id}, follow_redirects=False)
|
||||
active = session.scalar(select(Tenant).where(Tenant.name == "Mercado Ativo")); active_id, tenant_pk = active.external_client_id, active.id
|
||||
response = client.post("/agents/new", data={"csrf_token": csrf(client), "client_id": active_id, "display_name": "Teste", "release_id": release_id}, follow_redirects=False)
|
||||
assert response.status_code == 303
|
||||
with factory() as session:
|
||||
enr = session.scalar(select(AgentEnrollment))
|
||||
assert enr is not None and enr.tenant_id == active_id
|
||||
assert enr is not None and enr.tenant_id == tenant_pk
|
||||
|
||||
|
||||
def test_combobox_markup_and_client_data(hub):
|
||||
import json, re
|
||||
client, _factory, _release_id = hub
|
||||
login(client)
|
||||
body = client.get("/agents/new").text
|
||||
assert 'role="combobox"' in body and 'name="client_id"' in body and "<select name=\"tenant_id\"" not in body
|
||||
assert "Selecione um cliente da lista." in body
|
||||
data = json.loads(re.search(r'id="clientes-json">(.*?)</script>', body, re.S).group(1))
|
||||
assert data == [{"id": 1, "name": "Mercado Ativo", "code": "000001", "cnpj": "11222333000181"}] # active only, real external id, cnpj for search
|
||||
assert "Loja" not in body
|
||||
|
||||
|
||||
def test_free_text_or_unknown_client_id_is_rejected(hub):
|
||||
client, factory, release_id = hub
|
||||
login(client)
|
||||
for bad in ("", "Mercado Ativo", "999", "1; DROP"):
|
||||
response = client.post("/agents/new", data={"csrf_token": csrf(client), "client_id": bad, "display_name": "T", "release_id": release_id})
|
||||
assert response.status_code == 400 and "Selecione um cliente da lista." in response.text
|
||||
with factory() as session:
|
||||
assert session.scalar(select(AgentEnrollment)) is None
|
||||
|
||||
Reference in New Issue
Block a user