Skip to content

Commit 7832273

Browse files
authored
Update sds schema validation (#1538)
1 parent 85f3e52 commit 7832273

File tree

5 files changed

+68
-47
lines changed

5 files changed

+68
-47
lines changed

app/authentication/auth_payload_versions.py

-5
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,3 @@
33

44
class AuthPayloadVersion(Enum):
55
V2 = "v2"
6-
7-
8-
class SupplementaryDataSchemaVersion(Enum):
9-
V2 = "v2"
10-
V1 = "v1"

app/routes/session.py

+1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ def _set_questionnaire_supplementary_data(
177177
dataset_id=new_sds_dataset_id,
178178
identifier=identifier, # type: ignore
179179
survey_id=metadata["survey_id"], # type: ignore
180+
sds_schema_version=schema.json.get("sds_schema_version"),
180181
)
181182
logger.info(
182183
"fetched supplementary data",

app/services/supplementary_data.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ class InvalidSupplementaryData(Exception):
4444

4545

4646
def get_supplementary_data_v1(
47-
*, dataset_id: str, identifier: str, survey_id: str
47+
*,
48+
dataset_id: str,
49+
identifier: str,
50+
survey_id: str,
51+
sds_schema_version: str | None = None,
4852
) -> dict:
4953
# Type ignore: current_app is a singleton in this application and has the key_store key in its eq attribute.
5054
key_store = current_app.eq["key_store"] # type: ignore
@@ -93,6 +97,7 @@ def get_supplementary_data_v1(
9397
dataset_id=dataset_id,
9498
identifier=identifier,
9599
survey_id=survey_id,
100+
sds_schema_version=sds_schema_version,
96101
)
97102

98103
logger.error(
@@ -121,14 +126,19 @@ def decrypt_supplementary_data(
121126

122127

123128
def validate_supplementary_data(
124-
supplementary_data: Mapping, dataset_id: str, identifier: str, survey_id: str
125-
) -> dict:
129+
supplementary_data: Mapping,
130+
dataset_id: str,
131+
identifier: str,
132+
survey_id: str,
133+
sds_schema_version: str | None = None,
134+
) -> dict[str, str | dict | int | list]:
126135
try:
127136
return validate_supplementary_data_v1(
128137
supplementary_data=supplementary_data,
129138
dataset_id=dataset_id,
130139
identifier=identifier,
131140
survey_id=survey_id,
141+
sds_schema_version=sds_schema_version,
132142
)
133143
except ValidationError as e:
134144
raise ValidationError("Invalid supplementary data") from e

app/utilities/supplementary_data_parser.py

+15-15
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
validates_schema,
1111
)
1212

13-
from app.authentication.auth_payload_versions import SupplementaryDataSchemaVersion
1413
from app.utilities.metadata_parser_v2 import VALIDATORS, StripWhitespaceMixin
1514

1615

@@ -35,14 +34,6 @@ class ItemsData(Schema, StripWhitespaceMixin):
3534

3635
class SupplementaryData(Schema, StripWhitespaceMixin):
3736
identifier = VALIDATORS["string"](validate=validate.Length(min=1))
38-
schema_version = VALIDATORS["string"](
39-
validate=validate.OneOf(
40-
[
41-
SupplementaryDataSchemaVersion.V1.value,
42-
SupplementaryDataSchemaVersion.V2.value,
43-
]
44-
)
45-
)
4637
items = fields.Nested(ItemsData, required=False, unknown=INCLUDE)
4738

4839
@validates_schema()
@@ -66,27 +57,35 @@ class SupplementaryDataMetadataSchema(Schema, StripWhitespaceMixin):
6657
)
6758

6859
@validates_schema()
69-
def validate_dataset_and_survey_id( # pylint: disable=unused-argument
70-
self, data: Mapping, **kwargs: Any
60+
def validate_payload( # pylint: disable=unused-argument
61+
self, payload: Mapping, **kwargs: Any
7162
) -> None:
72-
if data:
73-
if data["dataset_id"] != self.context["dataset_id"]:
63+
if payload:
64+
if payload["dataset_id"] != self.context["dataset_id"]:
7465
raise ValidationError(
7566
"Supplementary data did not return the specified Dataset ID"
7667
)
7768

78-
if data["survey_id"] != self.context["survey_id"]:
69+
if payload["survey_id"] != self.context["survey_id"]:
7970
raise ValidationError(
8071
"Supplementary data did not return the specified Survey ID"
8172
)
8273

74+
if self.context["sds_schema_version"] and (
75+
payload["data"]["schema_version"] != self.context["sds_schema_version"]
76+
):
77+
raise ValidationError(
78+
"The Supplementary Dataset Schema Version does not match the version set in the Questionnaire Schema"
79+
)
80+
8381

8482
def validate_supplementary_data_v1(
8583
supplementary_data: Mapping,
8684
dataset_id: str,
8785
identifier: str,
8886
survey_id: str,
89-
) -> dict:
87+
sds_schema_version: str | None = None,
88+
) -> dict[str, str | dict | int | list]:
9089
"""Validate claims required for supplementary data"""
9190
supplementary_data_metadata_schema = SupplementaryDataMetadataSchema(
9291
unknown=INCLUDE
@@ -95,6 +94,7 @@ def validate_supplementary_data_v1(
9594
"dataset_id": dataset_id,
9695
"identifier": identifier,
9796
"survey_id": survey_id,
97+
"sds_schema_version": sds_schema_version,
9898
}
9999
validated_supplementary_data = supplementary_data_metadata_schema.load(
100100
supplementary_data

tests/app/parser/test_supplementary_data_parser.py

+39-24
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from contextlib import contextmanager
12
from copy import deepcopy
23

34
import pytest
@@ -6,6 +7,15 @@
67
from app.services.supplementary_data import validate_supplementary_data
78
from app.utilities.supplementary_data_parser import validate_supplementary_data_v1
89

10+
11+
@contextmanager
12+
def not_raises(exception):
13+
try:
14+
yield
15+
except exception as validation_error:
16+
raise pytest.fail(f"{validation_error} RAISED")
17+
18+
919
SUPPLEMENTARY_DATA_PAYLOAD = {
1020
"dataset_id": "44f1b432-9421-49e5-bd26-e63e18a30b69",
1121
"survey_id": "123",
@@ -54,6 +64,35 @@ def test_invalid_supplementary_data_payload_raises_error():
5464
assert str(error.value) == "Invalid supplementary data"
5565

5666

67+
def test_invalid_supplementary_dataset_version_raises_error():
68+
with pytest.raises(ValidationError) as error:
69+
validate_supplementary_data_v1(
70+
supplementary_data=SUPPLEMENTARY_DATA_PAYLOAD,
71+
dataset_id="44f1b432-9421-49e5-bd26-e63e18a30b69",
72+
identifier="12345678901",
73+
survey_id="123",
74+
sds_schema_version="v6",
75+
)
76+
77+
assert (
78+
str(error.value)
79+
== "{'_schema': ['The Supplementary Dataset Schema Version does not match the version set in the Questionnaire Schema']}"
80+
)
81+
82+
83+
def test_valid_supplementary_dataset_version_does_not_raise_error():
84+
with not_raises(ValidationError):
85+
validated_payload = validate_supplementary_data_v1(
86+
supplementary_data=SUPPLEMENTARY_DATA_PAYLOAD,
87+
dataset_id="44f1b432-9421-49e5-bd26-e63e18a30b69",
88+
identifier="12345678901",
89+
survey_id="123",
90+
sds_schema_version="v1",
91+
)
92+
93+
assert validated_payload == SUPPLEMENTARY_DATA_PAYLOAD
94+
95+
5796
def test_validate_supplementary_data_payload():
5897
validated_payload = validate_supplementary_data_v1(
5998
supplementary_data=SUPPLEMENTARY_DATA_PAYLOAD,
@@ -171,30 +210,6 @@ def test_validate_supplementary_data_payload_with_unknown_field():
171210
assert validated_payload == payload
172211

173212

174-
def test_validate_supplementary_data_invalid_schema_version():
175-
payload = {
176-
"dataset_id": "44f1b432-9421-49e5-bd26-e63e18a30b69",
177-
"survey_id": "123",
178-
"some_field": "value",
179-
"data": {
180-
"schema_version": "v3",
181-
"identifier": "12345678901",
182-
},
183-
}
184-
185-
with pytest.raises(ValidationError) as error:
186-
validate_supplementary_data_v1(
187-
supplementary_data=payload,
188-
dataset_id="001",
189-
identifier="12345678901",
190-
survey_id="123",
191-
)
192-
193-
assert (
194-
str(error.value) == "{'data': {'schema_version': ['Must be one of: v1, v2.']}}"
195-
)
196-
197-
198213
def test_validate_supplementary_data_payload_missing_identifier_in_items():
199214
payload = deepcopy(SUPPLEMENTARY_DATA_PAYLOAD)
200215
payload["data"]["items"]["local_units"][0].pop("identifier")

0 commit comments

Comments
 (0)