import importlib import sys from pathlib import Path import pytest from flask import Flask PROJECT_ROOT = Path(__file__).resolve().parents[1] if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) import app_security import crypto_utils from db import users as db_users def test_user_lookup_rejects_dynamic_field_name(): with pytest.raises(ValueError): db_users._get_user_by_field("username OR 1=1 --", "demo") def test_rate_limit_ip_does_not_trust_proxy_headers_by_default(monkeypatch): monkeypatch.delenv("TRUST_PROXY_HEADERS", raising=False) monkeypatch.delenv("TRUSTED_PROXY_CIDRS", raising=False) security_module = importlib.reload(app_security) app = Flask(__name__) with app.test_request_context( "/", environ_base={"REMOTE_ADDR": "10.0.0.9"}, headers={"X-Forwarded-For": "198.51.100.10"}, ): assert security_module.get_rate_limit_ip() == "10.0.0.9" def test_rate_limit_ip_can_use_forwarded_chain_when_explicitly_enabled(monkeypatch): monkeypatch.setenv("TRUST_PROXY_HEADERS", "true") monkeypatch.setenv("TRUSTED_PROXY_CIDRS", "10.0.0.0/8") security_module = importlib.reload(app_security) app = Flask(__name__) with app.test_request_context( "/", environ_base={"REMOTE_ADDR": "10.2.3.4"}, headers={"X-Forwarded-For": "198.51.100.10, 10.2.3.4"}, ): assert security_module.get_rate_limit_ip() == "198.51.100.10" def test_get_encryption_key_refuses_regeneration_when_encrypted_data_exists(monkeypatch, tmp_path): monkeypatch.setenv("ALLOW_NEW_KEY", "true") monkeypatch.delenv("ENCRYPTION_KEY_RAW", raising=False) monkeypatch.delenv("ENCRYPTION_KEY", raising=False) monkeypatch.setattr(crypto_utils, "ENCRYPTION_KEY_FILE", str(tmp_path / "missing_key.bin")) monkeypatch.setattr(crypto_utils, "_check_existing_encrypted_data", lambda: True) with pytest.raises(RuntimeError): crypto_utils.get_encryption_key()