Beispiel #1
0
class AccountSubmissionImageUpdateSerializer(Serializer):
    url = serializers.URLField()
    published = serializers.BooleanField(required=False)
    rotate = serializers.RegexField(regex=r'^left|right$', required=False)
Beispiel #2
0
class QQAuthUserSerializer(serializers.ModelSerializer):
    """QQ绑定数据序列化器类"""
    sms_code = serializers.CharField(label='短信验证码', write_only=True)
    access_token = serializers.CharField(label='加密OpenID', write_only=True)
    token = serializers.CharField(label='JWT Token', read_only=True)
    mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$', write_only=True)

    class Meta:
        model = User
        fields = ('id', 'username', 'mobile', 'password', 'sms_code', 'access_token', 'token')

        extra_kwargs = {
            'username': {
                'read_only': True
            },
            'password': {
                'write_only': True,
                'min_length': 8,
                'max_length': 20,
                'error_messages': {
                    'min_length': '最小长度为8',
                    'max_length': '最大长度为20'
                }

            }
        }

    # 手机号格式,短信验证码是否正确,access_token是否有效,如果手机已注册,校验密码是否正确
    def validate(self, attrs):
        # access_token是否有效
        access_token = attrs['access_token'] # 加密的openid

        openid = OAuthQQ.check_save_user_token(access_token)

        if openid is None:
            # 解密失败
            raise serializers.ValidationError('无效的access_token')

        attrs['openid'] = openid

        # 短信验证码是否正确
        # 从redis中获取真实的短信验证码内容
        redis_conn = get_redis_connection('verify_codes')

        mobile = attrs['mobile']
        real_sms_code = redis_conn.get('sms_%s' % mobile)  # bytes

        if real_sms_code is None:
            raise serializers.ValidationError('短信验证码已过期')

        # 获取客户端传递短信验证码内容
        sms_code = attrs['sms_code']  # str

        # 对比短信验证码内容
        if real_sms_code.decode() != sms_code:
            raise serializers.ValidationError('短信验证码错误')

        # 如果手机已注册,校验密码是否正确
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 用户不存在,mobile未注册
            user = None
        else:
            # 用户存在,mobile已注册,校验密码是否正确
            password = attrs['password']
            if not user.check_password(password):
                # 密码不正确
                raise serializers.ValidationError('密码错误')

        attrs['user'] = user

        return attrs

    def create(self, validated_data):
        """保存QQ登录绑定的数据"""
        # 如果mobile未注册,先创建新用户
        user = validated_data['user']

        if user is None:
            mobile = validated_data['mobile']
            password = validated_data['password']
            # 随机生成用户名
            username = base64.b64encode(os.urandom(9)).decode()
            user = User.objects.create_user(username=username,
                                            password=password,
                                            mobile=mobile)
        # 保存绑定的数据
        openid = validated_data['openid']
        OAuthWeixinUser.objects.create(user=user,
                                   openid=openid)

        # 生成jwt token
        from rest_framework_jwt.settings import api_settings

        # 生成载荷的内容
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        # 生成jwt token
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        # 给user对象增加属性token,保存jwt token的数据
        user.token = token

        return user
Beispiel #3
0
class AtomicPublicationSerializer(serializers.Serializer):  # pylint: disable=abstract-method
    """Serializer for saving and publishing a Course and associated products.

    Using a ModelSerializer for the Course data makes it difficult to use this serializer to handle updates.
    The automatically applied validation logic rejects course IDs which already exist in the database.
    """
    id = serializers.RegexField(COURSE_ID_REGEX, max_length=255)
    name = serializers.CharField(max_length=255)
    # Verification deadline should only be required if the course actually requires verification.
    verification_deadline = serializers.DateTimeField(required=False, allow_null=True)
    products = serializers.ListField()

    def __init__(self, *args, **kwargs):
        super(AtomicPublicationSerializer, self).__init__(*args, **kwargs)

        self.access_token = kwargs['context'].pop('access_token')
        self.partner = kwargs['context'].pop('partner', None)

    def validate_products(self, products):
        """Validate product data."""
        for product in products:
            # Verify that each product is intended to be a Seat.
            product_class = product.get('product_class')
            if product_class != 'Seat':
                raise serializers.ValidationError(
                    _(u"Invalid product class [{product_class}] requested.".format(product_class=product_class))
                )

            # Verify that attributes required to create a Seat are present.
            attrs = self._flatten(product['attribute_values'])
            if attrs.get('id_verification_required') is None:
                raise serializers.ValidationError(_(u"Products must indicate whether ID verification is required."))

            # Verify that a price is present.
            if product.get('price') is None:
                raise serializers.ValidationError(_(u"Products must have a price."))

        return products

    def get_partner(self):
        """Validate partner"""
        if not self.partner:
            partner = Partner.objects.get(id=1)
            return partner

        return self.partner

    def save(self):
        """Save and publish Course and associated products."

        Returns:
            tuple: A Boolean indicating whether the Course was created, an Exception,
                if one was raised (else None), and a message for the user, if necessary (else None).
        """
        course_id = self.validated_data['id']
        course_name = self.validated_data['name']
        course_verification_deadline = self.validated_data.get('verification_deadline')
        products = self.validated_data['products']
        partner = self.get_partner()

        try:
            if not waffle.switch_is_active('publish_course_modes_to_lms'):
                message = _(
                    u'Course [{course_id}] was not published to LMS '
                    u'because the switch [publish_course_modes_to_lms] is disabled. '
                    u'To avoid ghost SKUs, data has not been saved.'
                ).format(course_id=course_id)

                raise Exception(message)

            # Explicitly delimit operations which will be rolled back if an exception is raised.
            with transaction.atomic():
                course, created = Course.objects.get_or_create(id=course_id)
                course.name = course_name
                course.verification_deadline = course_verification_deadline
                course.save()

                for product in products:
                    attrs = self._flatten(product['attribute_values'])

                    # Extract arguments required for Seat creation, deserializing as necessary.
                    certificate_type = attrs.get('certificate_type', '')
                    create_enrollment_code = product['course'].get('create_enrollment_code') and \
                        self.context['request'].site.siteconfiguration.enable_enrollment_codes
                    id_verification_required = attrs['id_verification_required']
                    price = Decimal(product['price'])

                    # Extract arguments which are optional for Seat creation, deserializing as necessary.
                    expires = product.get('expires')
                    expires = parse(expires) if expires else None
                    credit_provider = attrs.get('credit_provider')
                    credit_hours = attrs.get('credit_hours')
                    credit_hours = int(credit_hours) if credit_hours else None

                    course.create_or_update_seat(
                        certificate_type,
                        id_verification_required,
                        price,
                        partner,
                        expires=expires,
                        credit_provider=credit_provider,
                        credit_hours=credit_hours,
                        create_enrollment_code=create_enrollment_code
                    )

                resp_message = course.publish_to_lms(access_token=self.access_token)
                published = (resp_message is None)

                if published:
                    return created, None, None
                else:
                    raise Exception(resp_message)

        except Exception as e:  # pylint: disable=broad-except
            logger.exception(u'Failed to save and publish [%s]: [%s]', course_id, e.message)
            return False, e, e.message

    def _flatten(self, attrs):
        """Transform a list of attribute names and values into a dictionary keyed on the names."""
        return {attr['name']: attr['value'] for attr in attrs}
Beispiel #4
0
    def __init__(self, instance=None, data=empty, **kwargs):
        # Instantiate the superclass normally
        super(FieldValueSerializer, self).__init__(data=data, **kwargs)
        field = kwargs["context"].pop("field", None)
        self.invalid_field_errors = {}

        if field.field_type in ["text", "textarea", "password"]:
            self.fields["value"] = serializers.CharField(
                max_length=field.max_length,
                min_length=field.min_length,
                allow_null=not field.required,
            )
        elif field.field_type == "email":
            self.fields["value"] = serializers.EmailField(
                max_length=field.max_length,
                min_length=field.min_length,
                allow_null=not field.required,
            )
        elif field.field_type == "float":
            self.fields["value"] = serializers.FloatField(
                allow_null=not field.required)
        elif field.field_type == "number":
            self.fields["value"] = serializers.IntegerField(
                allow_null=not field.required, max_value=None,
                min_value=None)  # add min and max
        elif field.field_type == "date":
            self.fields["value"] = serializers.DateField(
                allow_null=not field.required)
        elif field.field_type == "time":
            self.fields["value"] = serializers.TimeField(
                allow_null=not field.required)
        elif field.field_type in ["select", "radio"]:
            self.fields["value"] = serializers.ChoiceField(
                allow_null=not field.required, choices=field.choices)
        elif field.field_type == "multiselect":
            self.fields["value"] = serializers.MultipleChoiceField(
                allow_null=not field.required, choices=field.choices)
        elif field.field_type in ["checkbox", "switch"]:
            self.fields["value"] = serializers.BooleanField()
        elif field.field_type == "url":
            self.fields["value"] = serializers.URLField(
                max_length=field.max_length,
                min_length=field.min_length,
                allow_null=not field.required,
            )
        elif field.field_type == "array":
            self.fields["value"] = serializers.ListField(
                allow_null=not field.required)  # add minlen and max
        elif field.field_type == "regex":
            self.fields["value"] = serializers.RegexField(
                field.regex_pattern,
                max_length=field.max_length,
                min_length=field.min_length,
                allow_null=not field.required,
            )
        elif field.field_type == "file":
            self.fields["value"] = serializers.FileField(
                allow_null=not field.required)
        else:
            self.invalid_field_errors = {
                "fields": [f"{field.field_type} is not a valid field type."]
            }
Beispiel #5
0
 class ExampleSerializer(serializers.Serializer):
     name = serializers.RegexField(re.compile(r'\d'), required=True)
Beispiel #6
0
class OAuthQQUserSerializer(serializers.ModelSerializer):
    mobile = serializers.RegexField(label="手机号", regex=r'^1[3-9]\d{9}$')
    sms_code = serializers.CharField(label="短信验证码", write_only=True)
    access_token = serializers.CharField(label="操作凭证", write_only=True)
    token = serializers.CharField(label="JWTtoken", read_only=True)

    class Meta:
        model = User
        fields = ("mobile", "password", "sms_code", "access_token", "token", "id", "username")
        extra_kwargs = {
            "username":{
                "read_only":True
            },
            'password': {
                'write_only': True,
                'min_length': 8,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许8-20个字符的密码',
                    'max_length': '仅允许8-20个字符的密码',
                }
            }
        }

    # 校验参数
    def validate(self, attrs):
        # 校验access_token
        access_token = attrs["access_token"]
        openid = OAuthQQ.check_bind_user_access_token(access_token)
        if not openid:
            return serializers.ValidationError("无效的")

        # 将openid保存到atters中
        attrs["openid"] = openid

        # 校验短信验证码
        mobile = attrs["mobile"]
        sms_code = attrs["sms_code"]
        redis_conn = get_redis_connection("verify_codes")
        real_sms_code = redis_conn.get("sms_%s" % mobile)
        if sms_code != real_sms_code.decode():
            raise serializers.ValidationError("短信验证码错误")

        # 判断用户是否存在,若存在校验密码
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            pass
        else:
            password = attrs["password"]
            if not user.check_password(password):
                raise serializers.ValidationError("密码错误")

            attrs["user"] = user
        return attrs

    def create(self, validated_data):
        openid = validated_data['openid']
        mobile = validated_data["mobile"]
        user = validated_data["user"]
        password = validated_data["password"]

        # 判断用户是否存在
        if not user:
            # 如果不存在,先创建user, 再创建OAuthQQUser
            user = User.objects.create_user(username=mobile, mobile=mobile,password=password)

        # 如果存在,绑定,创建OAuthQQUser
        OAuthQQUser.objects.create(user=user, openid=openid)

        # 签发JWT token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        user.token = token
        self.context["view"].user = user

        return user
Beispiel #7
0
class AllFieldsSerializer(serializers.ModelSerializer):
    field_decimal_uncoerced = serializers.DecimalField(source='field_decimal',
                                                       max_digits=6,
                                                       decimal_places=3,
                                                       coerce_to_string=False)
    field_method_float = serializers.SerializerMethodField()

    def get_field_method_float(self, obj) -> float:
        return 1.3456

    field_method_object = serializers.SerializerMethodField()

    def get_field_method_object(self, obj) -> dict:
        return {'key': 'value'}

    field_regex = serializers.RegexField(r'^[a-zA-z0-9]{10}\-[a-z]',
                                         label='A regex field')

    field_hidden = serializers.HiddenField(default='')

    # composite fields
    field_list = serializers.ListField(
        child=serializers.FloatField(),
        min_length=3,
        max_length=100,
    )
    field_list_serializer = serializers.ListField(
        child=AuxSerializer(),
        source='field_list_object',
    )

    # extra related fields
    field_related_slug = serializers.SlugRelatedField(
        read_only=True, source='field_foreign',
        slug_field='id')  # type: ignore
    field_related_string = serializers.StringRelatedField(
        source='field_foreign')  # type: ignore
    field_related_hyperlink = serializers.HyperlinkedRelatedField(
        read_only=True, source='field_foreign',
        view_name='aux-detail')  # type: ignore
    field_identity_hyperlink = serializers.HyperlinkedIdentityField(
        read_only=True, view_name='allfields-detail')

    # read only - model traversal
    field_read_only_nav_uuid = serializers.ReadOnlyField(
        source='field_foreign.id')
    field_read_only_nav_uuid_3steps = serializers.ReadOnlyField(
        source='field_foreign.field_foreign.field_foreign.id',
        allow_null=True,  # force field output even if traversal fails
    )
    field_read_only_model_function_basic = serializers.ReadOnlyField(
        source='model_function_basic')
    field_read_only_model_function_model = serializers.ReadOnlyField(
        source='model_function_model.id')

    # override default writable bool field with readonly
    field_bool_override = serializers.ReadOnlyField()

    field_model_property_float = serializers.ReadOnlyField()

    field_model_cached_property_float = serializers.ReadOnlyField()

    field_dict_int = serializers.DictField(
        child=serializers.IntegerField(),
        source='field_json',
    )

    # there is a JSON model field for django>=3.1 that would be placed automatically. for <=3.1 we
    # need to set the field explicitly. defined here for both cases to have consistent ordering.
    field_json = serializers.JSONField()

    # traversal of non-model types of complex object
    field_sub_object_calculated = serializers.ReadOnlyField(
        source='sub_object.calculated')
    field_sub_object_nested_calculated = serializers.ReadOnlyField(
        source='sub_object.nested.calculated')
    field_sub_object_model_int = serializers.ReadOnlyField(
        source='sub_object.model_instance.field_int')

    field_sub_object_cached_calculated = serializers.ReadOnlyField(
        source='sub_object_cached.calculated')
    field_sub_object_cached_nested_calculated = serializers.ReadOnlyField(
        source='sub_object_cached.nested.calculated')
    field_sub_object_cached_model_int = serializers.ReadOnlyField(
        source='sub_object_cached.model_instance.field_int')

    # typing.Optional
    field_optional_sub_object_calculated = serializers.ReadOnlyField(
        source='optional_sub_object.calculated',
        allow_null=True,
    )
    field_sub_object_optional_int = serializers.ReadOnlyField(
        source='sub_object.optional_int',
        allow_null=True,
    )

    class Meta:
        fields = '__all__'
        model = AllFields
Beispiel #8
0
class OAuthQQUserSerializer(serializers.Serializer):

    access_token = serializers.CharField(label='操作凭证')
    mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')
    password = serializers.CharField(label='密码', max_length=20, min_length=8)
    sms_code = serializers.CharField(label='短信验证码')


    # def validate(self, data):
    def validate(self, attrs):

        #1. 需要对加密的openid进行处理
        access_token = attrs.get('access_token')
        print(access_token)
        openid = check_access_token(access_token)

        if openid is None:
            raise serializers.ValidationError('openid错误')

        # 我们通过attrs来传递数据
        attrs['openid']=openid

        #2. 需要对短信进行验证
        # 2.1 获取用户提交的
        mobile = attrs.get('mobile')
        sms_code = attrs['sms_code']
        # 2.2 获取 redis
        redis_conn = get_redis_connection('code')

        redis_code = redis_conn.get('sms_' + mobile)

        if redis_code is None:
            raise serializers.ValidationError('短信验证码已过期')

        # 最好删除短信
        redis_conn.delete('sms_' + mobile)
        # 2.3 比对
        if redis_code.decode() != sms_code:
            raise serializers.ValidationError('验证码不一致')

        #3. 需要对手机号进行判断
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            #说明没有注册过
            #创建用户
            # User.objects.create()
            pass
        else:
            #说明注册过,
            # 注册过需要验证密码
            if not user.check_password(attrs['password']):
                raise serializers.ValidationError('密码不正确')

            attrs['user']=user


        return attrs

    # request.data --> 序列化器(data=xxx)
    # data --> attrs -->validated_data
    def create(self, validated_data):

        user = validated_data.get('user')

        if user is None:
            #创建user
            user = User.objects.create(
                mobile=validated_data.get('mobile'),
                username=validated_data.get('mobile'),
                password=validated_data.get('password')
            )

            #对password进行加密
            user.set_password(validated_data['password'])
            user.save()

        qquser = OAuthQQUser.objects.create(
            user=user,
            openid=validated_data.get('openid')
        )


        return qquser
Beispiel #9
0
class QuerySerializer(serializers.Serializer):
    from_date = serializers.DateTimeField()
    to_date = serializers.DateTimeField()
    from_time = serializers.RegexField(regex='^\d{2}:\d{2}$')
    to_time = serializers.RegexField(regex='^\d{2}:\d{2}$')
    timezone = serializers.CharField()
Beispiel #10
0
class OrganizationSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=64)
    slug = serializers.RegexField(r"^[a-z0-9_\-]+$", max_length=50)
    accountRateLimit = EmptyIntegerField(
        min_value=0, max_value=1000000, required=False, allow_null=True
    )
    projectRateLimit = EmptyIntegerField(
        min_value=50, max_value=100, required=False, allow_null=True
    )
    avatar = AvatarField(required=False, allow_null=True)
    avatarType = serializers.ChoiceField(
        choices=(("upload", "upload"), ("letter_avatar", "letter_avatar")),
        required=False,
        allow_null=True,
    )

    openMembership = serializers.BooleanField(required=False)
    allowSharedIssues = serializers.BooleanField(required=False)
    enhancedPrivacy = serializers.BooleanField(required=False)
    dataScrubber = serializers.BooleanField(required=False)
    dataScrubberDefaults = serializers.BooleanField(required=False)
    sensitiveFields = ListField(child=serializers.CharField(), required=False)
    safeFields = ListField(child=serializers.CharField(), required=False)
    storeCrashReports = serializers.BooleanField(required=False)
    attachmentsRole = serializers.CharField(required=True)
    scrubIPAddresses = serializers.BooleanField(required=False)
    scrapeJavaScript = serializers.BooleanField(required=False)
    isEarlyAdopter = serializers.BooleanField(required=False)
    require2FA = serializers.BooleanField(required=False)
    trustedRelays = ListField(child=serializers.CharField(), required=False)

    @memoize
    def _has_legacy_rate_limits(self):
        org = self.context["organization"]
        return OrganizationOption.objects.filter(
            organization=org, key__in=LEGACY_RATE_LIMIT_OPTIONS
        ).exists()

    def _has_sso_enabled(self):
        org = self.context["organization"]
        return AuthProvider.objects.filter(organization=org).exists()

    def validate_slug(self, value):
        # Historically, the only check just made sure there was more than 1
        # character for the slug, but since then, there are many slugs that
        # fit within this new imposed limit. We're not fixing existing, but
        # just preventing new bad values.
        if len(value) < 3:
            raise serializers.ValidationError(
                'This slug "%s" is too short. Minimum of 3 characters.' % (value,)
            )
        if value in RESERVED_ORGANIZATION_SLUGS:
            raise serializers.ValidationError(
                'This slug "%s" is reserved and not allowed.' % (value,)
            )
        qs = Organization.objects.filter(slug=value).exclude(id=self.context["organization"].id)
        if qs.exists():
            raise serializers.ValidationError('The slug "%s" is already in use.' % (value,))
        return value

    def validate_sensitiveFields(self, value):
        if value and not all(value):
            raise serializers.ValidationError("Empty values are not allowed.")
        return value

    def validate_safeFields(self, value):
        if value and not all(value):
            raise serializers.ValidationError("Empty values are not allowed.")
        return value

    def validate_attachmentsRole(self, value):
        try:
            roles.get(value)
        except KeyError:
            raise serializers.ValidationError("Invalid role")
        return value

    def validate_require2FA(self, value):
        user = self.context["user"]
        has_2fa = Authenticator.objects.user_has_2fa(user)
        if value and not has_2fa:
            raise serializers.ValidationError(ERR_NO_2FA)

        if value and self._has_sso_enabled():
            raise serializers.ValidationError(ERR_SSO_ENABLED)
        return value

    def validate_trustedRelays(self, value):
        from sentry import features

        organization = self.context["organization"]
        request = self.context["request"]
        has_relays = features.has("organizations:relay", organization, actor=request.user)
        if not has_relays:
            raise serializers.ValidationError(
                "Organization does not have the relay feature enabled"
            )
        return value

    def validate_accountRateLimit(self, value):
        if not self._has_legacy_rate_limits:
            raise serializers.ValidationError(
                "The accountRateLimit option cannot be configured for this organization"
            )
        return value

    def validate_projectRateLimit(self, value):
        if not self._has_legacy_rate_limits:
            raise serializers.ValidationError(
                "The accountRateLimit option cannot be configured for this organization"
            )
        return value

    def validate(self, attrs):
        attrs = super(OrganizationSerializer, self).validate(attrs)
        if attrs.get("avatarType") == "upload":
            has_existing_file = OrganizationAvatar.objects.filter(
                organization=self.context["organization"], file__isnull=False
            ).exists()
            if not has_existing_file and not attrs.get("avatar"):
                raise serializers.ValidationError(
                    {"avatarType": "Cannot set avatarType to upload without avatar"}
                )
        return attrs

    def save(self):
        org = self.context["organization"]
        changed_data = {}

        for key, option, type_, default_value in ORG_OPTIONS:
            if key not in self.initial_data:
                continue
            try:
                option_inst = OrganizationOption.objects.get(organization=org, key=option)
            except OrganizationOption.DoesNotExist:
                OrganizationOption.objects.set_value(
                    organization=org, key=option, value=type_(self.initial_data[key])
                )

                if self.initial_data[key] != default_value:
                    changed_data[key] = u"to {}".format(self.initial_data[key])
            else:
                option_inst.value = self.initial_data[key]
                # check if ORG_OPTIONS changed
                if option_inst.has_changed("value"):
                    old_val = option_inst.old_value("value")
                    changed_data[key] = u"from {} to {}".format(old_val, option_inst.value)
                option_inst.save()

        if "openMembership" in self.initial_data:
            org.flags.allow_joinleave = self.initial_data["openMembership"]
        if "allowSharedIssues" in self.initial_data:
            org.flags.disable_shared_issues = not self.initial_data["allowSharedIssues"]
        if "enhancedPrivacy" in self.initial_data:
            org.flags.enhanced_privacy = self.initial_data["enhancedPrivacy"]
        if "isEarlyAdopter" in self.initial_data:
            org.flags.early_adopter = self.initial_data["isEarlyAdopter"]
        if "require2FA" in self.initial_data:
            org.flags.require_2fa = self.initial_data["require2FA"]
        if "name" in self.initial_data:
            org.name = self.initial_data["name"]
        if "slug" in self.initial_data:
            org.slug = self.initial_data["slug"]

        org_tracked_field = {
            "name": org.name,
            "slug": org.slug,
            "default_role": org.default_role,
            "flag_field": {
                "allow_joinleave": org.flags.allow_joinleave.is_set,
                "enhanced_privacy": org.flags.enhanced_privacy.is_set,
                "disable_shared_issues": org.flags.disable_shared_issues.is_set,
                "early_adopter": org.flags.early_adopter.is_set,
                "require_2fa": org.flags.require_2fa.is_set,
            },
        }

        # check if fields changed
        for f, v in six.iteritems(org_tracked_field):
            if f is not "flag_field":
                if org.has_changed(f):
                    old_val = org.old_value(f)
                    changed_data[f] = u"from {} to {}".format(old_val, v)
            else:
                # check if flag fields changed
                for f, v in six.iteritems(org_tracked_field["flag_field"]):
                    if org.flag_has_changed(f):
                        changed_data[f] = u"to {}".format(v)

        org.save()

        if "avatar" in self.initial_data or "avatarType" in self.initial_data:
            OrganizationAvatar.save_avatar(
                relation={"organization": org},
                type=self.initial_data.get("avatarType", "upload"),
                avatar=self.initial_data.get("avatar"),
                filename=u"{}.png".format(org.slug),
            )
        if "require2FA" in self.initial_data and self.initial_data["require2FA"] is True:
            org.handle_2fa_required(self.context["request"])
        return org, changed_data
Beispiel #11
0
class OrganizationSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=64, required=True)
    slug = serializers.RegexField(r'^[a-z0-9_\-]+$',
                                  max_length=50,
                                  required=False)
    defaultTeam = serializers.BooleanField(required=False)
Beispiel #12
0
class ClientInputSerializer(serializers.Serializer):
    name = serializers.RegexField(regex='^[a-z0-9_]+$', allow_blank=False)
    utc_offset = serializers.IntegerField()
    folder_name = serializers.CharField(allow_blank=False)
Beispiel #13
0
class DraftCertificationSerializer(RecaptchaSerializerMixin,
                                   CertificationLevelMixin, CouponMixin,
                                   serializers.Serializer):

    full_name = serializers.CharField()
    email = serializers.EmailField(allow_blank=False)
    recaptcha = serializers.CharField(read_only=True)
    referrer = serializers.RegexField('[a-zA-Z0-9]+:[a-zA-Z0-9]+',
                                      required=False,
                                      allow_blank=True)

    def validate_email(self, value):
        return UserModel._default_manager.normalize_email(value)

    def validate(self, attrs):
        attrs = super().validate(attrs)
        coupon = attrs.get('coupon', None)
        certification = ExOCertification.objects.get(level=attrs['level'])
        if coupon and not coupon.can_use_coupon(certification, False):
            raise serializers.ValidationError(
                {'coupon': ['Coupon is not valid']})
        return attrs

    def create(self, validated_data):
        email = validated_data.get('email')
        full_name = validated_data.get('full_name')
        level = validated_data.get('level')
        coupon = validated_data.get('coupon', None)
        referrer = validated_data.get('referrer', None)
        user = None

        try:
            user = UserModel.objects.get(email=email)
        except UserModel.DoesNotExist:
            pass

        if level == settings.EXO_CERTIFICATION_CERTIFICATION_CH_LEVEL_3:
            raise NotAuthenticated({'custom': 'LOGIN_REQUIRED_TO_PROCEED'})

        # Checks whether user can certificate or not
        requester = user if user else email
        certification = user_can_do_certification(requester, level)

        certification_request_defaults = {
            'requester_name': full_name,
        }

        certification_request, created = CertificationRequest.objects.get_or_create(
            certification=certification,
            requester_email=email,
            status__in=[
                settings.EXO_CERTIFICATION_REQUEST_STATUS_CH_DRAFT,
                settings.EXO_CERTIFICATION_REQUEST_STATUS_CH_PENDING,
            ],
            defaults=certification_request_defaults,
        )

        if created:
            certification_request.referrer = referrer

        if user:
            certification_request.user = user
            category = settings.EXO_CERTIFICATION_INSTRUMENTATION_EVENTS.get(
                certification_request.level)
            coupon_code = coupon.code if coupon else None
            SegmentAnalytics.event(
                user=user,
                category=category,
                event=settings.INSTRUMENTATION_EVENT_CERTIFICATION_INTERESTED,
                coupon=coupon_code,
                entry_point=settings.
                INSTRUMENTATION_USER_ENTRY_POINT_CERTIFICATIONS)

        certification_request.coupon = coupon
        certification_request.save(
            update_fields=['user', 'coupon', 'referrer'])

        return certification_request

    def to_representation(self, instance):
        return CertificationOutputSerializer(instance).data
Beispiel #14
0
class LoginSerializer(serializers.Serializer):
    email = serializers.EmailField(max_length=200)
    password = serializers.CharField(write_only=True)
    code = serializers.RegexField(
        regex=r'^[0-9]{6}$|^[a-zA-Z0-9]{10}$',
        min_length=6,
        max_length=10,
        allow_blank=True,
        required=False,
    )

    error_messages = {
        'invalid_login':
        _('Login failed. Note that fields may be case-sensitive.'),
        'invalid_recaptcha':
        _('Invalid reCAPTCHA response.'),
        'throttled_login':
        _('There were too many unsuccessful login attempts, please try '
          'again later.'),
        'invalid_mfa':
        _('Invalid one-time password code.')
    }

    def get_invalid_captcha_error(self):
        return serializers.ValidationError(
            self.error_messages['invalid_recaptcha'],
            code='invalid_recaptcha',
        )

    def get_throttled_login_error(self):
        return serializers.ValidationError(
            self.error_messages['throttled_login'],
            code='throttled_login',
        )

    def get_invalid_mfa_error(self):
        return serializers.ValidationError(
            self.error_messages['invalid_mfa'],
            code='invalid_mfa',
        )

    def get_invalid_login_error(self):
        return serializers.ValidationError(
            self.error_messages['invalid_login'],
            code='invalid_login',
        )

    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        code = attrs.get('code')

        if username and password:
            if not validate_device_cookie(self.request, username):
                raise self.get_throttled_login_error()

            if not is_valid_recaptcha(self.request):
                raise self.get_invalid_captcha_error()

            self.user = authenticate(self.request,
                                     username=username,
                                     password=password)

            if self.user is None or not self.user.is_active:
                raise self.get_invalid_login_error()
            else:
                if not is_valid_mfa_code(self.user, code):
                    raise self.get_invalid_mfa_error()

        return attrs
Beispiel #15
0
class OAuthQQUserSerializer(serializers.Serializer):
    """
    QQ登录创建用户序列化器
    """
    access_token = serializers.CharField(label='操作凭证')
    mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')
    password = serializers.CharField(label='密码', max_length=20, min_length=8)
    sms_code = serializers.CharField(label='短信验证码')

    def validate(self, data):
        # 检验access_token
        access_token = data['access_token']
        openid = OAuthQQ.check_save_user_token(access_token)
        if not openid:
            raise serializers.ValidationError('无效的access_token')

        data['openid'] = openid

        # 检验短信验证码
        mobile = data['mobile']
        sms_code = data['sms_code']
        redis_conn = get_redis_connection('verify_codes')
        real_sms_code = redis_conn.get('sms_%s' % mobile)
        if real_sms_code.decode() != sms_code:
            raise serializers.ValidationError('短信验证码错误')

        # 如果用户存在,检查用户密码
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            pass
        else:
            password = data['password']
            if not user.check_password(password):
                raise serializers.ValidationError('密码错误')
            data['user'] = user
        return data

    # def create(self, validated_data):
    #     user = validated_data.get('user')
    #     if not user:
    #         # 用户不存在,创建用户
    #         user = User.objects.create_user(
    #             username=validated_data['mobile'],
    #             password=validated_data['password'],
    #             mobile=validated_data['mobile'],
    #         )

    #     OAuthQQUser.objects.create(
    #         openid=validated_data['openid'],
    #         user=user
    #     )
    #     return user

    def create(self, validated_data):

        openid = validated_data['openid']
        user = validated_data.get('user')
        mobile = validated_data['mobile']
        password = validated_data['password']

        # 判断用户是否存在
        if not user:
            user = User.objects.create_user(username=mobile,
                                            mobile=mobile,
                                            password=password)

        OAuthQQUser.objects.create(user=user, openid=openid)

        # 签发JWT token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        user.token = token

        self.context['view'].user = user

        return user
Beispiel #16
0
class CreateConfigSerializer(serializers.Serializer):
    cron_id = serializers.PrimaryKeyRelatedField(
        help_text='Cron ID.',
        label='Cron ID',
        queryset=models.CronTab.objects.all(),
        required=True
    )

    domain = serializers.CharField(
        help_text='Domain name.',
        label='Domain',
        max_length=254,
        min_length=3,
        required=True
    )

    user = serializers.RegexField(
        help_text='System user name.',
        label='User',
        max_length=32,
        min_length=2,
        regex='^[a-z][a-z0-9]+$',
        required=True
    )

    def validate_domain(self, value):
        if not validators.domain(value):
            raise serializers.ValidationError(
                f"Domain '{value}' is invalid.",
                code='invalid'
            )

        return value

    def validate_user(self, value):
        try:
            pwd.getpwnam(value).pw_uid
        except KeyError:
            raise serializers.ValidationError(
                f"System User '{value}' does not exist.",
                code='not_found'
            )

        return value

    def validate(self, attrs):
        domain = attrs.get('domain')

        user = attrs.get('user')

        cron_id = attrs.get('cron_id')

        if os.path.exists(f"{CronPath.domain_dir(user)}{domain}"):
            raise serializers.ValidationError(
                "Cron Domain '{domain}' already exists.",
                code='exists'
            )

        elif os.path.exists(f"{CronPath.domain_dir(user)}{domain}/{user}_{cron_id.pk}"):
            raise serializers.ValidationError(
                f"Cron ID '{cron_id.pk}' currently exists.",
                code='exists'
            )

        elif not os.path.exists(f"{WebPath.www_dir(user)}{domain}"):
            raise serializers.ValidationError(
                f"Web Domain '{domain}' does not exist.",
                code='not_found'
            )

        return attrs

    def create(self, validated_data):
        validated_domain = validated_data['domain']

        validated_user = validated_data['user']

        validated_cron_id = validated_data['cron_id']

        path_cron = f"{CronPath.domain_dir(validated_user)}{validated_domain}/{validated_user}_{validated_cron_id.pk}"

        content = render_to_string('cron/tab.tmpl') \
            .replace('[CRON-FORMAT]', validated_cron_id.format) \
            .replace('[CRON-COMMAND]', validated_cron_id.command)

        handle = open(path_cron, 'w')
        handle.write(content)
        handle.close()

        return validated_data
class OrganizationSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=64)
    slug = serializers.RegexField(r"^[a-z0-9_\-]+$", max_length=50)
    accountRateLimit = EmptyIntegerField(
        min_value=0, max_value=1000000, required=False, allow_null=True
    )
    projectRateLimit = EmptyIntegerField(
        min_value=50, max_value=100, required=False, allow_null=True
    )
    avatar = AvatarField(required=False, allow_null=True)
    avatarType = serializers.ChoiceField(
        choices=(("upload", "upload"), ("letter_avatar", "letter_avatar")),
        required=False,
        allow_null=True,
    )

    openMembership = serializers.BooleanField(required=False)
    allowSharedIssues = serializers.BooleanField(required=False)
    enhancedPrivacy = serializers.BooleanField(required=False)
    dataScrubber = serializers.BooleanField(required=False)
    dataScrubberDefaults = serializers.BooleanField(required=False)
    sensitiveFields = ListField(child=serializers.CharField(), required=False)
    safeFields = ListField(child=serializers.CharField(), required=False)
    storeCrashReports = serializers.IntegerField(min_value=-1, max_value=20, required=False)
    attachmentsRole = serializers.CharField(required=True)
    debugFilesRole = serializers.CharField(required=True)
    eventsMemberAdmin = serializers.BooleanField(required=False)
    alertsMemberWrite = serializers.BooleanField(required=False)
    scrubIPAddresses = serializers.BooleanField(required=False)
    scrapeJavaScript = serializers.BooleanField(required=False)
    isEarlyAdopter = serializers.BooleanField(required=False)
    require2FA = serializers.BooleanField(required=False)
    requireEmailVerification = serializers.BooleanField(required=False)
    trustedRelays = ListField(child=TrustedRelaySerializer(), required=False)
    allowJoinRequests = serializers.BooleanField(required=False)
    relayPiiConfig = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    apdexThreshold = serializers.IntegerField(min_value=1, required=False)

    @memoize
    def _has_legacy_rate_limits(self):
        org = self.context["organization"]
        return OrganizationOption.objects.filter(
            organization=org, key__in=LEGACY_RATE_LIMIT_OPTIONS
        ).exists()

    def _has_sso_enabled(self):
        org = self.context["organization"]
        return AuthProvider.objects.filter(organization=org).exists()

    def validate_slug(self, value):
        # Historically, the only check just made sure there was more than 1
        # character for the slug, but since then, there are many slugs that
        # fit within this new imposed limit. We're not fixing existing, but
        # just preventing new bad values.
        if len(value) < 3:
            raise serializers.ValidationError(
                f'This slug "{value}" is too short. Minimum of 3 characters.'
            )
        if value in RESERVED_ORGANIZATION_SLUGS:
            raise serializers.ValidationError(f'This slug "{value}" is reserved and not allowed.')
        qs = Organization.objects.filter(slug=value).exclude(id=self.context["organization"].id)
        if qs.exists():
            raise serializers.ValidationError(f'The slug "{value}" is already in use.')
        return value

    def validate_relayPiiConfig(self, value):
        organization = self.context["organization"]
        return validate_pii_config_update(organization, value)

    def validate_sensitiveFields(self, value):
        if value and not all(value):
            raise serializers.ValidationError("Empty values are not allowed.")
        return value

    def validate_safeFields(self, value):
        if value and not all(value):
            raise serializers.ValidationError("Empty values are not allowed.")
        return value

    def validate_attachmentsRole(self, value):
        try:
            roles.get(value)
        except KeyError:
            raise serializers.ValidationError("Invalid role")
        return value

    def validate_debugFilesRole(self, value):
        try:
            roles.get(value)
        except KeyError:
            raise serializers.ValidationError("Invalid role")
        return value

    def validate_require2FA(self, value):
        user = self.context["user"]
        has_2fa = Authenticator.objects.user_has_2fa(user)
        if value and not has_2fa:
            raise serializers.ValidationError(ERR_NO_2FA)

        if value and self._has_sso_enabled():
            raise serializers.ValidationError(ERR_SSO_ENABLED)
        return value

    def validate_requireEmailVerification(self, value):
        user = self.context["user"]
        has_verified = UserEmail.objects.get_primary_email(user).is_verified
        if value and not has_verified:
            raise serializers.ValidationError(ERR_EMAIL_VERIFICATION)
        return value

    def validate_trustedRelays(self, value):
        from sentry import features

        organization = self.context["organization"]
        request = self.context["request"]
        has_relays = features.has("organizations:relay", organization, actor=request.user)
        if not has_relays:
            raise serializers.ValidationError(
                "Organization does not have the relay feature enabled"
            )

        # make sure we don't have multiple instances of one public key
        public_keys = set()
        if value is not None:
            for key_info in value:
                key = key_info.get("public_key")
                if key in public_keys:
                    raise serializers.ValidationError(f"Duplicated key in Trusted Relays: '{key}'")
                public_keys.add(key)

        return value

    def validate_accountRateLimit(self, value):
        if not self._has_legacy_rate_limits:
            raise serializers.ValidationError(
                "The accountRateLimit option cannot be configured for this organization"
            )
        return value

    def validate_projectRateLimit(self, value):
        if not self._has_legacy_rate_limits:
            raise serializers.ValidationError(
                "The accountRateLimit option cannot be configured for this organization"
            )
        return value

    def validate(self, attrs):
        attrs = super().validate(attrs)
        if attrs.get("avatarType") == "upload":
            has_existing_file = OrganizationAvatar.objects.filter(
                organization=self.context["organization"], file_id__isnull=False
            ).exists()
            if not has_existing_file and not attrs.get("avatar"):
                raise serializers.ValidationError(
                    {"avatarType": "Cannot set avatarType to upload without avatar"}
                )
        return attrs

    def save_trusted_relays(self, incoming, changed_data, organization):
        timestamp_now = datetime.utcnow().replace(tzinfo=UTC).isoformat()
        option_key = "sentry:trusted-relays"
        try:
            # get what we already have
            existing = OrganizationOption.objects.get(organization=organization, key=option_key)

            key_dict = {val.get("public_key"): val for val in existing.value}
            original_number_of_keys = len(existing.value)
        except OrganizationOption.DoesNotExist:
            key_dict = {}  # we don't have anything set
            original_number_of_keys = 0
            existing = None

        modified = False
        for option in incoming:
            public_key = option.get("public_key")
            existing_info = key_dict.get(public_key, {})

            option["created"] = existing_info.get("created", timestamp_now)
            option["last_modified"] = existing_info.get("last_modified")

            # check if we modified the current public_key info and update last_modified if we did
            if (
                not existing_info
                or existing_info.get("name") != option.get("name")
                or existing_info.get("description") != option.get("description")
            ):
                option["last_modified"] = timestamp_now
                modified = True

        # check to see if the only modifications were some deletions (which are not captured in the loop above)
        if len(incoming) != original_number_of_keys:
            modified = True

        if modified:
            # we have some modifications create a log message
            if existing is not None:
                # generate an update log message
                changed_data["trustedRelays"] = f"from {existing} to {incoming}"
                existing.value = incoming
                existing.save()
            else:
                # first time we set trusted relays, generate a create log message
                changed_data["trustedRelays"] = f"to {incoming}"
                OrganizationOption.objects.set_value(
                    organization=organization, key=option_key, value=incoming
                )

        return incoming

    def save(self):
        from sentry import features

        org = self.context["organization"]
        changed_data = {}
        if not hasattr(org, "__data"):
            update_tracked_data(org)

        for key, option, type_, default_value in ORG_OPTIONS:
            if key not in self.initial_data:
                continue
            try:
                option_inst = OrganizationOption.objects.get(organization=org, key=option)
                update_tracked_data(option_inst)
            except OrganizationOption.DoesNotExist:
                OrganizationOption.objects.set_value(
                    organization=org, key=option, value=type_(self.initial_data[key])
                )

                if self.initial_data[key] != default_value:
                    changed_data[key] = f"to {self.initial_data[key]}"
            else:
                option_inst.value = self.initial_data[key]
                # check if ORG_OPTIONS changed
                if has_changed(option_inst, "value"):
                    old_val = old_value(option_inst, "value")
                    changed_data[key] = f"from {old_val} to {option_inst.value}"
                option_inst.save()

        trusted_realy_info = self.validated_data.get("trustedRelays")
        if trusted_realy_info is not None:
            self.save_trusted_relays(trusted_realy_info, changed_data, org)

        if "openMembership" in self.initial_data:
            org.flags.allow_joinleave = self.initial_data["openMembership"]
        if "allowSharedIssues" in self.initial_data:
            org.flags.disable_shared_issues = not self.initial_data["allowSharedIssues"]
        if "enhancedPrivacy" in self.initial_data:
            org.flags.enhanced_privacy = self.initial_data["enhancedPrivacy"]
        if "isEarlyAdopter" in self.initial_data:
            org.flags.early_adopter = self.initial_data["isEarlyAdopter"]
        if "require2FA" in self.initial_data:
            org.flags.require_2fa = self.initial_data["require2FA"]
        if (
            features.has("organizations:required-email-verification", org)
            and "requireEmailVerification" in self.initial_data
        ):
            org.flags.require_email_verification = self.initial_data["requireEmailVerification"]
        if "name" in self.initial_data:
            org.name = self.initial_data["name"]
        if "slug" in self.initial_data:
            org.slug = self.initial_data["slug"]

        org_tracked_field = {
            "name": org.name,
            "slug": org.slug,
            "default_role": org.default_role,
            "flag_field": {
                "allow_joinleave": org.flags.allow_joinleave.is_set,
                "enhanced_privacy": org.flags.enhanced_privacy.is_set,
                "disable_shared_issues": org.flags.disable_shared_issues.is_set,
                "early_adopter": org.flags.early_adopter.is_set,
                "require_2fa": org.flags.require_2fa.is_set,
            },
        }

        # check if fields changed
        for f, v in org_tracked_field.items():
            if f != "flag_field":
                if has_changed(org, f):
                    old_val = old_value(org, f)
                    changed_data[f] = f"from {old_val} to {v}"
            else:
                # check if flag fields changed
                for f, v in org_tracked_field["flag_field"].items():
                    if flag_has_changed(org, f):
                        changed_data[f] = f"to {v}"

        org.save()

        if "avatar" in self.initial_data or "avatarType" in self.initial_data:
            OrganizationAvatar.save_avatar(
                relation={"organization": org},
                type=self.initial_data.get("avatarType", "upload"),
                avatar=self.initial_data.get("avatar"),
                filename=f"{org.slug}.png",
            )
        if self.initial_data.get("require2FA") is True:
            org.handle_2fa_required(self.context["request"])
        if (
            features.has("organizations:required-email-verification", org)
            and self.initial_data.get("requireEmailVerification") is True
        ):
            org.handle_email_verification_required(self.context["request"])
        return org, changed_data
Beispiel #18
0
class DeleteConfigSerializer(serializers.Serializer):
    cron_id = serializers.PrimaryKeyRelatedField(
        help_text='Cron ID.',
        label='Cron ID',
        queryset=models.CronTab.objects.all(),
        required=True
    )

    domain = serializers.CharField(
        help_text='Domain name.',
        label='Domain',
        max_length=254,
        min_length=3,
        required=True
    )

    user = serializers.RegexField(
        help_text='System user name.',
        label='User',
        max_length=32,
        min_length=2,
        regex='^[a-z][a-z0-9]+$',
        required=True
    )

    def validate_domain(self, value):
        if not validators.domain(value):
            raise serializers.ValidationError(
                f"Domain '{value}' is invalid.",
                code='invalid'
            )

        return value

    def validate_user(self, value):
        try:
            pwd.getpwnam(value).pw_uid
        except KeyError:
            raise serializers.ValidationError(
                f"System User '{value}' does not exist.",
                code='not_found'
            )

        return value

    def validate(self, attrs):
        domain = attrs.get('domain')

        user = attrs.get('user')

        cron_id = attrs.get('cron_id')

        if not os.path.exists(f"{CronPath.domain_dir(user)}{domain}"):
            raise serializers.ValidationError(
                f"Cron Domain '{domain}' was not found.",
                code='not_found'
            )

        elif not os.path.exists(f"{CronPath.domain_dir(user)}{domain}/{user}_{cron_id.pk}"):
            raise serializers.ValidationError(
                f"Cron ID '{cron_id.pk}' was not found.",
                code='not_found'
            )

        elif not os.path.exists(f"{WebPath.www_dir(user)}{domain}"):
            raise serializers.ValidationError(
                f"Web Domain '{domain}' does not exist.",
                code='not_found'
            )

        return attrs

    def create(self, validated_data):
        validated_domain = validated_data['domain']

        validated_user = validated_data['user']

        validated_cron_id = validated_data['cron_id']

        path_cron = f"{CronPath.domain_dir(validated_user)}{validated_domain}/{validated_user}_{validated_cron_id.pk}"

        if os.path.exists(path_cron):
            os.remove(path_cron)

        return validated_data
Beispiel #19
0
class QQUserSerializer(serializers.Serializer):
    """ QQ登录创建用户序列化器"""
    openid = serializers.CharField(label='openid', write_only=True)
    mobile = serializers.RegexField(label='手机号',
                                    regex=r'^1[3-9]\d{9}$',
                                    write_only=True)
    password = serializers.CharField(label='密码',
                                     max_length=20,
                                     min_length=8,
                                     write_only=True)
    sms_code = serializers.CharField(label='短信验证码', write_only=True)

    def validate(self, attrs):
        """校验

        :param attrs: 反序列化数据
        :return:
        """
        # 手机
        mobile_ = attrs.get('mobile')
        # 短信验证码
        sms_code_ = attrs.get('sms_code')
        # 密码
        password_ = attrs.get('password')
        # 获取openid, 校验openid是否有效
        openid_ = attrs.get('openid')

        # 解密
        openid_ = check_encrypted_openid(openid_)
        # 如果没有解密openid_
        if not openid_:
            raise serializers.ValidationError({'message': '无效的openid'})

        # 获取Redis数据库连接
        redis_conn = get_redis_connection('sms_codes')
        # 获取短信验证码数据
        real_sms_code = redis_conn.get('sms_%s' % mobile_)
        # 如果没有短信验证码数据
        if not real_sms_code:
            # 抛出异常
            raise serializers.ValidationError({'message': '短信验证码无效'})
        # 如果短信验证码和短信验证码数据不一致
        if real_sms_code.decode() != sms_code_:
            # 抛出异常
            raise serializers.ValidationError({'message': '短信验证码错误'})

        try:
            # 根据手机号查询美多用户
            user = User.objects.get(mobile=mobile_)
        except User.DoesNotExist:
            # 如果用户不存在, 则自动新增一个美多用户, 再进行绑定
            user = User.objects.create_user(username=mobile_,
                                            password=password_,
                                            mobile=mobile_)
        else:
            # 如果要绑定的用户存在, 则校验密码是否正确
            if not user.check_password(password_):
                raise serializers.ValidationError({'message': '密码错误'})

        # 将认证后的user放进校验字典中,绑定关联时用到
        attrs['user'] = user
        return attrs

    def create(self, validated_data):
        """创建记录

        :param validated_data: 校验后数据
        :return:
        """
        # 获取校验的用户
        user = validated_data.get('user')
        openid = validated_data.get('openid')

        # 绑定openid和美多用户: 新增一条表数据
        OAuthQQUser.objects.create(openid=openid, user=user)
        return user  # 返回美多用户对象
Beispiel #20
0
class DeleteDomainSerializer(serializers.Serializer):
    domain = serializers.CharField(
        help_text='Domain name.',
        label='Domain',
        max_length=254,
        min_length=3,
        required=True
    )

    user = serializers.RegexField(
        help_text='System user name.',
        label='User',
        max_length=32,
        min_length=2,
        regex='^[a-z][a-z0-9]+$',
        required=True
    )

    def validate_domain(self, value):
        if not validators.domain(value):
            raise serializers.ValidationError(
                f"Domain '{value}' is invalid.",
                code='invalid'
            )

        return value

    def validate_user(self, value):
        try:
            pwd.getpwnam(value).pw_uid
        except KeyError:
            raise serializers.ValidationError(
                f"System User '{value}' does not exist.",
                code='not_found'
            )

        return value

    def validate(self, attrs):
        domain = attrs.get('domain')

        user = attrs.get('user')

        if not os.path.exists(f"{CronPath.domain_dir(user)}{domain}"):
            raise serializers.ValidationError(
                f"Cron Domain '{domain}' does not exist.",
                code='not_found'
            )

        return attrs

    def create(self, validated_data):
        validated_domain = validated_data['domain']

        validated_user = validated_data['user']

        path_domain = f"{CronPath.domain_dir(validated_user)}{validated_domain}"

        if os.path.exists(path_domain):
            shutil.rmtree(path_domain)

        return validated_data
class OrganizationSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=64)
    slug = serializers.RegexField(r'^[a-z0-9_\-]+$', max_length=50)
    accountRateLimit = serializers.IntegerField(min_value=0,
                                                max_value=1000000,
                                                required=False)
    projectRateLimit = serializers.IntegerField(min_value=50,
                                                max_value=100,
                                                required=False)
    avatar = AvatarField(required=False)
    avatarType = serializers.ChoiceField(choices=(
        ('upload', 'upload'),
        ('letter_avatar', 'letter_avatar'),
    ),
                                         required=False)

    openMembership = serializers.BooleanField(required=False)
    allowSharedIssues = serializers.BooleanField(required=False)
    enhancedPrivacy = serializers.BooleanField(required=False)
    dataScrubber = serializers.BooleanField(required=False)
    dataScrubberDefaults = serializers.BooleanField(required=False)
    sensitiveFields = ListField(child=serializers.CharField(), required=False)
    safeFields = ListField(child=serializers.CharField(), required=False)
    scrubIPAddresses = serializers.BooleanField(required=False)
    isEarlyAdopter = serializers.BooleanField(required=False)
    require2FA = serializers.BooleanField(required=False)

    def validate_slug(self, attrs, source):
        value = attrs[source]
        # Historically, the only check just made sure there was more than 1
        # character for the slug, but since then, there are many slugs that
        # fit within this new imposed limit. We're not fixing existing, but
        # just preventing new bad values.
        if len(value) < 3:
            raise serializers.ValidationError(
                'This slug "%s" is too short. Minimum of 3 characters.' %
                (value, ))
        if value in RESERVED_ORGANIZATION_SLUGS:
            raise serializers.ValidationError(
                'This slug "%s" is reserved and not allowed.' % (value, ))
        qs = Organization.objects.filter(
            slug=value, ).exclude(id=self.context['organization'].id)
        if qs.exists():
            raise serializers.ValidationError(
                'The slug "%s" is already in use.' % (value, ))
        return attrs

    def validate_sensitiveFields(self, attrs, source):
        value = attrs[source]
        if value and not all(value):
            raise serializers.ValidationError('Empty values are not allowed.')
        return attrs

    def validate_safeFields(self, attrs, source):
        value = attrs[source]
        if value and not all(value):
            raise serializers.ValidationError('Empty values are not allowed.')
        return attrs

    def validate_require2FA(self, attrs, source):
        value = attrs[source]
        user = self.context['user']
        has_2fa = Authenticator.objects.user_has_2fa(user)
        if value and not has_2fa:
            raise serializers.ValidationError(
                'User setting two-factor authentication enforcement without two-factor authentication enabled.'
            )
        return attrs

    def validate(self, attrs):
        attrs = super(OrganizationSerializer, self).validate(attrs)
        if attrs.get('avatarType') == 'upload':
            has_existing_file = OrganizationAvatar.objects.filter(
                organization=self.context['organization'],
                file__isnull=False,
            ).exists()
            if not has_existing_file and not attrs.get('avatar'):
                raise serializers.ValidationError({
                    'avatarType':
                    'Cannot set avatarType to upload without avatar',
                })
        return attrs

    def save(self):
        org = self.context['organization']
        changed_data = {}

        for key, option, type_ in ORG_OPTIONS:
            if key not in self.init_data:
                continue
            try:
                option_inst = OrganizationOption.objects.get(organization=org,
                                                             key=option)
            except OrganizationOption.DoesNotExist:
                OrganizationOption.objects.set_value(
                    organization=org,
                    key=option,
                    value=type_(self.init_data[key]),
                )
                # TODO(kelly): This will not work if new ORG_OPTIONS are added and their
                # default value evaluates as truthy, but this should work for now with the
                # current ORG_OPTIONS (assumes ORG_OPTIONS are falsy)
                if type_(self.init_data[key]):
                    changed_data[key] = self.init_data[key]
            else:
                option_inst.value = self.init_data[key]
                # check if ORG_OPTIONS changed
                if option_inst.has_changed('value'):
                    old_val = option_inst.old_value('value')
                    changed_data[key] = u'from {} to {}'.format(
                        old_val, option_inst.value)
                option_inst.save()

        if 'openMembership' in self.init_data:
            org.flags.allow_joinleave = self.init_data['openMembership']
        if 'allowSharedIssues' in self.init_data:
            org.flags.disable_shared_issues = not self.init_data[
                'allowSharedIssues']
        if 'enhancedPrivacy' in self.init_data:
            org.flags.enhanced_privacy = self.init_data['enhancedPrivacy']
        if 'isEarlyAdopter' in self.init_data:
            org.flags.early_adopter = self.init_data['isEarlyAdopter']
        if 'require2FA' in self.init_data:
            org.flags.require_2fa = self.init_data['require2FA']
        if 'name' in self.init_data:
            org.name = self.init_data['name']
        if 'slug' in self.init_data:
            org.slug = self.init_data['slug']

        org_tracked_field = {
            'name': org.name,
            'slug': org.slug,
            'default_role': org.default_role,
            'flag_field': {
                'allow_joinleave': org.flags.allow_joinleave.is_set,
                'enhanced_privacy': org.flags.enhanced_privacy.is_set,
                'disable_shared_issues':
                org.flags.disable_shared_issues.is_set,
                'early_adopter': org.flags.early_adopter.is_set
            }
        }

        # check if fields changed
        for f, v in six.iteritems(org_tracked_field):
            if f is not 'flag_field':
                if org.has_changed(f):
                    old_val = org.old_value(f)
                    changed_data[f] = u'from {} to {}'.format(old_val, v)
            else:
                # check if flag fields changed
                for f, v in six.iteritems(org_tracked_field['flag_field']):
                    if org.flag_has_changed(f):
                        changed_data[f] = u'to {}'.format(v)

        org.save()

        if 'avatar' in self.init_data or 'avatarType' in self.init_data:
            OrganizationAvatar.save_avatar(
                relation={'organization': org},
                type=self.init_data.get('avatarType', 'upload'),
                avatar=self.init_data.get('avatar'),
                filename='{}.png'.format(org.slug),
            )
        if 'require2FA' in self.init_data and self.init_data[
                'require2FA'] is True:
            org.send_setup_2fa_emails()
        return org, changed_data
Beispiel #22
0
class AtomicPublicationSerializer(serializers.Serializer):  # pylint: disable=abstract-method
    """Serializer for saving and publishing a Course and associated products.

    Using a ModelSerializer for the Course data makes it difficult to use this serializer to handle updates.
    The automatically applied validation logic rejects course IDs which already exist in the database.
    """
    id = serializers.RegexField(COURSE_ID_REGEX, max_length=255)
    uuid = serializers.UUIDField(required=False)
    name = serializers.CharField(max_length=255)

    # Verification deadline should only be required if the course actually requires verification.
    verification_deadline = serializers.DateTimeField(required=False, allow_null=True)
    products = serializers.ListField()

    def __init__(self, *args, **kwargs):
        super(AtomicPublicationSerializer, self).__init__(*args, **kwargs)
        self.partner = kwargs['context'].pop('partner', None)

    def validate_products(self, products):
        """Validate product data."""
        for product in products:
            product_class = product.get('product_class')

            if product_class == COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME:
                EntitlementProductHelper.validate(product)
            elif product_class == SEAT_PRODUCT_CLASS_NAME:
                SeatProductHelper.validate(product)
            else:
                raise serializers.ValidationError(
                    _(u"Invalid product class [{product_class}] requested.").format(product_class=product_class)
                )

        return products

    def get_partner(self):
        """Validate partner"""
        if not self.partner:
            partner = Partner.objects.get(id=1)
            return partner

        return self.partner

    def save(self):
        """Save and publish Course and associated products."

        Returns:
            tuple: A Boolean indicating whether the Course was created, an Exception,
                if one was raised (else None), and a message for the user, if necessary (else None).
        """
        course_id = self.validated_data['id']
        course_uuid = self.validated_data.get('uuid')
        course_name = self.validated_data['name']
        course_verification_deadline = self.validated_data.get('verification_deadline')
        # ENT-803: by default enable enrollment code creation
        create_or_activate_enrollment_code = True
        products = self.validated_data['products']
        partner = self.get_partner()

        try:
            if not waffle.switch_is_active('publish_course_modes_to_lms'):
                message = _(
                    u'Course [{course_id}] was not published to LMS '
                    u'because the switch [publish_course_modes_to_lms] is disabled. '
                    u'To avoid ghost SKUs, data has not been saved.'
                ).format(course_id=course_id)

                raise Exception(message)

            # Explicitly delimit operations which will be rolled back if an exception is raised.
            with transaction.atomic():
                site = self.context['request'].site
                course, created = Course.objects.get_or_create(
                    id=course_id, partner=site.siteconfiguration.partner
                )
                course.name = course_name
                course.verification_deadline = course_verification_deadline
                course.save()

                for product in products:
                    product_class = product.get('product_class')

                    if product_class == COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME:
                        EntitlementProductHelper.save(partner, course, course_uuid, product)
                    elif product_class == SEAT_PRODUCT_CLASS_NAME:
                        SeatProductHelper.save(course, product, create_or_activate_enrollment_code)

                if course.get_enrollment_code():
                    course.toggle_enrollment_code_status(is_active=create_or_activate_enrollment_code)

                resp_message = course.publish_to_lms()
                published = (resp_message is None)

                if published:
                    return created, None, None
                else:
                    raise Exception(resp_message)

        except Exception as e:  # pylint: disable=broad-except
            logger.exception(u'Failed to save and publish [%s]: [%s]', course_id, e.message)
            return False, e, e.message
Beispiel #23
0
class QQUserSerializer(Serializer):
    """绑定openid与美多商城用户的序列化器
    只用到校验功能,没用到序列化的功能

    校验参数:
    mobile,password,sms_code,openid
    """
    openid = serializers.CharField(label='openid', write_only=True)
    mobile = serializers.RegexField(label='手机号',
                                    regex=r'^1[3-9]\d{9}$',
                                    write_only=True)
    password = serializers.CharField(label='密码',
                                     max_length=20,
                                     min_length=8,
                                     write_only=True)
    sms_code = serializers.CharField(label='短信验证码', write_only=True)

    # 校验参数
    def validate(self, attrs):
        # 获取请求参数
        openid = attrs.get('openid')
        mobile = attrs.get('mobile')
        password = attrs.get('password')
        sms_code = attrs.get('sms_code')

        # 校验 openid
        # 获取openid, 校验openid是否有效
        openid = check_encrypted_openid(openid)
        if not openid:
            raise serializers.ValidationError({'message': '无效的openid'})

        # 修改字典中openid的值, 以便保存正确的openid到映射表
        attrs['openid'] = openid

        # 校验短信验证码
        from django_redis import get_redis_connection
        redis_conn = get_redis_connection('sms_codes')
        real_sms_code = redis_conn.get('sms_%s' % mobile)  # 根据手机号拿到内存中的验证码
        if not real_sms_code:
            raise serializers.ValidationError({"message": "短信验证码无效"})
        if real_sms_code.decode() != sms_code:
            raise serializers.ValidationError({'message': '短信验证码错误'})

        # 到数据库查询有没有这个手机号
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 没有该手机号,则自动新增为美多用户在进行绑定
            user = User.objects.create_user(username=mobile,
                                            password=password,
                                            mobile=mobile)
        else:
            # 如果数据库里有这个手机号,则校验密码是否正确
            if not user.check_password(password):
                raise serializers.ValidationError({"message": "密码错误"})

        # 将认证后的user放进校验字典中,绑定关联时用到
        attrs['user'] = user

        # 返回校验后的参数
        return attrs

    def create(self, validated_data):  # validated_data 返回的校验后的 attrs
        # 获取校验的用户
        user = validated_data.get('user')  # attrs['user'] = user
        openid = validated_data.get('openid')

        # 绑定openid和美多用户:新增一条数据
        from oauth.models import OAuthQQUser
        OAuthQQUser.objects.create(user=user, openid=openid)
        return user  # 返回的user对象给前面的user = serializer.save() 接收
class OauthQQUserSerializer(serializers.Serializer):

    access_token = serializers.CharField(label='操作凭证')
    mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')
    password = serializers.CharField(label='密码', max_length=20, min_length=8)
    sms_code = serializers.CharField(label='短信验证码')

    def validate(self, attrs):

        #1. access_token
        access_token = attrs['access_token']

        openid = check_access_token(access_token)

        if openid is None:
            raise serializers.ValidationError('openid过期')

        #将openid添加到 attrs中
        attrs['openid'] = openid

        #2.短信验证码
        # 2.短信验证码
        # 2.1 用户提交的短信
        sms_code = attrs.get('sms_code')
        # 2.2 获取redis的短信
        # ① 连接redis
        redis_conn = get_redis_connection('code')
        # ② 获取数据
        mobile = attrs.get('mobile')
        redis_code = redis_conn.get('sms_%s' % mobile)
        # ③ 判断数据是否存在(有有效期)
        if redis_code is None:
            raise serializers.ValidationError('短信验证码已过期')
        # 2.3 比对
        if redis_code.decode() != sms_code:
            raise serializers.ValidationError('短信验证码输入错误')

        #3.判断用户
        # mobile
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            #说明 该手机号没有注册过
            #就应该创建一个用户
            # validate 方法主要是为了 进行 数据的验证,创建用户的代码
            # 我们写在后边
            pass
        else:
            #说明 注册过
            # 注册过就要验证密码是否正确
            password = attrs['password']
            if not user.check_password(password):
                raise serializers.ValidationError('密码不正确')

            attrs['user'] = user

        return attrs

    # data --> attrs --> validated_data
    def create(self, validated_data):

        user = validated_data.get('user')

        if user is None:
            #说明手机号没有注册过
            user = User.objects.create(username=validated_data.get('mobile'),
                                       mobile=validated_data.get('mobile'),
                                       password=validated_data.get('password'))

            user.set_password(validated_data.get('password'))
            user.save()

        qquser = OAuthQQUser.objects.create(
            user=user, openid=validated_data.get('openid'))

        return qquser
Beispiel #25
0
class OAuthQQUserSerializer(serializers.ModelSerializer):
    """
    保存QQ用户序列化器
    """
    sms_code = serializers.CharField(label='短信验证码', write_only=True)
    access_token = serializers.CharField(label='操作凭证', write_only=True)
    token = serializers.CharField(label='JWT token', read_only=True)
    mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')

    class Meta:
        model = User
        fields = ('mobile', 'password', 'sms_code', 'access_token', 'id',
                  'username', 'token')
        extra_kwargs = {
            'username': {
                'read_only': True
            },
            'password': {
                'write_only': True,
                'min_length': 8,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许8-20个字符的密码',
                    'max_length': '仅允许8-20个字符的密码',
                }
            }
        }

    def validate(self, attrs):
        # 检验access_token
        access_token = attrs['access_token']

        openid = OAuthQQ.check_save_user_token(access_token)
        if not openid:
            raise serializers.ValidationError('无效的access_token')

        attrs['openid'] = openid

        # 检验短信验证码
        mobile = attrs['mobile']
        sms_code = attrs['sms_code']
        redis_conn = get_redis_connection('verify_codes')
        real_sms_code = redis_conn.get('sms_%s' % mobile)
        if real_sms_code.decode() != sms_code:
            raise serializers.ValidationError('短信验证码错误')

        # 如果用户存在,检查用户密码
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            pass
        else:
            password = attrs['password']
            if not user.check_password(password):
                raise serializers.ValidationError('密码错误')
            attrs['user'] = user
        return attrs

    def create(self, validated_data):
        openid = validated_data['openid']
        user = validated_data.get('user')
        mobile = validated_data['mobile']
        password = validated_data['password']

        if not user:
            # 如果用户不存在,创建用户,绑定openid(创建了OAuthQQUser数据)
            username = base64.b64encode(os.urandom(9))
            user = User.objects.create_user(username=username,
                                            mobile=mobile,
                                            password=password)

        OAuthQQUser.objects.create(user=user, openid=openid)

        # 签发jwt token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        user.token = token

        return user
Beispiel #26
0
class RegistrationSerializer(serializers.ModelSerializer):
    """serializer for creating new users"""
    def __init__(self, *args, **kwargs) -> None:
        super(RegistrationSerializer, self).__init__(*args, **kwargs)

        for field in self.fields:
            error_messages = self.fields[field].error_messages
            error_messages["null"] = error_messages["blank"] = error_messages[
                "required"] = "Please fill in the {}.".format(field)

    email = serializers.RegexField(
        regex=r"^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$",
        validators=[
            validators.UniqueValidator(
                queryset=User.objects.all(),
                message="Email address already exists",
            )
        ],
        error_messages={"invalid": "Enter a valid email address"},
    )
    username = serializers.RegexField(
        regex=r"^[A-Za-z\-\_]+\d*$",
        min_length=4,
        max_length=30,
        required=True,
        validators=[
            validators.UniqueValidator(
                queryset=User.objects.all(),
                message="The username already exists. Kindly try another.",
            )
        ],
        error_messages={
            "min_length": "Username must have a minimum of 4 characters.",
            "max_length": "Username must have a maximum of 30 characters.",
            "invalid": "Username cannot only have alphanumeric characters.",
        },
    )
    password = serializers.RegexField(
        regex=r"^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{7,}$",
        max_length=128,
        min_length=7,
        write_only=True,
        error_messages={
            "required": "Password is required",
            "max_length": "Password cannot be more than 128 characters",
            "min_length": "Password must have at least 7 characters",
            "invalid": "Password must have a number and a letter",
        },
    )
    token = serializers.SerializerMethodField()

    class Meta:
        model = User
        # List all of the fields that could possibly be included in a request
        # or response, including fields specified explicitly above.
        fields = ["email", "username", "password", "token"]

    def create(self, validated_data: Dict[str, str]) -> User:
        # Use the `create_user` method we wrote earlier to create a new user.
        user = User.objects.create_user(**validated_data)

        return user
class RelayIdSerializer(serializers.Serializer):
    relay_id = serializers.RegexField(
        r"^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$",
        required=True)
Beispiel #28
0
class OrganizationSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=64)
    slug = serializers.RegexField(r'^[a-z0-9_\-]+$', max_length=50)
    accountRateLimit = serializers.IntegerField(min_value=0,
                                                max_value=1000000,
                                                required=False)
    projectRateLimit = serializers.IntegerField(min_value=50,
                                                max_value=100,
                                                required=False)
    avatar = AvatarField(required=False)
    avatarType = serializers.ChoiceField(choices=(
        ('upload', 'upload'),
        ('letter_avatar', 'letter_avatar'),
    ),
                                         required=False)

    openMembership = serializers.BooleanField(required=False)
    allowSharedIssues = serializers.BooleanField(required=False)
    enhancedPrivacy = serializers.BooleanField(required=False)
    dataScrubber = serializers.BooleanField(required=False)
    dataScrubberDefaults = serializers.BooleanField(required=False)
    sensitiveFields = ListField(child=serializers.CharField(), required=False)
    safeFields = ListField(child=serializers.CharField(), required=False)
    scrubIPAddresses = serializers.BooleanField(required=False)
    isEarlyAdopter = serializers.BooleanField(required=False)

    def validate_slug(self, attrs, source):
        value = attrs[source]
        qs = Organization.objects.filter(
            slug=value, ).exclude(id=self.context['organization'].id)
        if qs.exists():
            raise serializers.ValidationError(
                'The slug "%s" is already in use.' % (value, ))
        return attrs

    def validate_sensitiveFields(self, attrs, source):
        value = attrs[source]
        if value and not all(value):
            raise serializers.ValidationError('Empty values are not allowed.')
        return attrs

    def validate_safeFields(self, attrs, source):
        value = attrs[source]
        if value and not all(value):
            raise serializers.ValidationError('Empty values are not allowed.')
        return attrs

    def validate(self, attrs):
        attrs = super(OrganizationSerializer, self).validate(attrs)
        if attrs.get('avatarType') == 'upload':
            has_existing_file = OrganizationAvatar.objects.filter(
                organization=self.context['organization'],
                file__isnull=False,
            ).exists()
            if not has_existing_file and not attrs.get('avatar'):
                raise serializers.ValidationError({
                    'avatarType':
                    'Cannot set avatarType to upload without avatar',
                })
        return attrs

    def save(self):
        org = self.context['organization']
        if 'openMembership' in self.init_data:
            org.flags.allow_joinleave = self.init_data['openMembership']
        if 'allowSharedIssues' in self.init_data:
            org.flags.disable_shared_issues = not self.init_data[
                'allowSharedIssues']
        if 'enhancedPrivacy' in self.init_data:
            org.flags.enhanced_privacy = self.init_data['enhancedPrivacy']
        if 'isEarlyAdopter' in self.init_data:
            org.flags.early_adopter = self.init_data['isEarlyAdopter']
        if 'name' in self.init_data:
            org.name = self.init_data['name']
        if 'slug' in self.init_data:
            org.slug = self.init_data['slug']
        org.save()
        for key, option, type_ in ORG_OPTIONS:
            if key in self.init_data:
                OrganizationOption.objects.set_value(
                    organization=org,
                    key=option,
                    value=type_(self.init_data[key]),
                )
        if 'avatar' in self.init_data or 'avatarType' in self.init_data:
            OrganizationAvatar.save_avatar(
                relation={'organization': org},
                type=self.init_data.get('avatarType', 'upload'),
                avatar=self.init_data.get('avatar'),
                filename='{}.png'.format(org.slug),
            )
        return org
Beispiel #29
0
class RuleSerializer(serializers.Serializer):
    policy = serializers.ChoiceField(choices=Rule.POLICY_CHOICES)
    rule_type = serializers.ChoiceField(choices=Rule.RULE_TYPE_CHOICES)
    sha256 = serializers.RegexField('^[a-f0-9]{64}\Z')
    custom_msg = serializers.CharField(required=False)
Beispiel #30
0
class CertificateSerializer(serializers.Serializer):
    """
    This is the Gift Certificates REST API layer
    """

    language = serializers.ChoiceField(choices=settings.LANGUAGES, required=True)
    account_number = serializers.RegexField(regex='^[a-zA-Z0-9]{1,10}$', allow_blank=False, required=False)
    recipient_name = serializers.CharField(max_length=60, required=True)
    recipient_email = serializers.EmailField(required=True)
    department_id = serializers.UUIDField(format='hex_verbose', required=True)
    email_signature = serializers.IntegerField(required=True)
    cert_type = serializers.IntegerField(required=True)
    primary_course = serializers.IntegerField(required=True)

    secondary_course = serializers.IntegerField(required=False)
    expiry_date = serializers.DateField(format='%Y-%m-%d', input_formats=['%Y-%m-%d'], required=False)
    quantity = serializers.DecimalField(max_digits=6, decimal_places=2, required=False)
    power_cart = serializers.ChoiceField(choices=Certificate.POWER_CART_CHOICES, required=False)
    note = serializers.CharField(max_length=255, required=False)
    message = serializers.CharField(max_length=250, required=False)

    def validate(self, data):
        self.certificate_batch_data = {}
        self.certificate_data = {}

        if data.get('language') is not None:
            self.certificate_batch_data['language'] = data.get('language')

        if data.get('recipient_name') is not None:
            self.certificate_batch_data['recipient_name'] = data.get('recipient_name')

        if data.get('recipient_email') is not None:
            self.certificate_batch_data['recipient_email'] = data.get('recipient_email')

        if data.get('note') is not None:
            self.certificate_data['note'] = data.get('note')

        if data.get('message') is not None:
            self.certificate_data['message'] = data.get('message')

        # Account Number
        if data.get('account_number') is not None:
            try:
                User.objects.get(membership_number=data.get('account_number'))
                self.certificate_batch_data['account_number'] = data.get('account_number')
            except User.DoesNotExist:
                if data.get('account_number') != settings.DEFAULT_CERTIFICATE_MEMBERSHIP_NUMBER:
                    raise serializers.ValidationError({"account_number": _('Account number does not exist')})
            else:
                self.certificate_batch_data['account_number'] = settings.DEFAULT_CERTIFICATE_MEMBERSHIP_NUMBER
        else:
            self.certificate_batch_data['account_number'] = settings.DEFAULT_CERTIFICATE_MEMBERSHIP_NUMBER

        # Department
        try:
            self.certificate_batch_data['department'] = Department.objects.get(pk=data.get('department_id'))
        except Department.DoesNotExist:
            raise serializers.ValidationError({"department_id":_('Invalid department.')})

        # TODO: This will come with the authentication layer
        # if not Department.objects.filter(admins__in=self.context['employee']):
        #     raise serializers.ValidationError({"department_id":_('Employee does not have access to this department')})

        # Email Signature ( 1 is the default email_signature that gives access to all GC)
        if data.get('email_signature') is not None and data.get('email_signature') != 1:
            try:
                self.certificate_batch_data['email_signature'] = EmailSignature.objects.\
                    get(id=data.get('email_signature'), department=self.certificate_batch_data['department'])
            except EmailSignature.DoesNotExist:
                raise serializers.ValidationError({"email_signature":_('Email signature invalid access')})

        # Certificate Type
        try:
            self.certificate_data['type'] = CertificateType.objects.get(pk=data.get('cert_type'))
        except CertificateType.DoesNotExist:
            raise serializers.ValidationError({"cert_type":_('Certificate type does not exist')})

        # Primary Course
        try:
            self.certificate_data['club'] = Club.objects.get(pk=data.get('primary_course'))
        except Club.DoesNotExist:
            raise serializers.ValidationError({"primary_course":_('Invalid primary course')})

        # Secondary Course
        if data.get('secondary_course') is not None:
            try:
                self.certificate_data['club_secondary'] = Club.objects.get(pk=data.get('secondary_course'))
            except Club.DoesNotExist:
                raise serializers.ValidationError({"secondary_course":_('Invalid secondary course')})

        # Quantity
        if data.get('quantity') is None:
            if self.certificate_data['type'].quantity:
                if self.certificate_data['type'].category in DOLLAR_VALUE_CATEGORIES:
                    self.certificate_data['quantity'] = self.certificate_data['type'].quantity
                else:
                    self.certificate_data['quantity'] = int(self.certificate_data['type'].quantity)
            else:
                raise serializers.ValidationError({"quantity":_('quantity can not be empty.')})
        else:
            if self.certificate_data['type'].category in DOLLAR_VALUE_CATEGORIES:
                self.certificate_data['quantity'] = data.get('quantity')
            else:
                self.certificate_data['quantity'] = int(data.get('quantity'))

        # Expiry Date
        if data.get('expiry_date') is None:
            if self.certificate_data['type'].expiry_date:
                self.certificate_data['expiry_date'] = self.certificate_data['type'].expiry_date
            else:
                raise serializers.ValidationError({"expiry_date":_('expiry_date can not be empty.')})
        else:
            if data.get('expiry_date') < datetime.date.today():
                raise serializers.ValidationError({"expiry_date": _('expiry_date must be after today.')})
            self.certificate_data['expiry_date'] = data.get('expiry_date')

        # Power Cart
        if data.get('power_cart') is None:
            if self.certificate_data['type'].power_cart:
                self.certificate_data['power_cart'] = self.certificate_data['type'].power_cart
            else:
                raise serializers.ValidationError({"power_cart":_('power_cart can not be empty.')})
        else:
            self.certificate_data['power_cart'] = data.get('power_cart')

        return data