server/python/django2/renkanmanager/serializers.py
author durandn
Thu, 21 Apr 2016 15:18:19 +0200
changeset 605 13d355fd09bf
parent 594 b45eb8244cd9
child 608 8fd40139827c
permissions -rw-r--r--
updated uri to allow optional trailing slash on single resource URIs (django automatic redirects don't carry over the Authorization header that can sometimes be needed, for instance with OAuth)

import json
import uuid

from django.contrib.auth import get_user_model
from django.conf import settings
from guardian.shortcuts import assign_perm
from renkanmanager.models import Renkan, Workspace, Revision
from rest_framework import serializers

RENKAN_USER_DISPLAY_FIELD = getattr(settings, "RENKAN_USER_DISPLAY_FIELD", get_user_model().USERNAME_FIELD)

class RenkanSerializer(serializers.Serializer):
    id = serializers.ReadOnlyField(source="renkan_guid")
    current_revision_id = serializers.ReadOnlyField(source="current_revision_guid")
    workspace_id = serializers.CharField(source="workspace_guid", required=False)
    source_revision_id = serializers.CharField(source="source_revision_guid", required=False)
    revision_count = serializers.ReadOnlyField()
    created_by = serializers.SlugRelatedField(source="creator", slug_field=RENKAN_USER_DISPLAY_FIELD, read_only=True)
    last_updated_by = serializers.SerializerMethodField("get_current_revision_last_updator")
    title = serializers.CharField(required=False)
    content = serializers.JSONField(required=False)
    creation_date = serializers.ReadOnlyField()
    modification_date = serializers.SerializerMethodField("get_current_revision_modification_date")
    create_new_revision = serializers.BooleanField(write_only=True, required=False) # only used for updating
    
    # ADD ERROR HANDLING
    def get_current_revision_last_updator(self, renkan):
        current_revision = Revision.objects.get(revision_guid = renkan.current_revision_guid)
        return getattr(current_revision.last_updated_by, RENKAN_USER_DISPLAY_FIELD)
    
    
    def get_current_revision_modification_date(self, renkan):
        current_revision = Revision.objects.get(revision_guid = renkan.current_revision_guid)
        return current_revision.modification_date
    
    def create(self, validated_data):
        """
            Method to create a new Renkan (and its first revision)
        """
        creator = validated_data.get('creator')
        initial_revision = Revision.objects.create(
            title = validated_data.get('title', 'Untitled renkan'),
            creator = creator,
            last_updated_by = creator
        )
        renkan = Renkan.objects.create(
            current_revision_guid = initial_revision.revision_guid,
            workspace_guid = validated_data.get('workspace_guid', ''),
            source_revision_guid = validated_data.get('source_revision_guid', ''),
            creator = creator
        )
        initial_revision.parent_renkan_guid = renkan.renkan_guid
        initial_revision.content = validated_data.get('content', json.dumps(
            {
                "id": str(renkan.renkan_guid),
                "title": initial_revision.title,
                "description": "",
                "created": str(initial_revision.creation_date),
                "updated": str(initial_revision.modification_date),
                "edges": [],
                "nodes": [],
                "users": [],
                "space_id": str(renkan.workspace_guid),
                "views": []
            }
        ))
        initial_revision.save()
        renkan.save()
        assign_perm('view_renkan', creator, renkan)
        assign_perm('change_renkan', creator, renkan)
        assign_perm('delete_renkan', creator, renkan)
        assign_perm('view_revision', creator, initial_revision)
        assign_perm('delete_revision', creator, initial_revision)
        return renkan
    
    def update(self, renkan, validated_data):
        """
            Method to update a Renkan object. Creates a new revision if needed
        """
        updator = validated_data.get('updator')
        current_revision = Revision.objects.get(revision_guid=renkan.current_revision_guid)  
        if validated_data.get("create_new_revision", False):
            revision_to_update = Revision.objects.create()
            revision_to_update.parent_renkan_guid = renkan.renkan_guid
            revision_to_update.creator = updator
            renkan.current_revision_guid = revision_to_update.revision_guid
        else:
            revision_to_update = current_revision
        revision_to_update.title = validated_data.get('title', current_revision.title)
        revision_to_update.content = validated_data.get('content', current_revision.content)
        revision_to_update.last_updated_by = updator
        revision_to_update.save()
        if not updator.has_perm('view_revision', revision_to_update):
            assign_perm('view_revision', updator, revision_to_update)
            assign_perm('delete_revision', updator, revision_to_update)
        renkan.save()
        return renkan
    
    def validate_workspace_id(self, value):
        if self.instance is not None:
            raise serializers.ValidationError("You cannot update workspace_guid")
        return value
    
    def validate_source_revision_id(self, value):
        if self.instance is not None:
            raise serializers.ValidationError("You cannot update source_revision_guid")
        return value
    
    def validate_content(self, value):
        
        try:
            json.loads(value)
        except ValueError:
            raise serializers.ValidationError("Content format is not a JSON-serializable")
        loaded_json = json.loads(value)
            
        if (not "nodes" in loaded_json):
            raise serializers.ValidationError("Content requires a 'nodes' entry")
        if (not "edges" in loaded_json):
            raise serializers.ValidationError("Content requires a 'edges' entry")
        if (not "views" in loaded_json):
            raise serializers.ValidationError("Content requires a 'views' entry")
            
        return value


class RevisionSerializer(serializers.Serializer):
    id = serializers.ReadOnlyField(source="revision_guid")
    parent_renkan_id = serializers.ReadOnlyField(source="parent_renkan_guid")
    workspace_id = serializers.SerializerMethodField("get_related_workspace_guid")
    title = serializers.ReadOnlyField()
    content = serializers.JSONField(read_only=True)
    renkan_created_by = serializers.SerializerMethodField("get_related_renkan_creator")
    renkan_creation_date = serializers.SerializerMethodField("get_related_renkan_creation_date")
    revision_created_by = serializers.SlugRelatedField(source="creator", slug_field=RENKAN_USER_DISPLAY_FIELD, read_only=True)
    revision_last_updated_by = serializers.StringRelatedField(source="last_updated_by")
    revision_modification_date = serializers.ReadOnlyField(source="modification_date")
    
    def get_related_workspace_guid(self, revision):
        parent_renkan = Renkan.objects.get(renkan_guid = revision.parent_renkan_guid)
        return parent_renkan.workspace_guid
    
    def get_related_renkan_creator(self, revision):
        parent_renkan = Renkan.objects.get(renkan_guid = revision.parent_renkan_guid)
        return getattr(parent_renkan.creator, RENKAN_USER_DISPLAY_FIELD)
    
    def get_related_renkan_creation_date(self, revision):
        parent_renkan = Renkan.objects.get(renkan_guid = revision.parent_renkan_guid)
        return parent_renkan.creation_date
    

class WorkspaceSerializer(serializers.Serializer):
    id = serializers.ReadOnlyField(source="workspace_guid")
    workspace_created_by = serializers.SlugRelatedField(source="creator", slug_field=RENKAN_USER_DISPLAY_FIELD, read_only=True)
    creation_date = serializers.ReadOnlyField()
    renkan_count = serializers.ReadOnlyField()
    title = serializers.CharField()
    
    def create(self, validated_data):
        creator = validated_data.get('creator')
        workspace = Workspace.objects.create()
        workspace.title = validated_data.get('title', '')
        workspace.creator = creator
        workspace.save()
        assign_perm('view_workspace', creator, workspace)
        assign_perm('change_workspace', creator, workspace)
        assign_perm('delete_workspace', creator, workspace)
        return workspace
    
    def update(self, workspace, validated_data):
        workspace.title = validated_data.get('title', '')
        workspace.save()
        return workspace