Ejemplo n.º 1
0
 def get_subjects(self, obj):
     from api.taxonomies.serializers import TaxonomyField
     return [
         [
             TaxonomyField().to_representation(subj) for subj in hier
         ] for hier in obj.subject_hierarchy
     ]
Ejemplo n.º 2
0
class TaxonomySerializer(JSONAPISerializer):
    filterable_fields = frozenset([
        'text',
        'parents',
        'parent',
        'id',
    ])
    id = ser.CharField(source='_id', required=True)
    text = ser.CharField(max_length=200)
    parents = ShowIfVersion(
        ser.SerializerMethodField(),
        min_version='2.0',
        max_version='2.3',
    )
    parent = TaxonomyField()
    child_count = ser.SerializerMethodField()
    share_title = ser.CharField(source='provider.share_title', read_only=True)
    path = ser.CharField(read_only=True)

    links = LinksField({
        'parents': 'get_parent_urls',
        'self': 'get_absolute_url',
    })

    def get_child_count(self, obj):
        children_count = getattr(obj, 'children_count', None)
        return children_count if children_count is not None else obj.child_count

    def get_parents(self, obj):
        if not obj.parent:
            return []
        return [TaxonomyField().to_representation(obj.parent)]

    def get_parent_urls(self, obj):
        if obj.parent:
            return [obj.parent.get_absolute_url()]
        return []

    def get_absolute_url(self, obj):
        return obj.get_absolute_url()

    class Meta:
        type_ = 'taxonomies'
Ejemplo n.º 3
0
class PreprintSerializer(JSONAPISerializer):
    filterable_fields = frozenset([
        'id',
        'date_created',
        'date_modified',
        'date_published',
        'provider',
        'is_published',
    ])

    id = IDField(source='_id', read_only=True)
    subjects = JSONAPIListField(child=JSONAPIListField(child=TaxonomyField()),
                                allow_null=True,
                                required=False)
    date_created = DateByVersion(read_only=True)
    date_modified = DateByVersion(read_only=True)
    date_published = DateByVersion(read_only=True)
    doi = ser.CharField(source='article_doi', required=False, allow_null=True)
    is_published = ser.BooleanField(required=False)
    is_preprint_orphan = ser.BooleanField(read_only=True)
    license_record = NodeLicenseSerializer(required=False, source='license')

    node = NodeRelationshipField(related_view='nodes:node-detail',
                                 related_view_kwargs={'node_id': '<node._id>'},
                                 read_only=False)

    license = PreprintLicenseRelationshipField(
        related_view='licenses:license-detail',
        related_view_kwargs={'license_id': '<license.node_license._id>'},
        read_only=False)

    provider = PreprintProviderRelationshipField(
        related_view='preprint_providers:preprint_provider-detail',
        related_view_kwargs={'provider_id': '<provider._id>'},
        read_only=False)

    primary_file = PrimaryFileRelationshipField(
        related_view='files:file-detail',
        related_view_kwargs={'file_id': '<primary_file._id>'},
        lookup_url_kwarg='file_id',
        read_only=False)

    links = LinksField({
        'self': 'get_preprint_url',
        'html': 'get_absolute_html_url',
        'doi': 'get_doi_url'
    })

    class Meta:
        type_ = 'preprints'

    def get_preprint_url(self, obj):
        return absolute_reverse(
            'preprints:preprint-detail',
            kwargs={
                'preprint_id':
                obj._id,
                'version':
                self.context['request'].parser_context['kwargs']['version']
            })

    def get_absolute_url(self, obj):
        return self.get_preprint_url(obj)

    def get_doi_url(self, obj):
        return 'https://dx.doi.org/{}'.format(
            obj.article_doi) if obj.article_doi else None

    def update(self, preprint, validated_data):
        assert isinstance(
            preprint,
            PreprintService), 'You must specify a valid preprint to be updated'
        assert isinstance(
            preprint.node, Node
        ), 'You must specify a preprint with a valid node to be updated.'

        auth = get_user_auth(self.context['request'])
        if not preprint.node.has_permission(auth.user, 'admin'):
            raise exceptions.PermissionDenied(
                detail='User must be an admin to update a preprint.')

        save_node = False
        save_preprint = False
        recently_published = False

        primary_file = validated_data.pop('primary_file', None)
        if primary_file:
            self.set_field(preprint.set_primary_file, primary_file, auth)
            save_node = True

        if 'subjects' in validated_data:
            subjects = validated_data.pop('subjects', None)
            self.set_field(preprint.set_subjects, subjects, auth)
            save_preprint = True

        if 'article_doi' in validated_data:
            preprint.node.preprint_article_doi = validated_data['article_doi']
            save_node = True

        published = validated_data.pop('is_published', None)
        if published is not None:
            self.set_field(preprint.set_published, published, auth)
            save_preprint = True
            recently_published = published

        if 'license_type' in validated_data or 'license' in validated_data:
            license_details = get_license_details(preprint, validated_data)
            self.set_field(preprint.set_preprint_license, license_details,
                           auth)
            save_preprint = True

        if save_node:
            try:
                preprint.node.save()
            except ValidationValueError as e:
                # Raised from invalid DOI
                raise exceptions.ValidationError(detail=e.message)

        if save_preprint:
            preprint.save()

        # Send preprint confirmation email signal to new authors on preprint! -- only when published
        # TODO: Some more thought might be required on this; preprints made from existing
        # nodes will send emails making it seem like a new node.
        if recently_published:
            for author in preprint.node.contributors:
                if author != auth.user:
                    project_signals.contributor_added.send(
                        preprint.node,
                        contributor=author,
                        auth=auth,
                        email_template='preprint')

        return preprint

    def set_field(self, func, val, auth, save=False):
        try:
            func(val, auth, save=save)
        except PermissionsError as e:
            raise exceptions.PermissionDenied(detail=e.message)
        except ValueError as e:
            raise exceptions.ValidationError(detail=e.message)
        except NodeStateError as e:
            raise exceptions.ValidationError(detail=e.message)
Ejemplo n.º 4
0
 def get_subjects(self, obj):
     return [[TaxonomyField().to_representation(subj) for subj in hier]
             for hier in obj.subject_hierarchy]
Ejemplo n.º 5
0
 def get_parents(self, obj):
     if not obj.parent:
         return []
     return [TaxonomyField().to_representation(obj.parent)]
Ejemplo n.º 6
0
class PreprintSerializer(JSONAPISerializer):
    filterable_fields = frozenset([
        'id', 'title', 'tags', 'date_created', 'date_modified', 'contributors',
        'subjects', 'doi'
    ])

    title = ser.CharField(required=False)
    subjects = JSONAPIListField(child=TaxonomyField(),
                                required=False,
                                source='preprint_subjects')
    provider = ser.CharField(source='preprint_provider', required=False)
    date_created = ser.DateTimeField(read_only=True, source='preprint_created')
    date_modified = ser.DateTimeField(read_only=True)
    id = IDField(source='_id', required=False)
    abstract = ser.CharField(source='description', required=False)
    tags = JSONAPIListField(child=NodeTagField(), required=False)
    doi = ser.CharField(source='preprint_doi', required=False)

    primary_file = PrimaryFileRelationshipField(
        related_view='files:file-detail',
        related_view_kwargs={'file_id': '<preprint_file._id>'},
        lookup_url_kwarg='file_id',
        read_only=False)

    files = RelationshipField(related_view='nodes:node-providers',
                              related_view_kwargs={'node_id': '<pk>'})

    providers = RelationshipField(
        related_view='preprints:preprint-preprint_providers',
        related_view_kwargs={'node_id': '<pk>'},
        self_view='preprints:preprint-relationships-preprint_providers',
        self_view_kwargs={'node_id': '<pk>'})

    links = LinksField({
        'self': 'get_preprint_url',
        'html': 'get_absolute_html_url',
        'doi': 'get_doi_url'
    })

    contributors = RelationshipField(
        related_view='nodes:node-contributors',
        related_view_kwargs={'node_id': '<pk>'},
        related_meta={'count': 'get_contrib_count'},
    )

    class Meta:
        type_ = 'preprints'

    def get_preprint_url(self, obj):
        return absolute_reverse('preprints:preprint-detail',
                                kwargs={'node_id': obj._id})

    def get_absolute_url(self, obj):
        return self.get_preprint_url(obj)

    def get_doi_url(self, obj):
        return 'https://dx.doi.org/{}'.format(
            obj.preprint_doi) if obj.preprint_doi else None

    def create(self, validated_data):
        node = Node.load(validated_data.pop('_id', None))
        if not node:
            raise exceptions.NotFound('Unable to find Node with specified id.')

        auth = get_user_auth(self.context['request'])
        if not node.has_permission(auth.user, permissions.ADMIN):
            raise exceptions.PermissionDenied

        if node.is_preprint:
            raise Conflict(
                'This node already stored as a preprint, use the update method instead.'
            )

        primary_file = validated_data.pop('primary_file', None)
        if not primary_file:
            raise exceptions.ValidationError(
                detail='You must specify a primary_file to create a preprint.')

        self.set_node_field(node.set_preprint_file, primary_file, auth)

        subjects = validated_data.pop('preprint_subjects', None)
        if not subjects:
            raise exceptions.ValidationError(
                detail=
                'You must specify at least one subject to create a preprint.')

        self.set_node_field(node.set_preprint_subjects, subjects, auth)

        tags = validated_data.pop('tags', None)
        if tags:
            for tag in tags:
                node.add_tag(tag, auth, save=False, log=False)

        for key, value in validated_data.iteritems():
            setattr(node, key, value)
        try:
            node.save()
        except ValidationValueError as e:
            raise exceptions.ValidationError(detail=e.message)

        # Send preprint confirmation email signal to new authors on preprint!
        for author in node.contributors:
            if author != auth.user:
                project_signals.contributor_added.send(
                    node,
                    contributor=author,
                    auth=auth,
                    email_template='preprint')

        return node

    def update(self, node, validated_data):
        from website.models import Node
        assert isinstance(node,
                          Node), 'You must specify a valid node to be updated.'
        auth = get_user_auth(self.context['request'])
        primary_file = validated_data.pop('primary_file', None)
        if primary_file:
            self.set_node_field(node.set_preprint_file, primary_file, auth)
        subjects = validated_data.pop('preprint_subjects', None)
        if subjects:
            self.set_node_field(node.set_preprint_subjects, subjects, auth)

        old_tags = set([tag._id for tag in node.tags])
        if 'tags' in validated_data:
            current_tags = set(validated_data.pop('tags', []))
        elif self.partial:
            current_tags = set(old_tags)
        else:
            current_tags = set()

        for new_tag in (current_tags - old_tags):
            node.add_tag(new_tag, auth=auth)
        for deleted_tag in (old_tags - current_tags):
            node.remove_tag(deleted_tag, auth=auth)

        for key, value in validated_data.iteritems():
            setattr(node, key, value)
        try:
            node.save()
        except ValidationValueError as e:
            raise exceptions.ValidationError(detail=e.message)
        return node

    def set_node_field(self, func, val, auth):
        try:
            func(val, auth, save=False)
        except PermissionsError:
            raise exceptions.PermissionDenied(
                'Not authorized to update this node.')
        except ValueError as e:
            raise exceptions.ValidationError(detail=e.message)