data_transfer: validate Role.slug and Role.uuid fields (#52192)

This commit is contained in:
Benjamin Dauvergne 2021-03-18 15:29:36 +01:00
parent b21d5a56b1
commit 5baca2ba03
3 changed files with 62 additions and 7 deletions

View File

@ -16,10 +16,12 @@
from __future__ import unicode_literals
import uuid
from functools import wraps
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
from django.core.validators import validate_slug
from django.utils.text import format_lazy
from django.utils.translation import ugettext_lazy as _
@ -225,6 +227,22 @@ class RoleDeserializer(object):
if has_ou:
kwargs['ou'] = ou
if 'uuid' in kwargs:
if not isinstance(kwargs['uuid'], str):
raise ValidationError(_("Cannot import role '%s' with invalid uuid") % kwargs.get('name'))
try:
uuid.UUID(kwargs['uuid'])
except ValueError:
raise ValidationError(_("Cannot import role '%s' with invalid uuid") % kwargs.get('name'))
if 'slug' in kwargs:
if not isinstance(kwargs['slug'], str):
raise ValidationError(_("Cannot import role '%s' with invalid slug") % kwargs.get('name'))
try:
validate_slug(kwargs['slug'])
except ValidationError:
raise ValidationError(_("Cannot import role '%s' with invalid slug") % kwargs.get('name'))
if obj: # Role already exist
self._obj = obj
status = 'updated'
@ -366,7 +384,8 @@ def import_site(json_d, import_context=None):
roles_ds = []
for role_d in json_d.get('roles', []):
# ignore internal roles
if role_d.get('slug', '').startswith('_'):
slug = role_d.get('slug')
if isinstance(slug, str) and slug.startswith('_'):
continue
roles_ds.append(RoleDeserializer(role_d, import_context))

View File

@ -621,3 +621,39 @@ def test_role_validate_unique(db):
}
with pytest.raises(ValidationError, match=r'Role "role1": name="role1": Name already used'):
import_site(data)
@pytest.mark.parametrize('uuid', [None, 1, [], {}, '', 'a'])
def test_import_roles_invalid_uuid(uuid, db):
with pytest.raises(ValidationError, match='.*invalid uuid'):
import_site(
{
'roles': [
{
'ou': {'slug': 'default'},
'uuid': uuid,
'name': 'role',
'description': 'role',
'slug': '-role',
}
]
}
)
@pytest.mark.parametrize('slug', [None, 1, [], {}, '', 'é', 'x a'])
def test_import_roles_invalid_slug(slug, db):
with pytest.raises(ValidationError, match='.*invalid slug'):
import_site(
{
'roles': [
{
'ou': {'slug': 'default'},
'uuid': '1d2a8aea-f8e3-40c1-aed5-6fc1327fdba0',
'name': 'role',
'description': 'role',
'slug': slug,
}
]
}
)

View File

@ -71,7 +71,7 @@ def test_import_site_cmd_infos_on_stdout(db, monkeypatch, capsys, json_fixture):
content = {
'roles': [
{
'uuid': 'dqfewrvesvews2532',
'uuid': 'a' * 32,
'slug': 'role-slug',
'name': 'role-name',
'ou': None,
@ -108,7 +108,7 @@ def test_import_site_transaction_rollback_on_dry_run(db, monkeypatch, capsys, js
content = {
'roles': [
{
'uuid': 'dqfewrvesvews2532',
'uuid': 'a' * 32,
'slug': 'role-slug',
'name': 'role-name',
'ou': None,
@ -127,7 +127,7 @@ def test_import_site_cmd_unhandled_context_option(db, monkeypatch, capsys, json_
content = {
'roles': [
{
'uuid': 'dqfewrvesvews2532',
'uuid': 'a' * 32,
'slug': 'role-slug',
'name': 'role-name',
'ou': None,
@ -136,7 +136,7 @@ def test_import_site_cmd_unhandled_context_option(db, monkeypatch, capsys, json_
]
}
Role.objects.create(uuid='dqfewrvesvews2532', slug='role-slug', name='role-name')
Role.objects.create(uuid='a' * 32, slug='role-slug', name='role-name')
with pytest.raises(ValidationError):
management.call_command('import_site', '-o', 'role-delete-orphans', json_fixture(content))
@ -155,7 +155,7 @@ def test_import_site_confirm_prompt_yes(db, monkeypatch, json_fixture):
content = {
'roles': [
{
'uuid': 'dqfewrvesvews2532',
'uuid': 'a' * 32,
'slug': 'role-slug',
'name': 'role-name',
'ou': None,
@ -170,7 +170,7 @@ def test_import_site_confirm_prompt_yes(db, monkeypatch, json_fixture):
monkeypatch.setattr(__builtin__, 'input', yes_raw_input)
management.call_command('import_site', json_fixture(content), stdin='yes')
assert Role.objects.get(uuid='dqfewrvesvews2532')
assert Role.objects.get(uuid='a' * 32)
def test_import_site_update_roles(db, json_fixture):