Exemplo n.º 1
0
class NodeContributorsSerializer(JSONAPISerializer):
    """ Separate from UserSerializer due to necessity to override almost every field as read only
    """
    non_anonymized_fields = ['bibliographic', 'permission']
    filterable_fields = frozenset(
        ['id', 'bibliographic', 'permission', 'index'])

    id = IDField(source='_id', read_only=True)
    type = TypeField()
    index = ser.IntegerField(required=False, read_only=True, source='_order')

    bibliographic = ser.BooleanField(
        help_text=
        'Whether the user will be included in citations for this node or not.',
        default=True)
    permission = ser.ChoiceField(
        choices=osf_permissions.PERMISSIONS,
        required=False,
        allow_null=True,
        default=osf_permissions.reduce_permissions(
            osf_permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS),
        help_text=
        'User permission level. Must be "read", "write", or "admin". Defaults to "write".'
    )
    unregistered_contributor = ser.SerializerMethodField()

    links = LinksField({'self': 'get_absolute_url'})

    users = RelationshipField(related_view='users:user-detail',
                              related_view_kwargs={'user_id': '<user._id>'},
                              always_embed=True)

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

    class Meta:
        type_ = 'contributors'

    def get_absolute_url(self, obj):
        return absolute_reverse(
            'nodes:node-contributor-detail',
            kwargs={
                'user_id':
                obj.user._id,
                'node_id':
                self.context['request'].parser_context['kwargs']['node_id'],
                'version':
                self.context['request'].parser_context['kwargs']['version']
            })

    def get_unregistered_contributor(self, obj):
        unclaimed_records = obj.user.unclaimed_records.get(obj.node._id, None)
        if unclaimed_records:
            return unclaimed_records.get('name', None)
Exemplo n.º 2
0
class PreprintContributorsCreateSerializer(NodeContributorsCreateSerializer,
                                           PreprintContributorsSerializer):
    """
    Overrides PreprintContributorsSerializer to add email, full_name, send_email, and non-required index and users field.

    id and index redefined because of the two serializers we've inherited
    """
    id = IDField(source='_id', required=False, allow_null=True)
    index = ser.IntegerField(required=False, source='_order')

    email_preferences = ['preprint', 'false']
Exemplo n.º 3
0
class RegistrationDetailSerializer(RegistrationSerializer):
    """
    Overrides RegistrationSerializer make _id required and other fields writeable
    """

    id = IDField(source='_id', required=True)

    pending_withdrawal = HideIfWithdrawal(ser.BooleanField(
        source='is_pending_retraction', required=False,
        help_text='The registration is awaiting withdrawal approval by project admins.',
    ))
    withdrawal_justification = ser.CharField(required=False)
Exemplo n.º 4
0
class WaterbutlerMetadataSerializer(ser.Serializer):
    source = ser.CharField(write_only=True)
    destination = DestinationSerializer(write_only=True)

    id = IDField(source='_id', read_only=True)
    kind = ser.CharField(read_only=True)
    name = ser.CharField(read_only=True, help_text='Display name used in the general user interface')
    created = ser.CharField(read_only=True)
    modified = ser.CharField(read_only=True)
    path = ser.CharField(read_only=True)
    checkout = ser.SerializerMethodField(read_only=True)
    version = ser.IntegerField(help_text='Latest file version', read_only=True, source='current_version_number')
    downloads = ser.SerializerMethodField()

    sha256 = ser.SerializerMethodField()
    md5 = ser.SerializerMethodField()
    size = ser.SerializerMethodField()

    def get_checkout(self, obj):
        return obj.checkout._id if obj.checkout else None

    def get_downloads(self, obj):
        return obj.get_download_count()

    def get_sha256(self, obj):
        return obj.versions.first().metadata.get('sha256', None) if obj.versions.exists() else None

    def get_md5(self, obj):
        return obj.versions.first().metadata.get('md5', None) if obj.versions.exists() else None

    def get_size(self, obj):
        if obj.versions.exists():
            self.size = obj.versions.first().size
            return self.size
        return None

    def create(self, validated_data):
        source = validated_data.pop('source')
        destination = validated_data.pop('destination')
        name = validated_data.pop('name')

        try:
            return self.context['view'].perform_file_action(source, destination, name)
        except IntegrityError:
            raise exceptions.ValidationError('File already exists with this name.')
        except file_exceptions.FileNodeCheckedOutError:
            raise exceptions.ValidationError('Cannot move file as it is checked out.')
        except file_exceptions.FileNodeIsPrimaryFile:
            raise exceptions.ValidationError('Cannot move file as it is the primary file of preprint.')

    class Meta:
        type_ = 'file_metadata'
Exemplo n.º 5
0
class NodeViewOnlyLinkSerializer(JSONAPISerializer):
    filterable_fields = frozenset(['anonymous', 'name', 'date_created'])

    key = ser.CharField(read_only=True)
    id = IDField(source='_id', read_only=True)
    date_created = DateByVersion(source='created', read_only=True)
    anonymous = ser.BooleanField(required=False, default=False)
    name = ser.CharField(required=False, default='Shared project link')

    links = LinksField({'self': 'get_absolute_url'})

    creator = RelationshipField(
        related_view='users:user-detail',
        related_view_kwargs={'user_id': '<creator._id>'},
    )

    nodes = RelationshipField(
        related_view='view-only-links:view-only-link-nodes',
        related_view_kwargs={'link_id': '<_id>'},
        self_view='view-only-links:view-only-link-nodes-relationships',
        self_view_kwargs={'link_id': '<_id>'})

    def create(self, validated_data):
        name = validated_data.pop('name')
        user = get_user_auth(self.context['request']).user
        anonymous = validated_data.pop('anonymous')
        node = self.context['view'].get_node()

        try:
            view_only_link = new_private_link(name=name,
                                              user=user,
                                              nodes=[node],
                                              anonymous=anonymous)
        except ValidationError:
            raise exceptions.ValidationError('Invalid link name.')

        return view_only_link

    def get_absolute_url(self, obj):
        return absolute_reverse(
            'nodes:node-view-only-link-detail',
            kwargs={
                'link_id':
                obj._id,
                'node_id':
                self.context['request'].parser_context['kwargs']['node_id'],
                'version':
                self.context['request'].parser_context['kwargs']['version']
            })

    class Meta:
        type_ = 'view_only_links'
Exemplo n.º 6
0
class UserSerializer(JSONAPISerializer):
    filterable_fields = frozenset([
        'full_name',
        'given_name',
        'middle_names',
        'family_name',
        'id'
    ])
    id = IDField(source='_id', read_only=True)
    type = TypeField()
    full_name = ser.CharField(source='fullname', required=True, label='Full name', help_text='Display name used in the general user interface')
    given_name = ser.CharField(required=False, allow_blank=True, help_text='For bibliographic citations')
    middle_names = ser.CharField(required=False, allow_blank=True, help_text='For bibliographic citations')
    family_name = ser.CharField(required=False, allow_blank=True, help_text='For bibliographic citations')
    suffix = ser.CharField(required=False, allow_blank=True, help_text='For bibliographic citations')
    date_registered = ser.DateTimeField(read_only=True)

    # Social Fields are broken out to get around DRF complex object bug and to make API updating more user friendly.
    gitHub = DevOnly(ser.CharField(required=False, label='GitHub', source='social.github', allow_blank=True, help_text='GitHub Handle'))
    scholar = DevOnly(ser.CharField(required=False, source='social.scholar', allow_blank=True, help_text='Google Scholar Account'))
    personal_website = DevOnly(ser.URLField(required=False, source='social.personal', allow_blank=True, help_text='Personal Website'))
    twitter = DevOnly(ser.CharField(required=False, source='social.twitter', allow_blank=True, help_text='Twitter Handle'))
    linkedIn = DevOnly(ser.CharField(required=False, source='social.linkedIn', allow_blank=True, help_text='LinkedIn Account'))
    impactStory = DevOnly(ser.CharField(required=False, source='social.impactStory', allow_blank=True, help_text='ImpactStory Account'))
    orcid = DevOnly(ser.CharField(required=False, label='ORCID', source='social.orcid', allow_blank=True, help_text='ORCID'))
    researcherId = DevOnly(ser.CharField(required=False, label='ResearcherID', source='social.researcherId', allow_blank=True, help_text='ResearcherId Account'))
    profile_image_url = DevOnly(ser.SerializerMethodField(required=False, read_only=True))

    def get_profile_image_url(self, user):
        size = self.context['request'].query_params.get('profile_image_size')
        return user.profile_image_url(size=size)

    links = LinksField({'html': 'absolute_url'})
    nodes = JSONAPIHyperlinkedIdentityField(view_name='users:user-nodes', lookup_field='pk', lookup_url_kwarg='user_id',
                                             link_type='related')

    class Meta:
        type_ = 'users'

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

    def update(self, instance, validated_data):
        assert isinstance(instance, User), 'instance must be a User'
        for attr, value in validated_data.items():
            if 'social' == attr:
                for key, val in value.items():
                    instance.social[key] = val
            else:
                setattr(instance, attr, value)
        instance.save()
        return instance
Exemplo n.º 7
0
class NodeAlternativeCitationSerializer(JSONAPISerializer):

    id = IDField(source='_id', read_only=True)
    type = TypeField()
    name = ser.CharField(required=True)
    text = ser.CharField(required=True)

    class Meta:
        type_ = 'citations'

    def create(self, validated_data):
        errors = self.error_checker(validated_data)
        if len(errors) > 0:
            raise exceptions.ValidationError(detail=errors)
        node = self.context['view'].get_node()
        auth = Auth(self.context['request']._user)
        citation = node.add_citation(auth, save=True, **validated_data)
        return citation

    def update(self, instance, validated_data):
        errors = self.error_checker(validated_data)
        if len(errors) > 0:
            raise exceptions.ValidationError(detail=errors)
        node = self.context['view'].get_node()
        auth = Auth(self.context['request']._user)
        instance = node.edit_citation(auth,
                                      instance,
                                      save=True,
                                      **validated_data)
        return instance

    def error_checker(self, data):
        errors = []
        name = data.get('name', None)
        text = data.get('text', None)
        citations = self.context['view'].get_node().alternative_citations
        if not (self.instance and self.instance.name
                == name) and citations.find(Q('name', 'eq', name)).count() > 0:
            errors.append(
                "There is already a citation named '{}'".format(name))
        if not (self.instance and self.instance.text == text):
            matching_citations = citations.find(Q('text', 'eq', text))
            if matching_citations.count() > 0:
                names = "', '".join(
                    [str(citation.name) for citation in matching_citations])
                errors.append("Citation matches '{}'".format(names))
        return errors

    def get_absolute_url(self, obj):
        #  Citations don't have urls
        raise NotImplementedError
Exemplo n.º 8
0
class NodeLinksSerializer(JSONAPISerializer):

    id = IDField(source='_id', read_only=True)
    type = TypeField()
    target_node_id = ser.CharField(
        write_only=True,
        source='node._id',
        help_text='The ID of the node that this Node Link points to')

    # TODO: We don't show the title because the current user may not have access to this node. We may want to conditionally
    # include this field in the future.
    # title = ser.CharField(read_only=True, source='node.title', help_text='The title of the node that this Node Link '
    #                                                                      'points to')

    target_node = JSONAPIHyperlinkedIdentityField(
        view_name='nodes:node-detail',
        lookup_field='pk',
        link_type='related',
        lookup_url_kwarg='node_id')

    class Meta:
        type_ = 'node_links'

    links = LinksField({'self': 'get_absolute_url'})

    def get_absolute_url(self, obj):
        node_id = self.context['request'].parser_context['kwargs']['node_id']
        return absolute_reverse('nodes:node-pointer-detail',
                                kwargs={
                                    'node_id': node_id,
                                    'node_link_id': obj._id
                                })

    def create(self, validated_data):
        request = self.context['request']
        user = request.user
        auth = Auth(user)
        node = self.context['view'].get_node()
        pointer_node = Node.load(validated_data['node']['_id'])
        if not pointer_node:
            raise exceptions.NotFound('Node not found.')
        try:
            pointer = node.add_pointer(pointer_node, auth, save=True)
            return pointer
        except ValueError:
            raise exceptions.ValidationError(
                'Node link to node {} already in list'.format(
                    pointer_node._id))

    def update(self, instance, validated_data):
        pass
Exemplo n.º 9
0
class NodeLinksSerializer(JSONAPISerializer):

    id = IDField(source='_id')
    type = TypeField()
    target_type = TargetTypeField(target_type='nodes')

    # TODO: We don't show the title because the current user may not have access to this node. We may want to conditionally
    # include this field in the future.
    # title = ser.CharField(read_only=True, source='node.title', help_text='The title of the node that this Node Link '
    #                                                                      'points to')

    target_node = RelationshipField(related_view='nodes:node-detail',
                                    related_view_kwargs={'node_id': '<pk>'},
                                    always_embed=True)

    class Meta:
        type_ = 'node_links'

    links = LinksField({'self': 'get_absolute_url'})

    def get_absolute_url(self, obj):
        node_id = self.context['request'].parser_context['kwargs']['node_id']
        return absolute_reverse('nodes:node-pointer-detail',
                                kwargs={
                                    'node_id': node_id,
                                    'node_link_id': obj._id
                                })

    def create(self, validated_data):
        request = self.context['request']
        user = request.user
        auth = Auth(user)
        node = self.context['view'].get_node()
        target_node_id = validated_data['_id']
        pointer_node = Node.load(target_node_id)
        if not pointer_node or pointer_node.is_collection:
            raise InvalidModelValueError(
                source={'pointer': '/data/relationships/node_links/data/id'},
                detail='Target Node \'{}\' not found.'.format(target_node_id))
        try:
            pointer = node.add_pointer(pointer_node, auth, save=True)
            return pointer
        except ValueError:
            raise InvalidModelValueError(
                source={'pointer': '/data/relationships/node_links/data/id'},
                detail='Target Node \'{}\' already pointed to by \'{}\'.'.
                format(target_node_id, node._id))

    def update(self, instance, validated_data):
        pass
Exemplo n.º 10
0
class PreprintContributorsCreateSerializer(NodeContributorsCreateSerializer,
                                           PreprintContributorsSerializer):
    """
    Overrides PreprintContributorsSerializer to add email, full_name, send_email, and non-required index and users field.

    id and index redefined because of the two serializers we've inherited
    """
    id = IDField(source='_id', required=False, allow_null=True)
    index = ser.IntegerField(required=False, source='_order')

    email_preferences = ['preprint', 'false']

    def get_proposed_permissions(self, validated_data):
        return validated_data.get('permission') or osf_permissions.WRITE
class ApiOAuthApplicationBaseSerializer(JSONAPISerializer):
    """Base serializer class for OAuth2 applications """
    id = IDField(
        source='client_id',
        read_only=True,
        help_text='The client ID for this application (automatically generated)'
    )

    type = TypeField()

    client_id = ser.CharField(
        help_text=
        'The client ID for this application (automatically generated)',
        read_only=True,
    )

    client_secret = ser.CharField(
        help_text=
        'The client secret for this application (automatically generated)',
        read_only=True,
    )  # TODO: May change this later

    links = LinksField({
        'html': 'absolute_url',
        'reset': 'reset_url',
    })

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

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

    def reset_url(self, obj):
        if StrictVersion(
                self.context['request'].version) < StrictVersion('2.15'):
            return absolute_reverse(
                'applications:application-reset',
                kwargs={
                    'client_id':
                    obj.client_id,
                    'version':
                    self.context['request'].parser_context['kwargs']
                    ['version'],
                },
            )

    class Meta:
        type_ = 'applications'
Exemplo n.º 12
0
class GuidSerializer(JSONAPISerializer):

    class Meta:
        type_ = 'guids'

    filterable_fields = tuple()

    id = IDField(source='_id', read_only=True)
    type = TypeField()

    referent = RelationshipField(
        related_view=get_related_view,
        related_view_kwargs=get_related_view_kwargs,
        related_meta={
            'type': 'get_type',
        },
    )
    links = LinksField({
        'self': 'get_absolute_url',
        'html': 'get_absolute_html_url',
    })

    def get_type(self, guid):
        return get_type(guid.referent)

    def get_absolute_url(self, obj):
        return absolute_reverse(
            'guids:guid-detail', kwargs={
                'guids': obj._id,
                'version': self.context['request'].parser_context['kwargs']['version'],
            },
        )

    def get_absolute_html_url(self, obj):
        if not isinstance(obj.referent, BaseFileNode):
            return obj.referent.absolute_url
        return urlparse.urljoin(website_settings.DOMAIN, '/{}/'.format(obj._id))

    def to_representation(self, obj):
        if self.context['view'].kwargs.get('is_embedded'):
            # Force the referent to serialize instead.
            obj = obj.referent
            ser = resolve(reverse(
                get_related_view(obj),
                kwargs={'node_id': obj._id, 'version': self.context['view'].kwargs.get('version', '2')},
            )).func.cls.serializer_class(context=self.context)
            [ser.context.update({k: v}) for k, v in self.context.items()]
            return ser.to_representation(obj)
        return super(GuidSerializer, self).to_representation(obj)
Exemplo n.º 13
0
class CommentReportSerializer(JSONAPISerializer):
    id = IDField(source='_id', read_only=True)
    type = TypeField()
    category = ser.ChoiceField(choices=[('spam', 'Spam or advertising'),
                                        ('hate', 'Hate speech'),
                                        ('violence',
                                         'Violence or harmful behavior')],
                               required=True)
    message = ser.CharField(source='text', required=False, allow_blank=True)
    links = LinksField({'self': 'get_absolute_url'})

    class Meta:
        type_ = 'comment_reports'

    def get_absolute_url(self, obj):
        return absolute_reverse(
            'comments:report-detail',
            kwargs={
                'user_id':
                obj._id,
                'comment_id':
                self.context['request'].parser_context['kwargs']['comment_id'],
                'version':
                self.context['request'].parser_context['kwargs']['version']
            })

    def create(self, validated_data):
        user = self.context['request'].user
        comment = self.context['view'].get_comment()
        if user._id in comment.reports and not comment.reports[user._id].get(
                'retracted', True):
            raise ValidationError('Comment already reported.')
        try:
            comment.report_abuse(user, save=True, **validated_data)
        except ValueError:
            raise ValidationError('You cannot report your own comment.')
        return CommentReport(user._id, **validated_data)

    def update(self, comment_report, validated_data):
        user = self.context['request'].user
        comment = self.context['view'].get_comment()
        if user._id != comment_report._id:
            raise ValidationError(
                'You cannot report a comment on behalf of another user.')
        try:
            comment.report_abuse(user, save=True, **validated_data)
        except ValueError:
            raise ValidationError('You cannot report your own comment.')
        return CommentReport(user._id, **validated_data)
Exemplo n.º 14
0
class NodeCitationSerializer(JSONAPISerializer):
    id = IDField(read_only=True)
    title = ser.CharField(allow_blank=True, read_only=True)
    author = ser.ListField(read_only=True)
    publisher = ser.CharField(allow_blank=True, read_only=True)
    type = ser.CharField(allow_blank=True, read_only=True)
    doi = ser.CharField(allow_blank=True, read_only=True)

    links = LinksField({'self': 'get_absolute_url'})

    def get_absolute_url(self, obj):
        return obj['URL']

    class Meta:
        type_ = 'node-citation'
Exemplo n.º 15
0
class UserEmailsSerializer(JSONAPISerializer):
    id = IDField(read_only=True)
    type = TypeField()
    email_address = ser.CharField(source='address')
    confirmed = ser.BooleanField(read_only=True)
    primary = ser.BooleanField(required=False)
    links = LinksField({
        'self': 'get_absolute_url',
    })

    def get_absolute_url(self, obj):
        user = self.context['request'].user
        return absolute_reverse(
            'users:user-email-detail',
            kwargs={
                'user_id': user._id,
                'email_id': obj.id,
                'version': self.context['request'].parser_context['kwargs']['version'],
            },
        )

    class Meta:
        type_ = 'user_emails'

    def create(self, validated_data):
        user = self.context['request'].user
        address = validated_data['address']
        if address in user.unconfirmed_emails or address in user.emails.all().values_list('address', flat=True):
            raise Conflict('This user already has registered with the email address {}'.format(address))
        try:
            token = user.add_unconfirmed_email(address)
            user.save()
            if CONFIRM_REGISTRATIONS_BY_EMAIL:
                send_confirm_email(user, email=address)
        except ValidationError as e:
            raise exceptions.ValidationError(e.args[0])

        return UserEmail(email_id=token, address=address, confirmed=False, primary=False)

    def update(self, instance, validated_data):
        user = self.context['request'].user
        primary = validated_data.get('primary', None)
        if primary and instance.confirmed:
            user.username = instance.address
            user.save()
        elif primary and not instance.confirmed:
            raise exceptions.ValidationError('You cannot set an unconfirmed email address as your primary email address.')
        return instance
class PreprintCreateSerializer(PreprintSerializer):
    # Overrides PreprintSerializer to make id nullable, adds `create`
    id = IDField(source='_id', required=False, allow_null=True)

    def create(self, validated_data):
        creator = self.context['request'].user
        provider = validated_data.pop('provider', None)
        if not provider:
            raise exceptions.ValidationError(detail='You must specify a valid provider to create a preprint.')

        title = validated_data.pop('title')
        description = validated_data.pop('description', '')
        preprint = Preprint(provider=provider, title=title, creator=creator, description=description)
        preprint.save()

        return self.update(preprint, validated_data)
Exemplo n.º 17
0
class MetaSchemaSerializer(JSONAPISerializer):

    id = IDField(source='_id', read_only=True)
    type = TypeField()

    name = ser.CharField(read_only=True)
    schema_version = ser.IntegerField(read_only=True)
    schema = ser.DictField(read_only=True)

    links = LinksField({'self': 'get_absolute_url'})

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

    class Meta:
        type_ = 'metaschemas'
Exemplo n.º 18
0
class LicenseSerializer(JSONAPISerializer):
    filterable_fields = frozenset([
        'name',
        'id',
    ])
    non_anonymized_fields = ['type']
    id = IDField(source='_id', read_only=True)
    type = TypeField()
    name = ser.CharField(required=True, help_text='License name')
    text = ser.CharField(required=True, help_text='Full text of the license')
    links = LinksField({'self': 'get_absolute_url'})

    class Meta:
        type_ = 'licenses'

    def get_absolute_url(self, obj):
        return absolute_reverse('licenses:license-detail', kwargs={'license_id': obj._id})
Exemplo n.º 19
0
class PreprintCreateSerializer(PreprintSerializer):
    # Overrides PreprintSerializer to make id nullable, adds `create`
    id = IDField(source='_id', required=False, allow_null=True)

    def create(self, validated_data):
        node = Node.load(validated_data.pop('node', None))
        if not node:
            raise exceptions.NotFound('Unable to find Node with specified id.')
        elif node.is_deleted:
            raise exceptions.ValidationError(
                'Cannot create a preprint from a deleted node.')

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

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

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

        if PreprintService.find(
                Q('node', 'eq', node) & Q('provider', 'eq', provider)).count():
            conflict = PreprintService.find_one(
                Q('node', 'eq', node) & Q('provider', 'eq', provider))
            raise Conflict(
                'Only one preprint per provider can be submitted for a node. Check `meta[existing_resource_id]`.',
                meta={'existing_resource_id': conflict._id})

        preprint = PreprintService(node=node, provider=provider)
        self.set_field(preprint.set_primary_file,
                       primary_file,
                       auth,
                       save=True)
        preprint.node._has_abandoned_preprint = True
        preprint.node.save()

        return self.update(preprint, validated_data)
Exemplo n.º 20
0
class RegistrationIdentifierSerializer(JSONAPISerializer):

    category = ser.SerializerMethodField()

    filterable_fields = frozenset(['category'])

    value = ser.CharField(read_only=True)

    referent = RelationshipField(
        related_view='registrations:registration-detail',
        related_view_kwargs={'node_id': '<referent._id>'},
    )

    id = IDField(source='_id', read_only=True)

    links = LinksField({'self': 'self_url'})

    class Meta:
        type_ = 'identifiers'

    def get_category(self, obj):
        if obj.category == 'legacy_doi':
            return 'doi'
        return obj.category

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

    def get_id(self, obj):
        return obj._id

    def get_detail_url(self, obj):
        return '{}/identifiers/{}'.format(obj.absolute_api_v2_url, obj._id)

    def self_url(self, obj):
        return absolute_reverse(
            'identifiers:identifier-detail',
            kwargs={
                'identifier_id':
                obj._id,
                'version':
                self.context['request'].parser_context['kwargs']['version'],
            },
        )
Exemplo n.º 21
0
class NodeContributorsSerializer(JSONAPISerializer):
    """ Separate from UserSerializer due to necessity to override almost every field as read only
    """
    filterable_fields = frozenset([
        'id',
        'bibliographic',
        'permission'
    ])

    id = IDField(source='_id', required=True)
    type = TypeField()

    bibliographic = ser.BooleanField(help_text='Whether the user will be included in citations for this node or not.',
                                     default=True)
    permission = ser.ChoiceField(choices=osf_permissions.PERMISSIONS, required=False, allow_null=True,
                                 default=osf_permissions.reduce_permissions(osf_permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS),
                                 help_text='User permission level. Must be "read", "write", or "admin". Defaults to "write".')

    links = LinksField({
        'self': 'get_absolute_url'
    })

    users = RelationshipField(
        related_view='users:user-detail',
        related_view_kwargs={'user_id': '<pk>'},
        always_embed=True
    )

    class Meta:
        type_ = 'contributors'

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

    def get_absolute_url(self, obj):
        node_id = self.context['request'].parser_context['kwargs']['node_id']
        return absolute_reverse(
            'nodes:node-contributor-detail',
            kwargs={
                'node_id': node_id,
                'user_id': obj._id
            }
        )
class GroupSerializer(JSONAPISerializer):
    filterable_fields = frozenset([
        'name',
    ])

    non_anonymized_fields = [
        'type',
    ]

    id = IDField(source='_id', read_only=True)
    type = TypeField()
    name = ser.CharField(required=True)
    date_created = VersionedDateTimeField(source='created', read_only=True)
    date_modified = VersionedDateTimeField(source='modified', read_only=True)

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

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

    members = RelationshipField(
        related_view='groups:group-members',
        related_view_kwargs={'group_id': '<_id>'},
    )

    class Meta:
        type_ = 'groups'

    def create(self, validated_data):
        group = OSFGroup(creator=validated_data['creator'],
                         name=validated_data['name'])
        group.save()
        return group

    def update(self, instance, validated_data):
        if 'name' in validated_data:
            instance.set_group_name(validated_data.get('name'))
            instance.save()
        return instance
Exemplo n.º 23
0
class ApiOAuth2ApplicationSerializer(ApiOAuthApplicationBaseSerializer):
    """Serialize data about a registered OAuth2 application"""

    id = IDField(source='client_id', read_only=True, help_text='The client ID for this application (automatically generated)')

    type = TypeField()

    name = ser.CharField(help_text='A short, descriptive name for this application',
                         required=True)

    description = ser.CharField(help_text='An optional description displayed to all users of this application',
                                required=False,
                                allow_blank=True)
    home_url = ser.CharField(help_text="The full URL to this application's homepage.",
                             required=True,
                             validators=[URLValidator()],
                             label="Home URL")

    callback_url = ser.CharField(help_text='The callback URL for this application (refer to OAuth documentation)',
                                 required=True,
                                 validators=[URLValidator()],
                                 label="Callback URL")

    owner = ser.CharField(help_text='The id of the user who owns this application',
                          read_only=True,  # Don't let user register an application in someone else's name
                          source='owner._id')

    date_created = ser.DateTimeField(help_text='The date this application was generated (automatically filled in)',
                                     read_only=True)

    def create(self, validated_data):
        instance = ApiOAuth2Application(**validated_data)
        instance.save()
        return instance

    def update(self, instance, validated_data):
        assert isinstance(instance, ApiOAuth2Application), 'instance must be an ApiOAuth2Application'
        for attr, value in validated_data.iteritems():
            setattr(instance, attr, value)
        instance.save()
        return instance
class InstitutionUserMetricsSerializer(JSONAPISerializer):
    class Meta:
        type_ = 'institution-users'

    id = IDField(source='user_id', read_only=True)
    user_name = ser.CharField(read_only=True)
    public_projects = ser.IntegerField(source='public_project_count',
                                       read_only=True)
    private_projects = ser.IntegerField(source='private_project_count',
                                        read_only=True)
    department = ser.CharField(read_only=True)

    user = RelationshipField(
        related_view='users:user-detail',
        related_view_kwargs={'user_id': '<user_id>'},
    )

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

    filterable_fields = frozenset([
        'id',
        'user_name',
        'public_projects',
        'private_projects',
        'department',
    ])

    def get_absolute_url(self, obj):
        return absolute_reverse(
            'institutions:institution-user-metrics',
            kwargs={
                'institution_id':
                self.context['request'].parser_context['kwargs']
                ['institution_id'],
                'version':
                'v2',
            },
        )
Exemplo n.º 25
0
class UserIdentitiesSerializer(JSONAPISerializer):
    id = IDField(source='_id', read_only=True)
    type = TypeField()
    external_id = ser.CharField(read_only=True)
    status = ser.CharField(read_only=True)

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

    def get_absolute_url(self, obj):
        return absolute_reverse(
            'users:user-identities-detail',
            kwargs={
                'user_id': self.context['request'].parser_context['kwargs']['user_id'],
                'version': self.context['request'].parser_context['kwargs']['version'],
                'identity_id': obj['_id'],
            },
        )

    class Meta:
        type_ = 'external-identities'
Exemplo n.º 26
0
class LicenseSerializer(JSONAPISerializer):
    filterable_fields = frozenset([
        'name',
        'id',
    ])
    non_anonymized_fields = ['type']
    id = IDField(source='_id', read_only=True)
    type = TypeField()
    name = ser.CharField(required=True, help_text='License name')
    text = ser.CharField(required=True, help_text='Full text of the license')
    url = ser.URLField(required=False, help_text='URL for the license')
    required_fields = ser.ListField(source='properties', read_only=True,
                                    help_text='Fields required for this license (provided to help front-end validators)')
    links = LinksField({'self': 'get_absolute_url'})

    class Meta:
        type_ = 'licenses'

    def get_absolute_url(self, obj):
        return absolute_reverse('licenses:license-detail', kwargs={
            'license_id': obj._id,
            'version': self.context['request'].parser_context['kwargs']['version']
        })
Exemplo n.º 27
0
class UserSettingsSerializer(JSONAPISerializer):
    id = IDField(source='_id', read_only=True)
    type = TypeField()
    two_factor_enabled = ser.SerializerMethodField()
    subscribe_osf_general_email = ser.SerializerMethodField()
    subscribe_osf_help_email = ser.SerializerMethodField()

    def get_two_factor_enabled(self, obj):
        try:
            two_factor = TwoFactorUserSettings.objects.get(owner_id=obj.id)
            return not two_factor.deleted
        except TwoFactorUserSettings.DoesNotExist:
            return False

    def get_subscribe_osf_general_email(self, obj):
        return obj.mailchimp_mailing_lists.get(MAILCHIMP_GENERAL_LIST, False)

    def get_subscribe_osf_help_email(self, obj):
        return obj.osf_mailing_lists.get(OSF_HELP_LIST, False)

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

    def get_absolute_url(self, obj):
        return absolute_reverse(
            'users:user_settings',
            kwargs={
                'user_id':
                obj._id,
                'version':
                self.context['request'].parser_context['kwargs']['version'],
            },
        )

    class Meta:
        type_ = 'user_settings'
Exemplo n.º 28
0
class ViewOnlyLinkDetailSerializer(JSONAPISerializer):
    key = ser.CharField(read_only=True)
    id = IDField(source='_id', read_only=True)
    date_created = ser.DateTimeField(read_only=True)
    anonymous = ser.BooleanField(required=False)
    name = ser.CharField(required=False)

    nodes = RelationshipField(
        related_view='view-only-links:view-only-link-nodes',
        related_view_kwargs={'link_id': '<_id>'},
        self_view='view-only-links:view-only-link-nodes-relationships',
        self_view_kwargs={'link_id': '<_id>'})

    creator = RelationshipField(
        related_view='users:user-detail',
        related_view_kwargs={'user_id': '<creator._id>'},
    )

    def get_absolute_url(self, obj):
        return absolute_reverse('nodes:node-view-only-link-detail',
                                kwargs={'link_id': obj._id})

    class Meta:
        type_ = 'view-only-links'
class InstitutionSummaryMetricSerializer(JSONAPISerializer):
    class Meta:
        type_ = 'institution-summary-metrics'

    id = IDField(source='institution_id', read_only=True)
    public_project_count = ser.IntegerField(read_only=True)
    private_project_count = ser.IntegerField(read_only=True)
    user_count = ser.IntegerField(read_only=True)

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

    def get_absolute_url(self, obj):
        return absolute_reverse(
            'institutions:institution-summary-metrics',
            kwargs={
                'institution_id':
                self.context['request'].parser_context['kwargs']
                ['institution_id'],
                'version':
                'v2',
            },
        )
Exemplo n.º 30
0
class PreprintCreateSerializer(PreprintSerializer):
    # Overrides PreprintSerializer to make id nullable, adds `create`
    id = IDField(source='_id', required=False, allow_null=True)

    def create(self, validated_data):
        node = validated_data.pop('node', {})
        if isinstance(node, dict):
            node = Node.objects.create(creator=self.context['request'].user,
                                       **node)

        if node.is_deleted:
            raise exceptions.ValidationError(
                'Cannot create a preprint from a deleted node.')

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

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

        node_preprints = node.preprints.filter(provider=provider)
        if node_preprints.exists():
            raise Conflict(
                'Only one preprint per provider can be submitted for a node. Check `meta[existing_resource_id]`.',
                meta={'existing_resource_id': node_preprints.first()._id})

        preprint = PreprintService(node=node, provider=provider)
        preprint.save()
        preprint.node._has_abandoned_preprint = True
        preprint.node.save()

        return self.update(preprint, validated_data)