class OembedSerializer(serializers.Serializer): format = serializers.ChoiceField(choices=["json"]) url = serializers.URLField() maxheight = serializers.IntegerField(required=False) maxwidth = serializers.IntegerField(required=False) def validate(self, validated_data): try: match = common_utils.spa_resolve( urllib.parse.urlparse(validated_data["url"]).path ) except urls.exceptions.Resolver404: raise serializers.ValidationError( "Invalid URL {}".format(validated_data["url"]) ) data = { "version": "1.0", "type": "rich", "provider_name": settings.APP_NAME, "provider_url": settings.FUNKWHALE_URL, "height": validated_data.get("maxheight") or 400, "width": validated_data.get("maxwidth") or 600, } embed_id = None embed_type = None if match.url_name == "library_track": qs = models.Track.objects.select_related("artist", "album__artist").filter( pk=int(match.kwargs["pk"]) ) try: track = qs.get() except models.Track.DoesNotExist: raise serializers.ValidationError( "No track matching id {}".format(match.kwargs["pk"]) ) embed_type = "track" embed_id = track.pk data["title"] = "{} by {}".format(track.title, track.artist.name) if track.attachment_cover: data[ "thumbnail_url" ] = track.attachment_cover.download_url_medium_square_crop data["thumbnail_width"] = 200 data["thumbnail_height"] = 200 elif track.album and track.album.attachment_cover: data[ "thumbnail_url" ] = track.album.attachment_cover.download_url_medium_square_crop data["thumbnail_width"] = 200 data["thumbnail_height"] = 200 data["description"] = track.full_name data["author_name"] = track.artist.name data["height"] = 150 data["author_url"] = federation_utils.full_url( common_utils.spa_reverse( "library_artist", kwargs={"pk": track.artist.pk} ) ) elif match.url_name == "library_album": qs = models.Album.objects.select_related("artist").filter( pk=int(match.kwargs["pk"]) ) try: album = qs.get() except models.Album.DoesNotExist: raise serializers.ValidationError( "No album matching id {}".format(match.kwargs["pk"]) ) embed_type = "album" embed_id = album.pk if album.attachment_cover: data[ "thumbnail_url" ] = album.attachment_cover.download_url_medium_square_crop data["thumbnail_width"] = 200 data["thumbnail_height"] = 200 data["title"] = "{} by {}".format(album.title, album.artist.name) data["description"] = "{} by {}".format(album.title, album.artist.name) data["author_name"] = album.artist.name data["height"] = 400 data["author_url"] = federation_utils.full_url( common_utils.spa_reverse( "library_artist", kwargs={"pk": album.artist.pk} ) ) elif match.url_name == "library_artist": qs = models.Artist.objects.filter(pk=int(match.kwargs["pk"])) try: artist = qs.get() except models.Artist.DoesNotExist: raise serializers.ValidationError( "No artist matching id {}".format(match.kwargs["pk"]) ) embed_type = "artist" embed_id = artist.pk album = artist.albums.exclude(attachment_cover=None).order_by("-id").first() if album and album.attachment_cover: data[ "thumbnail_url" ] = album.attachment_cover.download_url_medium_square_crop data["thumbnail_width"] = 200 data["thumbnail_height"] = 200 data["title"] = artist.name data["description"] = artist.name data["author_name"] = artist.name data["height"] = 400 data["author_url"] = federation_utils.full_url( common_utils.spa_reverse("library_artist", kwargs={"pk": artist.pk}) ) elif match.url_name == "channel_detail": from funkwhale_api.audio.models import Channel kwargs = {} if "uuid" in match.kwargs: kwargs["uuid"] = match.kwargs["uuid"] else: username_data = federation_utils.get_actor_data_from_username( match.kwargs["username"] ) kwargs["actor__domain"] = username_data["domain"] kwargs["actor__preferred_username__iexact"] = username_data["username"] qs = Channel.objects.filter(**kwargs).select_related( "artist__attachment_cover" ) try: channel = qs.get() except models.Artist.DoesNotExist: raise serializers.ValidationError( "No channel matching id {}".format(match.kwargs["uuid"]) ) embed_type = "channel" embed_id = channel.uuid if channel.artist.attachment_cover: data[ "thumbnail_url" ] = channel.artist.attachment_cover.download_url_medium_square_crop data["thumbnail_width"] = 200 data["thumbnail_height"] = 200 data["title"] = channel.artist.name data["description"] = channel.artist.name data["author_name"] = channel.artist.name data["height"] = 400 data["author_url"] = federation_utils.full_url( common_utils.spa_reverse( "channel_detail", kwargs={"uuid": channel.uuid} ) ) elif match.url_name == "library_playlist": qs = playlists_models.Playlist.objects.filter( pk=int(match.kwargs["pk"]), privacy_level="everyone" ) try: obj = qs.get() except playlists_models.Playlist.DoesNotExist: raise serializers.ValidationError( "No artist matching id {}".format(match.kwargs["pk"]) ) embed_type = "playlist" embed_id = obj.pk playlist_tracks = obj.playlist_tracks.exclude( track__album__attachment_cover=None ) playlist_tracks = playlist_tracks.select_related( "track__album__attachment_cover" ).order_by("index") first_playlist_track = playlist_tracks.first() if first_playlist_track: data[ "thumbnail_url" ] = ( first_playlist_track.track.album.attachment_cover.download_url_medium_square_crop ) data["thumbnail_width"] = 200 data["thumbnail_height"] = 200 data["title"] = obj.name data["description"] = obj.name data["author_name"] = obj.name data["height"] = 400 data["author_url"] = federation_utils.full_url( common_utils.spa_reverse("library_playlist", kwargs={"pk": obj.pk}) ) else: raise serializers.ValidationError( "Unsupported url: {}".format(validated_data["url"]) ) data[ "html" ] = '<iframe width="{}" height="{}" scrolling="no" frameborder="no" src="{}"></iframe>'.format( data["width"], data["height"], get_embed_url(embed_type, embed_id) ) return data def create(self, data): return data
class AuthorSerializer(serializers.ModelSerializer): absolute_url = serializers.URLField(source='get_absolute_url') class Meta: model = MemberProfile fields = ('name', 'absolute_url')
class ContestBeerSerializer(serializers.Serializer): id = serializers.IntegerField(read_only=True) url = ContestBeerHyperlink(view_name='contest-beer-detail', ) name = serializers.CharField(required=True, max_length=250, source='beer.name') brewery = serializers.CharField(required=True, max_length=250, source='beer.brewery') untappd_url = serializers.URLField(source='beer.untappd_url') brewery_url = serializers.URLField(source='beer.brewery_url') brewery_city = serializers.CharField(required=False, max_length=250, source='beer.brewery_city') brewery_state = serializers.CharField(required=False, max_length=250, source='beer.brewery_state') brewery_lat = serializers.FloatField(required=False, source='beer.brewery_lat') brewery_lon = serializers.FloatField(required=False, source='beer.brewery_lon') point_value = serializers.IntegerField() challenger = ChallengerHyperlink( view_name='contest-player-detail', required=False, ) challenge_point_loss = serializers.IntegerField(required=False, ) max_point_loss = serializers.IntegerField(required=False, ) challenge_point_value = serializers.IntegerField(required=False, ) total_drank = serializers.IntegerField( required=False, read_only=True, ) def create(self, validated_data): contest = validated_data['contest'] beer = None beer_filter = models.Beer.objects.filter( name=validated_data['beer']['name'], brewery=validated_data['beer']['brewery']) if beer_filter.exists(): beer = beer_filter.get() else: beer = models.Beer.objects.create_beer(**validated_data['beer']) if 'challenger' in validated_data: key_names = [ 'point_value', 'challenge_point_value', 'challenge_point_loss', 'max_point_loss' ] kwargs = { key: value for key, value in validated_data.items() \ if key in key_names } return contest.add_challenge_beer(beer, validated_data['challenger'], **kwargs) else: return contest.add_beer(beer, validated_data.get('point_value', 1)) def update(self, contest_beer, validated_data): errors = {} if contest_beer.beer.name != validated_data['beer']['name']: errors['name'] = ['Beer name cannot be changed through update'] if contest_beer.beer.brewery != validated_data['beer']['brewery']: errors['brewery'] = [ 'Brewery name value cannot be changed through update' ] if contest_beer.brewery.untappd_url != validated_data['beer'][ 'untappd_url']: errors['untappd_url'] = [ 'Untappd URL value cannot be changed through update' ] if len(errors) > 0: raise serializers.ValidationError(errors) contest_beer.point_value = validated_data['point_value'] contest_beer.save()
class SiteSearchSerializer(serializers.Serializer): site = serializers.URLField() query = serializers.CharField() class Meta: fields = ('query',)
class CodebaseSerializer(serializers.ModelSerializer, FeaturedImageMixin): absolute_url = serializers.URLField(source='get_absolute_url', read_only=True) all_contributors = ContributorSerializer(many=True, read_only=True) date_created = serializers.DateTimeField( read_only=True, default=serializers.CreateOnlyDefault(timezone.now)) download_count = serializers.IntegerField(read_only=True) first_published_at = serializers.DateTimeField( format=DATE_PUBLISHED_FORMAT, read_only=True) last_published_on = serializers.DateTimeField(format=DATE_PUBLISHED_FORMAT, read_only=True) latest_version_number = serializers.ReadOnlyField( source='latest_version.version_number') releases = serializers.SerializerMethodField() submitter = LinkedUserSerializer(read_only=True, default=serializers.CurrentUserDefault()) summarized_description = serializers.CharField(read_only=True) identifier = serializers.ReadOnlyField() tags = TagSerializer(many=True) # FIXME: output should be raw markdown, not rendered description = MarkdownField() def get_releases(self, obj): request = self.context.get('request') user = request.user if request else User.get_anonymous() queryset = CodebaseRelease.objects.filter( codebase_id=obj.pk).accessible(user).order_by('-version_number') # queryset = obj.releases.order_by('-version_number') return RelatedCodebaseReleaseSerializer(queryset, read_only=True, many=True, context=self.context).data def create(self, validated_data): serialized_tags = TagSerializer(many=True, data=validated_data.pop('tags')) codebase = Codebase(**validated_data) codebase.submitter = self.context['request'].user codebase.identifier = codebase.uuid set_tags(codebase, serialized_tags) codebase.save() return codebase def update(self, instance, validated_data): validated_data['draft'] = False return update(super().update, instance, validated_data) class Meta: model = Codebase fields = ( 'absolute_url', 'all_contributors', 'date_created', 'download_count', 'featured_image', 'repository_url', 'first_published_at', 'last_published_on', 'latest_version_number', 'releases', 'submitter', 'summarized_description', 'tags', 'description', 'title', 'doi', 'identifier', 'id', 'references_text', 'associated_publication_text', 'replication_text', 'peer_reviewed', )
class WriteCommentSerializer(serializers.Serializer): content_type = serializers.CharField() object_pk = serializers.CharField() timestamp = serializers.CharField() security_hash = serializers.CharField() honeypot = serializers.CharField(allow_blank=True) name = serializers.CharField(allow_blank=True) email = serializers.EmailField(allow_blank=True) url = serializers.URLField(required=False) comment = serializers.CharField(max_length=COMMENT_MAX_LENGTH) followup = serializers.BooleanField(default=False) reply_to = serializers.IntegerField(default=0) def __init__(self, *args, **kwargs): self.request = kwargs['context']['request'] super(WriteCommentSerializer, self).__init__(*args, **kwargs) def validate_name(self, value): if not len(value): if (not len(self.request.user.get_full_name()) or not self.request.user.is_authenticated): raise serializers.ValidationError("This field is required") else: return (self.request.user.get_full_name() or self.request.user.get_username()) return value def validate_email(self, value): if not len(value): if (not len(self.request.user.email) or not self.request.user.is_authenticated): raise serializers.ValidationError("This field is required") else: return self.request.user.email return value def validate(self, data): ctype = data.get("content_type") object_pk = data.get("object_pk") if ctype is None or object_pk is None: return serializers.ValidationError("Missing content_type or " "object_pk field.") try: model = apps.get_model(*ctype.split(".", 1)) target = model._default_manager.get(pk=object_pk) except TypeError: return serializers.ValidationError( "Invalid content_type value: %r" % escape(ctype)) except AttributeError: return serializers.ValidationError( "The given content-type %r does " "not resolve to a valid model." % escape(ctype)) except model.ObjectDoesNotExist: return serializers.ValidationError( "No object matching content-type %r and object PK %r exists." % (escape(ctype), escape(object_pk))) except (ValueError, serializers.ValidationError) as e: return serializers.ValidationError( "Attempting go get content-type %r and object PK %r exists " "raised %s" % (escape(ctype), escape(object_pk), e.__class__.__name__)) self.form = get_form()(target, data=data) # Check security information if self.form.security_errors(): return serializers.ValidationError( "The comment form failed security verification: %s" % escape(str(self.form.security_errors()))) if self.form.errors: return serializers.ValidationError(self.form.errors) return data def save(self): # resp object is a dictionary. The code key indicates the possible # four states the comment can be in: # * Comment created (http 201), # * Confirmation sent by mail (http 204), # * Comment in moderation (http 202), # * Comment rejected (http 403). site = get_current_site(self.request) resp = { 'code': -1, 'comment': self.form.get_comment_object(site_id=site.id) } resp['comment'].ip_address = self.request.META.get("REMOTE_ADDR", None) if self.request.user.is_authenticated: resp['comment'].user = self.request.user # Signal that the comment is about to be saved responses = comment_will_be_posted.send(sender=TmpXtdComment, comment=resp['comment'], request=self.request) for (receiver, response) in responses: if response is False: resp['code'] = 403 # Rejected. return resp # Replicate logic from django_comments_xtd.views.on_comment_was_posted. if (not settings.COMMENTS_XTD_CONFIRM_EMAIL or self.request.user.is_authenticated): if not views._comment_exists(resp['comment']): new_comment = views._create_comment(resp['comment']) resp['comment'].xtd_comment = new_comment confirmation_received.send(sender=TmpXtdComment, comment=resp['comment'], request=self.request) comment_was_posted.send(sender=new_comment.__class__, comment=new_comment, request=self.request) if resp['comment'].is_public: resp['code'] = 201 views.notify_comment_followers(new_comment) else: resp['code'] = 202 else: key = signed.dumps(resp['comment'], compress=True, extra_key=settings.COMMENTS_XTD_SALT) views.send_email_confirmation_request(resp['comment'], key, site) resp['code'] = 204 # Confirmation sent by mail. return resp
class BadgeInstanceSerializerV2(DetailSerializerV2, OriginalJsonSerializerMixin): openBadgeId = serializers.URLField(source='jsonld_id', read_only=True) createdAt = serializers.DateTimeField(source='created_at', read_only=True) createdBy = EntityRelatedFieldV2(source='cached_creator', read_only=True) badgeclass = EntityRelatedFieldV2(source='cached_badgeclass', required=False, queryset=BadgeClass.cached) badgeclassOpenBadgeId = CachedUrlHyperlinkedRelatedField( source='badgeclass_jsonld_id', view_name='badgeclass_json', lookup_field='entity_id', queryset=BadgeClass.cached, required=False) issuer = EntityRelatedFieldV2(source='cached_issuer', required=False, queryset=Issuer.cached) issuerOpenBadgeId = serializers.URLField(source='issuer_jsonld_id', read_only=True) image = serializers.FileField(read_only=True) recipient = BadgeRecipientSerializerV2(source='*', required=False) issuedOn = serializers.DateTimeField(source='issued_on', required=False) narrative = MarkdownCharField(required=False, allow_null=True) evidence = EvidenceItemSerializerV2(source='evidence_items', many=True, required=False) revoked = HumanReadableBooleanField(read_only=True) revocationReason = serializers.CharField(source='revocation_reason', read_only=True) expires = serializers.DateTimeField(source='expires_at', required=False, allow_null=True) notify = HumanReadableBooleanField(write_only=True, required=False, default=False) extensions = serializers.DictField(source='extension_items', required=False, validators=[BadgeExtensionValidator()]) class Meta(DetailSerializerV2.Meta): model = BadgeInstance apispec_definition = ('Assertion', { 'properties': OrderedDict([ ('entityId', { 'type': "string", 'format': "string", 'description': "Unique identifier for this Assertion", }), ('entityType', { 'type': "string", 'format': "string", 'description': "\"Assertion\"", }), ('openBadgeId', { 'type': "string", 'format': "url", 'description': "URL of the OpenBadge compliant json", }), ('createdAt', { 'type': 'string', 'format': 'ISO8601 timestamp', 'description': "Timestamp when the Assertion was created", }), ('createdBy', { 'type': 'string', 'format': 'entityId', 'description': "BadgeUser who created the Assertion", }), ('badgeclass', { 'type': 'string', 'format': 'entityId', 'description': "BadgeClass that issued this Assertion", }), ('badgeclassOpenBadgeId', { 'type': 'string', 'format': 'url', 'description': "URL of the BadgeClass to award", }), ('revoked', { 'type': 'boolean', 'description': "True if this Assertion has been revoked", }), ('revocationReason', { 'type': 'string', 'format': "string", 'description': "Short description of why the Assertion was revoked", }), ('image', { 'type': 'string', 'format': 'url', 'description': "URL to the baked assertion image", }), ('issuedOn', { 'type': 'string', 'format': 'ISO8601 timestamp', 'description': "Timestamp when the Assertion was issued", }), ('narrative', { 'type': 'string', 'format': 'markdown', 'description': "Markdown narrative of the achievement", }), ('evidence', { 'type': 'array', 'items': { '$ref': '#/definitions/AssertionEvidence' }, 'description': "List of evidence associated with the achievement" }), ('recipient', { 'type': 'object', 'properties': OrderedDict([ ('identity', { 'type': 'string', 'format': 'string', 'description': 'Either the hash of the identity or the plaintext value' }), ('type', { 'type': 'string', 'enum': [ c[0] for c in BadgeInstance.RECIPIENT_TYPE_CHOICES ], 'description': "Type of identifier used to identify recipient" }), ('hashed', { 'type': 'boolean', 'description': "Whether or not the identity value is hashed." }), ('plaintextIdentity', { 'type': 'string', 'description': "The plaintext identity" }), ]), 'description': "Recipient that was issued the Assertion" }), ('expires', { 'type': 'string', 'format': 'ISO8601 timestamp', 'description': "Timestamp when the Assertion expires", }), ]) }) def update(self, instance, validated_data): updateable_fields = [ 'evidence_items', 'expires_at', 'extension_items', 'hashed', 'issued_on', 'narrative', 'recipient_identifier', 'recipient_type' ] for field_name in updateable_fields: if field_name in validated_data: setattr(instance, field_name, validated_data.get(field_name)) instance.save() instance.rebake() return instance def validate(self, data): request = self.context.get('request', None) if request and request.method != 'PUT': # recipient and badgeclass are only required on create, ignored on update if 'recipient_identifier' not in data: raise serializers.ValidationError( {'recipient_identifier': ["This field is required"]}) if 'cached_badgeclass' in data: # included badgeclass in request data['badgeclass'] = data.pop('cached_badgeclass') elif 'badgeclass' in self.context: # badgeclass was passed in context data['badgeclass'] = self.context.get('badgeclass') elif 'badgeclass_jsonld_id' in data: data['badgeclass'] = data.pop('badgeclass_jsonld_id') else: raise serializers.ValidationError( {"badgeclass": ["This field is required"]}) expected_issuer = self.context.get('kwargs', {}).get('issuer') if expected_issuer and data['badgeclass'].issuer != expected_issuer: raise serializers.ValidationError({ "badgeclass": ["Could not find matching badgeclass for this issuer."] }) if 'badgeclass' in data: data['issuer'] = data['badgeclass'].issuer return data
class IntegrationSerializer(serializers.Serializer): name = serializers.CharField(required=False) domain = serializers.URLField(required=False, allow_blank=True)
class RunUpdateTaskSerializer(serializers.ModelSerializer): result = serializers.URLField(max_length=200, min_length=None, allow_blank=True, allow_null=True) class Meta: model = RunUpdateTask fields = '__all__'
class AddonSerializer(serializers.ModelSerializer): authors = AddonDeveloperSerializer(many=True, source='listed_authors') categories = serializers.SerializerMethodField() contributions_url = serializers.URLField(source='contributions') current_beta_version = SimpleVersionSerializer() current_version = SimpleVersionSerializer() description = TranslationSerializerField() developer_comments = TranslationSerializerField() edit_url = serializers.SerializerMethodField() has_eula = serializers.SerializerMethodField() has_privacy_policy = serializers.SerializerMethodField() homepage = TranslationSerializerField() icon_url = serializers.SerializerMethodField() is_source_public = serializers.BooleanField(source='view_source') is_featured = serializers.SerializerMethodField() name = TranslationSerializerField() previews = PreviewSerializer(many=True, source='all_previews') ratings = serializers.SerializerMethodField() review_url = serializers.SerializerMethodField() status = ReverseChoiceField(choices=amo.STATUS_CHOICES_API.items()) summary = TranslationSerializerField() support_email = TranslationSerializerField() support_url = TranslationSerializerField() tags = serializers.SerializerMethodField() theme_data = serializers.SerializerMethodField() type = ReverseChoiceField(choices=amo.ADDON_TYPE_CHOICES_API.items()) url = serializers.SerializerMethodField() class Meta: model = Addon fields = ('id', 'authors', 'average_daily_users', 'categories', 'contributions_url', 'current_beta_version', 'current_version', 'default_locale', 'description', 'developer_comments', 'edit_url', 'guid', 'has_eula', 'has_privacy_policy', 'homepage', 'icon_url', 'is_disabled', 'is_experimental', 'is_featured', 'is_source_public', 'last_updated', 'name', 'previews', 'public_stats', 'ratings', 'requires_payment', 'review_url', 'slug', 'status', 'summary', 'support_email', 'support_url', 'tags', 'theme_data', 'type', 'url', 'weekly_downloads') def to_representation(self, obj): data = super(AddonSerializer, self).to_representation(obj) if 'theme_data' in data and data['theme_data'] is None: data.pop('theme_data') if 'homepage' in data: data['homepage'] = self.outgoingify(data['homepage']) if 'support_url' in data: data['support_url'] = self.outgoingify(data['support_url']) if obj.type == amo.ADDON_PERSONA: if 'weekly_downloads' in data: # weekly_downloads don't make sense for lightweight themes. data.pop('weekly_downloads') if ('average_daily_users' in data and not self.is_broken_persona(obj)): # In addition, their average_daily_users number must come from # the popularity field of the attached Persona. data['average_daily_users'] = obj.persona.popularity return data def outgoingify(self, data): if isinstance(data, basestring): return get_outgoing_url(data) elif isinstance(data, dict): return { key: get_outgoing_url(value) if value else None for key, value in data.items() } # Probably None... don't bother. return data def get_categories(self, obj): # Return a dict of lists like obj.app_categories does, but exposing # slugs for keys and values instead of objects. return { app.short: [cat.slug for cat in obj.app_categories[app]] for app in obj.app_categories.keys() } def get_has_eula(self, obj): return bool(getattr(obj, 'has_eula', obj.eula)) def get_is_featured(self, obj): # obj._is_featured is set from ES, so will only be present for list # requests. if not hasattr(obj, '_is_featured'): # Any featuring will do. obj._is_featured = obj.is_featured(app=None, lang=None) return obj._is_featured def get_has_privacy_policy(self, obj): return bool(getattr(obj, 'has_privacy_policy', obj.privacy_policy)) def get_tags(self, obj): if not hasattr(obj, 'tag_list'): attach_tags([obj]) # attach_tags() might not have attached anything to the addon, if it # had no tags. return getattr(obj, 'tag_list', []) def get_url(self, obj): return absolutify(obj.get_url_path()) def get_edit_url(self, obj): return absolutify(obj.get_dev_url()) def get_review_url(self, obj): return absolutify(reverse('reviewers.review', args=[obj.pk])) def get_icon_url(self, obj): if self.is_broken_persona(obj): return absolutify(obj.get_default_icon_url(64)) return absolutify(obj.get_icon_url(64)) def get_ratings(self, obj): return { 'average': obj.average_rating, 'bayesian_average': obj.bayesian_rating, 'count': obj.total_ratings, 'text_count': obj.text_ratings_count, } def get_theme_data(self, obj): theme_data = None if obj.type == amo.ADDON_PERSONA and not self.is_broken_persona(obj): theme_data = obj.persona.theme_data return theme_data def is_broken_persona(self, obj): """Find out if the object is a Persona and either is missing its Persona instance or has a broken one. Call this everytime something in the serializer is suceptible to call something on the Persona instance, explicitly or not, to avoid 500 errors and/or SQL queries in ESAddonSerializer.""" try: # Sadly, https://code.djangoproject.com/ticket/14368 prevents us # from setting obj.persona = None in ESAddonSerializer.fake_object # below. This is fixed in Django 1.9, but in the meantime we work # around it by creating a Persona instance with a custom '_broken' # attribute indicating that it should not be used. if obj.type == amo.ADDON_PERSONA and ( obj.persona is None or hasattr(obj.persona, '_broken')): raise Persona.DoesNotExist except Persona.DoesNotExist: # We got a DoesNotExist exception, therefore the Persona does not # exist or is broken. return True # Everything is fine, move on. return False
class TinyUrlSerializer(serializers.Serializer): url = serializers.URLField(max_length=5000)
class UserSerializer(DoNotRelateWhenAnonymous, JSONAPISerializer): filterable_fields = frozenset( ['full_name', 'given_name', 'middle_names', 'family_name', 'id']) non_anonymized_fields = ['type'] 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( AllowMissing(ser.CharField(required=False, source='social.github', allow_blank=True, help_text='GitHub Handle'), required=False, source='social.github')) scholar = DevOnly( AllowMissing(ser.CharField(required=False, source='social.scholar', allow_blank=True, help_text='Google Scholar Account'), required=False, source='social.scholar')) personal_website = DevOnly( AllowMissing(ser.URLField(required=False, source='social.personal', allow_blank=True, help_text='Personal Website'), required=False, source='social.personal')) twitter = DevOnly( AllowMissing(ser.CharField(required=False, source='social.twitter', allow_blank=True, help_text='Twitter Handle'), required=False, source='social.twitter')) linkedIn = DevOnly( AllowMissing(ser.CharField(required=False, source='social.linkedIn', allow_blank=True, help_text='LinkedIn Account'), required=False, source='social.linkedIn')) impactStory = DevOnly( AllowMissing(ser.CharField(required=False, source='social.impactStory', allow_blank=True, help_text='ImpactStory Account'), required=False, source='social.impactStory')) orcid = DevOnly( AllowMissing(ser.CharField(required=False, source='social.orcid', allow_blank=True, help_text='ORCID'), required=False, source='social.orcid')) researcherId = DevOnly( AllowMissing(ser.CharField(required=False, source='social.researcherId', allow_blank=True, help_text='ResearcherId Account'), required=False, source='social.researcherId')) links = LinksField( add_dev_only_items({ 'html': 'absolute_url', }, { 'profile_image': 'profile_image_url', })) nodes = RelationshipField( related_view='users:user-nodes', related_view_kwargs={'user_id': '<pk>'}, ) class Meta: type_ = 'users' def absolute_url(self, obj): if obj is not None: return obj.absolute_url return None def profile_image_url(self, user): size = self.context['request'].query_params.get('profile_image_size') return user.profile_image_url(size=size) 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) try: instance.save() except ValidationValueError as e: raise InvalidModelValueError(detail=e.message) return instance
class SearchImageByUrlSerializer(serializers.Serializer): image_url = serializers.URLField() # todo: add checks for proper url partitions = serializers.ListField(required=False) maximum_rating = serializers.CharField(required=False)
class ApplicationInfoSerializer(serializers.Serializer): name = serializers.CharField(read_only=True, source='get_visible_name') image = serializers.URLField(read_only=True, source='get_icon_url') website_url = serializers.URLField(read_only=True)
class IssuerSerializerV1(OriginalJsonSerializerMixin, serializers.Serializer): created_at = DateTimeWithUtcZAtEndField(read_only=True) created_by = BadgeUserIdentifierFieldV1() name = StripTagsCharField(max_length=1024) slug = StripTagsCharField(max_length=255, source='entity_id', read_only=True) image = ValidImageField(required=False) email = serializers.EmailField(max_length=255, required=True) description = StripTagsCharField(max_length=16384, required=False) url = serializers.URLField(max_length=1024, required=True) staff = IssuerStaffSerializerV1(read_only=True, source='cached_issuerstaff', many=True) badgrapp = serializers.CharField(read_only=True, max_length=255, source='cached_badgrapp') class Meta: apispec_definition = ('Issuer', {}) def validate_image(self, image): if image is not None: img_name, img_ext = os.path.splitext(image.name) image.name = 'issuer_logo_' + str(uuid.uuid4()) + img_ext return image def create(self, validated_data, **kwargs): user = validated_data['created_by'] potential_email = validated_data['email'] if not user.is_email_verified(potential_email): raise serializers.ValidationError( "Issuer email must be one of your verified addresses. Add this email to your profile and try again." ) new_issuer = Issuer(**validated_data) # set badgrapp new_issuer.badgrapp = BadgrApp.objects.get_current( self.context.get('request', None)) new_issuer.save() return new_issuer def update(self, instance, validated_data): force_image_resize = False instance.name = validated_data.get('name') if 'image' in validated_data: instance.image = validated_data.get('image') force_image_resize = True instance.email = validated_data.get('email') instance.description = validated_data.get('description') instance.url = validated_data.get('url') # set badgrapp if not instance.badgrapp_id: instance.badgrapp = BadgrApp.objects.get_current( self.context.get('request', None)) instance.save(force_resize=force_image_resize) return instance def to_representation(self, obj): representation = super(IssuerSerializerV1, self).to_representation(obj) representation['json'] = obj.get_json(obi_version='1_1', use_canonical_id=True) if self.context.get('embed_badgeclasses', False): representation['badgeclasses'] = BadgeClassSerializerV1( obj.badgeclasses.all(), many=True, context=self.context).data representation['badgeClassCount'] = len(obj.cached_badgeclasses()) representation['recipientGroupCount'] = len( obj.cached_recipient_groups()) representation['recipientCount'] = sum( g.member_count() for g in obj.cached_recipient_groups()) representation['pathwayCount'] = len(obj.cached_pathways()) return representation
class PostSerializer(serializers.ModelSerializer): status = serializers.CharField(source='get_status_display') word_count = serializers.IntegerField() reading_time = serializers.IntegerField() post_absolute_url = serializers.URLField(source='get_absolute_url') author_username = serializers.CharField(source='author.get_username') author_first_name = serializers.CharField(source='author.first_name') author_last_name = serializers.CharField(source='author.last_name') author_full_name = serializers.CharField(source='author.get_full_name') author_initials = serializers.CharField(source='author.profile.initials') author_display_name = serializers.CharField( source='author.profile.display_name') author_join_year = serializers.IntegerField( source='author.profile.join_year') author_view = serializers.IntegerField(source='author.profile.author_view') author_created_date = serializers.DateTimeField( source='author.profile.created_date') author_updated_date = serializers.DateTimeField( source='author.profile.updated_date') author_absolute_url = serializers.URLField( source='author.profile.get_absolute_url') author_profile_picture = serializers.ImageField( source='author.profile.profile_picture') categories = CategorySerializer(many=True, read_only=True) class Meta: model = Post fields = ( # Post fields 'id', 'title', 'slug', 'content', 'reference_url', 'publish_date', 'updated_date', 'image', 'status', 'word_count', 'reading_time', 'post_absolute_url', # Author fields 'author_username', 'author_first_name', 'author_last_name', 'author_full_name', 'author_initials', 'author_display_name', 'author_join_year', 'author_view', 'author_created_date', 'author_updated_date', 'author_absolute_url', 'author_profile_picture', # Category fields 'categories', ) def get_status(self, obj): return obj.get_status_display() # pragma: no cover ordering = ( '-updated_date', '-publish_date', )
class EventDetailsUpdateSerializer(serializers.Serializer): title = serializers.CharField( required=True, allow_null=False, ) description = serializers.CharField( required=True, allow_null=False, ) event_logo_image = serializers.JSONField( required=False, allow_null=True, ) external_url = serializers.URLField( required=False, allow_null=True, ) shown_to_whom = serializers.IntegerField( required=False, allow_null=True, ) can_be_posted_on_social_media = serializers.BooleanField( required=False, allow_null=True, ) def update(self, instance, validated_data): """ Override the `create` function to add extra functinality. """ request = self.context.get("request") title = validated_data.get("title") description = validated_data.get('description') event_logo_image = validated_data.get('event_logo_image') external_url = validated_data.get('external_url') shown_to_whom = validated_data.get('shown_to_whom') can_be_posted_on_social_media = validated_data.get( 'can_be_posted_on_social_media') # DEVELOPERS NOTE: # (1) The following code will either update the `event_logo_image` or # create a new image. # (2) Check to see if a previous image was uploaded and if so then # we need to delete it. event_logo_image_slug = event_logo_image.get("slug") if event_logo_image_slug: instance.event_logo_image__slug = event_logo_image_slug else: # print(event_logo_image) # For debugging purposes only. data = event_logo_image.get('data', None) filename = event_logo_image.get('file_name', None) if settings.DEBUG: filename = "QA_" + filename # NOTE: Attach `QA_` prefix if server running in QA mode. content_file = get_content_file_from_base64_string(data, filename) if instance.event_logo_image: instance.event_logo_image.delete() instance.event_logo_image = None private_image = PrivateImageUpload.objects.create( item=instance, user=request.user, image_file=content_file, created_by=request.user, created_from=request.client_ip, created_from_is_public=request.client_ip_is_routable, last_modified_by=request.user, last_modified_from=request.client_ip, last_modified_from_is_public=request.client_ip_is_routable, ) instance.event_logo_image = private_image # print("Created - event_logo_image") # Save it. instance.title = title instance.description = description instance.external_url = external_url instance.shown_to_whom = shown_to_whom instance.can_be_posted_on_social_media = can_be_posted_on_social_media instance.last_modified_by = request.user instance.last_modified_from = request.client_ip instance.last_modified_from_is_public = request.client_ip_is_routable instance.save() # raise serializers.ValidationError({ # Uncomment when not using this code but do not delete! # "error": "Terminating for debugging purposes only." # }) return instance
class QuestSerializer(SBSerializer): active = serializers.BooleanField(required=False) title = serializers.CharField(required=False, allow_blank=True, max_length=70) about = serializers.CharField(required=False, allow_blank=True, max_length=128) facebook = serializers.URLField(required=False, allow_blank=True) linkedin = serializers.URLField(required=False, allow_blank=True) youtube = serializers.URLField(required=False, allow_blank=True) twitter = serializers.URLField(required=False, allow_blank=True) website = serializers.URLField(required=False, allow_blank=True) wallpaper_pic = serializers.CharField(required=False) profile_pic = serializers.CharField(required=False) owner_username = serializers.CharField(read_only=True) first_name = serializers.CharField(read_only=True) last_name = serializers.CharField(read_only=True) stripe_token = serializers.CharField(write_only=True, required=False) customer_token = serializers.CharField(write_only=True, required=False) tos_acceptance = serializers.BooleanField(required=False) stripe_account_type = serializers.ChoiceField( required=False, choices=[('business', "Business"), ('individual', "Individual")], ) account_owner = serializers.CharField(required=False, allow_blank=True) stripe_default_card_id = serializers.CharField(write_only=True, required=False, allow_blank=True) ein = serializers.CharField(write_only=True, required=False, allow_blank=True) routing_number = serializers.CharField(write_only=True, required=False) account_number = serializers.CharField(write_only=True, required=False) ssn = serializers.CharField(write_only=True, required=False) promotion_key = serializers.CharField(write_only=True, required=False) account_type = serializers.ChoiceField(required=False, choices=[('paid', "Paid"), ('free', "Free"), ('promotion', "Promotion") ]) account_verified = serializers.ChoiceField(read_only=True, choices=[('unverified', "Unverified"), ('pending', "Pending"), ('verified', "Verified")]) application_fee = serializers.FloatField(read_only=True) # https://stripe.com/docs/connect/identity-verification # #confirming-id-verification # fields_needed is a list of fields that are still required for # verification of the managed account # ex. ["legal_entity.type", "legal_entity.business_name"] account_verification_fields_needed = serializers.ListField(read_only=True) verification_document_needed = serializers.BooleanField(read_only=True) verification_due_date = serializers.BooleanField(read_only=True) verification_disabled_reason = serializers.CharField(read_only=True) # https://stripe.com/docs/connect/identity-verification # #confirming-id-verification # verification_details is a user readable string that will contain a string # describing an problems with verification such as a corrupted/unreadable # image has been uploaded. # ex. "The image supplied was not readable" account_verification_details = serializers.CharField(read_only=True) url = serializers.SerializerMethodField() href = serializers.SerializerMethodField() updates = serializers.SerializerMethodField() is_editor = serializers.SerializerMethodField() is_moderator = serializers.SerializerMethodField() is_following = serializers.SerializerMethodField() completed_stripe = serializers.SerializerMethodField() completed_customer = serializers.SerializerMethodField() missions = serializers.SerializerMethodField() endorsed = serializers.SerializerMethodField() total_donation_amount = serializers.SerializerMethodField() fields_needed_human_readable = serializers.SerializerMethodField() identification_sent = serializers.SerializerMethodField() has_address = serializers.SerializerMethodField() title_summary = serializers.SerializerMethodField() def create(self, validated_data): stripe.api_key = settings.STRIPE_SECRET_KEY stripe.api_version = settings.STRIPE_API_VERSION request = self.context.get('request', None) account_type = validated_data.get('account_type', "free") tos_acceptance = validated_data.get('tos_acceptance', False) owner = Pleb.get(username=request.user.username) if owner.get_quest(): raise serializers.ValidationError( detail={ "detail": "You may only have one Quest!", "developer_message": "", "status_code": status.HTTP_400_BAD_REQUEST }) default_title = "%s %s" % (owner.first_name, owner.last_name) quest = Quest(first_name=owner.first_name, last_name=owner.last_name, owner_username=owner.username, object_uuid=owner.username, profile_pic=owner.profile_pic, account_type=account_type, title=default_title).save() quest.owner.connect(owner) quest.editors.connect(owner) quest.moderators.connect(owner) account = stripe.Account.create(managed=True, country="US", email=owner.email) quest.stripe_id = account['id'] x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') if x_forwarded_for: ip = x_forwarded_for.split(',')[0] else: ip = request.META.get('REMOTE_ADDR') account.legal_entity.additional_owners = [] if tos_acceptance: account.tos_acceptance.ip = ip account.tos_acceptance.date = int(time.time()) quest.tos_acceptance = True quest.save() account.save() # Potential optimization in combining these utilizing a transaction # Added these to ensure that the user has intercom when they hit the # Quest page for the first time. The privilege still is fired through # the spawn_task as a backup and to ensure all connections are made # correctly epoch_date = datetime(1970, 1, 1, tzinfo=pytz.utc) current_time = float( (datetime.now(pytz.utc) - epoch_date).total_seconds()) query = 'MATCH (pleb:Pleb {username: "******"}) WITH pleb ' \ 'MATCH (privilege:Privilege {name: "quest"}) WITH ' \ 'pleb, privilege ' \ 'MATCH (action:SBAction {resource: "intercom", ' \ 'permission: "write"}) WITH ' \ 'pleb, privilege, action CREATE UNIQUE ' \ '(action)<-[:CAN {active: true, gained_on: %f}]-(pleb)' \ '-[r:HAS {active: true, gained_on: %f}]->(privilege) ' \ 'RETURN r' % (owner.username, current_time, current_time) db.cypher_query(query) cache.set("%s_quest" % quest.object_uuid, quest) cache.delete(owner.username) cache.set("%s_privileges" % owner.username, owner.get_privileges(cache_buster=True)) cache.set("%s_actions" % owner.username, owner.get_actions(cache_buster=True)) spawn_task(task_func=check_privileges, task_param={"username": owner.username}) return quest def update(self, instance, validated_data): from sb_base.serializers import validate_is_owner logger.critical(validated_data) logger.critical('Updating Quest') if instance.owner_username == "andrea_nickelson": if validated_data.get('ssn', None) is not None: instance.ssn_temp = validated_data.get('ssn', "") if validated_data.get('routing_number', None) is not None: instance.routing_number_temp = validated_data.get( 'routing_number', "") if validated_data.get('account_number', None) is not None: instance.bank_account_temp = validated_data.get( 'account_number', "") instance.save() return instance request = self.context.get('request', None) validate_is_owner(request, instance, self.context.get('secret')) stripe.api_key = settings.STRIPE_SECRET_KEY stripe.api_version = settings.STRIPE_API_VERSION address = request.data.get('address') if address is not None: address_serializer = AddressSerializer( data=address, context={'request', request}) address_serializer.is_valid(raise_exception=True) address = address_serializer.save() query = 'MATCH (a:Quest {object_uuid: "%s"}) ' \ 'OPTIONAL MATCH (a)-[r:LOCATED_AT]-(:Address) ' \ 'DELETE r' % instance.object_uuid res, _ = db.cypher_query(query) instance.address.connect(address) stripe_token = validated_data.pop('stripe_token', None) promotion_key = validated_data.pop('promotion_key', None) customer_token = validated_data.pop('customer_token', instance.customer_token) account_type = validated_data.get('account_type', instance.account_type) instance.stripe_account_type = validated_data.get( 'stripe_account_type', instance.stripe_account_type) instance.account_owner = validated_data.get('account_owner', instance.account_owner) initial_state = instance.active customer = None ein = validated_data.pop('ein', instance.ein) ssn = validated_data.pop('ssn', instance.ssn) # ** Standard Settings Update ** # Remove any dashes from the ssn input. if ssn is not None: ssn = ssn.replace('-', "") active = validated_data.pop('active', instance.active) if initial_state is False and active is True: serializer = IntercomEventSerializer( data={ 'event_name': "take-quest-live", 'username': instance.owner_username }) # Don't raise an error because we rather not notify intercom than # hold up the quest activation process if serializer.is_valid(): serializer.save() db.cypher_query( 'MATCH (quest:Quest {object_uuid: "%s"})-[:EMBARKS_ON]' '-(mission:Mission)-' '[:MUST_COMPLETE]->(task:OnboardingTask {title: "%s"}) ' 'SET task.completed=true RETURN task' % (instance.object_uuid, settings.BANK_SETUP_TITLE)) instance.active = active instance.title = empty_text_to_none( validated_data.pop('title', instance.title)) instance.facebook = clean_url( validated_data.get('facebook', instance.facebook)) instance.linkedin = clean_url( validated_data.get('linkedin', instance.linkedin)) instance.youtube = clean_url( validated_data.get('youtube', instance.youtube)) instance.twitter = clean_url( validated_data.get('twitter', instance.twitter)) if initial_state is True and active is False: remove_search_object(instance.object_uuid, "quest") # TODO make all missions inactive upon taking quest inactive instance.website = clean_url( validated_data.get('website', instance.website)) instance.about = empty_text_to_none( validated_data.get('about', instance.about)) if instance.about is not None: db.cypher_query( 'MATCH (quest:Quest {object_uuid: "%s"})-[:EMBARKS_ON]' '-(mission:Mission)-' '[:MUST_COMPLETE]->(task:OnboardingTask {title: "%s"}) ' 'SET task.completed=true RETURN task' % (instance.object_uuid, settings.QUEST_ABOUT_TITLE)) instance.wallpaper_pic = validated_data.get('wallpaper_pic', instance.wallpaper_pic) if settings.DEFAULT_WALLPAPER not in instance.wallpaper_pic: db.cypher_query( 'MATCH (quest:Quest {object_uuid: "%s"})-[:EMBARKS_ON]' '-(mission:Mission)-' '[:MUST_COMPLETE]->(task:OnboardingTask {title: "%s"}) ' 'SET task.completed=true RETURN task' % (instance.object_uuid, settings.QUEST_WALLPAPER_TITLE)) instance.profile_pic = validated_data.get('profile_pic', instance.profile_pic) owner = Pleb.get(username=instance.owner_username) # ** Customer Creation/Card Assignment If Provided ** if customer_token is not None: # Customers must provide a credit card for us to create a customer # with stripe. Get the credit card # and create a customer instance # so we can charge it in the future. if instance.stripe_customer_id is None: customer = stripe.Customer.create( description="Customer for %s Quest" % instance.object_uuid, card=customer_token, email=owner.email) instance.stripe_customer_id = customer['id'] instance.stripe_default_card_id = customer['sources']['data'][ 0]['id'] else: customer = stripe.Customer.retrieve( instance.stripe_customer_id) card = customer.sources.create(source=customer_token) instance.stripe_default_card_id = card['id'] elif customer_token is None and account_type == "promotion": if instance.stripe_customer_id is None: customer = stripe.Customer.create( description="Customer for %s Quest" % instance.object_uuid, email=owner.email) instance.stripe_customer_id = customer['id'] # ** Account plan updating process ** if account_type != instance.account_type: if customer is None: customer = stripe.Customer.retrieve( instance.stripe_customer_id) if account_type == "paid": # if paid gets submitted create a subscription if it doesn't # already exist if instance.stripe_subscription_id is None: sub = customer.subscriptions.create(plan='quest_premium') instance.stripe_subscription_id = sub['id'] instance.application_fee = settings.STRIPE_PAID_ACCOUNT_FEE instance.account_type = account_type elif account_type == "promotion": if promotion_key in settings.PROMOTION_KEYS \ and settings.PRO_QUEST_PROMOTION: if datetime.now() < settings.PRO_QUEST_END_DATE: next_year = datetime.now() + relativedelta(years=+1) unix_stamp = time.mktime(next_year.timetuple()) # Only allow people without subscriptions to create # a new one with a trial. # TODO for existing customers we need to create # coupons through Stripe so that we don't have # duplicate subscriptions associated with one # user. if instance.stripe_subscription_id is None: sub = customer.subscriptions.create( plan='quest_premium', trial_end=int(unix_stamp)) instance.stripe_subscription_id = sub['id'] instance.application_fee = \ settings.STRIPE_PAID_ACCOUNT_FEE else: account_type = instance.account_type else: account_type = instance.account_type elif account_type == "free": # if we get a free submission and the subscription is already # set cancel it. if instance.stripe_subscription_id is not None: customer.subscriptions.retrieve( instance.stripe_subscription_id).delete() instance.stripe_subscription_id = None instance.application_fee = settings.STRIPE_FREE_ACCOUNT_FEE instance.account_type = account_type instance.account_type = account_type # ** Stripe update Address ** if address is not None: account = stripe.Account.retrieve(instance.stripe_id) street_additional = empty_text_to_none(address.street_additional) account.legal_entity.address.line1 = address.street account.legal_entity.address.line2 = street_additional account.legal_entity.address.city = address.city account.legal_entity.address.state = address.state account.legal_entity.address.postal_code = address.postal_code account.legal_entity.address.country = "US" account.save() # ** Managed Account Setup ** if stripe_token is not None: if instance.stripe_id is None or instance.stripe_id == "Not Set": account = stripe.Account.create(managed=True, country="US", email=owner.email) instance.stripe_id = account['id'] else: account = stripe.Account.retrieve(instance.stripe_id) try: account.external_accounts.create(external_account=stripe_token, default_for_currency=True) except InvalidRequestError: raise serializers.ValidationError( detail={ "detail": "Looks like we're having server " "issues, please contact us using the " "bubble in the bottom right", "status_code": status.HTTP_400_BAD_REQUEST }) query = 'MATCH (a:Quest {owner_username: "******"})' \ '-[:LOCATED_AT]->(b:Address) ' \ 'RETURN b' % instance.owner_username res, _ = db.cypher_query(query) account_address = Address.inflate(res.one) if not instance.tos_acceptance: request = self.context.get('request', None) if request is not None: x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') if x_forwarded_for: ip = x_forwarded_for.split(',')[0] else: ip = request.META.get('REMOTE_ADDR') account.tos_acceptance.ip = ip account.tos_acceptance.date = int(time.time()) instance.tos_acceptance = True account.legal_entity.additional_owners = [] account.legal_entity.personal_id_number = ssn if ein: account.legal_entity.business_tax_id = ein account.legal_entity.first_name = owner.first_name account.legal_entity.last_name = owner.last_name if instance.account_owner != "" \ and instance.account_owner is not None: account.business_name = instance.account_owner account.legal_entity.business_name = instance.account_owner stripe_account_type = instance.stripe_account_type if stripe_account_type == "business": stripe_account_type = 'company' account.legal_entity.type = stripe_account_type street_additional = empty_text_to_none( account_address.street_additional) account.legal_entity.address.line1 = account_address.street account.legal_entity.address.line2 = street_additional account.legal_entity.address.city = account_address.city account.legal_entity.address.state = account_address.state account.legal_entity.address.postal_code = \ account_address.postal_code account.legal_entity.address.country = "US" owner = Pleb.get(username=request.user.username) account.legal_entity.dob.day = owner.date_of_birth.day account.legal_entity.dob.month = owner.date_of_birth.month account.legal_entity.dob.year = owner.date_of_birth.year try: account = account.save() except stripe.InvalidRequestError: raise serializers.ValidationError( detail={ "detail": "Sorry, you can't change your " "Social Security Number after you " "have been verified. Please contact " "support at [email protected] " "or by using the " "bubble in the bottom right.", "status_code": status.HTTP_400_BAD_REQUEST }) # Default to pending to make sure customer doesn't think nothing # is happening on a slow update from Stripe. We can revert back # to unverified if Stripe alerts us to it. verification = "pending" if account.legal_entity.verification.status == "verified": verification = account.legal_entity.verification.status instance.account_verified = verification instance.last_four_soc = ssn[-4:] instance.save() cache.delete("%s_quest" % instance.owner_username) # ** Search Update ** if instance.active: return super(QuestSerializer, self).update(instance, validated_data) return instance def get_url(self, obj): if obj.owner_username is not None and obj.owner_username != "": # We need a try catch here as there are some campaigns that have # username set but may not have a Pleb. This is only seen in tests # and has not been observed in production. username = obj.owner_username else: username = obj.object_uuid return reverse('quest', kwargs={"username": username}, request=self.context.get('request', None)) def get_href(self, obj): return reverse('quest-detail', kwargs={'owner_username': obj.owner_username}, request=self.context.get('request', None)) def get_updates(self, obj): request, _, _, relation, _ = gather_request_data(self.context) updates = Quest.get_updates(obj.object_uuid) if relation == 'hyperlink': return [ reverse('update-detail', kwargs={'object_uuid': update}, request=request) for update in updates ] return updates def get_completed_stripe(self, obj): # Whether or not the user has completed the initial registration with # Stripe or not. This doesn't have anything to do with verification # it just indicates that the user submitted data to Stripe and # has started the process if obj.stripe_id == "Not Set": return False return True def get_is_editor(self, obj): request, _, _, _, _ = gather_request_data(self.context) if request is None: return None return request.user.username in Quest.get_editors(obj.object_uuid) def get_is_moderator(self, obj): request, _, _, _, _ = gather_request_data(self.context) if request is None: return None return request.user.username in Quest.get_moderators(obj.object_uuid) def get_completed_customer(self, obj): if obj.stripe_customer_id is None: return False return True def get_endorsed(self, obj): from sb_missions.neo_models import Mission from sb_missions.serializers import MissionSerializer expand = self.context.get('expand', 'false').lower() query = 'MATCH (quest:Quest {owner_username: "******"})-[:ENDORSES]->' \ '(mission:Mission) RETURN mission' % obj.owner_username res, _ = db.cypher_query(query) if res.one is None: return None if expand == 'true': return [ MissionSerializer(Mission.inflate(row[0])).data for row in res ] return [ reverse( 'mission-detail', kwargs={'object_uuid': Mission.inflate(row[0]).object_uuid}, request=self.context.get('request', None)) for row in res ] def get_missions(self, obj): from sb_missions.neo_models import Mission from sb_missions.serializers import MissionSerializer expand = self.context.get('expand', 'false').lower() query = 'MATCH (quest:Quest {owner_username: "******"})-[:EMBARKS_ON]->' \ '(mission:Mission) RETURN mission' % obj.owner_username res, _ = db.cypher_query(query) if res.one is None: return None if expand == 'true': return [ MissionSerializer(Mission.inflate(row[0])).data for row in res ] return [ reverse( 'mission-detail', kwargs={'object_uuid': Mission.inflate(row[0]).object_uuid}, request=self.context.get('request', None)) for row in res ] def get_total_donation_amount(self, obj): return obj.get_total_donation_amount() def get_is_following(self, obj): request, _, _, _, _ = gather_request_data(self.context) if request is None: return None return obj.is_following(request.user.username) def get_fields_needed_human_readable(self, obj): if obj.account_verification_fields_needed is not None: return (','.join([ settings.STRIPE_FIELDS_NEEDED[field_needed] for field_needed in obj.account_verification_fields_needed ])) else: return None def get_identification_sent(self, obj): return obj.stripe_identification_sent def get_has_address(self, obj): query = 'MATCH (p:Quest {owner_username: "******"}) ' \ 'OPTIONAL MATCH (p)-[r:LOCATED_AT]->(b:Address) ' \ 'RETURN r IS NOT NULL as has_address' % obj.owner_username res, _ = db.cypher_query(query) return res.one def get_title_summary(self, obj): if obj.title is not None: if len(obj.title) > 20: return smart_truncate(obj.title, 20) return obj.title
class BadgeClassSerializerV2(DetailSerializerV2, OriginalJsonSerializerMixin): openBadgeId = serializers.URLField(source='jsonld_id', read_only=True) createdAt = serializers.DateTimeField(source='created_at', read_only=True) createdBy = EntityRelatedFieldV2(source='cached_creator', read_only=True) issuer = EntityRelatedFieldV2(source='cached_issuer', required=False, queryset=Issuer.cached) issuerOpenBadgeId = serializers.URLField(source='issuer_jsonld_id', read_only=True) name = StripTagsCharField(max_length=1024) image = ValidImageField(required=False) description = StripTagsCharField(max_length=16384, required=True, convert_null=True) criteriaUrl = StripTagsCharField(source='criteria_url', required=False, allow_null=True, validators=[URLValidator()]) criteriaNarrative = MarkdownCharField(source='criteria_text', required=False, allow_null=True) alignments = AlignmentItemSerializerV2(source='alignment_items', many=True, required=False) tags = serializers.ListField(child=StripTagsCharField(max_length=1024), source='tag_items', required=False) extensions = serializers.DictField(source='extension_items', required=False, validators=[BadgeExtensionValidator()]) class Meta(DetailSerializerV2.Meta): model = BadgeClass apispec_definition = ('BadgeClass', { 'properties': OrderedDict([ ('entityId', { 'type': "string", 'format': "string", 'description': "Unique identifier for this BadgeClass", }), ('entityType', { 'type': "string", 'format': "string", 'description': "\"BadgeClass\"", }), ('openBadgeId', { 'type': "string", 'format': "url", 'description': "URL of the OpenBadge compliant json", }), ('createdAt', { 'type': 'string', 'format': 'ISO8601 timestamp', 'description': "Timestamp when the BadgeClass was created", }), ('createdBy', { 'type': 'string', 'format': 'entityId', 'description': "BadgeUser who created this BadgeClass", }), ('issuer', { 'type': 'string', 'format': 'entityId', 'description': "entityId of the Issuer who owns the BadgeClass", }), ('name', { 'type': "string", 'format': "string", 'description': "Name of the BadgeClass", }), ('description', { 'type': "string", 'format': "string", 'description': "Short description of the BadgeClass", }), ('image', { 'type': "string", 'format': "data:image/png;base64", 'description': "Base64 encoded string of an image that represents the BadgeClass.", }), ('criteriaUrl', { 'type': "string", 'format': "url", 'description': "External URL that describes in a human-readable format the criteria for the BadgeClass" }), ('criteriaNarrative', { 'type': "string", 'format': "markdown", 'description': "Markdown formatted description of the criteria" }), ('tags', { 'type': "array", 'items': { 'type': "string", 'format': "string" }, 'description': "List of tags that describe the BadgeClass" }), ('alignments', { 'type': "array", 'items': { '$ref': '#/definitions/BadgeClassAlignment' }, 'description': "List of objects describing objectives or educational standards" }), ]) }) def update(self, instance, validated_data): if 'cached_issuer' in validated_data: validated_data.pop('cached_issuer') # issuer is not updatable return super(BadgeClassSerializerV2, self).update(instance, validated_data) def create(self, validated_data): if 'cached_issuer' in validated_data: # included issuer in request validated_data['issuer'] = validated_data.pop('cached_issuer') elif 'issuer' in self.context: # issuer was passed in context validated_data['issuer'] = self.context.get('issuer') else: # issuer is required on create raise serializers.ValidationError( {"issuer": "This field is required"}) return super(BadgeClassSerializerV2, self).create(validated_data)
class DeploySerializer(serializers.Serializer): name = serializers.CharField(max_length=64, required=False) environment = serializers.CharField(max_length=64) url = serializers.URLField(required=False) dateStarted = serializers.DateTimeField(required=False) dateFinished = serializers.DateTimeField(required=False)
class IssuerSerializerV2(DetailSerializerV2, OriginalJsonSerializerMixin): openBadgeId = serializers.URLField(source='jsonld_id', read_only=True) createdAt = serializers.DateTimeField(source='created_at', read_only=True) createdBy = EntityRelatedFieldV2(source='cached_creator', read_only=True) name = StripTagsCharField(max_length=1024) image = ValidImageField(required=False) email = serializers.EmailField(max_length=255, required=True) description = StripTagsCharField(max_length=16384, required=False) url = serializers.URLField(max_length=1024, required=True) staff = IssuerStaffSerializerV2(many=True, source='staff_items', required=False) extensions = serializers.DictField(source='extension_items', required=False, validators=[BadgeExtensionValidator()]) class Meta(DetailSerializerV2.Meta): model = Issuer apispec_definition = ('Issuer', { 'properties': OrderedDict([ ('entityId', { 'type': "string", 'format': "string", 'description': "Unique identifier for this Issuer", }), ('entityType', { 'type': "string", 'format': "string", 'description': "\"Issuer\"", }), ('openBadgeId', { 'type': "string", 'format': "url", 'description': "URL of the OpenBadge compliant json", }), ('createdAt', { 'type': 'string', 'format': 'ISO8601 timestamp', 'description': "Timestamp when the Issuer was created", }), ('createdBy', { 'type': 'string', 'format': 'entityId', 'description': "BadgeUser who created this Issuer", }), ('name', { 'type': "string", 'format': "string", 'description': "Name of the Issuer", }), ('image', { 'type': "string", 'format': "data:image/png;base64", 'description': "Base64 encoded string of an image that represents the Issuer", }), ('email', { 'type': "string", 'format': "email", 'description': "Contact email for the Issuer", }), ('url', { 'type': "string", 'format': "url", 'description': "Homepage or website associated with the Issuer", }), ('description', { 'type': "string", 'format': "text", 'description': "Short description of the Issuer", }), ]) }) def validate_image(self, image): if image is not None: img_name, img_ext = os.path.splitext(image.name) image.name = 'issuer_logo_' + str(uuid.uuid4()) + img_ext return image def create(self, validated_data): user = validated_data['created_by'] potential_email = validated_data['email'] # if not user.is_email_verified(potential_email): # raise serializers.ValidationError( # "Issuer email must be one of your verified addresses. Add this email to your profile and try again.") staff = validated_data.pop('staff_items', []) new_issuer = super(IssuerSerializerV2, self).create(validated_data) # update staff after issuer is created new_issuer.staff_items = staff # set badgrapp new_issuer.badgrapp = BadgrApp.objects.get_current( self.context.get('request', None)) return new_issuer
class AssociateRetrieveSerializer(serializers.Serializer): # ------ MEMBER ------ # slug = serializers.SlugField( source="user.slug", read_only=True, ) type_of = serializers.IntegerField( source="user.member.type_of", read_only=True, ) type_of_label = serializers.CharField( source="user.member.get_pretty_type_of", read_only=True, ) avatar_url = serializers.SerializerMethodField() state = serializers.CharField( source="user.member.state", read_only=True, ) # ------ MEMBER CONTACT ------ # is_ok_to_email = serializers.IntegerField( source="user.member.contact.is_ok_to_email", read_only=True, ) is_ok_to_text = serializers.IntegerField( source="user.member.contact.is_ok_to_text", read_only=True, ) organization_name = serializers.CharField( source="user.member.contact.organization_name", read_only=True, allow_blank=True, ) organization_type_of = serializers.IntegerField( source="user.member.contact.organization_type_of", read_only=True, ) first_name = serializers.CharField( source="user.member.contact.first_name", read_only=True, ) last_name = serializers.CharField( source="user.member.contact.last_name", read_only=True, ) full_name = serializers.SerializerMethodField() email = serializers.EmailField( source="user.member.contact.email", read_only=True, ) primary_phone_e164 = E164PhoneNumberField( source="user.member.contact.primary_phone", read_only=True, ) primary_phone_national = NationalPhoneNumberField( source="user.member.contact.primary_phone", read_only=True, ) secondary_phone_e164 = E164PhoneNumberField( source="user.member.contact.secondary_phone", read_only=True, ) secondary_phone_national = NationalPhoneNumberField( source="user.member.contact.secondary_phone", read_only=True, ) # ------ MEMBER ADDRESS ------ # country = serializers.CharField( source="user.member.address.country", read_only=True, ) province = serializers.CharField( source="user.member.address.province", read_only=True, ) city = serializers.CharField( source="user.member.address.city", read_only=True, ) street_number = serializers.CharField( source="user.member.address.street_number", read_only=True, ) street_name = serializers.CharField( source="user.member.address.street_name", read_only=True, ) apartment_unit = serializers.CharField( source="user.member.address.apartment_unit", read_only=True, ) street_type = serializers.IntegerField( source="user.member.address.street_type", read_only=True, ) street_type_other = serializers.CharField( source="user.member.address.street_type_other", read_only=True, ) street_direction = serializers.IntegerField( source="user.member.address.street_direction", read_only=True, ) postal_code = serializers.CharField( source="user.member.address.postal_code", read_only=True, ) address = serializers.CharField( source="user.member.address.street_address", read_only=True, ) google_maps_url = serializers.URLField( source="user.member.address.google_maps_url", read_only=True, ) position = serializers.SerializerMethodField() # ------ MEMBER WATCH ------ # #TODO: IMPLEMENT FIELDS. # ------ MEMBER METRICS ------ # tags = TagListCreateSerializer( source="user.member.metric.tags", many=True, read_only=True, ) how_did_you_hear = serializers.PrimaryKeyRelatedField( source="user.member.metric.how_did_you_hear", many=False, read_only=True, allow_null=False, ) how_did_you_hear_other = serializers.CharField( source="user.member.metric.how_did_you_hear_other", allow_null=True, allow_blank=True, read_only=True, ) how_did_you_hear_label = serializers.CharField( source="user.member.metric.how_did_you_hear.text", read_only=True, allow_blank=True, allow_null=True, ) expectation = serializers.PrimaryKeyRelatedField( source="user.member.metric.expectation", many=False, read_only=True, allow_null=False, ) expectation_other = serializers.CharField( source="user.member.metric.expectation_other", allow_null=True, allow_blank=True, read_only=True, ) expectation_label = serializers.CharField( source="user.member.metric.expectation.text", read_only=True, allow_null=True, allow_blank=True, ) meaning = serializers.PrimaryKeyRelatedField( source="user.member.metric.meaning", many=False, read_only=True, allow_null=False, ) meaning_other = serializers.CharField( source="user.member.metric.meaning_other", allow_null=True, allow_blank=True, read_only=True, ) meaning_label = serializers.CharField( source="user.member.metric.meaning.text", read_only=True, allow_null=True, allow_blank=True, ) gender = serializers.IntegerField( source="user.member.metric.gender", read_only=True, ) gender_label = serializers.CharField( source="user.member.metric.get_pretty_gender", read_only=True, ) willing_to_volunteer = serializers.IntegerField( source="user.member.metric.willing_to_volunteer", read_only=True, ) willing_to_volunteer_label = serializers.CharField( source="user.member.metric.get_pretty_willing_to_volunteer", read_only=True, ) another_household_member_registered = serializers.BooleanField( source="user.member.metric.another_household_member_registered", read_only=True, ) year_of_birth = serializers.IntegerField( source="user.member.metric.year_of_birth", read_only=True, ) total_household_count = serializers.IntegerField( source="user.member.metric.total_household_count", read_only=True, ) over_18_years_household_count = serializers.IntegerField( source="user.member.metric.over_18_years_household_count", read_only=True, ) organization_employee_count = serializers.IntegerField( source="user.member.metric.organization_employee_count", read_only=True, ) organization_founding_year = serializers.IntegerField( source="user.member.metric.organization_founding_year", read_only=True, ) governing = serializers.SerializerMethodField() # ------ AUDITING ------ # created_by = serializers.CharField( source="created_by.get_full_name", allow_null=True, read_only=True, ) last_modified_by = serializers.CharField( source="last_modified_by.get_full_name", allow_null=True, read_only=True, ) # ------ FUNCTIONS ------ # def get_full_name(self, obj): try: return obj.user.member.contact.first_name + " " + obj.user.member.contact.last_name except Exception as e: print(e) return None def get_avatar_url(self, obj): try: return obj.user.member.avatar_image.image_file.url except Exception as e: return def get_governing(self, obj): try: s = GoverningDistrictRetrieveSerializer(obj.governing.all(), many=True, context=self.context) return s.data except Exception as e: # print("get_governing |", e) return None def get_position(self, obj): return get_arr_from_point(obj.user.member.address.position)
class DistrictUpdateSerializer(serializers.Serializer): slug = serializers.SlugField(write_only=True, ) type_of = serializers.IntegerField( write_only=True, required=True, ) name = serializers.CharField( write_only=True, required=True, ) description = serializers.CharField( write_only=True, required=False, ) counselor_name = serializers.CharField( write_only=True, required=False, ) counselor_email = serializers.EmailField( write_only=True, required=False, ) counselor_phone = serializers.CharField( write_only=True, required=False, ) website_url = serializers.URLField( write_only=True, required=False, allow_blank=True, allow_null=True, ) is_archived = serializers.BooleanField( write_only=True, required=False, ) facebook_url = serializers.URLField( required=False, allow_blank=True, allow_null=True, ) # REACT-DJANGO UPLOAD | STEP 1 OF 4: We define two string fields required (write-only) # for accepting our file uploads. upload_content = serializers.CharField( write_only=True, allow_null=True, allow_blank=True, required=False, ) upload_filename = serializers.CharField( write_only=True, allow_null=True, allow_blank=True, required=False, ) def update(self, instance, validated_data): request = self.context.get("request") instance.type_of = validated_data.get('type_of') instance.description = validated_data.get('description') instance.name = validated_data.get('name') instance.counselor_name = validated_data.get('counselor_name', None) instance.counselor_email = validated_data.get('counselor_email', None) instance.counselor_phone = validated_data.get('counselor_phone', None) instance.website_url = validated_data.get('website_url', None) instance.facebook_url = validated_data.get('facebook_url', None) instance.created_by = request.user instance.created_from = request.client_ip instance.created_from_is_public = request.client_ip_is_routable instance.last_modified_by = request.user instance.last_modified_from = request.client_ip instance.last_modified_from_is_public = request.client_ip_is_routable instance.save() logger.info("New district was been updated.") try: # Extract our upload file data content = validated_data.get('upload_content', None) filename = validated_data.get('upload_filename', None) if content and filename: if settings.DEBUG: filename = "QA_" + filename # NOTE: Attach `QA_` prefix if server running in QA mode. content_file = get_content_file_from_base64_string( content, filename ) # REACT-DJANGO UPLOAD | STEP 3 OF 4: Convert to `ContentFile` type. # Create our file. private_file = PrivateImageUpload.objects.create( is_archived=False, user=request.user, image_file= content_file, # REACT-DJANGO UPLOAD | STEP 4 OF 4: When you attack a `ContentImage`, Django handles all file uploading. created_by=request.user, created_from=request.client_ip, created_from_is_public=request.client_ip_is_routable, last_modified_by=request.user, last_modified_from=request.client_ip, last_modified_from_is_public=request.client_ip_is_routable, ) logger.info("Private file was been created.") instance.logo_image = private_file instance.save() except Exception as e: print(e) private_file = None # raise serializers.ValidationError({ # Uncomment when not using this code but do not delete! # "error": "Terminating for debugging purposes only." # }) return instance
class UploadBlobSerializer(NoModelSerializer): """ Upload a picture or other POD content """ location = serializers.URLField(help_text=_("URL to uploaded content"))
class CodebaseReleaseSerializer(serializers.ModelSerializer): absolute_url = serializers.URLField( source='get_absolute_url', read_only=True, help_text=_('URL to the detail page of the codebase')) citation_text = serializers.ReadOnlyField() codebase = CodebaseSerializer(read_only=True) release_contributors = ReleaseContributorSerializer( read_only=True, source='index_ordered_release_contributors', many=True) date_created = serializers.DateTimeField(format=YMD_DATETIME_FORMAT, read_only=True) first_published_at = serializers.DateTimeField( format=DATE_PUBLISHED_FORMAT, read_only=True) last_published_on = serializers.DateTimeField(format=DATE_PUBLISHED_FORMAT, read_only=True) output_data_url = serializers.URLField(required=False) license = LicenseSerializer() live = serializers.ReadOnlyField() os_display = serializers.ReadOnlyField(source='get_os_display') platforms = TagSerializer(many=True, source='platform_tags') programming_languages = TagSerializer(many=True) submitter = LinkedUserSerializer(read_only=True, label='Submitter') version_number = serializers.ReadOnlyField() release_notes = MarkdownField(max_length=2048) urls = serializers.SerializerMethodField() review_status = serializers.SerializerMethodField() def get_urls(self, instance): request_peer_review_url = instance.get_request_peer_review_url() review = instance.get_review() review_url = review.get_absolute_url() if review else None notify_reviewers_of_changes_url = instance.get_notify_reviewers_of_changes_url( ) if review else None return { 'request_peer_review': request_peer_review_url, 'review': review_url, 'notify_reviewers_of_changes': notify_reviewers_of_changes_url } def get_review_status(self, instance): return instance.review.status if instance.get_review() else None class Meta: model = CodebaseRelease fields = ( 'absolute_url', 'citation_text', 'release_contributors', 'date_created', 'dependencies', 'release_notes', 'documentation', 'doi', 'download_count', 'embargo_end_date', 'first_published_at', 'last_modified', 'last_published_on', 'license', 'live', 'os', 'os_display', 'peer_reviewed', 'platforms', 'programming_languages', 'submitted_package', 'submitter', 'codebase', 'review_status', 'output_data_url', 'version_number', 'id', 'share_url', 'urls', )
class UserMainSerializer(rest_serializers.ModelSerializer): cost_sum = rest_serializers.IntegerField(read_only=True) avatar_main = rest_serializers.URLField(source='avatar.main.url', read_only=True) avatar_small = rest_serializers.URLField(source='avatar.small.url', read_only=True) old_password = rest_serializers.CharField(write_only=True, required=False, allow_blank=True) password = rest_serializers.CharField(write_only=True, required=False, allow_blank=True) personal_info = UserPersonalInfoSerializer(required=False) can_create_tasks = rest_serializers.BooleanField(read_only=True) can_create_contests = rest_serializers.BooleanField(read_only=True) is_admin = rest_serializers.BooleanField(read_only=True) class Meta: model = api.models.User fields = ( 'avatar_main', 'avatar_small', 'can_create_contests', 'can_create_tasks', 'cost_sum', 'email', 'is_admin', 'hide_personal_info', 'id', 'max_rating', 'old_password', 'password', 'personal_info', 'rating', 'username', ) extra_kwargs = { 'password': { 'write_only': True, }, 'email': { 'read_only': True, }, 'rating': { 'read_only': True, }, 'max_rating': { 'read_only': True, }, 'username': { 'read_only': True, }, } def validate(self, data): password = data.pop('password', None) old_password = data.pop('old_password', None) user = self.instance if not password: return data if not old_password: raise rest_serializers.ValidationError({ 'old_password': '******' }) if not user.check_password(raw_password=old_password): raise rest_serializers.ValidationError( {'old_password': '******'}) errors = dict() try: validate_password(password=password, user=user) except django_core_exceptions.ValidationError as e: errors['password'] = list(e.messages) if errors: raise rest_serializers.ValidationError(errors) data['password'] = password return data def update(self, instance, validated_data): password = validated_data.pop('password', None) personal_info = validated_data.pop('personal_info', None) if personal_info: validated_data.update(**personal_info) if password: instance.set_password(password) return super(UserMainSerializer, self).update(instance, validated_data)
class VersionURLsSerializer(serializers.Serializer): documentation = serializers.SerializerMethodField() vcs = serializers.URLField(source='vcs_url') def get_documentation(self, obj): return obj.project.get_docs_url(version_slug=obj.slug, )
class BadgeInstanceSerializerV1(OriginalJsonSerializerMixin, serializers.Serializer): created_at = DateTimeWithUtcZAtEndField(read_only=True, default_timezone=pytz.utc) created_by = BadgeUserIdentifierFieldV1(read_only=True) slug = serializers.CharField(max_length=255, read_only=True, source='entity_id') image = serializers.FileField( read_only=True) # use_url=True, might be necessary email = serializers.EmailField(max_length=1024, required=False, write_only=True) recipient_identifier = serializers.CharField(max_length=1024, required=False) recipient_type = serializers.CharField(default=RECIPIENT_TYPE_EMAIL) allow_uppercase = serializers.BooleanField(default=False, required=False, write_only=True) evidence = serializers.URLField(write_only=True, required=False, allow_blank=True, max_length=1024) narrative = MarkdownCharField(required=False, allow_blank=True, allow_null=True) evidence_items = EvidenceItemSerializer(many=True, required=False) revoked = HumanReadableBooleanField(read_only=True) revocation_reason = serializers.CharField(read_only=True) expires = DateTimeWithUtcZAtEndField(source='expires_at', required=False, allow_null=True, default_timezone=pytz.utc) create_notification = HumanReadableBooleanField(write_only=True, required=False, default=False) allow_duplicate_awards = serializers.BooleanField(write_only=True, required=False, default=True) hashed = serializers.NullBooleanField(default=None, required=False) extensions = serializers.DictField(source='extension_items', required=False, validators=[BadgeExtensionValidator()]) class Meta: apispec_definition = ('Assertion', {}) def validate(self, data): recipient_type = data.get('recipient_type') if data.get('recipient_identifier') and data.get('email') is None: if recipient_type == RECIPIENT_TYPE_EMAIL: recipient_validator = EmailValidator() elif recipient_type in (RECIPIENT_TYPE_URL, RECIPIENT_TYPE_ID): recipient_validator = URLValidator() else: recipient_validator = TelephoneValidator() try: recipient_validator(data['recipient_identifier']) except DjangoValidationError as e: raise serializers.ValidationError(e.message) elif data.get('email') and data.get('recipient_identifier') is None: data['recipient_identifier'] = data.get('email') allow_duplicate_awards = data.pop('allow_duplicate_awards') if allow_duplicate_awards is False and self.context.get( 'badgeclass') is not None: previous_awards = BadgeInstance.objects.filter( recipient_identifier=data['recipient_identifier'], badgeclass=self.context['badgeclass']).filter( Q(expires_at__isnull=True) | Q(expires_at__lt=timezone.now())) if previous_awards.exists(): raise serializers.ValidationError( "A previous award of this badge already exists for this recipient." ) hashed = data.get('hashed', None) if hashed is None: if recipient_type in (RECIPIENT_TYPE_URL, RECIPIENT_TYPE_ID): data['hashed'] = False else: data['hashed'] = True return data def validate_narrative(self, data): if data is None or data == "": return None else: return data def to_representation(self, instance): representation = super(BadgeInstanceSerializerV1, self).to_representation(instance) representation['json'] = instance.get_json(obi_version="1_1", use_canonical_id=True) if self.context.get('include_issuer', False): representation['issuer'] = IssuerSerializerV1( instance.cached_badgeclass.cached_issuer).data else: representation['issuer'] = OriginSetting.HTTP + reverse( 'issuer_json', kwargs={'entity_id': instance.cached_issuer.entity_id}) if self.context.get('include_badge_class', False): representation['badge_class'] = BadgeClassSerializerV1( instance.cached_badgeclass, context=self.context).data else: representation['badge_class'] = OriginSetting.HTTP + reverse( 'badgeclass_json', kwargs={'entity_id': instance.cached_badgeclass.entity_id}) representation['public_url'] = OriginSetting.HTTP + reverse( 'badgeinstance_json', kwargs={'entity_id': instance.entity_id}) return representation def create(self, validated_data): """ Requires self.context to include request (with authenticated request.user) and badgeclass: issuer.models.BadgeClass. """ evidence_items = [] # ob1 evidence url evidence_url = validated_data.get('evidence') if evidence_url: evidence_items.append({'evidence_url': evidence_url}) # ob2 evidence items submitted_items = validated_data.get('evidence_items') if submitted_items: evidence_items.extend(submitted_items) try: return self.context.get('badgeclass').issue( recipient_id=validated_data.get('recipient_identifier'), narrative=validated_data.get('narrative'), evidence=evidence_items, notify=validated_data.get('create_notification'), created_by=self.context.get('request').user, allow_uppercase=validated_data.get('allow_uppercase'), recipient_type=validated_data.get('recipient_type', RECIPIENT_TYPE_EMAIL), badgr_app=BadgrApp.objects.get_current( self.context.get('request')), expires_at=validated_data.get('expires_at', None), extensions=validated_data.get('extension_items', None)) except DjangoValidationError as e: raise serializers.ValidationError(e.message) def update(self, instance, validated_data): updateable_fields = [ 'evidence_items', 'expires_at', 'extension_items', 'hashed', 'narrative', 'recipient_identifier', 'recipient_type' ] for field_name in updateable_fields: if field_name in validated_data: setattr(instance, field_name, validated_data.get(field_name)) instance.rebake(save=False) instance.save() return instance
class PasswordResetSerializer(UsernameOrEmailSerializer): """Serializer to request a password reset e-mail.""" redirect_uri = serializers.URLField(required=False)
class ScreenOneSerializer(serializers.Serializer): Home = serializers.ReadOnlyField() Video = serializers.URLField(read_only=True) appointment = serializers.URLField(read_only=True)