class ResponseTemplateSerializer(DynamicFieldsMixin, RevalidateMixin, HyperlinkedMixin, ModelSerializer):
    hyperlinks = (
        ('self', 'response-templates-detail', (
            'instance.name',
            'name',
        )),
        ('rename', 'response-templates-rename', (
            'instance.name',
            'name',
        )),
    )

    name = LowercaseCharField(validators=[
        UniqueValidator(queryset=ResponseTemplate.objects.all()),
        DjangoValidator()
    ])
    context = JSONField(default={}, validators=[validate_template_context])
    content = serializers.CharField(validators=[Jinja2TemplateValidator()])
    content_type = serializers.CharField(validators=[RegexValidator(
        regex=re.compile(r'^([a-z]+)\/([a-z0-9+-\.]+)*$', re.IGNORECASE),
        message='Not a valid content_type.')],
    )

    class Meta:
        fields = ('name', 'content', 'content_type', 'context', 'description')
        model = ResponseTemplate
Esempio n. 2
0
class Migration(migrations.Migration):

    dependencies = [
        ('hosting', '0002_hosting_domains'),
    ]

    operations = [
        migrations.RenameField(model_name='hosting',
                               old_name='label',
                               new_name='name'),
        migrations.RunPython(fill_hosting_names),
        migrations.AlterField(
            model_name='hosting',
            name='name',
            field=LowercaseCharField(max_length=253),
        ),
        migrations.AlterField(
            model_name='hosting',
            name='_is_live',
            field=LiveField(default=True),
        ),
        migrations.AlterUniqueTogether(
            name='hosting',
            unique_together=set([('name', '_is_live')]),
        ),
    ]
Esempio n. 3
0
class Coupon(models.Model):
    """Coupon describes possible discount.

    It's defined by unique name and should have either information
    about percent_off or amount_off.

    Currently only supported currency is USD.

    Coupon can be used for more than one month - by setting
    duration accordingly.

    Coupon can also expire and should generate discounts after expiration
    date which is specified by `redeem_by` field.
    """
    CURRENCY_CHOICES = (('usd', 'USD'), )

    name = models.CharField(max_length=32, unique=True, primary_key=True)
    percent_off = models.SmallIntegerField(null=True)
    amount_off = models.FloatField(null=True)

    currency = LowercaseCharField(max_length=3,
                                  choices=CURRENCY_CHOICES,
                                  default='usd')
    duration = models.SmallIntegerField(default=1)  # in months
    redeem_by = models.DateField()

    class Meta:
        ordering = ('name', )

    def redeem(self, instance, customer, save=True):
        """Use coupon generating a discount from it"""
        start = timezone.now().date()
        end = start + relativedelta(months=self.duration)
        discount = Discount(instance=instance,
                            coupon=self,
                            start=start,
                            end=end,
                            customer=customer)
        discount.full_clean()
        if save:
            discount.save()
        return discount

    def __str__(self):
        return 'Coupon[name=%s]' % self.name
Esempio n. 4
0
class User(AclAbstractBaseModel, CacheableAbstractModel, LiveAbstractModel,
           TrackChangesAbstractModel, UniqueKeyAbstractModel):
    # v1 permission fields
    PERMISSION_CONFIG = {
        'api_key': {API_PERMISSIONS.READ, API_PERMISSIONS.UPDATE},
        'admin': {
            'write': FULL_PERMISSIONS,
            'read': {API_PERMISSIONS.READ},
        }
    }

    # v2 permission config
    WRITE_PERMISSION = Permission('write',
                                  actions=('update', 'partial_update',
                                           'destroy', 'reset_key'))
    OBJECT_ACL_PERMISSIONS = (
        DataObject.READ_PERMISSION,
        WRITE_PERMISSION,
    )

    UPDATE_PERMISSION = Permission('update',
                                   actions=('update', 'partial_update',
                                            'reset_key'))
    ENDPOINT_ACL_PERMISSIONS = (
        DataObject.GET_PERMISSION,
        DataObject.LIST_PERMISSION,
        DataObject.CREATE_PERMISSION,
        UPDATE_PERMISSION,
        DataObject.DELETE_PERMISSION,
    )

    KEY_FIELD_KWARGS = {}

    username = LowercaseCharField(max_length=64, db_index=True)
    password = models.CharField(max_length=128)
    created_at = models.DateTimeField(auto_now_add=True, db_index=True)
    groups = models.ManyToManyField('Group', through='Membership')

    class Meta:
        ordering = ('id', )
        unique_together = ('username', '_is_live')

    def __init__(self, *args, **kwargs):
        self.profile_data = kwargs.pop('profile_data', None)
        super().__init__(*args, **kwargs)

    def __str__(self):
        return 'User[id=%s, username=%s]' % (self.id, self.username)

    def generate_key(self):
        return generate_key(parity=True)

    def set_password(self, raw_password):
        self.password = make_password(raw_password)

    def check_password(self, raw_password):
        """
        Returns a boolean of whether the raw_password was correct. Handles
        hashing formats behind the scenes.
        """
        def setter(raw_password):
            self.set_password(raw_password)
            self.save(update_fields=["password"])

        return check_password(raw_password, self.password, setter)

    @staticmethod
    @cached()
    def get_group_ids_for_user(user_id):
        return list(
            Membership.objects.filter(user=user_id).values_list('group_id',
                                                                flat=True))

    def get_group_ids(self):
        return self.get_group_ids_for_user(self.id)
Esempio n. 5
0
 def add_key_field(sender, **kwargs):
     if issubclass(sender,
                   UniqueKeyAbstractModel) and not sender._meta.proxy:
         field = LowercaseCharField(max_length=40,
                                    **sender.KEY_FIELD_KWARGS)
         field.contribute_to_class(sender, sender.KEY_FIELD_NAME)
Esempio n. 6
0
class Hosting(LiveAbstractModel, DescriptionAbstractModel,
              CacheableAbstractModel, CreatedUpdatedAtAbstractModel,
              TrackChangesAbstractModel):
    PERMISSION_CONFIG = {
        'admin': {
            'full': FULL_PERMISSIONS,
            'write': {API_PERMISSIONS.READ},
            'read': {API_PERMISSIONS.READ},
        }
    }
    UPDATE_LOCK_KEY_TEMPLATE = 'lock:hosting:update:{instance.id}'

    class SSL_STATUSES(MetaIntEnum):
        CHECKING = -1, 'checking'
        OFF = 0, 'off'
        ON = 1, 'on'
        INVALID_DOMAIN = 2, 'invalid_domain'
        CNAME_NOT_SET = 3, 'cname_not_set'
        WRONG_CNAME = 4, 'wrong_cname'
        UNKNOWN = 5, 'unknown'

    name = LowercaseCharField(max_length=253)
    domains = ArrayField(base_field=models.CharField(max_length=253), default=[])
    is_active = models.BooleanField(default=True)
    is_default = models.BooleanField(default=False)
    ssl_status = models.SmallIntegerField(choices=SSL_STATUSES.as_choices(),
                                          default=SSL_STATUSES.OFF.value)
    config = NullableJSONField(default={})
    socket = models.ForeignKey('sockets.Socket', blank=True, null=True, default=None, on_delete=models.CASCADE)
    auth = HStoreField(default={})

    _storage = None

    class Meta:
        ordering = ('id',)
        unique_together = ('name', '_is_live')
        verbose_name = 'Hosting'

    def __str__(self):
        return 'Hosting[id=%s, name=%s]' % (self.id, self.name)

    @classmethod
    def get_storage(cls):
        if cls._storage is None:
            cls._storage = DefaultStorage.create_storage(
                bucket_name=get_cur_loc_env('STORAGE_HOSTING_BUCKET'),
                storage_url=get_cur_loc_env('STORAGE_HOSTING_BUCKET_URL'),
            )
        return cls._storage

    @classmethod
    def get_instance_lock_key(cls, instance):
        return cls.UPDATE_LOCK_KEY_TEMPLATE.format(instance=instance)

    @staticmethod
    @cached()
    def is_hosting_empty(hosting_id):
        return not HostingFile.objects.filter(hosting=hosting_id).exists()

    @classmethod
    def cnames_generator(cls, domains):
        return (d for d in domains if VALID_DOMAIN_REGEX.match(d))

    @classmethod
    def find_cname(cls, domains):
        return next(cls.cnames_generator(domains), None)

    def get_cname(self):
        return Hosting.find_cname(self.domains)

    @property
    def is_empty(self):
        return Hosting.is_hosting_empty(self.id)

    @property
    def is_locked(self):
        return self.ssl_status == Hosting.SSL_STATUSES.CHECKING

    @property
    def is_browser_router_enabled(self):
        return self.config.get('browser_router', False)

    @classmethod
    def encrypt_passwd(cls, passwd):
        def salt():
            symbols = ascii_letters + digits
            return choice(symbols) + choice(symbols)
        return 'crypt:{}'.format(crypt(passwd, salt()))

    def check_auth(self, uname, passwd):
        if uname in self.auth:
            _, encrypted_passwd = self.auth[uname].split(':', 1)
            return crypt(passwd, encrypted_passwd) == encrypted_passwd
        return False