Skip to content

Commit 97bade1

Browse files
committed
Reject boolean counts in V1 analytics payload
1 parent dcd9372 commit 97bade1

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

api/app_analytics/serializers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def to_internal_value(self, data: Any) -> dict[str, int]:
137137
return {
138138
name: count
139139
for name, count in data.items()
140-
if isinstance(name, str) and isinstance(count, int)
140+
if isinstance(name, str) and type(count) is int
141141
}
142142

143143
def validate(self, attrs: dict[str, int]) -> dict[str, int]:

api/tests/unit/app_analytics/test_unit_app_analytics_views.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,31 @@ def test_sdk_analytics_ignores_bad_data(
110110
)
111111

112112

113+
def test_sdk_analytics_flags_v1__boolean_count__is_skipped(
114+
mocker: MockerFixture,
115+
environment: Environment,
116+
feature: Feature,
117+
api_client: APIClient,
118+
) -> None:
119+
# Given
120+
api_client.credentials(HTTP_X_ENVIRONMENT_KEY=environment.api_key)
121+
data = {feature.name: True}
122+
mocked_feature_eval_cache = mocker.patch(
123+
"app_analytics.views.feature_evaluation_cache"
124+
)
125+
126+
url = reverse("api-v1:analytics-flags")
127+
128+
# When
129+
response = api_client.post(
130+
url, data=json.dumps(data), content_type="application/json"
131+
)
132+
133+
# Then
134+
assert response.status_code == status.HTTP_200_OK
135+
mocked_feature_eval_cache.track_feature_evaluation.assert_not_called()
136+
137+
113138
def test_get_usage_data(mocker, admin_client, organisation): # type: ignore[no-untyped-def]
114139
# Given
115140
url = reverse("api-v1:organisations:usage-data", args=[organisation.id])

0 commit comments

Comments
 (0)