🐛(back) allow ASCII characters in user sub field

All ASCII characters are allowed in a sub, we change the sub validator
to reflect this.
This commit is contained in:
Manuel Raynaud
2025-08-29 15:59:06 +02:00
committed by GitHub
parent 8d42149304
commit 09de014a43
7 changed files with 55 additions and 20 deletions

View File

@@ -25,6 +25,7 @@ and this project adheres to
- #1270
- #1282
- ♻️(backend) fallback to email identifier when no name #1298
- 🐛(backend) allow ASCII characters in user sub field #1295
### Fixed

View File

@@ -13,7 +13,7 @@ from django.utils.translation import gettext_lazy as _
import magic
from rest_framework import serializers
from core import choices, enums, models, utils
from core import choices, enums, models, utils, validators
from core.services.ai_services import AI_ACTIONS
from core.services.converter_services import (
ConversionError,
@@ -422,7 +422,7 @@ class ServerCreateDocumentSerializer(serializers.Serializer):
content = serializers.CharField(required=True)
# User
sub = serializers.CharField(
required=True, validators=[models.User.sub_validator], max_length=255
required=True, validators=[validators.sub_validator], max_length=255
)
email = serializers.EmailField(required=True)
language = serializers.ChoiceField(

View File

@@ -2,6 +2,8 @@
from django.db import migrations, models
import core.validators
class Migration(migrations.Migration):
dependencies = [
@@ -33,4 +35,17 @@ class Migration(migrations.Migration):
verbose_name="language",
),
),
migrations.AlterField(
model_name="user",
name="sub",
field=models.CharField(
blank=True,
help_text="Required. 255 characters or fewer. ASCII characters only.",
max_length=255,
null=True,
unique=True,
validators=[core.validators.sub_validator],
verbose_name="sub",
),
),
]

View File

@@ -14,7 +14,7 @@ from django.contrib.auth import models as auth_models
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.postgres.fields import ArrayField
from django.contrib.sites.models import Site
from django.core import mail, validators
from django.core import mail
from django.core.cache import cache
from django.core.files.base import ContentFile
from django.core.files.storage import default_storage
@@ -39,6 +39,7 @@ from .choices import (
RoleChoices,
get_equivalent_link_definition,
)
from .validators import sub_validator
logger = getLogger(__name__)
@@ -136,22 +137,12 @@ class UserManager(auth_models.UserManager):
class User(AbstractBaseUser, BaseModel, auth_models.PermissionsMixin):
"""User model to work with OIDC only authentication."""
sub_validator = validators.RegexValidator(
regex=r"^[\w.@+-:]+\Z",
message=_(
"Enter a valid sub. This value may contain only letters, "
"numbers, and @/./+/-/_/: characters."
),
)
sub = models.CharField(
_("sub"),
help_text=_(
"Required. 255 characters or fewer. Letters, numbers, and @/./+/-/_/: characters only."
),
help_text=_("Required. 255 characters or fewer. ASCII characters only."),
max_length=255,
unique=True,
validators=[sub_validator],
unique=True,
blank=True,
null=True,
)

View File

@@ -148,7 +148,7 @@ def test_api_documents_create_for_owner_invalid_sub():
data = {
"title": "My Document",
"content": "Document content",
"sub": "123!!",
"sub": "invalid süb",
"email": "john.doe@example.com",
}
@@ -163,10 +163,7 @@ def test_api_documents_create_for_owner_invalid_sub():
assert not Document.objects.exists()
assert response.json() == {
"sub": [
"Enter a valid sub. This value may contain only letters, "
"numbers, and @/./+/-/_/: characters."
]
"sub": ["Enter a valid sub. This value should be ASCII only."]
}

View File

@@ -44,3 +44,25 @@ def test_models_users_send_mail_main_missing():
user.email_user("my subject", "my message")
assert str(excinfo.value) == "User has no email address."
@pytest.mark.parametrize(
"sub,is_valid",
[
("valid_sub.@+-:=/", True),
("invalid süb", False),
(12345, True),
],
)
def test_models_users_sub_validator(sub, is_valid):
"""The "sub" field should be validated."""
user = factories.UserFactory()
user.sub = sub
if is_valid:
user.full_clean()
else:
with pytest.raises(
ValidationError,
match=("Enter a valid sub. This value should be ASCII only."),
):
user.full_clean()

View File

@@ -0,0 +1,9 @@
"""Custom validators for the core app."""
from django.core.exceptions import ValidationError
def sub_validator(value):
"""Validate that the sub is ASCII only."""
if not value.isascii():
raise ValidationError("Enter a valid sub. This value should be ASCII only.")