Skip to content

Commit fd3e9fb

Browse files
committed
Validate environment key pairs
1 parent 551a4be commit fd3e9fb

File tree

4 files changed

+48
-23
lines changed

4 files changed

+48
-23
lines changed

src/edge_proxy/settings.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,15 @@
88

99
import structlog
1010

11-
from pydantic import AliasChoices, BaseModel, HttpUrl, IPvAnyAddress, Field
11+
from pydantic import AliasChoices, BaseModel, HttpUrl, IPvAnyAddress, Field, constr
1212

1313
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource
1414

15-
1615
CONFIG_PATH = os.environ.get(
1716
"CONFIG_PATH",
1817
default="config.json",
1918
)
2019

21-
2220
logger = structlog.get_logger()
2321

2422

@@ -65,8 +63,8 @@ def json_config_settings_source() -> dict[str, Any]:
6563

6664

6765
class EnvironmentKeyPair(BaseModel):
68-
server_side_key: str
69-
client_side_key: str
66+
server_side_key: constr(pattern=r"ser\.*", strip_whitespace=True)
67+
client_side_key: constr(min_length=1, strip_whitespace=True)
7068

7169

7270
class EndpointCacheSettings(BaseModel):
@@ -105,14 +103,7 @@ class HealthCheckSettings(BaseModel):
105103

106104

107105
class AppSettings(BaseModel):
108-
environment_key_pairs: list[EnvironmentKeyPair] = Field(
109-
default_factory=lambda: [
110-
EnvironmentKeyPair(
111-
server_side_key="ser.environment_key",
112-
client_side_key="environment_key",
113-
)
114-
]
115-
)
106+
environment_key_pairs: list[EnvironmentKeyPair]
116107
api_url: HttpUrl = HttpUrl("https://edge.api.flagsmith.com/api/v1")
117108
api_poll_frequency_seconds: int = Field(
118109
default=10,

tests/conftest.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,15 @@ def environment_1_feature_states_response_list_response_with_identity_override(
5151

5252

5353
@pytest.fixture(autouse=True)
54-
def skip_json_config_settings_source(mocker: MockerFixture) -> None:
55-
mocker.patch("edge_proxy.settings.json_config_settings_source", dict)
54+
def mock_settings(mocker: MockerFixture) -> None:
55+
mock_config = {
56+
"environment_key_pairs": [
57+
{"server_side_key": "ser.abc123", "client_side_key": "def456"}
58+
]
59+
}
60+
mocker.patch(
61+
"edge_proxy.settings.json_config_settings_source", return_value=mock_config
62+
)
5663

5764

5865
@pytest.fixture

tests/test_server.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from fastapi.testclient import TestClient
77
from pytest_mock import MockerFixture
88

9-
from edge_proxy.settings import AppSettings, HealthCheckSettings
9+
from edge_proxy.settings import HealthCheckSettings
1010
from tests.fixtures.response_data import environment_1
1111

1212
if typing.TYPE_CHECKING:
@@ -59,10 +59,8 @@ def test_health_check_returns_200_if_cache_is_stale_and_health_check_configured_
5959
client: TestClient,
6060
) -> None:
6161
# Given
62-
settings = AppSettings(
63-
health_check=HealthCheckSettings(environment_update_grace_period_seconds=None)
64-
)
65-
mocker.patch("edge_proxy.server.settings", settings)
62+
health_check = HealthCheckSettings(environment_update_grace_period_seconds=None)
63+
mocker.patch("edge_proxy.server.settings.health_check", health_check)
6664

6765
last_updated_at = datetime.now() - timedelta(days=10)
6866
mocked_environment_service = mocker.patch("edge_proxy.server.environment_service")

tests/test_settings.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,37 @@
22

33
import pytest
44
from pytest_mock import MockerFixture
5+
from pydantic import ValidationError
56

6-
from edge_proxy.settings import get_settings
7+
from edge_proxy.settings import get_settings, AppSettings
8+
9+
10+
def test_client_side_key_validation() -> None:
11+
"""
12+
Test that client_side_key is properly validated.
13+
"""
14+
# Valid
15+
AppSettings(
16+
environment_key_pairs=[
17+
{"server_side_key": "ser.abc123", "client_side_key": "def456"}
18+
]
19+
)
20+
21+
# Missing client_side_key
22+
with pytest.raises(ValidationError):
23+
AppSettings(
24+
environment_key_pairs=[
25+
{"server_side_key": "ser.abc123", "client_side_key": ""}
26+
]
27+
)
28+
29+
# Invalid server_side_key
30+
with pytest.raises(ValidationError):
31+
AppSettings(
32+
environment_key_pairs=[
33+
{"server_side_key": "abc123", "client_side_key": "abc123"}
34+
]
35+
)
736

837

938
@pytest.mark.parametrize(
@@ -12,7 +41,7 @@
1241
(
1342
{
1443
"environment_key_pairs": [
15-
{"server_side_key": "abc123", "client_side_key": "ser.def456"}
44+
{"server_side_key": "ser.abc123", "client_side_key": "def456"}
1645
],
1746
"api_poll_frequency": 10,
1847
"api_poll_timeout": 10,
@@ -23,7 +52,7 @@
2352
(
2453
{
2554
"environment_key_pairs": [
26-
{"server_side_key": "abc123", "client_side_key": "ser.def456"}
55+
{"server_side_key": "ser.abc123", "client_side_key": "def456"}
2756
],
2857
"api_poll_frequency_seconds": 10,
2958
"api_poll_timeout_seconds": 10,

0 commit comments

Comments
 (0)