class RegionSerializer(JSONAPISerializer): id = ser.CharField(source='_id', read_only=True) name = ser.CharField(read_only=True) links = LinksField({ 'self': 'get_absolute_url', }) class Meta: type_ = 'regions' def get_absolute_url(self, obj): return obj.absolute_api_v2_url
class UserQuickFilesSerializer(QuickFilesSerializer): links = LinksField({ 'info': Link('files:file-detail', kwargs={'file_id': '<_id>'}), 'upload': WaterbutlerLink(), 'delete': WaterbutlerLink(), 'move': WaterbutlerLink(), 'download': WaterbutlerLink(must_be_file=True), })
class ScopeSerializer(JSONAPISerializer): filterable_fields = frozenset(['id']) id = ser.CharField(read_only=True, source='name') description = ser.CharField(read_only=True) links = LinksField({'self': 'get_absolute_url'}) class Meta: type_ = 'scopes' def get_absolute_url(self, obj): return obj.absolute_url()
class NodeInstitutionRelationshipSerializer(ser.Serializer): id = ser.CharField(source='institution_id', required=False, allow_null=True) type = TypeField(required=False, allow_null=True) links = LinksField({ 'self': 'get_self_link', 'related': 'get_related_link', }) class Meta: type_ = 'institutions' def get_self_link(self, obj): return obj.institution_relationship_url() def get_related_link(self, obj): return obj.institution_url() def update(self, instance, validated_data): node = instance user = self.context['request'].user inst = validated_data.get('institution_id', None) if inst: inst = Institution.load(inst) if not inst: raise exceptions.NotFound try: node.add_primary_institution(inst=inst, user=user) except UserNotAffiliatedError: raise exceptions.ValidationError(detail='User not affiliated with institution') node.save() return node node.remove_primary_institution(user) node.save() return node def to_representation(self, obj): data = {} meta = getattr(self, 'Meta', None) type_ = getattr(meta, 'type_', None) assert type_ is not None, 'Must define Meta.type_' relation_id_field = self.fields['id'] data['data'] = None if obj.primary_institution: attribute = obj.primary_institution._id relationship = relation_id_field.to_representation(attribute) data['data'] = {'type': type_, 'id': relationship} data['links'] = {key: val for key, val in self.fields.get('links').to_representation(obj).iteritems()} return data
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
class PreprintStorageProviderSerializer(NodeStorageProviderSerializer): node = HideIfPreprint(ser.CharField(source='node_id', read_only=True)) preprint = ser.CharField(source='node_id', read_only=True) files = NodeFileHyperLinkField( related_view='preprints:preprint-files', related_view_kwargs={'preprint_id': '<node._id>'}, kind='folder', never_embed=True, ) links = LinksField({ 'upload': WaterbutlerLink(), })
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 = ContributorIDField(read_only=True, source='_id') type = TypeField() index = ser.IntegerField(required=False, read_only=True) 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) node = RelationshipField(related_view='nodes:node-detail', related_view_kwargs={'node_id': '<node_id>'}) 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 ChronosJournalSerializer(JSONAPISerializer): class Meta: type_ = 'chronos-journals' filterable_fields = frozenset(['title', 'name', 'id']) id = ser.CharField(source='journal_id', read_only=True) name = ser.CharField(read_only=True) title = ser.CharField(read_only=True) links = LinksField({'self': 'get_absolute_url'}) def get_absolute_url(self, obj): return absolute_reverse('chronos:chronos-journal-detail', kwargs={'journal_id': obj.journal_id})
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 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
class ProviderSerializer(JSONAPISerializer): class Meta: type_ = 'providers' 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) email_support = ser.CharField(read_only=True, allow_null=True) facebook_app_id = ser.IntegerField(read_only=True, allow_null=True) allow_submissions = ser.BooleanField(read_only=True) allow_commenting = ser.BooleanField(read_only=True) assets = ser.SerializerMethodField(read_only=True) links = LinksField({ 'self': 'get_absolute_url', 'external_url': 'get_external_url' }) taxonomies = TypedRelationshipField( related_view='providers:taxonomy-list', related_view_kwargs={'provider_id': '<_id>'}) highlighted_taxonomies = TypedRelationshipField( related_view='providers:highlighted-taxonomy-list', related_view_kwargs={'provider_id': '<_id>'}, related_meta={ 'has_highlighted_subjects': 'get_has_highlighted_subjects' }) licenses_acceptable = TypedRelationshipField( related_view='providers:license-list', related_view_kwargs={'provider_id': '<_id>'}) 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_external_url(self, obj): return obj.external_url def get_assets(self, obj): return {asset.name: asset.file.url for asset in obj.asset_files.all()} or None
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' 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>'}, ) 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 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 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'
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)
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'
class RegistrationProviderSerializer(ProviderSerializer): class Meta: type_ = 'registration-providers' branded_discovery_page = ser.BooleanField(read_only=True) brand = RelationshipField( related_view='brands:brand-detail', related_view_kwargs={'brand_id': '<brand.id>'}, ) moderators = RelationshipField( related_view='providers:registration-providers:provider-moderator-list', related_view_kwargs={'provider_id': '<_id>'}, ) primary_collection = RelationshipField( related_view='collections:collection-detail', related_view_kwargs={'collection_id': '<primary_collection._id>'}, ) filterable_fields = frozenset([ 'allow_submissions', 'allow_commenting', 'brand', 'description', 'domain', 'domain_redirect_enabled', 'id', 'name', 'reviews_workflow', 'permissions', ]) reviews_workflow = ser.ChoiceField(choices=Workflows.choices(), read_only=True) reviews_comments_anonymous = ser.BooleanField(read_only=True) allow_updates = ser.BooleanField(read_only=True) allow_bulk_uploads = ser.BooleanField(read_only=True) registrations = ReviewableCountsRelationshipField( related_view='providers:registration-providers:registrations-list', related_view_kwargs={'provider_id': '<_id>'}, ) links = LinksField({ 'self': 'get_absolute_url', 'external_url': 'get_external_url', })
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 = ser.DateTimeField(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 ValidationValueError: raise exceptions.ValidationError('Invalid link name.') return view_only_link def get_absolute_url(self, obj): node_id = self.context['request'].parser_context['kwargs']['node_id'] return absolute_reverse('nodes:node-view-only-link-detail', kwargs={ 'link_id': obj._id, 'node_id': node_id }) class Meta: type_ = 'view_only_links'
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 NodeProviderSerializer(JSONAPISerializer): id = ser.SerializerMethodField(read_only=True) kind = ser.CharField(read_only=True) name = ser.CharField(read_only=True) path = ser.CharField(read_only=True) node = ser.CharField(source='node_id', read_only=True) provider = ser.CharField(read_only=True) files = NodeFileHyperLinkField(related_view='nodes:node-files', related_view_kwargs={ 'node_id': '<node._id>', 'path': '<path>', 'provider': '<provider>' }, kind='folder', never_embed=True) links = LinksField({ 'upload': WaterbutlerLink(), 'new_folder': WaterbutlerLink(kind='folder'), 'storage_addons': 'get_storage_addons_url' }) class Meta: type_ = 'files' @staticmethod def get_id(obj): return '{}:{}'.format(obj.node._id, obj.provider) def get_absolute_url(self, obj): return absolute_reverse( 'nodes:node-provider-detail', kwargs={ 'node_id': obj.node._id, 'provider': obj.provider, 'version': self.context['request'].parser_context['kwargs']['version'] }) def get_storage_addons_url(self, obj): return absolute_reverse( 'addons:addon-list', kwargs={ 'version': self.context['request'].parser_context['kwargs']['version'] }, query_kwargs={'filter[categories]': 'storage'})
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'
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})
class UserInstitutionsRelationshipSerializer(ser.Serializer): data = ser.ListField(child=RelatedInstitution()) links = LinksField({'self': 'get_self_url', 'html': 'get_related_url'}) def get_self_url(self, obj): return absolute_reverse('users:user-institutions-relationship', kwargs={'user_id': obj['self']._id}) def get_related_url(self, obj): return absolute_reverse('users:user-institutions', kwargs={'user_id': obj['self']._id}) def get_absolute_url(self, obj): return obj.absolute_api_v2_url class Meta: type_ = 'institutions'
class InstitutionNodesRelationshipSerializer(ser.Serializer): data = ser.ListField(child=NodeRelated()) links = LinksField({'self': 'get_self_url', 'html': 'get_related_url'}) def get_self_url(self, obj): return obj['self'].nodes_relationship_url def get_related_url(self, obj): return obj['self'].nodes_url class Meta: type_ = 'nodes' def create(self, validated_data): inst = self.context['view'].get_object()['self'] user = self.context['request'].user node_dicts = validated_data['data'] changes_flag = False for node_dict in node_dicts: node = Node.load(node_dict['_id']) if not node: raise exceptions.NotFound( detail='Node with id "{}" was not found'.format( node_dict['_id'])) if not node.has_permission(user, osf_permissions.ADMIN): raise exceptions.PermissionDenied( detail='Admin permission on node {} required'.format( node_dict['_id'])) if inst not in node.affiliated_institutions: node.add_affiliated_institution(inst, user, save=True) changes_flag = True if not changes_flag: raise RelationshipPostMakesNoChanges return { 'data': list( Node.find_by_institutions( inst, Q('is_registration', 'eq', False) & Q('is_deleted', 'ne', True))), 'self': inst }
class UserSerializer(JSONAPISerializer): filterable_fields = frozenset( ['fullname', 'given_name', 'middle_name', 'family_name', 'id']) id = ser.CharField(read_only=True, source='_id') fullname = ser.CharField( help_text='Display name used in the general user interface') given_name = ser.CharField(help_text='For bibliographic citations') middle_name = ser.CharField(source='middle_names', help_text='For bibliographic citations') family_name = ser.CharField(help_text='For bibliographic citations') suffix = ser.CharField(help_text='For bibliographic citations') date_registered = ser.DateTimeField(read_only=True) gravatar_url = ser.CharField( help_text= 'URL for the icon used to identify the user. Relies on http://gravatar.com ' ) employment_institutions = ser.ListField( source='jobs', help_text='An array of dictionaries representing the ' 'places the user has worked') educational_institutions = ser.ListField( source='schools', help_text='An array of dictionaries representing the ' 'places the user has attended school') social_accounts = ser.DictField( source='social', help_text='A dictionary of various social media account ' 'identifiers including an array of user-defined URLs') links = LinksField({ 'html': 'absolute_url', 'nodes': { 'relation': Link('users:user-nodes', kwargs={'user_id': '<pk>'}) } }) class Meta: type_ = 'users' def absolute_url(self, obj): return obj.absolute_url def update(self, instance, validated_data): # TODO pass
class InstitutionRegistrationsRelationshipSerializer(BaseAPISerializer): data = ser.ListField(child=RegistrationRelated()) links = LinksField({ 'self': 'get_self_url', 'html': 'get_related_url', }) def get_self_url(self, obj): return obj['self'].registrations_relationship_url def get_related_url(self, obj): return obj['self'].registrations_url class Meta: type_ = 'registrations' def create(self, validated_data): inst = self.context['view'].get_object()['self'] user = self.context['request'].user registration_dicts = validated_data['data'] changes_flag = False for registration_dict in registration_dicts: registration = Registration.load(registration_dict['_id']) if not registration: raise exceptions.NotFound( detail='Registration with id "{}" was not found'.format( registration_dict['_id'])) if not registration.has_permission(user, osf_permissions.WRITE): raise exceptions.PermissionDenied( detail='Write permission on registration {} required'. format(registration_dict['_id'])) if not registration.is_affiliated_with_institution(inst): registration.add_affiliated_institution(inst, user, save=True) changes_flag = True if not changes_flag: raise RelationshipPostMakesNoChanges return { 'data': list(inst.nodes.filter(is_deleted=False, type='osf.registration')), 'self': inst, }
class UserAddonSettingsSerializer(JSONAPISerializer): """ Overrides UserSerializer to make id required. """ id = ser.CharField(source='config.short_name', read_only=True) user_has_auth = ser.BooleanField(source='has_auth', read_only=True) links = LinksField({ 'self': 'get_absolute_url', 'accounts': 'account_links', }) class Meta: @staticmethod def get_type(request): return get_kebab_snake_case_field(request.version, 'user-addons') def get_absolute_url(self, obj): return absolute_reverse( 'users:user-addon-detail', kwargs={ 'provider': obj.config.short_name, 'user_id': self.context['request'].parser_context['kwargs']['user_id'], 'version': self.context['request'].parser_context['kwargs']['version'], }, ) def account_links(self, obj): # TODO: [OSF-4933] remove this after refactoring Figshare if hasattr(obj, 'external_accounts'): return { account._id: { 'account': absolute_reverse( 'users:user-external_account-detail', kwargs={ 'user_id': obj.owner._id, 'provider': obj.config.short_name, 'account_id': account._id, 'version': self.context['request'].parser_context['kwargs']['version'], }, ), 'nodes_connected': [n.absolute_api_v2_url for n in obj.get_attached_nodes(account)], } for account in obj.external_accounts.all() } return {}
class BannerSerializer(JSONAPISerializer): start_date = VersionedDateTimeField(read_only=True) end_date = VersionedDateTimeField(read_only=True) color = ser.CharField(read_only=True) license = ser.CharField(read_only=True) link = ser.URLField(read_only=True) name = ser.CharField(read_only=True) default_alt_text = ser.SerializerMethodField() mobile_alt_text = ser.SerializerMethodField() links = LinksField({ 'self': 'get_absolute_url', 'default_photo': 'get_default_photo_url', 'mobile_photo': 'get_mobile_photo_url', }) def get_default_photo_url(self, banner): if banner.default_photo: return banner.default_photo.url def get_mobile_photo_url(self, banner): if banner.mobile_photo: return banner.mobile_photo.url def get_default_alt_text(self, banner): return self.add_license(banner, banner.default_alt_text) def get_mobile_alt_text(self, banner): if banner.mobile_alt_text: return self.add_license(banner, banner.mobile_alt_text) return self.get_default_alt_text(banner) def add_license(self, banner, text): if banner.license and not banner.license.lower() == 'none': return text + ' Image copyright {}.'.format(banner.license) return text # Only the current banner's URL is surfaced through the API # Individual banners are not accessible publicly def get_absolute_url(self, obj): return absolute_reverse('banners:current') class Meta: type_ = 'banners'
class DraftRegistrationDetailSerializer(DraftRegistrationSerializer, DraftRegistrationDetailLegacySerializer): """ Overrides DraftRegistrationLegacySerializer to make id required. registration_supplement, node, cannot be changed after draft has been created. """ links = LinksField({ 'self': 'get_self_url', }) def get_self_url(self, obj): return absolute_reverse( 'draft_registrations:draft-registration-detail', kwargs={ 'version': self.context['request'].parser_context['kwargs']['version'], 'draft_id': self.context['request'].parser_context['kwargs']['draft_id'], }, ) def update(self, draft, validated_data): draft = super(DraftRegistrationDetailSerializer, self).update(draft, validated_data) user = self.context['request'].user auth = get_user_auth(self.context['request']) if 'tags' in validated_data: new_tags = set(validated_data.pop('tags', [])) draft.update_tags(new_tags, auth=auth) if 'license_type' in validated_data or 'license' in validated_data: license_details = get_license_details(draft, validated_data) validated_data['node_license'] = license_details if 'affiliated_institutions' in validated_data: institutions_list = validated_data.pop('affiliated_institutions') new_institutions = [{'_id': institution} for institution in institutions_list] update_institutions(draft, new_institutions, user) if 'subjects' in validated_data: subjects = validated_data.pop('subjects', None) self.update_subjects(draft, subjects, auth) try: draft.update(validated_data, auth=auth) except PermissionsError: raise exceptions.PermissionDenied except DraftRegistrationStateError as e: raise InvalidModelValueError(detail=str(e)) return draft
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'], }, )