models: use kilobytes in size limits, use bigintegerfield for partner.size (fixes #19497)

Make test on partner size limits clearer by nost using JSON, and just sending
plain text documents of the needed sizes.
This commit is contained in:
Benjamin Dauvergne 2017-10-17 16:26:08 +02:00
parent a968380ae5
commit 3ad3bb14d3
5 changed files with 86 additions and 31 deletions

View File

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('petale', '0005_auto_20170721_1416'),
]
operations = [
migrations.AlterField(
model_name='partner',
name='hard_global_max_size',
field=models.IntegerField(help_text='as kilobytes', verbose_name='Hard max size'),
),
migrations.AlterField(
model_name='partner',
name='hard_per_key_max_size',
field=models.IntegerField(help_text='as kilobytes', verbose_name='Hard max size per key'),
),
migrations.AlterField(
model_name='partner',
name='size',
field=models.BigIntegerField(default=0, help_text='as bytes', verbose_name='Size'),
),
migrations.AlterField(
model_name='partner',
name='soft_global_max_size',
field=models.IntegerField(help_text='as kilobytes', verbose_name='Soft max size'),
),
migrations.AlterField(
model_name='partner',
name='soft_per_key_max_size',
field=models.IntegerField(help_text='as kilobytes', verbose_name='Soft max size per key'),
),
]

View File

@ -41,17 +41,17 @@ class Partner(models.Model):
help_text=_('List of admin emails separated by comma'))
hard_global_max_size = models.IntegerField(
verbose_name=_('Hard max size'),
help_text=_('as bytes'))
help_text=_('as kilobytes'))
soft_global_max_size = models.IntegerField(
verbose_name=_('Soft max size'),
help_text=_('as bytes'))
help_text=_('as kilobytes'))
hard_per_key_max_size = models.IntegerField(
verbose_name=_('Hard max size per key'),
help_text=_('as bytes'))
help_text=_('as kilobytes'))
soft_per_key_max_size = models.IntegerField(
verbose_name=_('Soft max size per key'),
help_text=_('as bytes'))
size = models.IntegerField(
help_text=_('as kilobytes'))
size = models.BigIntegerField(
verbose_name=_('Size'),
default=0,
help_text=_('as bytes'))
@ -62,16 +62,16 @@ class Partner(models.Model):
def check_limits(self, size_delta, **kwargs):
new_size = self.size + size_delta
if new_size > self.hard_global_max_size:
if new_size > self.hard_global_max_size * 1024:
raise GlobalSpaceExhausted
if (self.size < self.soft_global_max_size
and new_size > self.soft_global_max_size):
if (self.size < self.soft_global_max_size * 1024
and new_size > self.soft_global_max_size * 1024):
self.notify_admins(
subject=_('Partner %s space almost exhausted') % self.name,
body=_('Current size: {current_size}, Max size: {max_size}').format(
current_size=new_size,
max_size=self.hard_global_max_size),
max_size=self.hard_global_max_size * 1024),
**kwargs)
def notify_admins(self, subject, body, **kwargs):
@ -159,17 +159,18 @@ class Petal(models.Model):
cut=self.cut.uuid,
key=self.name)
if content_length > self.partner.hard_per_key_max_size:
if content_length > self.partner.hard_per_key_max_size * 1024:
raise PetalSizeExhausted
if content_length > self.partner.soft_per_key_max_size:
if (self.size <= self.partner.soft_per_key_max_size * 1024 and content_length >
self.partner.soft_per_key_max_size * 1024):
self.partner.notify_admins(
_('Key {key} space of partner {partner} almost exhausted').format(
key=self.name,
partner=self.partner.name),
_('Current size: {current_size}, Max size: {max_size}').format(
current_size=content_length,
max_size=self.partner.hard_per_key_max_size),
max_size=self.partner.hard_per_key_max_size * 1024),
partner=self.partner.name,
cut=self.cut.uuid,
key=self.name)

View File

@ -54,7 +54,7 @@ def partner_southpark(service_family, service_library, service_cityhall, service
@pytest.fixture
def partner_gotham():
create_service('arkham')
return create_partner('gotham', admins='b.wayne@gotham.gov', hg=2048, sg=1600, hk=400, sk=370)
return create_partner('gotham', admins='b.wayne@gotham.gov', hg=20, sg=10, hk=2, sk=1)
@pytest.fixture

View File

@ -261,42 +261,57 @@ def test_caching(app, partner_southpark, cut_kevin_uuid, acl):
def test_partner_size_limit(app, cut_kevin_uuid, acl, petal_invoice, petal_books, mailoutbox):
# gotham sizes:
# Global hard max: 20Ko
# Global soft max: 10Ko
# Per key hard max: 2Ko
# Per key soft max: 1Ko
app.authorization = ('Basic', ('arkham', 'arkham'))
payload = json.loads(get_tests_file_content('taxe.json'))
# test sending data sized above key limits
payload['phonenumber'] = '+18855776644'
payload['birthdate'] = '1980/06/21'
payload['birthplace'] = 'Chelsea, Quebec'
# test sending data sized above per key hard max size
url = '/api/gotham/%s/taxes-fail/' % cut_kevin_uuid
resp = app.put_json(url, params=payload, headers={'If-None-Match': '*'}, status=500)
resp = app.put(url,
params='a' * 3 * 1024, # 3ko
headers={'If-None-Match': '*'},
content_type='text/plain',
status=500)
assert resp.json['error'] == 'key-space-exhausted'
# test sending data sized within soft and hard key limit
payload.pop('birthplace')
resp = app.put_json(url, params=payload, headers={'If-None-Match': '*'}, status=201)
resp = app.put(url,
params='a' * (1024 + 1), # 1ko + 1
headers={'If-None-Match': '*'},
content_type='text/plain',
status=201)
assert len(mailoutbox) == 1
sent_mail = mailoutbox[0]
assert sent_mail.to[0] == 'b.wayne@gotham.gov'
assert 'taxes-fail' in sent_mail.subject
assert 'gotham' in sent_mail.subject
assert '395' in sent_mail.message().as_string()
assert '400' in sent_mail.message().as_string()
assert '1025' in sent_mail.message().as_string()
assert '2048' in sent_mail.message().as_string()
payload.pop('birthdate')
for i in range(4):
for i in range(18):
url = '/api/gotham/%s/taxes-%d/' % (cut_kevin_uuid, i)
app.put_json(url, params=payload, headers={'If-None-Match': '*'}, status=201)
app.put(url,
params='a' * 1024,
headers={'If-None-Match': '*'},
content_type='text/plain',
status=201)
assert len(mailoutbox) == 2
sent_mail = mailoutbox[1]
assert sent_mail.to[0] == 'b.wayne@gotham.gov'
assert 'gotham' in sent_mail.subject
assert '1867' in sent_mail.message().as_string()
assert '2048' in sent_mail.message().as_string()
assert '10241' in sent_mail.message().as_string()
assert str(1024 * 20) in sent_mail.message().as_string()
url = '/api/gotham/%s/taxes-4/' % cut_kevin_uuid
resp = app.put_json(url, params=payload, headers={'If-None-Match': '*'}, status=500)
url = '/api/gotham/%s/taxes-100/' % cut_kevin_uuid
resp = app.put(url,
params='a' * (1024 * 2 - 1),
headers={'If-None-Match': '*'},
content_type='text/plain',
status=500)
assert resp.json['error'] == 'global-space-exhausted'

View File

@ -34,7 +34,7 @@ def get_service(name):
return User.objects.get(username=name)
def create_partner(name, admins=None, hg=2048, sg=1536, hk=1024, sk=768):
def create_partner(name, admins=None, hg=2, sg=1, hk=1, sk=1):
if not admins:
admins = 'e.cartman@southpark.com,t.blakc@southpark.com'
return Partner.objects.create(