OpenSlides/openslides/users/serializers.py

191 lines
5.4 KiB
Python
Raw Normal View History

from django.contrib.auth.hashers import make_password
2015-09-16 00:55:27 +02:00
from django.contrib.auth.models import Permission
from ..utils.autoupdate import inform_changed_data
2015-09-16 00:55:27 +02:00
from ..utils.rest_api import (
IdPrimaryKeyRelatedField,
2017-05-23 14:07:06 +02:00
JSONField,
ModelSerializer,
RelatedField,
ValidationError,
)
from ..utils.validate import validate_html
from .models import Group, PersonalNote, User
2015-01-06 00:11:22 +01:00
USERCANSEESERIALIZER_FIELDS = (
2019-01-06 16:22:33 +01:00
"id",
"username",
"title",
"first_name",
"last_name",
"structure_level",
"number",
"about_me",
"groups",
"is_present",
"is_committee",
"vote_weight",
)
USERCANSEEEXTRASERIALIZER_FIELDS = USERCANSEESERIALIZER_FIELDS + (
2019-01-18 17:58:45 +01:00
"gender",
2019-01-06 16:22:33 +01:00
"email",
"last_email_send",
"comment",
"is_active",
2019-08-20 12:00:54 +02:00
"auth_type",
)
class UserSerializer(ModelSerializer):
"""
Serializer for users.models.User objects.
Serializes all relevant fields for manager.
"""
2019-01-06 16:22:33 +01:00
groups = IdPrimaryKeyRelatedField(
many=True,
required=False,
queryset=Group.objects.exclude(pk=1),
2019-01-12 23:01:42 +01:00
help_text=(
2019-01-06 16:22:33 +01:00
"The groups this user belongs to. A user will "
"get all permissions granted to each of "
"his/her groups."
),
)
class Meta:
model = User
2019-01-06 16:22:33 +01:00
fields = USERCANSEEEXTRASERIALIZER_FIELDS + (
"default_password",
"session_auth_hash",
)
2019-08-20 12:00:54 +02:00
read_only_fields = ("last_email_send", "auth_type")
def validate(self, data):
"""
Checks if the given data is empty. Generates the
username if it is empty.
"""
2015-05-05 10:42:31 +02:00
try:
2019-01-06 16:22:33 +01:00
action = self.context["view"].action
2015-05-05 10:42:31 +02:00
except (KeyError, AttributeError):
action = None
# Check if we are in Patch context, if not, check if we have the mandatory fields
2019-01-06 16:22:33 +01:00
if action != "partial_update":
if not (
data.get("username") or data.get("first_name") or data.get("last_name")
):
raise ValidationError(
2019-01-12 23:01:42 +01:00
{"detail": "Username, given name and surname can not all be empty."}
2019-01-06 16:22:33 +01:00
)
# Generate username. But only if it is not set and the serializer is not
# called in a PATCH context (partial_update).
2019-01-06 16:22:33 +01:00
if not data.get("username") and action != "partial_update":
data["username"] = User.objects.generate_username(
data.get("first_name", ""), data.get("last_name", "")
)
# check the about_me html
if "about_me" in data:
data["about_me"] = validate_html(data["about_me"])
return data
2017-04-19 09:28:21 +02:00
def prepare_password(self, validated_data):
"""
2017-04-19 09:28:21 +02:00
Sets the default password.
"""
# Prepare setup password.
2019-01-06 16:22:33 +01:00
if not validated_data.get("default_password"):
validated_data["default_password"] = User.objects.make_random_password()
2019-01-06 16:22:33 +01:00
validated_data["password"] = make_password(validated_data["default_password"])
2017-04-19 09:28:21 +02:00
return validated_data
def create(self, validated_data):
"""
Creates the user.
"""
# Perform creation in the database and return new user.
2017-04-19 09:28:21 +02:00
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.
"""
2019-01-06 16:22:33 +01:00
default_error_messages = {
2019-01-12 23:01:42 +01:00
"incorrect_value": 'Incorrect value "{value}". Expected app_label.codename string.',
"does_not_exist": 'Invalid permission "{value}". Object does not exist.',
2019-01-06 16:22:33 +01:00
}
def to_representation(self, value):
"""
Returns the permission code string (app_label.codename).
"""
2019-01-06 16:22:33 +01:00
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:
2019-01-06 16:22:33 +01:00
app_label, codename = data.split(".")
except ValueError:
2019-01-06 16:22:33 +01:00
self.fail("incorrect_value", value=data)
try:
2019-01-06 16:22:33 +01:00
permission = Permission.objects.get(
content_type__app_label=app_label, codename=codename
)
except Permission.DoesNotExist:
2019-01-06 16:22:33 +01:00
self.fail("does_not_exist", value=data)
return permission
class GroupSerializer(ModelSerializer):
"""
Serializer for django.contrib.auth.models.Group objects.
"""
2019-01-06 16:22:33 +01:00
permissions = PermissionRelatedField(
many=True, queryset=Permission.objects.all(), required=False
)
class Meta:
model = Group
2019-01-06 16:22:33 +01:00
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)
2017-05-23 14:07:06 +02:00
class PersonalNoteSerializer(ModelSerializer):
"""
Serializer for users.models.PersonalNote objects.
"""
2019-01-06 16:22:33 +01:00
2017-05-23 14:07:06 +02:00
notes = JSONField()
class Meta:
model = PersonalNote
2019-01-06 16:22:33 +01:00
fields = ("id", "user", "notes")
read_only_fields = ("user",)