import importlib.util import sys from pathlib import Path from sqlalchemy import create_engine from sqlalchemy.orm import Session from central.app.auth import authenticate, token_hash from central.app.models import Base SCRIPT = Path(__file__).parents[1] / "scripts" / "register_agent.py" def load_module(): spec = importlib.util.spec_from_file_location("register_agent", SCRIPT) module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module spec.loader.exec_module(module) return module register_agent_module = load_module() def test_register_agent_creates_tenant_and_hashed_token_only(): engine = create_engine("sqlite://") Base.metadata.create_all(engine) with Session(engine) as session: info, token = register_agent_module.register_agent(session, "Restaurante X", "loja-01") found = authenticate(session, token) assert found is not None assert found.id == info["id"] assert found.token_hash == token_hash(token) assert found.token_hash != token # only the hash is ever persisted # Mirrors the real CLI's main(): reading the returned info AFTER the # session (and its `with` block) has closed. This is exactly the scenario # that broke when register_agent() returned live ORM objects instead of # plain values (DetachedInstanceError) — must keep working unattached. assert info["enabled"] is True assert isinstance(info["tenant_id"], int) def test_register_agent_reuses_existing_tenant(): engine = create_engine("sqlite://") Base.metadata.create_all(engine) with Session(engine) as session: info1, _ = register_agent_module.register_agent(session, "Restaurante X", "loja-01") info2, _ = register_agent_module.register_agent(session, "Restaurante X", "loja-02") assert info1["tenant_id"] == info2["tenant_id"] assert info1["id"] != info2["id"] def test_register_agent_generates_unique_tokens(): engine = create_engine("sqlite://") Base.metadata.create_all(engine) with Session(engine) as session: _, token1 = register_agent_module.register_agent(session, "A", "a1") _, token2 = register_agent_module.register_agent(session, "A", "a2") assert token1 != token2 def test_disabled_agent_cannot_authenticate(): from sqlalchemy import create_engine from sqlalchemy.orm import Session from central.app.auth import authenticate, token_hash from central.app.models import Agent, Base, Tenant engine = create_engine("sqlite://") Base.metadata.create_all(engine) with Session(engine) as s: tenant = Tenant(name="t"); s.add(tenant); s.flush() agent = Agent(tenant_id=tenant.id, name="a", token_hash=token_hash("secret-token")); s.add(agent); s.commit() assert authenticate(s, "secret-token").id == agent.id agent.enabled = False; s.commit() assert authenticate(s, "secret-token") is None assert authenticate(s, "wrong") is None