clarify and test overlimit notifications code.
This commit is contained in:
parent
0fb8df565c
commit
ac77c29ab7
|
@ -198,9 +198,10 @@ class Form(DB.Model):
|
|||
# check if the forms are over the counter and the user is not upgraded
|
||||
overlimit = False
|
||||
monthly_counter = self.get_monthly_counter()
|
||||
monthly_limit = settings.MONTHLY_SUBMISSIONS_LIMIT if \
|
||||
self.id > settings.FORM_LIMIT_DECREASE_ACTIVATION_SEQUENCE \
|
||||
monthly_limit = settings.MONTHLY_SUBMISSIONS_LIMIT \
|
||||
if self.id > settings.FORM_LIMIT_DECREASE_ACTIVATION_SEQUENCE \
|
||||
else settings.GRANDFATHER_MONTHLY_LIMIT
|
||||
|
||||
if monthly_counter > monthly_limit and not self.upgraded:
|
||||
overlimit = True
|
||||
|
||||
|
@ -208,7 +209,7 @@ class Form(DB.Model):
|
|||
# send email notification
|
||||
send_email(
|
||||
to=self.email,
|
||||
subject="[WARNING] Approaching submission limit",
|
||||
subject="Formspree Notice: Approaching submission limit.",
|
||||
text=render_template('email/90-percent-warning.txt',
|
||||
unconfirm_url=unconfirm, limit=monthly_limit
|
||||
),
|
||||
|
@ -222,6 +223,7 @@ class Form(DB.Model):
|
|||
now = datetime.datetime.utcnow().strftime('%I:%M %p UTC - %d %B %Y')
|
||||
|
||||
if not overlimit:
|
||||
g.log.info('Submitted.')
|
||||
text = render_template('email/form.txt',
|
||||
data=data, host=self.host, keys=keys, now=now,
|
||||
unconfirm_url=unconfirm)
|
||||
|
@ -235,19 +237,20 @@ class Form(DB.Model):
|
|||
data=data, host=self.host, keys=keys, now=now,
|
||||
unconfirm_url=unconfirm)
|
||||
else:
|
||||
if monthly_counter - monthly_limit > 25:
|
||||
g.log.info('Submission rejected. Form over quota.',
|
||||
monthly_counter=monthly_counter)
|
||||
# only send this overlimit notification for the first 25 overlimit emails
|
||||
# after that, return an error so the user can know the website owner is not
|
||||
# going to read his message.
|
||||
g.log.info('Submission rejected. Form over quota.',
|
||||
monthly_counter=monthly_counter)
|
||||
# send an overlimit notification for the first x overlimit emails
|
||||
# after that, return an error so the user can know the website owner is not
|
||||
# going to read his message.
|
||||
if monthly_counter <= monthly_limit + settings.OVERLIMIT_NOTIFICATION_QUANTITY:
|
||||
subject = 'Formspree Notice: Your submission limit has been reached.'
|
||||
text = render_template('email/overlimit-notification.txt',
|
||||
host=self.host, unconfirm_url=unconfirm, limit=monthly_limit)
|
||||
html = render_template_string(TEMPLATES.get('overlimit-notification.html'),
|
||||
host=self.host, unconfirm_url=unconfirm, limit=monthly_limit)
|
||||
else:
|
||||
return {'code': Form.STATUS_OVERLIMIT}
|
||||
|
||||
text = render_template('email/overlimit-notification.txt',
|
||||
host=self.host, unconfirm_url=unconfirm, limit=monthly_limit)
|
||||
html = render_template_string(TEMPLATES.get('overlimit-notification.html'),
|
||||
host=self.host, unconfirm_url=unconfirm, limit=monthly_limit)
|
||||
|
||||
# if emails are disabled and form is upgraded, don't send email notification
|
||||
if self.disable_email and self.upgraded:
|
||||
return {'code': Form.STATUS_NO_EMAIL, 'next': next}
|
||||
|
|
|
@ -95,7 +95,6 @@ def send(email_or_string):
|
|||
|
||||
g.log = g.log.bind(host=host, wants='json' if request_wants_json() else 'html')
|
||||
|
||||
g.log.info('Submitted.')
|
||||
if not IS_VALID_EMAIL(email_or_string):
|
||||
# in this case it can be a hashid identifying a
|
||||
# form generated from the dashboard
|
||||
|
|
|
@ -19,6 +19,7 @@ HASHIDS_SALT = os.getenv('HASHIDS_SALT') or ''
|
|||
NONCE_SECRET = (os.getenv('NONCE_SECRET') or '').encode('utf-8')
|
||||
|
||||
GRANDFATHER_MONTHLY_LIMIT = 1000
|
||||
OVERLIMIT_NOTIFICATION_QUANTITY = 25
|
||||
MONTHLY_SUBMISSIONS_LIMIT = int(os.getenv('MONTHLY_SUBMISSIONS_LIMIT') or 100)
|
||||
ARCHIVED_SUBMISSIONS_LIMIT = int(os.getenv('ARCHIVED_SUBMISSIONS_LIMIT') or 1000)
|
||||
FORM_LIMIT_DECREASE_ACTIVATION_SEQUENCE = int(os.getenv('FORM_LIMIT_DECREASE_ACTIVATION_SEQUENCE') or 0)
|
||||
|
|
|
@ -33,6 +33,7 @@ def msend():
|
|||
def app():
|
||||
settings.MONTHLY_SUBMISSIONS_LIMIT = 2
|
||||
settings.ARCHIVED_SUBMISSIONS_LIMIT = 2
|
||||
settings.OVERLIMIT_NOTIFICATION_QUANTITY = 2
|
||||
settings.FORM_LIMIT_DECREASE_ACTIVATION_SEQUENCE = 0
|
||||
settings.EXPENSIVELY_WIPE_SUBMISSIONS_FREQUENCY = 1
|
||||
settings.PRESERVE_CONTEXT_ON_EXCEPTION = False
|
||||
|
|
|
@ -219,50 +219,59 @@ def test_grandfather_limit_and_decrease(client, msend):
|
|||
settings.GRANDFATHER_MONTHLY_LIMIT = 2
|
||||
settings.MONTHLY_SUBMISSIONS_LIMIT = 1
|
||||
settings.FORM_LIMIT_DECREASE_ACTIVATION_SEQUENCE = 1
|
||||
# the form limit should be 3 for the first form and 1 for the second
|
||||
# the form limit should be 2 for the first form and 1 for the second
|
||||
|
||||
# submit the forms
|
||||
client.post('/1@example.com',
|
||||
client.post('/grandfathered@example.com',
|
||||
headers = {'referer': 'http://somewhere.com'},
|
||||
data={'name': 'john'}
|
||||
)
|
||||
form1 = Form.query.filter_by(host='somewhere.com',
|
||||
email='1@example.com').first()
|
||||
form_grandfathered = Form.query.filter_by(host='somewhere.com',
|
||||
email='grandfathered@example.com').first()
|
||||
|
||||
client.post('/2@example.com',
|
||||
client.post('/new@example.com',
|
||||
headers = {'referer': 'http://somewhere.com'},
|
||||
data={'name': 'john'}
|
||||
)
|
||||
form2 = Form.query.filter_by(host='somewhere.com',
|
||||
email='2@example.com').first()
|
||||
form_new = Form.query.filter_by(host='somewhere.com',
|
||||
email='new@example.com').first()
|
||||
|
||||
# confirm formS
|
||||
form1.confirmed = True
|
||||
DB.session.add(form1)
|
||||
form2.confirmed = True
|
||||
DB.session.add(form2)
|
||||
form_grandfathered.confirmed = True
|
||||
DB.session.add(form_grandfathered)
|
||||
form_new.confirmed = True
|
||||
DB.session.add(form_new)
|
||||
DB.session.commit()
|
||||
|
||||
# submit each form 3 times
|
||||
for _ in range(3):
|
||||
client.post('/1@example.com',
|
||||
msend.reset_mock()
|
||||
for i in range(3):
|
||||
client.post('/grandfathered@example.com',
|
||||
headers = {'referer': 'http://somewhere.com'},
|
||||
data={'_replyto': 'johann@gmail.com', 'name': 'johann', 'value': 'fivela'}
|
||||
)
|
||||
client.post('/2@example.com',
|
||||
headers = {'referer': 'http://somewhere.com'},
|
||||
data={'_replyto': 'johann@gmail.com', 'name': 'johann', 'value': 'fivela'}
|
||||
data={'_replyto': 'johann@gmail.com', 'name': 'johann', 'value': 'v%s' % i}
|
||||
)
|
||||
|
||||
assert '1@example.com' == msend.call_args_list[-6][1]['to']
|
||||
assert 'fivela' in msend.call_args_list[-6][1]['text']
|
||||
assert '2@example.com' == msend.call_args_list[-5][1]['to']
|
||||
assert 'fivela' in msend.call_args_list[-5][1]['text']
|
||||
assert '1@example.com' == msend.call_args_list[-4][1]['to']
|
||||
assert 'fivela' in msend.call_args_list[-4][1]['text']
|
||||
assert '2@example.com' == msend.call_args_list[-3][1]['to']
|
||||
assert 'past the limit of 1' in msend.call_args_list[-3][1]['text']
|
||||
assert '1@example.com' == msend.call_args_list[-2][1]['to']
|
||||
assert 'past the limit of 2' in msend.call_args_list[-2][1]['text']
|
||||
assert '2@example.com' == msend.call_args_list[-1][1]['to']
|
||||
assert 'past the limit of 1' in msend.call_args_list[-1][1]['text']
|
||||
assert len(msend.call_args_list) == 4
|
||||
assert 'grandfathered@example.com' == msend.call_args_list[-4][1]['to']
|
||||
assert '90%' in msend.call_args_list[-4][1]['text']
|
||||
assert 'grandfathered@example.com' == msend.call_args_list[-3][1]['to']
|
||||
assert 'v0' in msend.call_args_list[-3][1]['text']
|
||||
assert 'grandfathered@example.com' == msend.call_args_list[-2][1]['to']
|
||||
assert 'v1' in msend.call_args_list[-2][1]['text']
|
||||
assert 'grandfathered@example.com' == msend.call_args_list[-1][1]['to']
|
||||
assert 'limit' in msend.call_args_list[-1][1]['text']
|
||||
|
||||
msend.reset_mock()
|
||||
for i in range(3):
|
||||
client.post('/new@example.com',
|
||||
headers = {'referer': 'http://somewhere.com'},
|
||||
data={'_replyto': 'johann@gmail.com', 'name': 'johann', 'value': 'v%s' % i}
|
||||
)
|
||||
|
||||
assert len(msend.call_args_list) == 3
|
||||
assert 'new@example.com' == msend.call_args_list[-3][1]['to']
|
||||
assert 'v0' in msend.call_args_list[-3][1]['text']
|
||||
assert 'new@example.com' == msend.call_args_list[-2][1]['to']
|
||||
assert 'limit' in msend.call_args_list[-2][1]['text']
|
||||
assert 'new@example.com' == msend.call_args_list[-1][1]['to']
|
||||
assert 'limit' in msend.call_args_list[-1][1]['text']
|
||||
|
|
|
@ -53,7 +53,7 @@ def test_various_content_types(client, msend):
|
|||
|
||||
# for this test only we will relax this limit.
|
||||
default_limit = settings.MONTHLY_SUBMISSIONS_LIMIT
|
||||
settings.MONTHLY_SUBMISSIONS_LIMIT = len(types)
|
||||
settings.MONTHLY_SUBMISSIONS_LIMIT = len(types) * 2
|
||||
|
||||
for ct, acc, check in types:
|
||||
headers = {'Referer': 'http://testwebsite.com'}
|
||||
|
|
|
@ -223,7 +223,7 @@ def test_monthly_limits(client, msend):
|
|||
assert r.status_code == 302 # the response to the user is the same
|
||||
# being the form over the limits or not
|
||||
|
||||
# but the mocked sendgrid should never receive this last form
|
||||
# the mocked sendgrid should never receive this last form
|
||||
assert 'maria' not in msend.call_args[1]['text']
|
||||
assert 'past the limit' in msend.call_args[1]['text']
|
||||
|
||||
|
@ -252,6 +252,40 @@ def test_monthly_limits(client, msend):
|
|||
assert r.status_code == 302
|
||||
assert 'noah' in msend.call_args[1]['text']
|
||||
|
||||
def test_overlimit_notifications(client, msend):
|
||||
# monthly limit is set to 2 during tests
|
||||
assert settings.MONTHLY_SUBMISSIONS_LIMIT == 2
|
||||
|
||||
# we'll send two overlimit notifications and no more
|
||||
assert settings.OVERLIMIT_NOTIFICATION_QUANTITY == 2
|
||||
|
||||
# manually verify luke@example.com
|
||||
r = client.post('/luke@testwebsite.com',
|
||||
headers=http_headers,
|
||||
data={'name': 'luke'}
|
||||
)
|
||||
f = Form.query.first()
|
||||
f.confirm_sent = True
|
||||
f.confirmed = True
|
||||
DB.session.add(f)
|
||||
DB.session.commit()
|
||||
|
||||
# submit the form multiple times
|
||||
msend.reset_mock()
|
||||
for i in range(0, 20):
|
||||
r = client.post('/luke@testwebsite.com',
|
||||
headers=http_headers,
|
||||
data={'name': 'matthew'}
|
||||
)
|
||||
|
||||
# but we'll only send 5 emails (1 warning, 2 normal, 2 overlimit)
|
||||
assert len(msend.call_args_list) == 5
|
||||
assert '90%' in msend.call_args_list[-5][1]['text']
|
||||
assert 'matthew' in msend.call_args_list[-4][1]['text']
|
||||
assert 'matthew' in msend.call_args_list[-3][1]['text']
|
||||
assert 'limit' in msend.call_args_list[-2][1]['text']
|
||||
assert 'limit' in msend.call_args_list[-1][1]['text']
|
||||
|
||||
def test_first_submission_is_stored(client, msend):
|
||||
r = client.post('/what@firstsubmissed.com',
|
||||
headers=http_headers,
|
||||
|
|
Loading…
Reference in New Issue