import json from pathlib import Path import pytest from cryptography.fernet import Fernet from werkzeug.security import check_password_hash from vfire_monitor import create_app from vfire_monitor.core import ( LicenseService, contiguous_ranges, load_license_key, normalize_config, validate_node_payload, ) def test_validate_node_payload_normalizes_fields(): node = validate_node_payload({"nome": " Central A ", "ip": " 10.0.0.1 ", "unit": "3"}) assert node == {"nome": "Central A", "ip": "10.0.0.1", "unit": 3} def test_validate_node_payload_rejects_invalid_unit(): with pytest.raises(ValueError): validate_node_payload({"nome": "Central A", "ip": "10.0.0.1", "unit": 999}) def test_normalize_config_migrates_legacy_password(): config = normalize_config( { "web_user": "admin", "web_password": "segredo", "nodes": [{"nome": "Node 1", "ip": "1.1.1.1", "unit": 1}], }, default_password="admin", ) assert "web_password" not in config assert check_password_hash(config["web_password_hash"], "segredo") assert config["nodes"][0]["nome"] == "Node 1" def test_contiguous_ranges_splits_large_blocks(): ranges = contiguous_ranges(list(range(1, 125))) assert ranges == [(1, 120), (121, 124)] def test_license_service_validates_serial(tmp_path, monkeypatch): monkeypatch.setattr("vfire_monitor.core.get_hardware_id", lambda: "HW-123") key = Fernet.generate_key() payload = {"h": "HW-123", "c": "Cliente", "e": "2099-01-01"} serial = Fernet(key).encrypt(json.dumps(payload).encode("utf-8")).decode("utf-8") license_path = tmp_path / "license.key" license_path.write_text(serial, encoding="utf-8") service = LicenseService(license_path, key) status = service.verify() assert status.valid is True assert "Cliente" in status.message def test_load_license_key_requires_env_in_production(monkeypatch): monkeypatch.delenv("VFM_LICENSE_MASTER_KEY", raising=False) with pytest.raises(RuntimeError): load_license_key(require_env=True) @pytest.fixture def app(tmp_path, monkeypatch): monkeypatch.setenv("VFM_DEFAULT_PASSWORD", "admin") monkeypatch.setenv("VFM_LICENSE_MASTER_KEY", Fernet.generate_key().decode("utf-8")) application = create_app(base_dir=tmp_path, start_monitor=False) application.config["TESTING"] = True runtime_state = application.extensions["runtime_state"] runtime_state.config["web_user"] = "admin" runtime_state.config["web_password_hash"] = normalize_config({}, "admin")["web_password_hash"] runtime_state.save_config() return application @pytest.fixture def client(app): return app.test_client() def login(client): return client.post("/login", data={"username": "admin", "password": "admin"}, follow_redirects=False) def test_login_success(client): response = login(client) assert response.status_code == 302 def test_api_nodes_requires_auth(client): response = client.post("/api/nodes", json={}) assert response.status_code == 302 def test_api_nodes_updates_configuration(client, app): login(client) response = client.post( "/api/nodes", json={ "zabbix_server": "127.0.0.1", "hostname_zabbix": "HOST-01", "nodes": [{"nome": "Central A", "ip": "10.0.0.5", "unit": 3}], }, ) assert response.status_code == 200 assert response.get_json()["status"] == "success" config_path = Path(app.extensions["runtime_state"].config_store.path) config = json.loads(config_path.read_text(encoding="utf-8")) assert config["hostname_zabbix"] == "HOST-01" assert config["nodes"][0]["nome"] == "Central A"