Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update sds schema validation #1538

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions app/authentication/auth_payload_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,3 @@

class AuthPayloadVersion(Enum):
V2 = "v2"


class SupplementaryDataSchemaVersion(Enum):
V2 = "v2"
V1 = "v1"
1 change: 1 addition & 0 deletions app/routes/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def _set_questionnaire_supplementary_data(
dataset_id=new_sds_dataset_id,
identifier=identifier, # type: ignore
survey_id=metadata["survey_id"], # type: ignore
sds_schema_version=schema.json.get("sds_schema_version"),
)
logger.info(
"fetched supplementary data",
Expand Down
14 changes: 12 additions & 2 deletions app/services/supplementary_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ class InvalidSupplementaryData(Exception):


def get_supplementary_data_v1(
*, dataset_id: str, identifier: str, survey_id: str
*,
dataset_id: str,
identifier: str,
survey_id: str,
sds_schema_version: str | None = None,
) -> dict:
# Type ignore: current_app is a singleton in this application and has the key_store key in its eq attribute.
key_store = current_app.eq["key_store"] # type: ignore
Expand Down Expand Up @@ -93,6 +97,7 @@ def get_supplementary_data_v1(
dataset_id=dataset_id,
identifier=identifier,
survey_id=survey_id,
sds_schema_version=sds_schema_version,
)

logger.error(
Expand Down Expand Up @@ -121,14 +126,19 @@ def decrypt_supplementary_data(


def validate_supplementary_data(
supplementary_data: Mapping, dataset_id: str, identifier: str, survey_id: str
supplementary_data: Mapping,
dataset_id: str,
identifier: str,
survey_id: str,
sds_schema_version: str | None = None,
) -> dict:
try:
return validate_supplementary_data_v1(
supplementary_data=supplementary_data,
dataset_id=dataset_id,
identifier=identifier,
survey_id=survey_id,
sds_schema_version=sds_schema_version,
)
except ValidationError as e:
raise ValidationError("Invalid supplementary data") from e
26 changes: 13 additions & 13 deletions app/utilities/supplementary_data_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
validates_schema,
)

from app.authentication.auth_payload_versions import SupplementaryDataSchemaVersion
from app.utilities.metadata_parser_v2 import VALIDATORS, StripWhitespaceMixin


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

class SupplementaryData(Schema, StripWhitespaceMixin):
identifier = VALIDATORS["string"](validate=validate.Length(min=1))
schema_version = VALIDATORS["string"](
validate=validate.OneOf(
[
SupplementaryDataSchemaVersion.V1.value,
SupplementaryDataSchemaVersion.V2.value,
]
)
)
items = fields.Nested(ItemsData, required=False, unknown=INCLUDE)

@validates_schema()
Expand All @@ -67,25 +58,33 @@ class SupplementaryDataMetadataSchema(Schema, StripWhitespaceMixin):

@validates_schema()
def validate_dataset_and_survey_id( # pylint: disable=unused-argument
self, data: Mapping, **kwargs: Any
self, payload: Mapping, **kwargs: Any
) -> None:
if data:
if data["dataset_id"] != self.context["dataset_id"]:
if payload:
if payload["dataset_id"] != self.context["dataset_id"]:
raise ValidationError(
"Supplementary data did not return the specified Dataset ID"
)

if data["survey_id"] != self.context["survey_id"]:
if payload["survey_id"] != self.context["survey_id"]:
raise ValidationError(
"Supplementary data did not return the specified Survey ID"
)

if (self.context["sds_schema_version"]) and (
payload["data"]["schema_version"] != self.context["sds_schema_version"]
):
raise ValidationError(
"The Supplementary Dataset Schema Version does not match the version set in the Questionnaire Schema"
)


def validate_supplementary_data_v1(
supplementary_data: Mapping,
dataset_id: str,
identifier: str,
survey_id: str,
sds_schema_version: str | None = None,
) -> dict:
"""Validate claims required for supplementary data"""
supplementary_data_metadata_schema = SupplementaryDataMetadataSchema(
Expand All @@ -95,6 +94,7 @@ def validate_supplementary_data_v1(
"dataset_id": dataset_id,
"identifier": identifier,
"survey_id": survey_id,
"sds_schema_version": sds_schema_version,
}
validated_supplementary_data = supplementary_data_metadata_schema.load(
supplementary_data
Expand Down
192 changes: 192 additions & 0 deletions schemas/test/en/test_supplementary_data_with_sds_schema_version.json
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new schema is not actually being used anywhere?

Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
{
"mime_type": "application/json/ons/eq",
"language": "en",
"schema_version": "0.0.1",
"sds_schema_version": "v1",
"data_version": "0.0.3",
"survey_id": "123",
"title": "Test Supplementary Data with sds_schema_version Field",
"theme": "default",
"description": "A questionnaire to demo the support of the sds_schema_version field in schemas",
"metadata": [
{
"name": "survey_id",
"type": "string"
},
{
"name": "user_id",
"type": "string"
},
{
"name": "period_id",
"type": "string"
},
{
"name": "ru_name",
"type": "string"
},
{
"name": "sds_dataset_id",
"type": "string"
}
],
"supplementary_data": {
"lists": ["employees", "products"]
},
"questionnaire_flow": {
"type": "Hub",
"options": {
"required_completed_sections": ["introduction-section"]
}
},
"post_submission": {
"view_response": true
},
"sections": [
{
"id": "introduction-section",
"title": "Introduction",
"groups": [
{
"id": "introduction-group",
"title": "Introduction Group",
"blocks": [
{
"id": "loaded-successfully-block",
"type": "Interstitial",
"content": {
"title": "Supplementary Data",
"contents": [
{
"title": "You have successfully loaded Supplementary data",
"description": {
"text": "List of products: {products}",
"placeholders": [
{
"placeholder": "products",
"transforms": [
{
"transform": "format_list",
"arguments": {
"list_to_format": {
"source": "supplementary_data",
"identifier": "products",
"selectors": ["name"]
}
}
}
]
}
]
},
"guidance": {
"contents": [
{
"description": {
"text": "The purpose of this block is to test the survey opens successfully, given that sds_schema_version (defined in the questionnaire schema) matches the version set in the supplementary data payload. Separate to using the supplementary data, the surnames of the employees are: {surnames}.",
"placeholders": [
{
"placeholder": "surnames",
"transforms": [
{
"transform": "concatenate_list",
"arguments": {
"list_to_concatenate": [
{
"source": "supplementary_data",
"identifier": "employees",
"selectors": ["personal_details", "surname"]
}
],
"delimiter": ", "
}
}
]
}
]
}
}
]
}
}
]
}
},
{
"id": "introduction-block",
"type": "Introduction",
"primary_content": [
{
"id": "business-details",
"title": {
"text": "You are completing this survey for {company_name}",
"placeholders": [
{
"placeholder": "company_name",
"value": {
"source": "supplementary_data",
"identifier": "company_name"
}
}
]
},
"contents": [
{
"description": {
"text": "If the company details or structure have changed contact us on {telephone_number_link}",
"placeholders": [
{
"placeholder": "telephone_number_link",
"value": {
"source": "supplementary_data",
"identifier": "company_details",
"selectors": ["telephone_number"]
}
}
]
}
},
{
"guidance": {
"contents": [
{
"title": "Guidance for completing this survey",
"list": [
"The company name, telephone number all come from supplementary data",
"if you picked the supplementary dataset with guidance, there will be a 3rd bullet point below this one, with the supplementary guidance.",
{
"text": "{survey_guidance}",
"placeholders": [
{
"placeholder": "survey_guidance",
"transforms": [
{
"transform": "first_non_empty_item",
"arguments": {
"items": [
{
"source": "supplementary_data",
"identifier": "guidance"
}
]
}
}
]
}
]
}
]
}
]
}
}
]
}
]
}
]
}
]
}
]
}
52 changes: 28 additions & 24 deletions tests/app/parser/test_supplementary_data_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,34 @@ def test_invalid_supplementary_data_payload_raises_error():
assert str(error.value) == "Invalid supplementary data"


def test_invalid_supplementary_dataset_version_raises_error():
with pytest.raises(ValidationError) as error:
validate_supplementary_data_v1(
supplementary_data=SUPPLEMENTARY_DATA_PAYLOAD,
dataset_id="44f1b432-9421-49e5-bd26-e63e18a30b69",
identifier="12345678901",
survey_id="123",
sds_schema_version="v6",
)

assert (
str(error.value)
== "{'_schema': ['The Supplementary Dataset version does not match the version set in the questionnaire schema']}"
)


def test_valid_supplementary_dataset_version():
validated_payload = validate_supplementary_data_v1(
supplementary_data=SUPPLEMENTARY_DATA_PAYLOAD,
dataset_id="44f1b432-9421-49e5-bd26-e63e18a30b69",
identifier="12345678901",
survey_id="123",
sds_schema_version="v1",
)

assert validated_payload == SUPPLEMENTARY_DATA_PAYLOAD


def test_validate_supplementary_data_payload():
validated_payload = validate_supplementary_data_v1(
supplementary_data=SUPPLEMENTARY_DATA_PAYLOAD,
Expand Down Expand Up @@ -171,30 +199,6 @@ def test_validate_supplementary_data_payload_with_unknown_field():
assert validated_payload == payload


def test_validate_supplementary_data_invalid_schema_version():
payload = {
"dataset_id": "44f1b432-9421-49e5-bd26-e63e18a30b69",
"survey_id": "123",
"some_field": "value",
"data": {
"schema_version": "v3",
"identifier": "12345678901",
},
}

with pytest.raises(ValidationError) as error:
validate_supplementary_data_v1(
supplementary_data=payload,
dataset_id="001",
identifier="12345678901",
survey_id="123",
)

assert (
str(error.value) == "{'data': {'schema_version': ['Must be one of: v1, v2.']}}"
)


def test_validate_supplementary_data_payload_missing_identifier_in_items():
payload = deepcopy(SUPPLEMENTARY_DATA_PAYLOAD)
payload["data"]["items"]["local_units"][0].pop("identifier")
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/create_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"trad_as": "Integration Tests",
"employment_date": "1983-06-02",
"display_address": "68 Abingdon Road, Goathill",
"sds_dataset_id": "44f1b432-9421-49e5-bd26-e63e18a30b69",
"sds_dataset_id": "203b2f9d-c500-8175-98db-86ffcfdccfa3",
"survey_id": "123",
}
},
Expand Down
Loading
Loading