api_views: provide a default slug for ous (#22250)

This commit is contained in:
Paul Marillonnet 2020-09-14 16:53:24 +02:00
parent 41aa3734e3
commit f41c11d259
2 changed files with 78 additions and 1 deletions

View File

@ -25,6 +25,7 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.hashers import identify_hasher
from django.core.exceptions import MultipleObjectsReturned
from django.utils.translation import ugettext as _
from django.utils.text import slugify
from django.utils.encoding import force_text
from django.utils.dateparse import parse_datetime
from django.views.decorators.vary import vary_on_headers
@ -887,13 +888,31 @@ class RoleMembershipsAPI(ExceptionHandlerMixin, APIView):
role_memberships = RoleMembershipsAPI.as_view()
class SlugFromNameDefault:
requires_context = False
serializer_instance = None
def set_context(self, instance):
self.serializer_instance = instance
def __call__(self):
name = self.serializer_instance.context['request'].data.get('name', '')
return slugify(name)
class BaseOrganizationalUnitSerializer(serializers.ModelSerializer):
slug = serializers.SlugField(
required=False,
allow_blank=False,
max_length=256,
default=SlugFromNameDefault(),
)
class Meta:
model = get_ou_model()
fields = '__all__'
class OrganizationalUnitAPI(ExceptionHandlerMixin, ModelViewSet):
class OrganizationalUnitAPI(api_mixins.GetOrCreateMixinView, ExceptionHandlerMixin, ModelViewSet):
permission_classes = (DjangoPermission('a2_rbac.search_organizationalunit'),)
serializer_class = BaseOrganizationalUnitSerializer
lookup_field = 'uuid'

View File

@ -30,6 +30,7 @@ from django.contrib.contenttypes.models import ContentType
from django.core import mail
from django.urls import reverse
from django.utils.encoding import force_text
from django.utils.text import slugify
from django.utils.timezone import now
from django.utils.http import urlencode
@ -1254,6 +1255,63 @@ def test_api_post_role_no_ou(app, superuser):
assert role.ou == get_default_ou()
def test_api_post_ou_no_slug(app, superuser):
app.authorization = ('Basic', (superuser.username, superuser.username))
OU = get_ou_model()
ou_data = {
'name': 'Some Organizational Unit',
}
resp = app.post_json('/api/ous/', params=ou_data)
uuid = resp.json['uuid']
ou = OU.objects.get(uuid=uuid)
assert ou.id != get_default_ou().id
assert ou.slug == slugify(ou.name)
assert ou.slug == slugify(ou_data['name'])
# another call with same ou name
ou_data = {
'name': 'Some Organizational Unit',
}
resp = app.post_json('/api/ous/', params=ou_data, status=400)
assert resp.json['errors']['__all__'] == [
"The fields name must make a unique set.",
"The fields slug must make a unique set."
]
# no slug no name
ou_data = {
'id': 42,
}
resp = app.post_json('/api/ous/', params=ou_data, status=400)
assert resp.json['errors']['name'] == ['This field is required.']
def test_api_post_ou_get_or_create(app, superuser):
app.authorization = ('Basic', (superuser.username, superuser.username))
OU = get_ou_model()
# first get-or-create? -> create
ou_data = {
'name': 'Some Organizational Unit',
}
resp = app.post_json('/api/ous/', params=ou_data)
uuid = resp.json['uuid']
ou = OU.objects.get(uuid=uuid)
# second get-or-create? -> get
ou_data = {
'name': 'Some Organizational Unit',
'slug': ou.slug,
}
resp = app.post_json('/api/ous/?get_or_create=slug', params=ou_data)
assert resp.json['uuid'] == ou.uuid
# update-or-create? -> update
ou_data = {
'name': 'Another name',
'slug': ou.slug,
}
resp = app.post_json('/api/ous/?update_or_create=slug', params=ou_data)
assert resp.json['uuid'] == ou.uuid
assert OU.objects.get(uuid=resp.json['uuid']).name == ou_data['name']
def test_api_post_role_unauthorized(app, simple_user, ou1):
app.authorization = ('Basic', (simple_user.username, simple_user.username))
Role = get_role_model()