class ReviewActionSerializer(BaseActionSerializer): class Meta: type_ = 'review-actions' filterable_fields = frozenset([ 'id', 'trigger', 'from_state', 'to_state', 'date_created', 'date_modified', 'provider', 'target', ]) comment = HideIfProviderCommentsPrivate( ser.CharField(max_length=65535, required=False)) provider = RelationshipField( read_only=True, related_view='preprint_providers:preprint_provider-detail', related_view_kwargs={'provider_id': '<target.provider._id>'}, filter_key='target__provider___id', ) creator = HideIfProviderCommentsAnonymous( RelationshipField( read_only=True, related_view='users:user-detail', related_view_kwargs={'user_id': '<creator._id>'}, filter_key='creator__guids___id', always_embed=True, )) target = TargetRelationshipField( target_class=PreprintService, read_only=False, required=True, related_view='preprints:preprint-detail', related_view_kwargs={'preprint_id': '<target._id>'}, filter_key='target__guids___id', )
class NodeLogSerializer(JSONAPISerializer): filterable_fields = frozenset(['action', 'date']) non_anonymized_fields = [ 'id', 'date', 'action', ] id = ser.CharField(read_only=True, source='_id') date = ser.DateTimeField(read_only=True) action = ser.CharField(read_only=True) params = NodeLogParamsSerializer(read_only=True) links = LinksField({'self': 'get_absolute_url'}) class Meta: type_ = 'logs' nodes = RelationshipField( related_view='logs:log-nodes', related_view_kwargs={'log_id': '<pk>'}, ) user = RelationshipField( related_view='users:user-detail', related_view_kwargs={'user_id': '<user._id>'}, ) contributors = RelationshipField( related_view='logs:log-contributors', related_view_kwargs={'log_id': '<pk>'}, ) # This would be a node_link, except that data isn't stored in the node log params linked_node = RelationshipField( related_view='nodes:node-detail', related_view_kwargs={'node_id': '<params.pointer.id>'}) template_node = RelationshipField( related_view='nodes:node-detail', related_view_kwargs={'node_id': '<params.template_node.id>'}) def get_absolute_url(self, obj): return obj.absolute_url
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): return absolute_reverse( 'nodes:node-pointer-detail', kwargs={ 'node_link_id': obj._id, 'node_id': self.context['request'].parser_context['kwargs']['node_id'], 'version': self.context['request'].parser_context['kwargs']['version'] }) 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
class NodeContributorsCreateSerializer(NodeContributorsSerializer): """ Overrides NodeContributorsSerializer to add email, full_name, send_email, and non-required index and users field. """ id = IDField(source='_id', required=False, allow_null=True) full_name = ser.CharField(required=False) email = ser.EmailField(required=False, source='user.email') index = ser.IntegerField(required=False, source='_order') users = RelationshipField( related_view='users:user-detail', related_view_kwargs={'user_id': '<user._id>'}, required=False ) email_preferences = ['default', 'preprint', 'false'] def validate_data(self, node, user_id=None, full_name=None, email=None, index=None): if user_id and (full_name or email): raise Conflict(detail='Full name and/or email should not be included with a user ID.') if not user_id and not full_name: raise exceptions.ValidationError(detail='A user ID or full name must be provided to add a contributor.') if index > len(node.contributors): raise exceptions.ValidationError(detail='{} is not a valid contributor index for node with id {}'.format(index, node._id)) def create(self, validated_data): id = validated_data.get('_id') email = validated_data.get('user', {}).get('email', None) index = None if '_order' in validated_data: index = validated_data.pop('_order') node = self.context['view'].get_node() auth = Auth(self.context['request'].user) full_name = validated_data.get('full_name') bibliographic = validated_data.get('bibliographic') send_email = self.context['request'].GET.get('send_email') or 'default' permissions = osf_permissions.expand_permissions(validated_data.get('permission')) or osf_permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS self.validate_data(node, user_id=id, full_name=full_name, email=email, index=index) if send_email not in self.email_preferences: raise exceptions.ValidationError(detail='{} is not a valid email preference.'.format(send_email)) try: contributor_obj = node.add_contributor_registered_or_not( auth=auth, user_id=id, email=email, full_name=full_name, send_email=send_email, permissions=permissions, bibliographic=bibliographic, index=index, save=True ) except ValidationError as e: raise exceptions.ValidationError(detail=e.messages[0]) except ValueError as e: raise exceptions.NotFound(detail=e.args[0]) return contributor_obj
class ReviewActionSerializer(BaseActionSerializer): class Meta: type_ = 'review-actions' filterable_fields = frozenset([ 'id', 'trigger', 'from_state', 'to_state', 'date_created', 'date_modified', 'provider', 'target', ]) provider = RelationshipField( read_only=True, related_view='preprint_providers:preprint_provider-detail', related_view_kwargs={'provider_id': '<target.provider._id>'}, filter_key='target__provider___id', ) creator = HideIfProviderCommentsAnonymous(RelationshipField( read_only=True, related_view='users:user-detail', related_view_kwargs={'user_id': '<creator._id>'}, filter_key='creator__guids___id', always_embed=True, )) target = TargetRelationshipField( target_class=PreprintService, read_only=False, required=True, related_view='preprints:preprint-detail', related_view_kwargs={'preprint_id': '<target._id>'}, filter_key='target__guids___id', ) def get_action_url(self, obj): return utils.absolute_reverse('actions:action-detail', kwargs={'action_id': obj._id, 'version': self.context['request'].parser_context['kwargs']['version']})
class InstitutionSerializer(JSONAPISerializer): filterable_fields = frozenset([ 'id', 'name', 'auth_url', ]) name = ser.CharField(read_only=True) id = ser.CharField(read_only=True, source='_id') logo_path = ser.CharField(read_only=True) description = ser.CharField(read_only=True) auth_url = ser.CharField(read_only=True) links = LinksField({ 'self': 'get_api_url', 'html': 'get_absolute_html_url', }) nodes = RelationshipField( related_view='institutions:institution-nodes', related_view_kwargs={'institution_id': '<_id>'}, ) registrations = RelationshipField( related_view='institutions:institution-registrations', related_view_kwargs={'institution_id': '<_id>'}, ) users = RelationshipField( related_view='institutions:institution-users', related_view_kwargs={'institution_id': '<_id>'}, ) def get_api_url(self, obj): return obj.absolute_api_v2_url def get_absolute_url(self, obj): return obj.absolute_api_v2_url class Meta: type_ = 'institutions'
class NodeLogSerializer(JSONAPISerializer): filterable_fields = frozenset(['action', 'date']) non_anonymized_fields = [ 'id', 'date', 'action', ] id = ser.CharField(read_only=True, source='_id') date = DateByVersion(read_only=True) action = ser.CharField(read_only=True) params = ser.SerializerMethodField(read_only=True) links = LinksField({'self': 'get_absolute_url'}) class Meta: type_ = 'logs' node = RelationshipField( related_view=lambda n: 'registrations:registration-detail' if getattr(n, 'is_registration', False) else 'nodes:node-detail', related_view_kwargs={'node_id': '<node._id>'}, ) original_node = RelationshipField( related_view=lambda n: 'registrations:registration-detail' if getattr(n, 'is_registration', False) else 'nodes:node-detail', related_view_kwargs={'node_id': '<original_node._id>'}, ) user = RelationshipField( related_view='users:user-detail', related_view_kwargs={'user_id': '<user._id>'}, ) # This would be a node_link, except that data isn't stored in the node log params linked_node = HideIfNotNodePointerLog( RelationshipField( related_view='nodes:node-detail', related_view_kwargs={'node_id': '<params.pointer.id>'})) linked_registration = HideIfNotRegistrationPointerLog( RelationshipField( related_view='registrations:registration-detail', related_view_kwargs={'node_id': '<params.pointer.id>'})) template_node = RelationshipField( related_view='nodes:node-detail', related_view_kwargs={'node_id': '<params.template_node.id>'}) def get_absolute_url(self, obj): return obj.absolute_url def get_params(self, obj): if obj.action == 'osf_storage_folder_created' and obj.params.get( 'urls'): obj.params.pop('urls') return NodeLogParamsSerializer(obj.params, context=self.context, read_only=True).data
class NodeRequestSerializer(RequestSerializer): class Meta: type_ = 'node-requests' target = RelationshipField( read_only=True, related_view='nodes:node-detail', related_view_kwargs={'node_id': '<target._id>'}, filter_key='target__guids___id', ) def get_target_url(self, obj): return absolute_reverse('nodes:node-detail', kwargs={'node_id': obj.target._id, 'version': self.context['request'].parser_context['kwargs']['version']})
class ChronosSubmissionSerializer(JSONAPISerializer): class Meta: type_ = 'chronos-submissions' id = ser.CharField(source='publication_id', read_only=True) submission_url = ser.CharField(read_only=True) status = ser.SerializerMethodField() modified = ser.DateTimeField(read_only=True) journal = RelationshipField( read_only=True, related_view='chronos:chronos-journal-detail', related_view_kwargs={'journal_id': '<journal.journal_id>'}, ) preprint = RelationshipField( read_only=True, related_view='preprints:preprint-detail', related_view_kwargs={'preprint_id': '<preprint._id>'}, ) submitter = RelationshipField( read_only=True, related_view='users:user-detail', related_view_kwargs={'user_id': '<submitter._id>'}, ) links = LinksField({'self': 'get_absolute_url'}) def get_absolute_url(self, obj): return absolute_reverse('chronos:chronos-submission-detail', kwargs={ 'preprint_id': obj.preprint._id, 'submission_id': obj.publication_id }) def get_status(self, obj): value_lookup = { val.value: key for key, val in ChronosSubmissionStatus.__members__.items() } return value_lookup[obj.status]
class MeetingSerializer(CollectionSerializer): location = serializers.CharField(allow_blank=True, allow_null=True, required=False) address = serializers.CharField(allow_blank=True, allow_null=True, required=False) start_date = serializers.DateTimeField(allow_null=True, required=False) end_date = serializers.DateTimeField(allow_null=True, required=False) groups = RelationshipField( related_view='meeting-group-list', related_view_kwargs={'pk': '<pk>'} ) items = RelationshipField( related_view='meeting-item-list', related_view_kwargs={'pk': '<pk>'} ) class Meta: model = Meeting class JSONAPIMeta: resource_name = 'meetings' def create(self, validated_data): user = self.context['request'].user meeting = Meeting.objects.create(created_by=user, **validated_data) assign_perm('api.approve_meeting_items', user, CollectionBase(meeting)) return meeting def update(self, meeting, validated_data): meeting.title = validated_data.get('title', meeting.title) meeting.description = validated_data.get('description', meeting.description) meeting.tags = validated_data.get('tags', meeting.tags) meeting.settings = validated_data.get('settings', meeting.settings) meeting.submission_settings = validated_data.get('submission_settings', meeting.submission_settings) meeting.created_by_org = validated_data.get('created_by_org', meeting.created_by_org) meeting.location = validated_data.get('location', meeting.location) meeting.start_date = validated_data.get('start_date', meeting.start_date) meeting.end_date = validated_data.get('end_date', meeting.end_date) meeting.save() return meeting
class FakeSerializer(ser.Serializer): filterable_fields = ('id', 'string_field', 'second_string_field','list_field', 'date_field', 'int_field', 'bool_field', 'relationship_field') id = ser.CharField() string_field = ser.CharField() second_string_field = ser.CharField() list_field = ser.ListField() date_field = ser.DateField() datetime_field = ser.DateTimeField() int_field = ser.IntegerField() float_field = ser.FloatField() bool_field = ser.BooleanField(source='foobar') relationship_field = RelationshipField(related_view='fake', related_view_kwargs={})
class RequestSerializer(JSONAPISerializer): class Meta: type_ = 'node-requests' filterable_fields = frozenset([ 'creator', 'request_type', 'machine_state', 'created', 'id', 'target' ]) id = ser.CharField(source='_id', read_only=True) request_type = ser.ChoiceField(read_only=True, required=False, choices=RequestTypes.choices()) machine_state = ser.ChoiceField(read_only=True, required=False, choices=DefaultStates.choices()) comment = ser.CharField(required=False, allow_blank=True, max_length=65535) created = VersionedDateTimeField(read_only=True) modified = VersionedDateTimeField(read_only=True) date_last_transitioned = VersionedDateTimeField(read_only=True) creator = RelationshipField( read_only=True, related_view='users:user-detail', related_view_kwargs={'user_id': '<creator._id>'}, filter_key='creator___id', ) links = LinksField({ 'self': 'get_absolute_url', 'target': 'get_target_url' }) @property def target(self): raise NotImplementedError() def get_absolute_url(self, obj): return absolute_reverse( 'requests:request-detail', kwargs={ 'request_id': obj._id, 'version': self.context['request'].parser_context['kwargs']['version'] }) def get_target_url(self, obj): raise NotImplementedError() def create(self, validated_data): raise NotImplementedError()
class RegistrationActionSerializer(BaseActionSerializer): class Meta: type_ = 'registration-actions' target = RelationshipField( read_only=True, related_view='registrations:registration-detail', related_view_kwargs={'node_id': '<target._id>'}, filter_key='target__guids___id', ) permissions = ser.ChoiceField( choices=permissions.API_CONTRIBUTOR_PERMISSIONS, required=False) visible = ser.BooleanField(default=True, required=False)
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)
class RegistrationSchemaSerializer(SchemaSerializer): description = ser.CharField(read_only=True, allow_blank=True) schema_blocks = RelationshipField( related_view='schemas:registration-schema-blocks', related_view_kwargs={'schema_id': '<_id>'}, ) filterable_fields = ['active'] class Meta: @staticmethod def get_type(request): return get_kebab_snake_case_field(request.version, 'registration-schemas')
class SubjectSerializer(JSONAPISerializer): filterable_fields = frozenset([ 'text', 'parent', 'id', ]) id = ser.CharField(source='_id', required=True) text = ser.CharField(max_length=200) taxonomy_name = ser.CharField(source='provider.share_title', read_only=True) parent = RelationshipField( related_view='subjects:subject-detail', related_view_kwargs={'subject_id': '<parent._id>'}, always_embed=True, ) children = RelationshipField( related_view='subjects:subject-children', related_view_kwargs={'subject_id': '<_id>'}, related_meta={'count': 'get_children_count'}, ) links = LinksField({ 'self': 'get_absolute_url', }) def get_absolute_url(self, obj): return obj.absolute_api_v2_subject_url def get_children_count(self, obj): return obj.children_count if hasattr( obj, 'children_count') else obj.child_count class Meta: type_ = 'subjects'
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 CollectionSerializer(serializers.Serializer): id = serializers.CharField(read_only=True) title = serializers.CharField(required=True) description = serializers.CharField(allow_blank=True) tags = serializers.CharField(allow_blank=True) settings = serializers.CharField(required=False) created_by = UserSerializer(read_only=True) date_created = serializers.DateTimeField(read_only=True) date_updated = serializers.DateTimeField(read_only=True) groups = RelationshipField(related_view='collection-group-list', related_view_kwargs={'pk': '<pk>'}) items = RelationshipField(related_view='collection-item-list', related_view_kwargs={'pk': '<pk>'}) class Meta: model = Collection class JSONAPIMeta: resource_name = 'collections' def create(self, validated_data): user = self.context['request'].user collection = Collection.objects.create(created_by=user, **validated_data) assign_perm('api.approve_items', user, collection) return collection def update(self, collection, validated_data): collection.title = validated_data.get('title', collection.title) collection.description = validated_data.get('description', collection.description) collection.tags = validated_data.get('tags', collection.tags) collection.settings = validated_data.get('settings', collection.settings) collection.save() return collection
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' ]) 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".') unregistered_contributor = ser.SerializerMethodField() 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 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 } ) def get_unregistered_contributor(self, obj): unclaimed_records = obj.unclaimed_records.get(obj.node_id, None) if unclaimed_records: return unclaimed_records.get('name', None)
class CollectionProviderSerializer(ProviderSerializer): class Meta: type_ = 'collection-providers' primary_collection = RelationshipField( related_view='collections:collection-detail', related_view_kwargs={'collection_id': '<primary_collection._id>'}) filterable_fields = frozenset([ 'allow_submissions', 'allow_commenting', 'description', 'domain', 'domain_redirect_enabled', 'id', 'name', ])
class RegistrationFileSerializer(OsfStorageFileSerializer): files = NodeFileHyperLinkField( related_view='registrations:registration-files', related_view_kwargs={'node_id': '<node._id>', 'path': '<path>', 'provider': '<provider>'}, kind='folder' ) comments = FileCommentRelationshipField(related_view='registrations:registration-comments', related_view_kwargs={'node_id': '<node._id>'}, related_meta={'unread': 'get_unread_comments_count'}, filter={'target': 'get_file_guid'} ) node = RelationshipField(related_view='registrations:registration-detail', related_view_kwargs={'node_id': '<node._id>'}, help_text='The registration that this file belongs to' )
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'], }, )
class CollectionNodeLinkSerializer(NodeLinksSerializer): target_node = RelationshipField( related_view='nodes:node-detail', related_view_kwargs={'node_id': '<guid.referent._id>'}, always_embed=True, ) def get_absolute_url(self, obj): return absolute_reverse( 'collections:node-pointer-detail', kwargs={ 'collection_id': self.context['request'].parser_context['kwargs'] ['collection_id'], 'node_link_id': obj.guid._id, 'version': self.context['request'].parser_context['kwargs']['version'], }, ) # Override NodeLinksSerializer def create(self, validated_data): request = self.context['request'] user = request.user collection = self.context['view'].get_collection() target_node_id = validated_data['_id'] pointer_node = AbstractNode.load(target_node_id) if not pointer_node: raise InvalidModelValueError( source={'pointer': '/data/relationships/node_links/data/id'}, detail='Target Node \'{}\' not found.'.format(target_node_id), ) try: pointer = collection.collect_object(pointer_node, user) except ValidationError: raise InvalidModelValueError( source={'pointer': '/data/relationships/node_links/data/id'}, detail='Target Node \'{}\' already pointed to by \'{}\'.'. format(target_node_id, collection._id), ) return pointer
class GroupSerializer(serializers.Serializer): id = serializers.CharField(read_only=True) title = serializers.CharField(required=True) description = serializers.CharField(allow_blank=True, required=False) created_by = UserSerializer(read_only=True) date_created = serializers.DateTimeField(read_only=True) date_updated = serializers.DateTimeField(read_only=True) items = RelationshipField( related_view='group-item-list', related_view_kwargs={'pk': '<collection.id>', 'group_id': '<pk>'} ) items = serializers.HyperlinkedRelatedField( many=True, read_only=True, view_name='track-detail' ) class Meta: model = Group class JSONAPIMeta: resource_name = 'groups' def create(self, validated_data): user = self.context['request'].user collection_id = self.context.get('collection_id', None) or self.context['request'].parser_context['kwargs'].get( 'pk', None) collection = CollectionBase.objects.get(id=collection_id) return Group.objects.create( created_by=user, collection=collection, **validated_data ) def update(self, group, validated_data): group.title = validated_data.get('title', None) description = validated_data.get('description', None) if description: group.description = description group.save() return group
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
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', }, )
class PreprintProviderSerializer(JSONAPISerializer): filterable_fields = frozenset(['name', 'description', 'id']) name = ser.CharField(required=True) description = ser.CharField(required=False) id = ser.CharField(max_length=200, source='_id') logo_path = ser.CharField(read_only=True) banner_path = ser.CharField(read_only=True) preprints = RelationshipField( related_view='preprint_providers:preprints-list', related_view_kwargs={'provider_id': '<_id>'}) links = LinksField({ 'self': 'get_absolute_url', 'preprints': 'get_preprints_url', 'external_url': 'get_external_url' }) class Meta: type_ = 'preprint_providers' def get_absolute_url(self, obj): return obj.absolute_api_v2_url def get_preprints_url(self, obj): return absolute_reverse( 'preprint_providers:preprints-list', kwargs={ 'provider_id': obj._id, 'version': self.context['request'].parser_context['kwargs']['version'] }) def get_external_url(self, obj): return obj.external_url
def __init__(self, *args, **kwargs): super(ApiOAuth2PersonalTokenSerializer, self).__init__(*args, **kwargs) request = kwargs['context']['request'] # Dynamically adding scopes field here, depending on the version if expect_scopes_as_relationships(request): field = TokenScopesRelationshipField( related_view='tokens:token-scopes-list', related_view_kwargs={'_id': '<_id>'}, always_embed=True, read_only=False, ) self.fields['scopes'] = field self.fields['owner'] = RelationshipField( related_view='users:user-detail', related_view_kwargs={'user_id': '<owner._id>'}, ) # Making scopes embeddable self.context['embed']['scopes'] = self.context[ 'view']._get_embed_partial('scopes', field) else: self.fields['scopes'] = ser.SerializerMethodField() self.fields['owner'] = ser.SerializerMethodField()
class PreprintProviderSerializer(JSONAPISerializer): filterable_fields = frozenset([ 'allow_submissions', 'description', 'domain', 'domain_redirect_enabled', 'id', 'name', 'share_publish_type', 'reviews_workflow', 'permissions', ]) name = ser.CharField(read_only=True) description = ser.CharField(read_only=True) id = ser.CharField(read_only=True, max_length=200, source='_id') advisory_board = ser.CharField(read_only=True) example = ser.CharField(read_only=True, allow_null=True) domain = ser.CharField(read_only=True, allow_null=False) domain_redirect_enabled = ser.BooleanField(read_only=True) footer_links = ser.CharField(read_only=True) share_source = ser.CharField(read_only=True) share_publish_type = ser.CharField(read_only=True) email_support = ser.CharField(read_only=True, allow_null=True) preprint_word = ser.CharField(read_only=True, allow_null=True) allow_submissions = ser.BooleanField(read_only=True) additional_providers = ser.ListField(read_only=True, child=ser.CharField()) facebook_app_id = ser.IntegerField(read_only=True, allow_null=True) # Reviews settings are the only writable fields reviews_workflow = ser.ChoiceField(choices=Workflows.choices()) reviews_comments_private = ser.BooleanField() reviews_comments_anonymous = ser.BooleanField() permissions = ser.SerializerMethodField() preprints = ReviewableCountsRelationshipField( related_view='preprint_providers:preprints-list', related_view_kwargs={'provider_id': '<_id>'}) taxonomies = RelationshipField( related_view='preprint_providers:taxonomy-list', related_view_kwargs={'provider_id': '<_id>'}) highlighted_taxonomies = RelationshipField( related_view='preprint_providers:highlighted-taxonomy-list', related_view_kwargs={'provider_id': '<_id>'}, related_meta={ 'has_highlighted_subjects': 'get_has_highlighted_subjects' }) licenses_acceptable = RelationshipField( related_view='preprint_providers:license-list', related_view_kwargs={'provider_id': '<_id>'}) links = LinksField({ 'self': 'get_absolute_url', 'preprints': 'get_preprints_url', 'external_url': 'get_external_url' }) # Deprecated fields header_text = ShowIfVersion(ser.CharField(read_only=True, default=''), min_version='2.0', max_version='2.3') banner_path = ShowIfVersion(ser.CharField(read_only=True, default=''), min_version='2.0', max_version='2.3') logo_path = ShowIfVersion(ser.CharField(read_only=True, default=''), min_version='2.0', max_version='2.3') email_contact = ShowIfVersion(ser.CharField(read_only=True, allow_null=True), min_version='2.0', max_version='2.3') social_twitter = ShowIfVersion(ser.CharField(read_only=True, allow_null=True), min_version='2.0', max_version='2.3') social_facebook = ShowIfVersion(ser.CharField(read_only=True, allow_null=True), min_version='2.0', max_version='2.3') social_instagram = ShowIfVersion(ser.CharField(read_only=True, allow_null=True), min_version='2.0', max_version='2.3') subjects_acceptable = ShowIfVersion(ser.ListField(read_only=True, default=[]), min_version='2.0', max_version='2.4') class Meta: type_ = 'preprint_providers' def get_has_highlighted_subjects(self, obj): return obj.has_highlighted_subjects def get_absolute_url(self, obj): return obj.absolute_api_v2_url def get_preprints_url(self, obj): return absolute_reverse( 'preprint_providers:preprints-list', kwargs={ 'provider_id': obj._id, 'version': self.context['request'].parser_context['kwargs']['version'] }) def get_external_url(self, obj): return obj.external_url def get_permissions(self, obj): auth = get_user_auth(self.context['request']) if not auth.user: return [] return get_perms(auth.user, obj) def validate(self, data): required_fields = ('reviews_workflow', 'reviews_comments_private', 'reviews_comments_anonymous') for field in required_fields: if data.get(field) is None: raise ValidationError( 'All reviews fields must be set at once: `{}`'.format( '`, `'.join(required_fields))) return data def update(self, instance, validated_data): instance.reviews_workflow = validated_data['reviews_workflow'] instance.reviews_comments_private = validated_data[ 'reviews_comments_private'] instance.reviews_comments_anonymous = validated_data[ 'reviews_comments_anonymous'] instance.save() return instance
class NodeSerializer(JSONAPISerializer): # TODO: If we have to redo this implementation in any of the other serializers, subclass ChoiceField and make it # handle blank choices properly. Currently DRF ChoiceFields ignore blank options, which is incorrect in this # instance filterable_fields = frozenset([ 'title', 'description', 'public', 'tags', 'category', 'date_created', 'date_modified', 'registration' ]) id = IDField(source='_id', read_only=True) type = TypeField() category_choices = Node.CATEGORY_MAP.keys() category_choices_string = ', '.join(["'{}'".format(choice) for choice in category_choices]) title = ser.CharField(required=True) description = ser.CharField(required=False, allow_blank=True, allow_null=True) category = ser.ChoiceField(choices=category_choices, help_text="Choices: " + category_choices_string) date_created = ser.DateTimeField(read_only=True) date_modified = ser.DateTimeField(read_only=True) registration = ser.BooleanField(read_only=True, source='is_registration') fork = ser.BooleanField(read_only=True, source='is_fork') collection = DevOnly(ser.BooleanField(read_only=True, source='is_folder')) dashboard = ser.BooleanField(read_only=True, source='is_dashboard') tags = JSONAPIListField(child=NodeTagField(), required=False) # Public is only write-able by admins--see update method public = ser.BooleanField(source='is_public', required=False, help_text='Nodes that are made public will give read-only access ' 'to everyone. Private nodes require explicit read ' 'permission. Write and admin access are the same for ' 'public and private nodes. Administrators on a parent ' 'node have implicit read permissions for all child nodes') links = LinksField({'html': 'get_absolute_url'}) # TODO: When we have osf_permissions.ADMIN permissions, make this writable for admins children = RelationshipField( related_view='nodes:node-children', related_view_kwargs={'node_id': '<pk>'}, related_meta={'count': 'get_node_count'}, ) comments = RelationshipField( related_view='nodes:node-comments', related_view_kwargs={'node_id': '<pk>'}, related_meta={'unread': 'get_unread_comments_count'}) contributors = RelationshipField( related_view='nodes:node-contributors', related_view_kwargs={'node_id': '<pk>'}, related_meta={'count': 'get_contrib_count'}, ) files = RelationshipField( related_view='nodes:node-providers', related_view_kwargs={'node_id': '<pk>'} ) forked_from = RelationshipField( related_view='nodes:node-detail', related_view_kwargs={'node_id': '<forked_from_id>'} ) node_links = DevOnly(RelationshipField( related_view='nodes:node-pointers', related_view_kwargs={'node_id': '<pk>'}, related_meta={'count': 'get_pointers_count'}, )) parent = RelationshipField( related_view='nodes:node-detail', related_view_kwargs={'node_id': '<parent_id>'} ) registrations = DevOnly(HideIfRegistration(RelationshipField( related_view='nodes:node-registrations', related_view_kwargs={'node_id': '<pk>'}, related_meta={'count': 'get_registration_count'} ))) logs = RelationshipField( related_view='nodes:node-logs', related_view_kwargs={'node_id': '<pk>'}, ) class Meta: type_ = 'nodes' def get_absolute_url(self, obj): return obj.absolute_url # TODO: See if we can get the count filters into the filter rather than the serializer. def get_user_auth(self, request): user = request.user if user.is_anonymous(): auth = Auth(None) else: auth = Auth(user) return auth def get_node_count(self, obj): auth = self.get_user_auth(self.context['request']) nodes = [node for node in obj.nodes if node.can_view(auth) and node.primary and not node.is_deleted] return len(nodes) def get_contrib_count(self, obj): return len(obj.contributors) def get_registration_count(self, obj): auth = self.get_user_auth(self.context['request']) registrations = [node for node in obj.node__registrations if node.can_view(auth)] return len(registrations) def get_pointers_count(self, obj): return len(obj.nodes_pointer) def get_unread_comments_count(self, obj): auth = self.get_user_auth(self.context['request']) user = auth.user return Comment.find_unread(user=user, node=obj) def create(self, validated_data): node = Node(**validated_data) try: node.save() except ValidationValueError as e: raise InvalidModelValueError(detail=e.message) return node def update(self, node, validated_data): """Update instance with the validated data. Requires the request to be in the serializer context. """ assert isinstance(node, Node), 'node must be a Node' auth = self.get_user_auth(self.context['request']) old_tags = set([tag._id for tag in node.tags]) if 'tags' in validated_data: current_tags = set(validated_data.get('tags')) del validated_data['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) if validated_data: try: node.update(validated_data, auth=auth) except ValidationValueError as e: raise InvalidModelValueError(detail=e.message) except PermissionsError: raise exceptions.PermissionDenied return node