mirror of
https://github.com/suitenumerique/drive.git
synced 2026-09-10 03:37:55 +02:00
♻️(backend) custom pydantic errors to be compatible with our handler
We are using the drf_standardized_errors handler to have "nice" errors for the frontend application. We decided to override the SchemaField from the django_pydantic_field library in order to make it compatible with this error handler.
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
"""A JSONField for DRF to handle serialization/deserialization."""
|
||||
|
||||
import json
|
||||
import typing as ty
|
||||
|
||||
from rest_framework import serializers
|
||||
import pydantic
|
||||
from django_pydantic_field.v2.rest_framework.fields import (
|
||||
SchemaField as PydanticSchemaField,
|
||||
)
|
||||
from rest_framework import exceptions, serializers
|
||||
|
||||
|
||||
class JSONField(serializers.Field):
|
||||
@@ -23,3 +28,26 @@ class JSONField(serializers.Field):
|
||||
if data is None:
|
||||
return None
|
||||
return json.dumps(data)
|
||||
|
||||
|
||||
class SchemaField(PydanticSchemaField):
|
||||
"""
|
||||
Custom SchemaField in order to create error messages compatible with
|
||||
drf_standardized_errors handler.
|
||||
"""
|
||||
|
||||
def to_internal_value(self, data: ty.Any):
|
||||
try:
|
||||
if isinstance(data, (str, bytes)):
|
||||
return self.adapter.validate_json(data)
|
||||
return self.adapter.validate_python(data)
|
||||
except pydantic.ValidationError as exc:
|
||||
pydantic_errors = exc.errors(
|
||||
include_url=False, include_context=False, include_input=False
|
||||
)
|
||||
errors = []
|
||||
for pydantic_error in pydantic_errors:
|
||||
for location in pydantic_error.get("loc"):
|
||||
errors.append({location: pydantic_error.get("msg")})
|
||||
|
||||
raise exceptions.ValidationError(errors, code="invalid") from exc
|
||||
|
||||
@@ -12,12 +12,12 @@ from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from django_pydantic_field.rest_framework import SchemaField
|
||||
from lasuite.drf.models.choices import LinkReachChoices, get_equivalent_link_definition
|
||||
from rest_framework import serializers
|
||||
|
||||
from core import models
|
||||
from core.api import utils
|
||||
from core.api.fields import SchemaField
|
||||
from core.storage import get_storage_compute_backend
|
||||
from wopi import utils as wopi_utils
|
||||
|
||||
|
||||
@@ -213,9 +213,7 @@ class User(AbstractBaseUser, BaseModel, auth_models.PermissionsMixin):
|
||||
short_name = models.CharField(_("short name"), max_length=100, null=True, blank=True)
|
||||
|
||||
email = models.EmailField(_("identity email address"), blank=True, null=True)
|
||||
column_preferences = SchemaField(
|
||||
ColumnPreferences, blank=True, null=True, default=None
|
||||
)
|
||||
column_preferences = SchemaField(ColumnPreferences, blank=True, null=True, default=None)
|
||||
|
||||
# Unlike the "email" field which stores the email coming from the OIDC token, this field
|
||||
# stores the email used by staff users to login to the admin site
|
||||
|
||||
@@ -684,8 +684,10 @@ def test_api_users_patch_column_preferences_valid(column2, column1):
|
||||
assert user.column_preferences == models.ColumnPreferences(**column_preferences)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("column_name", ["column1", "column2"])
|
||||
def test_api_users_patch_column_preferences_missing_column_should_fail(column_name):
|
||||
@pytest.mark.parametrize(
|
||||
"column_name,missing_column", [("column1", "column2"), ("column2", "column1")]
|
||||
)
|
||||
def test_api_users_patch_column_preferences_missing_column_should_fail(column_name, missing_column):
|
||||
"""Patching column_preferences with a missing required column parameter should fails."""
|
||||
|
||||
user = factories.UserFactory()
|
||||
@@ -705,6 +707,17 @@ def test_api_users_patch_column_preferences_missing_column_should_fail(column_na
|
||||
format="json",
|
||||
)
|
||||
|
||||
assert response.json() == {
|
||||
"type": "validation_error",
|
||||
"errors": [
|
||||
{
|
||||
"code": "invalid",
|
||||
"detail": "Field required",
|
||||
"attr": f"column_preferences.0.{missing_column}",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
@@ -732,6 +745,17 @@ def test_api_users_patch_column_preferences_extra_value_should_fail():
|
||||
format="json",
|
||||
)
|
||||
|
||||
assert response.json() == {
|
||||
"type": "validation_error",
|
||||
"errors": [
|
||||
{
|
||||
"code": "invalid",
|
||||
"detail": "Extra inputs are not permitted",
|
||||
"attr": "column_preferences.0.not_allowed",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
@@ -758,6 +782,24 @@ def test_api_users_patch_column_preferences_invalid_value():
|
||||
format="json",
|
||||
)
|
||||
|
||||
assert response.json() == {
|
||||
"type": "validation_error",
|
||||
"errors": [
|
||||
{
|
||||
"code": "invalid",
|
||||
"detail": "Input should be 'last_modified', 'created', 'created_by', "
|
||||
"'file_type' or 'file_size'",
|
||||
"attr": "column_preferences.0.column1",
|
||||
},
|
||||
{
|
||||
"code": "invalid",
|
||||
"detail": "Input should be 'last_modified', 'created', 'created_by', "
|
||||
"'file_type' or 'file_size'",
|
||||
"attr": "column_preferences.1.column2",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user