diff --git a/gittip/billing/payday.py b/gittip/billing/payday.py index 83ca3cface..85f583f3a2 100644 --- a/gittip/billing/payday.py +++ b/gittip/billing/payday.py @@ -188,7 +188,7 @@ def get_participants(self, ts_start): , balance , balanced_account_uri , stripe_customer_id - , payin_suspended + , is_suspicious FROM participants WHERE claimed_time IS NOT NULL AND claimed_time < %s @@ -230,8 +230,8 @@ def charge_and_or_transfer(self, ts_start, participant, tips, total): money between Gittip accounts. """ - if participant['payin_suspended']: - log("PAYIN SUSPENDED: %s" % participant['id']) + if participant['is_suspicious']: + log("SUSPICIOUS: %s" % participant['id']) return short = total - participant['balance'] diff --git a/gittip/participant.py b/gittip/participant.py deleted file mode 100644 index 4c4ebdba16..0000000000 --- a/gittip/participant.py +++ /dev/null @@ -1,17 +0,0 @@ -from gittip import db - - -class Participant(object): - - def __init__(self, participant_id): - self.participant_id = participant_id - - def suspend_payin(self): - db.execute( "UPDATE participants SET payin_suspended=true WHERE id=%s" - , (self.participant_id,) - ) - - def unsuspend_payin(self): - db.execute( "UPDATE participants SET payin_suspended=false WHERE id=%s" - , (self.participant_id,) - ) diff --git a/gittip/testing.py b/gittip/testing.py index 8b48ff3eed..9c043e4d8b 100644 --- a/gittip/testing.py +++ b/gittip/testing.py @@ -15,6 +15,7 @@ from aspen.testing import Website, StubRequest from aspen.utils import utcnow from gittip import wireup +from gittip.authentication import User from gittip.billing.payday import Payday @@ -312,24 +313,24 @@ def setup_tips(*recs): _participants = {} for rec in recs: - defaults = good_cc, payin_suspended, claimed = (True, False, True) + defaults = good_cc, is_suspicious, claimed = (True, False, True) if len(rec) == 3: tipper, tippee, amount = rec elif len(rec) == 4: tipper, tippee, amount, good_cc = rec - payin_suspended, claimed = (False, True) + is_suspicious, claimed = (False, True) elif len(rec) == 5: - tipper, tippee, amount, good_cc, payin_suspended = rec + tipper, tippee, amount, good_cc, is_suspicious = rec claimed = True elif len(rec) == 6: - tipper, tippee, amount, good_cc, payin_suspended, claimed = rec + tipper, tippee, amount, good_cc, is_suspicious, claimed = rec assert good_cc in (True, False, None), good_cc - assert payin_suspended in (True, False), payin_suspended + assert is_suspicious in (True, False), is_suspicious assert claimed in (True, False), claimed - _participants[tipper] = (good_cc, payin_suspended, claimed) + _participants[tipper] = (good_cc, is_suspicious, claimed) if tippee not in _participants: _participants[tippee] = defaults now = utcnow() @@ -343,12 +344,12 @@ def setup_tips(*recs): then = utcnow() - datetime.timedelta(seconds=3600) participants = [] - for participant_id, (good_cc, payin_suspended, claimed) in _participants.items(): + for participant_id, (good_cc, is_suspicious, claimed) in _participants.items(): rec = {"id": participant_id} if good_cc is not None: rec["last_bill_result"] = "" if good_cc else "Failure!" rec["balanced_account_uri"] = "/v1/blah/blah/" + participant_id - rec["payin_suspended"] = payin_suspended + rec["is_suspicious"] = is_suspicious if claimed: rec["claimed_time"] = then participants.append(rec) @@ -363,11 +364,15 @@ def setup_tips(*recs): , '--project_root', str('..') ]) -def serve_request(path): +def serve_request(path, user=None): """Given an URL path, return response. """ request = StubRequest(path) request.website = test_website + if user is not None: + user = User.from_id(user) + # Note that Cookie needs a bytestring. + request.headers.cookie[str('session')] = user.session_token response = test_website.handle_safely(request) return response diff --git a/schema.sql b/schema.sql index 5c61327899..84fe3f8c28 100644 --- a/schema.sql +++ b/schema.sql @@ -201,3 +201,11 @@ ALTER TABLE participants ALTER COLUMN balance SET NOT NULL; -- https://github.com/whit537/www.gittip.com/issues/350 ALTER TABLE participants ADD COLUMN payin_suspended bool NOT NULL DEFAULT FALSE; + + +------------------------------------------------------------------------------- +-- https://github.com/whit537/www.gittip.com/issues/354 + +ALTER TABLE participants ADD COLUMN is_suspicious bool DEFAULT NULL; +UPDATE participants SET is_suspicious=true WHERE payin_suspended; +ALTER TABLE participants DROP COLUMN payin_suspended; diff --git a/tests/test_billing.py b/tests/test_billing.py index 2e0e1371e1..75a15c2d69 100644 --- a/tests/test_billing.py +++ b/tests/test_billing.py @@ -408,7 +408,7 @@ def test_payday_moves_money(charge_on_balanced): assert actual == expected, actual @mock.patch('gittip.billing.payday.Payday.charge_on_balanced') -def test_payday_doesnt_move_money_from_a_suspended_payin_account(charge_on_balanced): +def test_payday_doesnt_move_money_from_a_suspicious_account(charge_on_balanced): charge_on_balanced.return_value = (Decimal('10.00'), Decimal('0.68'), None) tips = testing.setup_tips(('buz', 'bar', '6.00', True, True)) # under $10! with testing.load(*tips) as context: @@ -417,7 +417,7 @@ def test_payday_doesnt_move_money_from_a_suspended_payin_account(charge_on_balan assert actual == {"paydays": [1,0,0]}, actual @mock.patch('gittip.billing.payday.Payday.charge_on_balanced') -def test_payday_does_move_money_TO_a_suspended_payin_account(charge_on_balanced): +def test_payday_does_move_money_TO_a_suspicious_account(charge_on_balanced): charge_on_balanced.return_value = (Decimal('10.00'), Decimal('0.68'), None) tips = testing.setup_tips( ('buz', 'bar', '6.00', True, True) , ('foo', 'buz', '1.00') @@ -731,7 +731,7 @@ def test_charge_and_or_transfer_no_tips(self, get_tips_and_total): participant = { 'balance': 1 , 'id': self.participant_id , 'balanced_account_uri': self.balanced_account_uri - , 'payin_suspended': False + , 'is_suspicious': False } initial_payday = self._get_payday() @@ -763,7 +763,7 @@ def test_charge_and_or_transfer(self, tip, get_tips_and_total): participant = { 'balance': 1 , 'id': self.participant_id , 'balanced_account_uri': self.balanced_account_uri - , 'payin_suspended': False + , 'is_suspicious': False } return_values = [1, 1, 0, -1] @@ -803,7 +803,7 @@ def test_charge_and_or_transfer_short(self, charge, get_tips_and_total): participant = { 'balance': 0 , 'id': self.participant_id , 'balanced_account_uri': self.balanced_account_uri - , 'payin_suspended': False + , 'is_suspicious': False } diff --git a/tests/test_is_suspicious.py b/tests/test_is_suspicious.py new file mode 100644 index 0000000000..9e458ae86d --- /dev/null +++ b/tests/test_is_suspicious.py @@ -0,0 +1,53 @@ +from gittip.testing import load, serve_request + + +def participants(foo_starts_suspicious=None): + participants = ( {"id": "foo"} + , {"id": "bar", "is_admin": True} + ) + if foo_starts_suspicious is not None: + participants[0]["is_suspicious"] = foo_starts_suspicious + return load('participants', *participants) + + +def toggle_is_suspicious(): + response = serve_request('/foo/toggle-is-suspicious.json', user='bar') + return response.body + + +def test_participants_start_out_with_is_suspicious_None(): + with participants() as context: + actual = context.dump()['participants']['foo']['is_suspicious'] + assert actual is None, actual + +def test_toggling_NULL_gives_true(): + with participants() as context: + toggle_is_suspicious() + actual = context.diff()['participants']['updates'][0]['is_suspicious'] + assert actual is True, actual + +def test_toggling_changes_two_things(): + with participants() as context: + toggle_is_suspicious() + actual = context.diff(compact=True) + assert actual == {'participants': [0,2,0]}, actual + +def test_but_the_second_thing_is_just_bars_session(): + with participants() as context: + toggle_is_suspicious() + expected = ('bar', ['id', 'session_expires', 'session_token']) + second = context.diff()['participants']['updates'][1] + actual = (second['id'], sorted(second.keys())) + assert actual == expected, actual + +def test_toggling_true_gives_false(): + with participants(True) as context: + toggle_is_suspicious() + actual = context.diff()['participants']['updates'][0]['is_suspicious'] + assert actual is False, actual + +def test_toggling_false_gives_true(): + with participants(False) as context: + toggle_is_suspicious() + actual = context.diff()['participants']['updates'][0]['is_suspicious'] + assert actual is True, actual diff --git a/tests/test_suspension.py b/tests/test_suspension.py deleted file mode 100644 index ae4a3d6ce5..0000000000 --- a/tests/test_suspension.py +++ /dev/null @@ -1,44 +0,0 @@ -from gittip.testing import load -from gittip.participant import Participant - - -def test_participants_start_out_unpayin_suspended(): - with load('participants', ('foo',)) as context: - actual = context.dump()['participants']['foo']['payin_suspended'] - assert actual is False, actual - -def test_suspend_suspends(): - with load('participants', ('foo',)) as context: - Participant('foo').suspend_payin() - actual = context.diff()['participants']['updates'][0]['payin_suspended'] - assert actual is True, actual - -def test_suspend_changes_one_thing_only(): - with load('participants', ('foo',)) as context: - Participant('foo').suspend_payin() - actual = context.diff(compact=True) - assert actual == {'participants': [0,1,0]}, actual - -def test_suspend_is_a_noop_when_payin_suspended(): - with load('participants', {'id': 'foo', 'payin_suspended': True}) as context: - Participant('foo').suspend_payin() - actual = context.diff(compact=True) - assert actual == {}, actual - -def test_unsuspend_is_a_noop_when_not_payin_suspended(): - with load('participants', ('foo',)) as context: - Participant('foo').unsuspend_payin() - actual = context.diff(compact=True) - assert actual == {}, actual - -def test_unsuspend_unsuspends(): - with load('participants', {'id': 'foo', 'payin_suspended': True}) as context: - Participant('foo').unsuspend_payin() - actual = context.diff()['participants']['updates'][0]['payin_suspended'] - assert actual is False, actual - -def test_unsuspend_changes_one_thing_only(): - with load('participants', {'id': 'foo', 'payin_suspended': True}) as context: - Participant('foo').unsuspend_payin() - actual = context.diff(compact=True) - assert actual == {'participants': [0,1,0]}, actual diff --git a/www/%participant_id/toggle-payin-suspension.json b/www/%participant_id/toggle-is-suspicious.json similarity index 50% rename from www/%participant_id/toggle-payin-suspension.json rename to www/%participant_id/toggle-is-suspicious.json index 8c7a7dd56e..ba5075d119 100644 --- a/www/%participant_id/toggle-payin-suspension.json +++ b/www/%participant_id/toggle-is-suspicious.json @@ -1,3 +1,4 @@ +from aspen import Response from gittip import db ^L if not user.ADMIN: @@ -6,12 +7,12 @@ if not user.ADMIN: rec = db.fetchone(""" UPDATE participants - SET payin_suspended = not payin_suspended + SET is_suspicious = (is_suspicious IS NULL) OR (is_suspicious IS false) WHERE id=%s - RETURNING payin_suspended + RETURNING is_suspicious """, (path['participant_id'],)) assert rec is not None -response.body = {"payin_suspended": rec['payin_suspended']} +response.body = {"is_suspicious": rec['is_suspicious']} diff --git a/www/about/fraud/index.html b/www/about/fraud/index.html index 213e6a0bd2..e084665752 100644 --- a/www/about/fraud/index.html +++ b/www/about/fraud/index.html @@ -11,7 +11,7 @@ SELECT id , balance FROM participants - WHERE payin_suspended + WHERE is_suspicious """) if _suspicious is None: @@ -23,7 +23,7 @@ person['gives_to'] = db.fetchall(""" SELECT DISTINCT tippee AS id - , payin_suspended AS is_suspicious + , is_suspicious FROM tips JOIN participants p ON tippee = p.id @@ -34,7 +34,7 @@ person['receives_from'] = db.fetchall(""" SELECT DISTINCT tipper AS id - , payin_suspended AS is_suspicious + , is_suspicious FROM tips JOIN participants p ON tipper = p.id