Beispiel #1
0
class CollectionVersionCreateSerializer(
        CollectionVersionCreateOrUpdateSerializer):
    id = serializers.CharField(
        required=True,
        validators=[RegexValidator(regex=NAMESPACE_REGEX)],
        source='mnemonic')
    released = serializers.BooleanField(required=False)
    description = serializers.CharField(required=False)
    version_external_id = serializers.CharField(required=False)
    previous_version = serializers.CharField(
        required=False, source='previous_version_mnemonic')
    parent_version = serializers.CharField(required=False,
                                           source='parent_version_mnemonic')
    extras = serializers.WritableField(required=False)
    external_id = serializers.CharField(required=False)

    def restore_object(self, attrs, instance=None):
        version = CollectionVersion()
        version.mnemonic = attrs.get(self.Meta.lookup_field)
        return super(CollectionVersionCreateSerializer,
                     self).restore_object(attrs, instance=version)

    def save_object(self, obj, **kwargs):
        request_user = self.context['request'].user
        snap_serializer = CollectionDetailSerializer(
            kwargs['versioned_object'])
        snapshot_data = snap_serializer.data
        snapshot_data.pop('references')
        obj.collection_snapshot = snapshot_data
        errors = CollectionVersion.persist_new(obj,
                                               user=request_user,
                                               **kwargs)
        if errors:
            self._errors.update(errors)
        else:
            update_children_for_resource_version.delay(obj.id, 'collection')
Beispiel #2
0
class ConceptVersionUpdateSerializer(serializers.Serializer):
    external_id = serializers.CharField(required=False)
    concept_class = serializers.CharField(required=False)
    datatype = serializers.CharField(required=False)
    names = LocalizedTextListField(required=False)
    descriptions = LocalizedTextListField(required=False,
                                          name_override='description')
    retired = serializers.BooleanField(required=False)
    extras = serializers.WritableField(required=False)
    update_comment = serializers.CharField(required=False)

    class Meta:
        model = ConceptVersion

    def restore_object(self, attrs, instance=None):
        instance.concept_class = attrs.get('concept_class',
                                           instance.concept_class)
        instance.datatype = attrs.get('datatype', instance.datatype)
        instance.extras = attrs.get('extras', instance.extras)
        instance.external_id = attrs.get('external_id', instance.external_id)
        instance.update_comment = attrs.get('update_comment')

        # Is this desired behavior??
        instance.names = attrs.get('names', instance.names)

        # Is this desired behavior??
        instance.descriptions = attrs.get('descriptions',
                                          instance.descriptions)

        instance.retired = attrs.get('retired', instance.retired)
        return instance

    def save_object(self, obj, **kwargs):
        user = self.context['request'].user
        errors = ConceptVersion.persist_clone(obj, user, **kwargs)
        self._errors.update(errors)
Beispiel #3
0
class NodeCreatorSerializer(NodeListSerializer):
    layer = serializers.WritableField(source='layer')
Beispiel #4
0
class ApiRecipeSerializer(CookboothModelSerializer):
    private = IntegerBooleanField()
    draft = IntegerBooleanField()

    added = serializers.SerializerMethodField('has_added')
    liked = serializers.SerializerMethodField('has_liked')
    shared = serializers.SerializerMethodField('has_shared')
    reported = serializers.SerializerMethodField('has_reported')
    commented = serializers.SerializerMethodField('has_commented')
    book_for_sale = serializers.SerializerMethodField('get_book_for_sale')
    bought = serializers.SerializerMethodField('has_bought_it')
    public_url = serializers.Field()
    cover_photo = serializers.SerializerMethodField('get_cover_photo')

    nb_added = serializers.Field('cache_added')

    ingredients = serializers.WritableField(required=False)
    tags = serializers.WritableField(required=False)
    products = ProductSerializer(many=True, read_only=True)

    class Meta:
        model = Recipes
        fields = ('id', 'creation_date', 'edit_date', 'chef', 'name',
                  'ingredients', 'tags', 'commensals', 'private', 'draft',
                  'added', 'liked', 'shared', 'reported', 'commented',
                  'public_url', 'cover_photo', 'nb_added', 'nb_likes',
                  'nb_shares', 'nb_comments', 'products', 'serves',
                  'prep_time', 'book_for_sale', 'bought', 'description')
        read_only_fields = ('chef', 'edit_date', 'creation_date')

    def __init__(self, *args, **kwargs):
        super(ApiRecipeSerializer, self).__init__(*args, **kwargs)
        self.user = self.context.get('user')
        self.return_user_properties = self.context.get(
            'return_user_properties', [])

    def has_added(self, obj):
        if 'added' in self.return_user_properties:
            return obj.added_by(self.user)
        return False

    def has_liked(self, obj):
        if 'liked' in self.return_user_properties:
            return obj.liked_by(self.user)
        return False

    def has_shared(self, obj):
        if 'shared' in self.return_user_properties:
            return obj.shared_by(self.user)
        return False

    def has_reported(self, obj):
        if 'reported' in self.return_user_properties:
            return obj.reported_by(self.user)
        return False

    def has_commented(self, obj):
        if 'commented' in self.return_user_properties:
            return obj.commented_by(self.user)
        return False

    def get_book_for_sale(self, obj):
        book = obj.book_for_sale()
        return ApiBookMinimalSerializer(book).data if book else None

    def has_bought_it(self, obj):
        book = obj.book_for_sale()
        if not book:
            return False
        return book.user_has_bought_it(self.user)

    def get_cover_photo(self, obj):
        photos = obj.photos.filter(is_cover=True)[:1]
        if photos:
            photo = photos[0]
            if photo.s3_url:
                if photo.s3_url.name and photo.s3_url.name.startswith('http'):
                    photo_url = photo.s3_url.name
                else:
                    photo_url = photo.s3_url.url

                return {
                    'id':
                    photo.pk,
                    'url':
                    photo_url,
                    'creation_date':
                    self.datetime_to_timestamp(photo.creation_date),
                    'edit_date':
                    self.datetime_to_timestamp(photo.edit_date),
                }
        return None

    def transform_chef(self, obj, value):
        return embeded_chef_serializer(obj.chef)

    def transform_ingredients(self, obj, value):
        return [{
            'id': i.pk,
            'name': i.name
        } for i in obj.get_sorted_ingredients()]

    def transform_tags(self, obj, value):
        return [{'id': t.pk, 'name': t.name} for t in obj.tags.all()]

    def restore_object(self, attrs, instance=None):
        self._ingredients = [
            i.strip(',') for i in attrs.pop('ingredients', '').split('\n') if i
        ]
        self._tags = [
            t.strip(',') for t in attrs.pop('tags', '').split(' ') if t
        ]
        return super(ApiRecipeSerializer, self).restore_object(attrs, instance)

    def save_object(self, obj, **kwargs):
        ingredients = []
        for i in self._ingredients:
            try:
                db_ingredients = Ingredients.objects.filter(name=i)[:1]
                ing = db_ingredients[0]
            except (Ingredients.DoesNotExist, IndexError):
                ing = Ingredients.objects.create(name=i)
                ing.save()
            ingredients.append(ing)

        obj.set_ingredients_order(ingredients)

        obj.chef = self.user
        super(ApiRecipeSerializer, self).save_object(obj, **kwargs)

        RecipesHasIngredients.objects.filter(recipe=obj).delete()
        for ingredient in ingredients:
            RecipesHasIngredients.objects.get_or_create(recipe=obj,
                                                        ingredient=ingredient)

        # obj.tags.clear()
        RecipesHasTags.objects.filter(recipe=obj).delete()
        for t in self._tags:
            try:
                db_tags = Tags.objects.filter(name=t)[:1]
                tag = db_tags[0]
            except (Tags.DoesNotExist, IndexError):
                tag = Tags.objects.create(name=t)
                tag.save()
            RecipesHasTags.objects.create(recipe=obj, tag=tag)

    def to_native(self, obj):
        ret = super(ApiRecipeSerializer, self).to_native(obj)
        if not ret['name']:
            del ret['name']
        if not ret['cover_photo']:
            del ret['cover_photo']
        return ret
Beispiel #5
0
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
    is_org = serializers.SerializerMethodField('is_organization')
    username = serializers.WritableField(source='user.username')
    email = serializers.WritableField(source='user.email')
    website = serializers.WritableField(source='home_page', required=False)
    gravatar = serializers.Field(source='gravatar')
    password = serializers.WritableField(
        source='user.password', widget=widgets.PasswordInput(), required=False)
    user = serializers.HyperlinkedRelatedField(
        view_name='user-detail', lookup_field='username', read_only=True)
    metadata = JsonField(source='metadata', required=False)
    id = serializers.Field(source='user.id')
    joined_on = serializers.Field(source='user.date_joined')

    class Meta:
        model = UserProfile
        fields = ('id', 'is_org', 'url', 'username', 'name', 'password',
                  'email', 'city', 'country', 'organization', 'website',
                  'twitter', 'gravatar', 'require_auth', 'user', 'metadata',
                  'joined_on')
        lookup_field = 'user'

    def is_organization(self, obj):
        return is_organization(obj)

    def to_native(self, obj):
        """
        Serialize objects -> primitives.
        """
        ret = super(UserProfileSerializer, self).to_native(obj)
        if 'password' in ret:
            del ret['password']

        request = self.context['request'] \
            if 'request' in self.context else None

        if 'email' in ret and request is None or request.user \
                and not request.user.has_perm(CAN_VIEW_PROFILE, obj):
            del ret['email']

        return ret

    def restore_object(self, attrs, instance=None):
        params = copy.deepcopy(attrs)
        username = attrs.get('user.username', None)
        password = attrs.get('user.password', None)
        name = attrs.get('name', None)
        email = attrs.get('user.email', None)

        if username:
            params['username'] = username

        if email:
            params['email'] = email

        if password:
            params.update({'password1': password, 'password2': password})

        if instance:
            form = UserProfileForm(params, instance=instance)

            # form.is_valid affects instance object for partial updates [PATCH]
            # so only use it for full updates [PUT], i.e shallow copy effect
            if not self.partial and form.is_valid():
                instance = form.save()

            # get user
            if email:
                instance.user.email = form.cleaned_data['email']

            if name:
                first_name, last_name = _get_first_last_names(name)
                instance.user.first_name = first_name
                instance.user.last_name = last_name

            if email or name:
                instance.user.save()

            return super(
                UserProfileSerializer, self).restore_object(attrs, instance)

        form = RegistrationFormUserProfile(params)
        # does not require captcha
        form.REGISTRATION_REQUIRE_CAPTCHA = False

        if form.is_valid():
            site = Site.objects.get(pk=settings.SITE_ID)
            new_user = RegistrationProfile.objects.create_inactive_user(
                username=username,
                password=password,
                email=email,
                site=site,
                send_email=True)
            new_user.is_active = True
            new_user.save()

            created_by = self.context['request'].user
            created_by = None if created_by.is_anonymous() else created_by
            profile = UserProfile(
                user=new_user, name=attrs.get('name', u''),
                created_by=created_by,
                city=attrs.get('city', u''),
                country=attrs.get('country', u''),
                organization=attrs.get('organization', u''),
                home_page=attrs.get('home_page', u''),
                twitter=attrs.get('twitter', u''))

            return profile

        else:
            self.errors.update(form.errors)

        return attrs

    def validate_username(self, attrs, source):
        request_method = self.context['request'].method

        if request_method == 'PATCH' and source not in attrs:
            return attrs

        current_username = self.object.user.username if self.object else None
        username = attrs[source].lower()
        is_edit = current_username is not None and current_username != username
        form = RegistrationFormUserProfile

        if username in form._reserved_usernames and is_edit:
            raise ValidationError(
                u"%s is a reserved name, please choose another" % username)
        elif not form.legal_usernames_re.search(username):
            raise ValidationError(
                u'username may only contain alpha-numeric characters and '
                u'underscores')
        try:
            User.objects.get(username=username)
        except User.DoesNotExist:
            attrs[source] = username
        else:
            if not current_username or is_edit:
                raise ValidationError(u'%s already exists' % username)

        return attrs
Beispiel #6
0
class ProfileSerializer(serializers.ModelSerializer):
    username = serializers.WritableField(source='user.username')
    display_name = serializers.WritableField(source='name', required=False)
    date_joined = DateTimeUTCField(source='user.date_joined', read_only=True)
    avatar = serializers.SerializerMethodField('get_avatar_url')
    email = (PermissionMod(serializers.WritableField,
                           permissions=[OnlySelf])(source='user.email',
                                                   required=False))
    settings = (PermissionMod(UserSettingSerializer,
                              permissions=[OnlySelf])(many=True,
                                                      read_only=True))
    helpfulness = serializers.Field(source='answer_helpfulness')
    answer_count = serializers.SerializerMethodField('get_answer_count')
    question_count = serializers.SerializerMethodField('get_question_count')
    solution_count = serializers.SerializerMethodField('get_solution_count')
    # These are write only fields. It is very important they stays that way!
    password = serializers.WritableField(source='user.password',
                                         write_only=True)
    is_active = (PermissionMod(serializers.BooleanField,
                               permissions=[OnlySelf])(source='user.is_active',
                                                       read_only=True))

    class Meta:
        model = Profile
        fields = [
            'username',
            'display_name',
            'date_joined',
            'avatar',
            'bio',
            'website',
            'twitter',
            'facebook',
            'mozillians',
            'irc_handle',
            'timezone',
            'country',
            'city',
            'locale',
            'email',
            'settings',
            'helpfulness',
            'question_count',
            'answer_count',
            'solution_count',
            # Password and email are here so they can be involved in write
            # operations. They is marked as write-only above, so will not be
            # visible.
            'password',
            'is_active',
        ]

    def get_avatar_url(self, profile):
        return profile_avatar(profile.user)

    def get_question_count(self, profile):
        return num_questions(profile.user)

    def get_answer_count(self, profile):
        return num_answers(profile.user)

    def get_solution_count(self, profile):
        return num_solutions(profile.user)

    def restore_object(self, attrs, instance=None):
        """
        Override the default behavior to make a user if one doesn't exist.

        This user may not be saved here, but will be saved if/when the .save()
        method of the serializer is called.
        """
        instance = (super(ProfileSerializer,
                          self).restore_object(attrs, instance))
        if instance.user_id is None:
            # The Profile doesn't have a user, so create one. If an email is
            # specified, the user will be inactive until the email is
            # confirmed. Otherwise the user can be created immediately.
            if 'user.email' in attrs:
                u = RegistrationProfile.objects.create_inactive_user(
                    attrs['user.username'], attrs['user.password'],
                    attrs['user.email'])
            else:
                u = User(username=attrs['user.username'])
                u.set_password(attrs['user.password'])
            instance._nested_forward_relations['user'] = u
        return instance

    def validate_username(self, attrs, source):
        obj = self.object
        if obj is None:
            # This is a create
            if User.objects.filter(username=attrs['user.username']).exists():
                raise ValidationError('A user with that username exists')
        else:
            # This is an update
            new_username = attrs.get('user.username', obj.user.username)
            if new_username != obj.user.username:
                raise ValidationError("Can't change this field.")

        if re.match(r'^[\w.-]{4,30}$', attrs['user.username']) is None:
            raise ValidationError(
                'Usernames may only be letters, numbers, "." and "-".')

        return attrs

    def validate_display_name(self, attrs, source):
        if attrs.get('name') is None:
            attrs['name'] = attrs.get('user.username')
        return attrs

    def validate_email(self, attrs, source):
        email = attrs.get('user.email')
        if email and User.objects.filter(email=email).exists():
            raise ValidationError('A user with that email address '
                                  'already exists.')
        return attrs
Beispiel #7
0
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
    username = serializers.WritableField(source='user.username')
    email = serializers.WritableField(source='user.email')
    website = serializers.WritableField(source='home_page', required=False)
    gravatar = serializers.Field(source='gravatar')
    password = serializers.WritableField(source='user.password',
                                         widget=widgets.PasswordInput(),
                                         required=False)
    user = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                               lookup_field='username',
                                               read_only=True)

    class Meta:
        model = UserProfile
        fields = ('url', 'username', 'name', 'password', 'email', 'city',
                  'country', 'organization', 'website', 'twitter', 'gravatar',
                  'require_auth', 'user')
        lookup_field = 'user'

    def to_native(self, obj):
        """
        Serialize objects -> primitives.
        """
        ret = super(UserProfileSerializer, self).to_native(obj)
        if 'password' in ret:
            del ret['password']
        return ret

    def restore_object(self, attrs, instance=None):
        def _get_first_last_names(name):
            name_split = name.split()
            first_name = name_split[0]
            last_name = u''
            if len(name_split) > 1:
                last_name = u' '.join(name_split[1:])
            return first_name, last_name

        params = copy.deepcopy(attrs)
        username = attrs.get('user.username', None)
        password = attrs.get('user.password', None)
        name = attrs.get('name', None)
        email = attrs.get('user.email', None)
        if username:
            params['username'] = username
        if email:
            params['email'] = email
        if password:
            params.update({'password1': password, 'password2': password})
        if instance:
            form = UserProfileForm(params, instance=instance)
            # form.is_valid affects instance object for partial updates [PATCH]
            # so only use it for full updates [PUT], i.e shallow copy effect
            if not self.partial and form.is_valid():
                instance = form.save()
            # get user
            if email:
                instance.user.email = form.cleaned_data['email']
            if name:
                first_name, last_name = _get_first_last_names(name)
                instance.user.first_name = first_name
                instance.user.last_name = last_name
            if email or name:
                instance.user.save()
            return super(UserProfileSerializer,
                         self).restore_object(attrs, instance)
            #return instance  # TODO: updates
        form = RegistrationFormUserProfile(params)
        if form.is_valid():
            first_name, last_name = _get_first_last_names(name)
            new_user = User(username=username,
                            first_name=first_name,
                            last_name=last_name,
                            email=email)
            new_user.set_password(password)
            new_user.save()
            created_by = self.context['request'].user
            profile = UserProfile(user=new_user,
                                  name=attrs.get('name', u''),
                                  created_by=created_by,
                                  city=attrs.get('city', u''),
                                  country=attrs.get('country', u''),
                                  organization=attrs.get('organization', u''),
                                  home_page=attrs.get('home_page', u''),
                                  twitter=attrs.get('twitter', u''))
            return profile
        else:
            self.errors.update(form.errors)
        return attrs
class JobExclusionSerializer(serializers.ModelSerializer):
    info = serializers.WritableField()

    class Meta:
        model = models.JobExclusion
Beispiel #9
0
class OrganizationSerializer(serializers.HyperlinkedModelSerializer):
    org = serializers.WritableField(source='user.username')
    user = serializers.HyperlinkedRelatedField(
        view_name='user-detail', lookup_field='username', read_only=True)
    creator = serializers.HyperlinkedRelatedField(
        view_name='user-detail', lookup_field='username', read_only=True)
    users = serializers.SerializerMethodField('get_org_permissions')

    class Meta:
        model = OrganizationProfile
        lookup_field = 'user'
        exclude = ('created_by', 'is_organization', 'organization')

    def restore_object(self, attrs, instance=None):
        if instance:
            return super(OrganizationSerializer, self)\
                .restore_object(attrs, instance)

        org = attrs.get('user.username', None)
        org_name = attrs.get('name', None)
        org_exists = False
        creator = None

        try:
            User.objects.get(username=org)
        except User.DoesNotExist:
            pass
        else:
            self.errors['org'] = u'Organization %s already exists.' % org
            org_exists = True

        if 'request' in self.context:
            creator = self.context['request'].user

        if org and org_name and creator and not org_exists:
            attrs['organization'] = org_name
            orgprofile = tools.create_organization_object(org, creator, attrs)

            return orgprofile

        if not org:
            self.errors['org'] = u'org is required!'

        if not org_name:
            self.errors['name'] = u'name is required!'

        return attrs

    def validate_org(self, attrs, source):
        org = attrs[source].lower()
        if org in RegistrationFormUserProfile._reserved_usernames:
            raise ValidationError(
                u"%s is a reserved name, please choose another" % org)
        elif not RegistrationFormUserProfile.legal_usernames_re.search(org):
            raise ValidationError(
                u'organization may only contain alpha-numeric characters and '
                u'underscores')
        try:
            User.objects.get(username=org)
        except User.DoesNotExist:
            attrs[source] = org

            return attrs
        raise ValidationError(u'%s already exists' % org)

    def get_org_permissions(self, obj):
        members = get_organization_members(obj) if obj else []

        return [{
            'user': u.username,
            'role': get_role_in_org(u, obj)
        } for u in members]
Beispiel #10
0
 def mandatory_fields(self):
     return {
         "datetime": serializers.WritableField(),
         "value": serializers.WritableField(),
     }
Beispiel #11
0
class DeviceAddSerializer(NodeDeviceListSerializer):
    """ Serializer for Device Creation """
    node = serializers.WritableField(source='node_id')
    type = serializers.WritableField(source='type')
    details = serializers.HyperlinkedIdentityField(
        view_name='api_device_details')
Beispiel #12
0
class CardSerializer(DynamicFieldsModelSerializer):
    created_by = NestedUserSerializer(read_only=True)
    modified_by = NestedUserSerializer(read_only=True)

    thumbnail_xs_path = serializers.Field(source='signed_thumbnail_xs_path')
    thumbnail_sm_path = serializers.Field(source='signed_thumbnail_sm_path')
    thumbnail_md_path = serializers.Field(source='signed_thumbnail_md_path')
    thumbnail_lg_path = serializers.Field(source='signed_thumbnail_lg_path')

    html_url = serializers.Field()
    download_html_url = serializers.Field()
    original_html_url = serializers.Field()

    metadata = serializers.WritableField(required=False, source='metadata')

    class Meta:
        model = Card
        read_only_fields = ('slug', 'stack', 'comments_count')
        exclude = ('data', )

    def validate_metadata(self, attrs, source):
        metadata = attrs.get(source)
        valid_metadata_keys = ['pattern']
        validation_message = 'Invalid metadata.'
        self.valid_metadata = {}

        if not metadata:
            return attrs

        if not isinstance(metadata, dict):
            raise serializers.ValidationError(validation_message)

        for key in metadata.keys():
            if key not in valid_metadata_keys:
                raise serializers.ValidationError(validation_message)

        self.valid_metadata = metadata

        return attrs

    def validate_content(self, attrs, source):
        content = attrs.get(source)
        card_type = attrs.get('type')

        if card_type != 'stack' and not content:
            raise serializers.ValidationError(self.error_messages['required'])

        return attrs

    def save_object(self, obj, **kwargs):
        created = bool(obj.pk)
        featured_diff = obj.get_field_diff('featured')
        user = self.context['request'].user

        if not created:
            obj.created_by = user

        obj.modified_by = user

        valid_metadata = getattr(self, 'valid_metadata', None)

        if obj.data and valid_metadata:
            obj.data.update(valid_metadata)
        elif valid_metadata:
            obj.data = valid_metadata

        super(CardSerializer, self).save_object(obj, **kwargs)

        # Try to request previews for new card
        if not created:
            obj.request_previews()

        if featured_diff and featured_diff[1]:
            obj.notify_featured(user)

    def restore_object(self, attrs, instance=None):
        """
        Restore the model instance.
        """
        if 'metadata' in attrs:
            del attrs['metadata']

        return super(CardSerializer, self).restore_object(attrs, instance)
Beispiel #13
0
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
    is_org = serializers.SerializerMethodField('is_organization')
    username = serializers.WritableField(source='user.username')
    name = serializers.CharField(required=False)
    first_name = serializers.WritableField(source='user.first_name',
                                           required=False)
    last_name = serializers.WritableField(source='user.last_name',
                                          required=False)
    email = serializers.EmailField(source='user.email')
    website = serializers.WritableField(source='home_page', required=False)
    twitter = serializers.WritableField(required=False)
    gravatar = serializers.Field(source='gravatar')
    password = serializers.WritableField(source='user.password',
                                         widget=widgets.PasswordInput(),
                                         required=False)
    user = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                               lookup_field='username',
                                               read_only=True)
    metadata = JsonField(source='metadata', required=False)
    id = serializers.Field(source='user.id')
    joined_on = serializers.Field(source='user.date_joined')

    class Meta:
        model = UserProfile
        fields = ('id', 'is_org', 'url', 'username', 'password', 'first_name',
                  'last_name', 'email', 'city', 'country', 'organization',
                  'website', 'twitter', 'gravatar', 'require_auth', 'user',
                  'metadata', 'joined_on', 'name')
        lookup_field = 'user'

    def is_organization(self, obj):
        if obj:
            is_org = cache.get('{}{}'.format(IS_ORG, obj.pk))
            if is_org:
                return is_org

        is_org = is_organization(obj)
        cache.set('{}{}'.format(IS_ORG, obj.pk), is_org)
        return is_org

    def to_native(self, obj):
        """
        Serialize objects -> primitives.
        """
        ret = super(UserProfileSerializer, self).to_native(obj)
        if 'password' in ret:
            del ret['password']

        request = self.context['request'] \
            if 'request' in self.context else None

        if 'email' in ret and request is None or request.user \
                and not request.user.has_perm(CAN_VIEW_PROFILE, obj):
            del ret['email']

        if 'first_name' in ret:
            ret['name'] = u' '.join(
                [ret.get('first_name'),
                 ret.get('last_name', "")])

        return ret

    def restore_object(self, attrs, instance=None):
        params = copy.deepcopy(attrs)
        username = attrs.get('user.username', None)
        password = attrs.get('user.password', None)
        first_name = attrs.get('user.first_name', None)
        last_name = attrs.get('user.last_name', None)
        email = attrs.get('user.email', None)
        name = attrs.get('name', None)

        if username:
            params['username'] = username

        if email:
            params['email'] = email

        if password:
            params.update({'password1': password, 'password2': password})

        if first_name:
            params['first_name'] = first_name

        if last_name:
            params['last_name'] = last_name

        # For backward compatibility, Users who still use only name
        if name:
            first_name, last_name = \
                _get_first_last_names(name)
            params['first_name'] = first_name
            params['last_name'] = last_name

        if instance:
            form = UserProfileForm(params, instance=instance)

            # form.is_valid affects instance object for partial updates [PATCH]
            # so only use it for full updates [PUT], i.e shallow copy effect
            if not self.partial and form.is_valid():
                instance = form.save()

            # get user
            if email:
                instance.user.email = email

            if first_name:
                instance.user.first_name = first_name

            if last_name:
                instance.user.last_name = last_name

            (email or first_name or last_name) and instance.user.save()

            return super(UserProfileSerializer,
                         self).restore_object(attrs, instance)

        form = RegistrationFormUserProfile(params)
        # does not require captcha
        form.REGISTRATION_REQUIRE_CAPTCHA = False

        if form.is_valid():

            site = Site.objects.get(pk=settings.SITE_ID)
            new_user = RegistrationProfile.objects.create_inactive_user(
                username=username,
                password=password,
                email=email,
                site=site,
                send_email=settings.SEND_EMAIL_ACTIVATION_API)
            new_user.is_active = True
            new_user.first_name = first_name
            new_user.last_name = last_name
            new_user.save()

            created_by = self.context['request'].user
            created_by = None if created_by.is_anonymous() else created_by
            profile = UserProfile(user=new_user,
                                  name=first_name,
                                  created_by=created_by,
                                  city=attrs.get('city', u''),
                                  country=attrs.get('country', u''),
                                  organization=attrs.get('organization', u''),
                                  home_page=attrs.get('home_page', u''),
                                  twitter=attrs.get('twitter', u''))

            return profile

        else:
            self.errors.update(form.errors)

        return attrs

    def validate_username(self, attrs, source):
        request_method = self.context['request'].method

        if request_method == 'PATCH' and source not in attrs:
            return attrs

        current_username = self.object.user.username if self.object else None
        username = attrs[source].lower()
        is_edit = current_username is not None and current_username != username
        form = RegistrationFormUserProfile

        if username in form._reserved_usernames and is_edit:
            raise ValidationError(
                u"%s is a reserved name, please choose another" % username)
        elif not form.legal_usernames_re.search(username):
            raise ValidationError(
                u'username may only contain alpha-numeric characters and '
                u'underscores')
        try:
            User.objects.get(username=username)
        except User.DoesNotExist:
            attrs[source] = username
        else:
            if not current_username or is_edit:
                raise ValidationError(u'%s already exists' % username)

        return attrs

    def validate_name(self, attrs, source):
        if (attrs.get('name') is None) and\
                (attrs.get('user.first_name') is None):
            raise ValidationError(
                u"Either name or first_name should be provided")

        return attrs

    def validate_email(self, attrs, source):
        request_method = self.context['request'].method
        if request_method == 'PUT' and source in attrs:
            return attrs

        if User.objects.filter(email=attrs.get('user.email')).exists():
            raise ValidationError("This email address is already in use. ")
        return attrs

    def validate_twitter(self, attrs, source):
        if isinstance(attrs.get('twitter'), basestring):
            if attrs.get('twitter'):
                match = re.search(r"^[A-Za-z0-9_]{1,15}$",
                                  attrs.get('twitter'))
                if not match:
                    raise ValidationError("Invalid twitter username")
        else:
            attrs['twitter'] = ''
        return attrs
Beispiel #14
0
class ProfileSerializer(serializers.ModelSerializer):
    username = serializers.WritableField(source='user.username')
    display_name = serializers.WritableField(source='name', required=False)
    date_joined = DateTimeUTCField(source='user.date_joined', read_only=True)
    avatar = serializers.SerializerMethodField('get_avatar_url')
    email = (PermissionMod(serializers.EmailField,
                           permissions=[OnlySelf])(source='user.email',
                                                   required=True))
    settings = (PermissionMod(UserSettingSerializer,
                              permissions=[OnlySelf])(many=True,
                                                      read_only=True))
    helpfulness = serializers.Field(source='answer_helpfulness')
    answer_count = serializers.SerializerMethodField('get_answer_count')
    question_count = serializers.SerializerMethodField('get_question_count')
    solution_count = serializers.SerializerMethodField('get_solution_count')
    last_answer_date = serializers.SerializerMethodField(
        'get_last_answer_date')
    is_active = serializers.BooleanField(source='user.is_active',
                                         read_only=True)
    # These are write only fields. It is very important they stays that way!
    password = serializers.WritableField(source='user.password',
                                         write_only=True)

    class Meta:
        model = Profile
        fields = [
            'username',
            'display_name',
            'date_joined',
            'avatar',
            'bio',
            'website',
            'twitter',
            'facebook',
            'mozillians',
            'irc_handle',
            'timezone',
            'country',
            'city',
            'locale',
            'email',
            'settings',
            'helpfulness',
            'question_count',
            'answer_count',
            'solution_count',
            'last_answer_date',
            # Password and email are here so they can be involved in write
            # operations. They is marked as write-only above, so will not be
            # visible.
            'password',
            'is_active',
        ]

    def get_avatar_url(self, profile):
        request = self.context.get('request')
        size = request.REQUEST.get('avatar_size', 48) if request else 48
        return profile_avatar(profile.user, size=size)

    def get_question_count(self, profile):
        return num_questions(profile.user)

    def get_answer_count(self, profile):
        return num_answers(profile.user)

    def get_solution_count(self, profile):
        return num_solutions(profile.user)

    def get_last_answer_date(self, profile):
        last_answer = profile.user.answers.order_by('-created').first()
        return last_answer.created if last_answer else None

    def save_object(self, obj, **kwargs):
        """It is universally a bad idea to force_insert=True on this object. So don't."""
        kwargs.pop('force_insert', None)
        return super(ProfileSerializer, self).save_object(obj, **kwargs)

    def restore_object(self, attrs, instance=None):
        """
        Override the default behavior to make a user if one doesn't exist.

        This user may not be saved here, but will be saved if/when the .save()
        method of the serializer is called.
        """
        instance = (super(ProfileSerializer,
                          self).restore_object(attrs, instance))
        if instance.user_id is None:
            # This is a bit of cheat. The user shouldn't be saved yet, but
            # ``create_inactive_user`` saves it, so their isn't much of a choice.
            u = RegistrationProfile.objects.create_inactive_user(
                attrs['user.username'], attrs['user.password'],
                attrs['user.email'])
            instance.user_id = u.id
            instance.save()
        return instance

    def validate_username(self, attrs, source):
        obj = self.object
        if obj is None:
            # This is a create
            if User.objects.filter(username=attrs['user.username']).exists():
                raise ValidationError('A user with that username exists')
        else:
            # This is an update
            new_username = attrs.get('user.username', obj.user.username)
            if new_username != obj.user.username:
                raise ValidationError("Can't change this field.")

        if re.match(r'^[\w.-]{4,30}$', attrs['user.username']) is None:
            raise ValidationError(
                'Usernames may only be letters, numbers, "." and "-".')

        return attrs

    def validate_display_name(self, attrs, source):
        if attrs.get('name') is None:
            attrs['name'] = attrs.get('user.username')
        return attrs

    def validate_email(self, attrs, source):
        email = attrs.get('user.email')
        if email and User.objects.filter(email=email).exists():
            raise ValidationError('A user with that email address '
                                  'already exists.')
        return attrs
Beispiel #15
0
class CollectionDetailSerializer(CollectionCreateOrUpdateSerializer):
    type = serializers.CharField(source='resource_type', read_only=True)
    uuid = serializers.CharField(source='id', read_only=True)
    id = serializers.CharField(
        required=False,
        validators=[RegexValidator(regex=NAMESPACE_REGEX)],
        source='mnemonic')
    short_code = serializers.CharField(source='mnemonic', read_only=True)
    name = serializers.CharField(required=False)
    full_name = serializers.CharField(required=False)
    preferred_source = serializers.CharField(required=False)
    repository_type = serializers.CharField(required=False)
    custom_resources_linked_source = serializers.CharField(required=False)
    description = serializers.CharField(required=False)
    external_id = serializers.CharField(required=False)
    collection_type = serializers.CharField(required=False)
    custom_validation_schema = serializers.CharField(required=False)
    public_access = serializers.ChoiceField(required=False,
                                            choices=ACCESS_TYPE_CHOICES)
    default_locale = serializers.CharField(required=False)
    supported_locales = serializers.CharField(required=False)
    website = serializers.CharField(required=False)
    url = serializers.CharField(read_only=True)
    versions_url = serializers.CharField(read_only=True)
    concepts_url = serializers.CharField(read_only=True)
    mappings_url = serializers.CharField(read_only=True)
    owner = serializers.CharField(source='parent_resource', read_only=True)
    owner_type = serializers.CharField(source='parent_resource_type',
                                       read_only=True)
    owner_url = serializers.CharField(source='parent_url', read_only=True)
    versions = serializers.IntegerField(source='num_versions', read_only=True)
    created_on = serializers.DateTimeField(source='created_at', read_only=True)
    updated_on = serializers.DateTimeField(source='updated_at', read_only=True)
    created_by = serializers.CharField(read_only=True)
    updated_by = serializers.CharField(read_only=True)
    extras = serializers.WritableField(required=False)
    references = CollectionReferenceSerializer(many=True)
    active_concepts = serializers.SerializerMethodField(
        method_name='get_active_concepts')
    active_mappings = serializers.SerializerMethodField(
        method_name='get_active_mappings')

    def get_fields(self, *args, **kwargs):
        fields = super(CollectionDetailSerializer,
                       self).get_fields(*args, **kwargs)
        from collection.views import INCLUDE_REFERENCES_PARAM
        include_references = self.context.get(INCLUDE_REFERENCES_PARAM, True)
        if not include_references:
            fields.pop('references', None)
        return fields

    def save_object(self, obj, **kwargs):
        request_user = kwargs.pop('user', None) or self.context['request'].user
        errors = Collection.persist_changes(obj, request_user, **kwargs)
        if errors:
            self._errors = self._errors or {}
            self._errors.update(errors)
        else:
            head_obj = obj.get_head()
            head_obj.update_version_data(obj)
            head_obj.save()
Beispiel #16
0
class UpdateStorySerializer(StorySerializer):
    chapters = serializers.WritableField(source='chapters')

    class Meta:
        model = Story
Beispiel #17
0
 def mandatory_fields(self):
     return {
         "uuid": serializers.WritableField(),
         "events": EventListSerializer(),
     }