OpenSlides/openslides/users/serializers.py
Oskar Hahn dd4754d045 Disable the future-lock when updating the restircted data cache
Before this commit, there where two different locks when updating the restricted
data cache. A future lock, what is faster but only works in the same thread. The
other lock is in redis, it is not so fast, but also works in many threads.

The future lock was buggy, because on a second call of update_restricted_data
the same future was reused. So on the second run, the future was already done.

I don't see any way to delete. The last client would have to delete it, but there
is no way to find out which client the last one is.
2019-03-04 21:37:00 +01:00

181 lines
5.2 KiB
Python

from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import Permission
from .models import Group, PersonalNote, User
from ..utils.autoupdate import inform_changed_data
from ..utils.rest_api import (
IdPrimaryKeyRelatedField,
JSONField,
ModelSerializer,
RelatedField,
ValidationError,
)
USERCANSEESERIALIZER_FIELDS = (
"id",
"username",
"title",
"first_name",
"last_name",
"structure_level",
"number",
"about_me",
"groups",
"is_present",
"is_committee",
)
USERCANSEEEXTRASERIALIZER_FIELDS = USERCANSEESERIALIZER_FIELDS + (
"gender",
"email",
"last_email_send",
"comment",
"is_active",
)
class UserFullSerializer(ModelSerializer):
"""
Serializer for users.models.User objects.
Serializes all relevant fields for manager.
"""
groups = IdPrimaryKeyRelatedField(
many=True,
required=False,
queryset=Group.objects.exclude(pk=1),
help_text=(
"The groups this user belongs to. A user will "
"get all permissions granted to each of "
"his/her groups."
),
)
class Meta:
model = User
fields = USERCANSEEEXTRASERIALIZER_FIELDS + (
"default_password",
"session_auth_hash",
)
read_only_fields = ("last_email_send",)
def validate(self, data):
"""
Checks if the given data is empty. Generates the
username if it is empty.
"""
try:
action = self.context["view"].action
except (KeyError, AttributeError):
action = None
# Check if we are in Patch context, if not, check if we have the mandatory fields
if action != "partial_update":
if not (
data.get("username") or data.get("first_name") or data.get("last_name")
):
raise ValidationError(
{"detail": "Username, given name and surname can not all be empty."}
)
# Generate username. But only if it is not set and the serializer is not
# called in a PATCH context (partial_update).
if not data.get("username") and action != "partial_update":
data["username"] = User.objects.generate_username(
data.get("first_name", ""), data.get("last_name", "")
)
return data
def prepare_password(self, validated_data):
"""
Sets the default password.
"""
# Prepare setup password.
if not validated_data.get("default_password"):
validated_data["default_password"] = User.objects.generate_password()
validated_data["password"] = make_password(validated_data["default_password"])
return validated_data
def create(self, validated_data):
"""
Creates the user.
"""
# Perform creation in the database and return new user.
user = super().create(self.prepare_password(validated_data))
# TODO: This autoupdate call is redundant (required by issue #2727). See #2736.
inform_changed_data(user)
return user
class PermissionRelatedField(RelatedField):
"""
A custom field to use for the permission relationship.
"""
default_error_messages = {
"incorrect_value": 'Incorrect value "{value}". Expected app_label.codename string.',
"does_not_exist": 'Invalid permission "{value}". Object does not exist.',
}
def to_representation(self, value):
"""
Returns the permission code string (app_label.codename).
"""
return ".".join((value.content_type.app_label, value.codename))
def to_internal_value(self, data):
"""
Returns the permission object represented by data. The argument data is
what is sent by the client. This method expects permission code strings
(app_label.codename) like to_representation() returns.
"""
try:
app_label, codename = data.split(".")
except ValueError:
self.fail("incorrect_value", value=data)
try:
permission = Permission.objects.get(
content_type__app_label=app_label, codename=codename
)
except Permission.DoesNotExist:
self.fail("does_not_exist", value=data)
return permission
class GroupSerializer(ModelSerializer):
"""
Serializer for django.contrib.auth.models.Group objects.
"""
permissions = PermissionRelatedField(many=True, queryset=Permission.objects.all())
class Meta:
model = Group
fields = ("id", "name", "permissions")
def update(self, *args, **kwargs):
"""
Customized update method. We just refresh the instance from the
database because of an unknown bug in Django REST framework.
"""
instance = super().update(*args, **kwargs)
return Group.objects.get(pk=instance.pk)
class PersonalNoteSerializer(ModelSerializer):
"""
Serializer for users.models.PersonalNote objects.
"""
notes = JSONField()
class Meta:
model = PersonalNote
fields = ("id", "user", "notes")
read_only_fields = ("user",)