Skip to content

Commit

Permalink
fixup! ✨(dashboard) add validation and data updates for consent manag…
Browse files Browse the repository at this point in the history
…ement
  • Loading branch information
ssorin committed Feb 5, 2025
1 parent e438b6a commit 9acbad2
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 36 deletions.
4 changes: 3 additions & 1 deletion src/dashboard/apps/consent/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ class ConsentConfig(AppConfig):
verbose_name = _("Consent")

def ready(self):
"""Register signals."""
"""Register signals and validate CONSENT_CONTROL_AUTHORITY on ready."""
from .signals import handle_new_delivery_point # noqa: F401
from .validators import validate_control_authority_schema_on_ready
validate_control_authority_schema_on_ready()
8 changes: 4 additions & 4 deletions src/dashboard/apps/consent/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@
"address_1": {"type": ["string", "null"], "maxLength": 255},
"address_2": {"type": ["string", "null"], "maxLength": 255},
"zip_code": {
"type": ["string", "null"],
"maxLength": 5,
"pattern": "^[0-9]{1,5}$",
},
"type": ["string", "null"],
"maxLength": 5,
"pattern": "^[0-9]{1,5}$",
},
"city": {"type": ["string", "null"], "maxLength": 255},
},
"required": ["name", "represented_by", "email", "address_1", "zip_code", "city"],
Expand Down
44 changes: 43 additions & 1 deletion src/dashboard/apps/consent/tests/test_validators.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
"""Dashboard consent validators tests."""

import pytest
from django.core.exceptions import ValidationError
from django.core.exceptions import ImproperlyConfigured, ValidationError

from apps.consent.validators import (
validate_company_schema,
validate_control_authority_schema,
validate_control_authority_schema_on_ready,
validate_representative_schema,
)

Expand Down Expand Up @@ -237,3 +238,44 @@ def test_validate_control_authority_schema_invalid():
invalid_value["additional_property"] = ""
with pytest.raises(ValidationError):
validate_control_authority_schema(invalid_value)


def test_valid_control_authority(settings):
"""Test validate_control_authority_schema_on_ready with valid data."""

# Change temporally settings.CONSENT_CONTROL_AUTHORITY.
settings.CONSENT_CONTROL_AUTHORITY = {
"name": "Control Authority Name",
"represented_by": "John Doe",
"email": "[email protected]",
"address_1": "123 Street Name",
"address_2": "",
"zip_code": "12345",
"city": "City Name",
}

# ImproperlyConfigured should not be raised
try:
validate_control_authority_schema_on_ready()
except ImproperlyConfigured as e:
pytest.fail(f"settings.CONSENT_CONTROL_AUTHORITY validation error: {e.message}")


def test_invalid_control_authority(settings):
"""Test validate_control_authority_schema_on_ready with invalid data."""

# Change temporally settings.CONSENT_CONTROL_AUTHORITY with invalid data.
# invalid: the key 'name' is expected, not 'firstname'
settings.CONSENT_CONTROL_AUTHORITY = {
"firstname": "Control Authority Name",
"represented_by": "John Doe",
"email": "[email protected]",
"address_1": "",
"address_2": "",
"zip_code": "12345",
"city": "City Name",
}

# must raise ImproperlyConfigured
with pytest.raises(ImproperlyConfigured):
validate_control_authority_schema_on_ready()
5 changes: 3 additions & 2 deletions src/dashboard/apps/consent/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ def test_bulk_update_consent_status(rf):
assert c.control_authority is not None
control_authority = settings.CONSENT_CONTROL_AUTHORITY
assert c.control_authority["name"] == control_authority["name"]
assert (c.control_authority["represented_by"] ==
control_authority["represented_by"])
assert (
c.control_authority["represented_by"] == control_authority["represented_by"]
)
assert c.control_authority["email"] == control_authority["email"]
assert c.control_authority["address_1"] == control_authority["address_1"]
assert c.control_authority["address_2"] == control_authority["address_2"]
Expand Down
16 changes: 15 additions & 1 deletion src/dashboard/apps/consent/validators.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Dashboard consent app validators."""

from django.core.exceptions import ValidationError
from django.core.exceptions import ImproperlyConfigured, ValidationError
from jsonschema import ValidationError as JSONSchemaValidationError
from jsonschema import validate

Expand Down Expand Up @@ -40,3 +40,17 @@ def validate_control_authority_schema(value):

validator = json_schema_validator(CONTROL_AUTHORITY_SCHEMA)
return validator(value)

def validate_control_authority_schema_on_ready():
"""Validate the control authority schema on the consent app ready.
Check if settings.CONSENT_CONTROL_AUTHORITY is valid,
raise ImproperlyConfigured otherwise.
"""
from django.conf import settings
try:
validate_control_authority_schema(settings.CONSENT_CONTROL_AUTHORITY)
except ValidationError as e:
raise ImproperlyConfigured(
f"settings.CONSENT_CONTROL_AUTHORITY validation error: {e.message}"
) from e
39 changes: 12 additions & 27 deletions src/dashboard/apps/consent/views.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
"""Dashboard consent app views."""

from typing import Optional, TypedDict
from uuid import UUID

import sentry_sdk
from django.conf import settings
from django.contrib import messages
Expand All @@ -24,22 +21,6 @@
from .models import Consent


class ConsentObject(TypedDict):
"""Consent object type."""

id: UUID
delivery_point__entity__name: str
delivery_point__entity__company_type: str
delivery_point__entity__legal_form: Optional[str]
delivery_point__entity__trade_name: Optional[str]
delivery_point__entity__siret: Optional[str]
delivery_point__entity__naf: Optional[str]
delivery_point__entity__address_1: Optional[str]
delivery_point__entity__address_2: Optional[str]
delivery_point__entity__address_zip_code: Optional[str]
delivery_point__entity__address_city: Optional[str]


class IndexView(BreadcrumbContextMixin, TemplateView):
"""Index view of the consent app."""

Expand Down Expand Up @@ -134,13 +115,17 @@ def _bulk_update_consent(
Note: Only `AWAITING` consents can be updated by users.
"""
# retrieve consents to update
consents = Consent.objects.filter(
consents = (
Consent.objects.filter(
id__in=ids,
status=AWAITING,
).filter(
)
.filter(
Q(delivery_point__entity__users=self.request.user)
| Q(delivery_point__entity__proxies__users=self.request.user)
).select_related('delivery_point__entity')
)
.select_related("delivery_point__entity")
)

# build consent object with validated fields to update
update_objects = [
Expand Down Expand Up @@ -185,12 +170,12 @@ def _build_consent_object(
self,
status: str,
form_values: dict,
consent,
consent: Consent,
) -> Consent:
"""Builds and returns a `Consent` object with validated data.
Parameters:
- status (str): Consent status (e.g., "AWAITING", "VALIDATED").
- status (str): Consent status (e.g., AWAITING”, “VALIDATED).
- form_values (dict): Validated data from the consent form.
- control_authority (dict): Details about the control authority.
- company_representative (dict): Information about the company representative.
Expand All @@ -213,9 +198,9 @@ def _build_consent_object(
}

company_representative = {
"firstname": self.request.user.first_name,
"lastname": self.request.user.last_name,
"email": self.request.user.email,
"firstname": self.request.user.first_name, # type: ignore[union-attr]
"lastname": self.request.user.last_name, # type: ignore[union-attr]
"email": self.request.user.email, # type: ignore[union-attr]
}

# build a Consent object with all validated data
Expand Down

0 comments on commit 9acbad2

Please sign in to comment.