This repository has been archived by the owner on Feb 8, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 309
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Write parser/validator for homepage form
- Loading branch information
1 parent
75e8816
commit 41dfd1a
Showing
5 changed files
with
166 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# -*- coding: utf-8 -*- | ||
"""This is the Python library behind gratipay.com. | ||
""" | ||
from __future__ import absolute_import, division, print_function, unicode_literals | ||
|
||
from gratipay import utils | ||
|
||
|
||
def pay_for_open_source(app, raw): | ||
parsed, errors = _parse(raw) | ||
if not errors: | ||
transaction_id = _charge_card(app, parsed) | ||
if not transaction_id: | ||
errors.append('charge_card') | ||
if not errors: | ||
message_id = None | ||
if parsed['email_address']: | ||
message_id = _send_receipt(app, parsed['email_address']) | ||
if not message_id: | ||
errors.append('send_receipt') | ||
_store_info(parsed, transaction_id, message_id) | ||
parsed = {} | ||
return {'parsed': parsed, 'errors': errors} | ||
|
||
|
||
def _parse(raw): | ||
"""Given a POST request.body, return (parsed<dict>, errors<list>). | ||
""" | ||
|
||
errors = [] | ||
x = lambda f: raw.get(f, '').strip() | ||
|
||
# amount | ||
amount = x('amount') or '0' | ||
if (not amount.isdigit()) or (int(amount) < 50): | ||
errors.append('amount') | ||
amount = ''.join(x for x in amount.split('.')[0] if x.isdigit()) | ||
|
||
# TODO credit card token? | ||
|
||
# name | ||
name = x('name') | ||
if len(name) > 256: | ||
name = name[:256] | ||
errors.append('name') | ||
|
||
# email address | ||
email_address = x('email_address') | ||
if email_address and not utils.is_valid_email_address(email_address): | ||
email_address = email_address[:255] | ||
errors.append('email_address') | ||
|
||
# follow_up | ||
follow_up = x('follow_up') | ||
if follow_up not in ('monthly', 'quarterly', 'yearly', 'never'): | ||
follow_up = 'monthly' | ||
errors.append('follow_up') | ||
|
||
promotion_name = x('promotion_name') | ||
if len(promotion_name) > 32: | ||
promotion_name = promotion_name[:32] | ||
errors.append('promotion_name') | ||
|
||
promotion_url = x('promotion_url') | ||
is_link = lambda x: (x.startswith('http://') or x.startswith('https://')) and '.' in x | ||
if len(promotion_url) > 256 or not is_link(promotion_url): | ||
promotion_url = promotion_url[:256] | ||
errors.append('promotion_url') | ||
|
||
promotion_twitter = x('promotion_twitter') | ||
if len(promotion_twitter) > 32: | ||
promotion_twitter = promotion_twitter[:32] | ||
# TODO What are Twitter's rules? | ||
errors.append('promotion_twitter') | ||
|
||
promotion_message = x('promotion_message') | ||
if len(promotion_message) > 128: | ||
promotion_message = promotion_message[:128] | ||
errors.append('promotion_message') | ||
|
||
parsed = { 'amount': amount | ||
, 'name': name | ||
, 'email_address': email_address | ||
, 'follow_up': follow_up | ||
, 'promotion_name': promotion_name | ||
, 'promotion_url': promotion_url | ||
, 'promotion_twitter': promotion_twitter | ||
, 'promotion_message': promotion_message | ||
} | ||
return parsed, errors | ||
|
||
|
||
def _charge_card(app, parsed): | ||
raise NotImplementedError | ||
|
||
|
||
def _send_receipt(app, parsed): | ||
raise NotImplementedError | ||
app.email_queue.put() | ||
|
||
|
||
def _store_info(parsed, transaction_id, message_id): | ||
raise NotImplementedError | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# -*- coding: utf-8 -*- | ||
from __future__ import absolute_import, division, print_function, unicode_literals | ||
|
||
from gratipay.homepage import _parse | ||
from gratipay.testing import Harness | ||
|
||
|
||
class Parse(Harness): | ||
|
||
def test_good_values_survive(self): | ||
parsed, errors = _parse({ 'amount': '1000' | ||
, 'name': 'Alice Liddell' | ||
, 'email_address': '[email protected]' | ||
, 'follow_up': 'monthly' | ||
, 'promotion_name': 'Wonderland' | ||
, 'promotion_url': 'http://www.example.com/' | ||
, 'promotion_twitter': 'thebestbutter' | ||
, 'promotion_message': 'Love me! Love me! Say that you love me!' | ||
}) | ||
assert parsed == { 'amount': '1000' | ||
, 'name': 'Alice Liddell' | ||
, 'email_address': '[email protected]' | ||
, 'follow_up': 'monthly' | ||
, 'promotion_name': 'Wonderland' | ||
, 'promotion_url': 'http://www.example.com/' | ||
, 'promotion_twitter': 'thebestbutter' | ||
, 'promotion_message': 'Love me! Love me! Say that you love me!' | ||
} | ||
assert errors == [] | ||
|
||
|
||
def test_bad_values_get_scrubbed_and_flagged(self): | ||
parsed, errors = _parse({ 'amount': '1,000' | ||
, 'name': 'Alice Liddell' * 20 | ||
, 'email_address': 'alice' * 100 + '@example.com' | ||
, 'follow_up': 'cheese' | ||
, 'promotion_name': 'Wonderland' * 100 | ||
, 'promotion_url': 'http://www.example.com/' + 'cheese' * 100 | ||
, 'promotion_twitter': 'thebestbutter' * 10 | ||
, 'promotion_message': 'Love me!' * 50 | ||
}) | ||
assert parsed == { 'amount': '1000' | ||
, 'name': 'Alice Liddell' * 19 + 'Alice Lid' | ||
, 'email_address': 'alice' * 51 | ||
, 'follow_up': 'monthly' | ||
, 'promotion_name': 'WonderlandWonderlandWonderlandWo' | ||
, 'promotion_url': 'http://www.example.com/' + 'cheese' * 38 + 'chees' | ||
, 'promotion_twitter': 'thebestbutterthebestbutterthebes' | ||
, 'promotion_message': 'Love me!' * 16 | ||
} | ||
assert errors == ['amount', 'name', 'email_address', 'follow_up', 'promotion_name', | ||
'promotion_url', 'promotion_twitter', 'promotion_message'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters