Skip to content
This repository has been archived by the owner on Feb 8, 2018. It is now read-only.

fake identities, with dashboard #4006

Merged
merged 2 commits into from
May 11, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 148 additions & 74 deletions gratipay/utils/fake_data.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""This module contains utilities for populating a non-production environment with fake data.
"""
import datetime
from decimal import Decimal as D
import random
Expand All @@ -16,7 +18,15 @@

faker = Factory.create()

def _fake_thing(db, tablename, **kw):

def insert_fake_data(db, tablename, **kw):
"""Insert fake data into the database.

:param Postgres db: a ``Postgres`` or ``Cursor`` object
:param unicode tablename: the name of the table to insert into
:param dict **kw: a mapping of column names to values

"""
column_names = []
column_value_placeholders = []
column_values = []
Expand Down Expand Up @@ -48,28 +58,61 @@ def fake_sentence(start=1, stop=100):
return faker.sentence(random.randrange(start,stop))


def fake_participant(db, is_admin=False):
def fake_participant(db, is_admin=False, random_identities=True):
"""Create a fake User.

:param Postgres db: a ``Postgres`` or ``Cursor`` object
:param bool is_admin: whether to make the participant an admin
:param bool random_identities: whether to give the participant random identities

"""
username = faker.first_name() + fake_text_id(3)
try:
_fake_thing( db
, "participants"
, username=username
, username_lower=username.lower()
, ctime=faker.date_time_this_year()
, is_admin=is_admin
, balance=0
, anonymous_giving=(random.randrange(5) == 0)
, balanced_customer_href=faker.uri()
, is_suspicious=False
, claimed_time=faker.date_time_this_year()
)
insert_fake_data( db
, "participants"
, username=username
, username_lower=username.lower()
, ctime=faker.date_time_this_year()
, is_admin=is_admin
, balance=0
, anonymous_giving=(random.randrange(5) == 0)
, balanced_customer_href=faker.uri()
, is_suspicious=False
, claimed_time=faker.date_time_this_year()
, email_address='{}@example.com'.format(username)
)
participant = Participant.from_username(username)

if random_identities:
if random.randrange(100) < 66:
fake_participant_identity(participant)
if random.randrange(100) < 33:
fake_participant_identity(participant)
if random.randrange(100) < 50:
fake_participant_identity(participant)

except IntegrityError:
return fake_participant(db, is_admin)
return fake_participant(db, is_admin)

#Call participant constructor to perform other DB initialization
return Participant.from_username(username)
return participant


def fake_participant_identity(participant, verification=None):
"""Pick a country and make an identity for the participant there.

:param Participant participant: a participant object
:param bool verification: the value to set verification to; None will result in a 50% chance
either way
:returns: a country id

"""
country_id = random_country_id(participant.db)
participant.store_identity_info(country_id, 'nothing-enforced', {})
if verification:
participant.set_identity_verification(country_id, verification)
elif (random.randrange(2) == 0): # 50%
participant.set_identity_verification(country_id, True)
return country_id


def fake_team(db, teamowner):
Expand All @@ -84,36 +127,38 @@ def fake_team(db, teamowner):
try:
teamslug = slugize(teamslugname)
homepage = 'http://www.example.org/' + fake_text_id(3)
_fake_thing( db
, "teams"
, slug=teamslug
, slug_lower=teamslug.lower()
, name=teamname
, homepage=homepage
, product_or_service=random.sample(productorservice,1)[0]
, todo_url=homepage + '/tickets'
, onboarding_url=homepage + '/contributing'
, owner=teamowner.username
, is_approved=random.sample(isapproved,1)[0]
, receiving=0.1
, nreceiving_from=3
)
insert_fake_data( db
, "teams"
, slug=teamslug
, slug_lower=teamslug.lower()
, name=teamname
, homepage=homepage
, product_or_service=random.sample(productorservice,1)[0]
, todo_url=homepage + '/tickets'
, onboarding_url=homepage + '/contributing'
, owner=teamowner.username
, is_approved=random.sample(isapproved,1)[0]
, receiving=0.1
, nreceiving_from=3
)
except IntegrityError:
return fake_team(db, teamowner)

return Team.from_slug(teamslug)


def fake_payment_instruction(db, participant, team):
"""Create a fake payment_instruction
"""
return _fake_thing( db
, "payment_instructions"
, ctime=faker.date_time_this_year()
, mtime=faker.date_time_this_month()
, participant=participant.username
, team=team.slug
, amount=fake_tip_amount()
)
return insert_fake_data( db
, "payment_instructions"
, ctime=faker.date_time_this_year()
, mtime=faker.date_time_this_month()
, participant=participant.username
, team=team.slug
, amount=fake_tip_amount()
)


def fake_community(db, creator):
"""Create a fake community
Expand Down Expand Up @@ -143,48 +188,54 @@ def fake_tip_amount():
def fake_tip(db, tipper, tippee):
"""Create a fake tip.
"""
return _fake_thing( db
, "tips"
, ctime=faker.date_time_this_year()
, mtime=faker.date_time_this_month()
, tipper=tipper.username
, tippee=tippee.username
, amount=fake_tip_amount()
)
return insert_fake_data( db
, "tips"
, ctime=faker.date_time_this_year()
, mtime=faker.date_time_this_month()
, tipper=tipper.username
, tippee=tippee.username
, amount=fake_tip_amount()
)


def fake_elsewhere(db, participant, platform):
"""Create a fake elsewhere.
"""
_fake_thing( db
, "elsewhere"
, platform=platform
, user_id=fake_text_id()
, user_name=participant.username
, participant=participant.username
, extra_info=None
)
insert_fake_data( db
, "elsewhere"
, platform=platform
, user_id=fake_text_id()
, user_name=participant.username
, participant=participant.username
, extra_info=None
)


def fake_transfer(db, tipper, tippee):
return _fake_thing( db
, "transfers"
, timestamp=faker.date_time_this_year()
, tipper=tipper.username
, tippee=tippee.username
, amount=fake_tip_amount()
, context='tip'
)
return insert_fake_data( db
, "transfers"
, timestamp=faker.date_time_this_year()
, tipper=tipper.username
, tippee=tippee.username
, amount=fake_tip_amount()
, context='tip'
)


def fake_exchange(db, participant, amount, fee, timestamp):
return _fake_thing( db
, "exchanges"
, timestamp=timestamp
, participant=participant.username
, amount=amount
, fee=fee
, status='succeeded'
)
return insert_fake_data( db
, "exchanges"
, timestamp=timestamp
, participant=participant.username
, amount=amount
, fee=fee
, status='succeeded'
)


def random_country_id(db):
return db.one("SELECT id FROM countries ORDER BY random() LIMIT 1")


def prep_db(db):
db.run("""
Expand Down Expand Up @@ -225,6 +276,7 @@ def prep_db(db):
FOR EACH ROW EXECUTE PROCEDURE process_exchange();
""")


def clean_db(db):
db.run("""
DROP FUNCTION IF EXISTS process_transfer() CASCADE;
Expand All @@ -236,10 +288,25 @@ def populate_db(db, num_participants=100, ntips=200, num_teams=5, num_transfers=
"""Populate DB with fake data.
"""
print("Making Participants")
make_flag_tester = num_participants > 1

participants = []
for i in xrange(num_participants):
for i in xrange(num_participants - 1 if make_flag_tester else num_participants):
participants.append(fake_participant(db))

if make_flag_tester:
# make a participant for testing weird flags
flag_tester = fake_participant(db, random_identities=False)
participants.append(flag_tester)

nepal = db.one("SELECT id FROM countries WHERE code='NP'")
flag_tester.store_identity_info(nepal, 'nothing-enforced', {})
flag_tester.set_identity_verification(nepal, True)

vatican = db.one("SELECT id FROM countries WHERE code='VA'")
flag_tester.store_identity_info(vatican, 'nothing-enforced', {})
flag_tester.set_identity_verification(vatican, True)

print("Making Teams")
teams = []
teamowners = random.sample(participants, num_teams)
Expand Down Expand Up @@ -337,13 +404,20 @@ def populate_db(db, num_participants=100, ntips=200, num_teams=5, num_transfers=
'nusers': len(actives),
'volume': sum(x['amount'] for x in week_transfers)
}
_fake_thing(db, "paydays", **payday)
insert_fake_data(db, "paydays", **payday)
date = end_date
print("")


def _wireup():
env = wireup.env()
db = wireup.db(env)
wireup.crypto(env)
return db


def main(db=None, *a, **kw):
db = db or wireup.db(wireup.env())
db = db or _wireup()
clean_db(db)
prep_db(db)
populate_db(db, *a, **kw)
Expand Down
6 changes: 6 additions & 0 deletions tests/py/test_fake_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ def test_fake_data(self):
assert len(payment_instructions) == num_tips
else:
assert len(payment_instructions) == (num_participants - num_teams)


def test_fake_participant_identity(self):
crusher = self.make_participant('crusher', email_address='[email protected]')
country_id = fake_data.fake_participant_identity(crusher)
assert [x.country.id for x in crusher.list_identity_metadata()] == [country_id]
62 changes: 62 additions & 0 deletions www/dashboard/countries.spt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from aspen import Response

[---]
if not user.ADMIN:
raise Response(403)

countries = website.db.all("""

SELECT name
, array_agg(username) as usernames
, array_agg(is_verified) as verifications
FROM participant_identities pi
JOIN participants p
ON p.id = participant_id
JOIN countries c
ON c.id = country_id
GROUP BY c.name

""")

multiple = website.db.all("""

WITH counts AS (
SELECT participant_id, count(*) count
FROM participant_identities
GROUP BY participant_id
)
SELECT p.*::participants
FROM participants p
JOIN counts c
ON p.id = c.participant_id
WHERE c.count > 1

""")

zip = zip
[---] text/html
<h1>Multiple</h1>
{% for participant in multiple %}
<a href="/~{{ participant.username }}/">{{ participant.username }}</a>
{% for identity in participant.list_identity_metadata() %}
| {% if identity.is_verified %}
<b>{{ identity.country.name }}</b>
{% else %}
{{ identity.country.name }}
{% endif %}
{% endfor %}
<br>
{% endfor %}

<h1>By Country</h1>
{% for country in countries %}
<b>{{ country.name }}</b>
{% for username, is_verified in zip(country.usernames, country.verifications) %}
| {% if is_verified %}
<b><a href="/~{{ username }}/">{{ username }}</a></b>
{% else %}
<a href="/~{{ username }}/">{{ username }}</a>
{% endif %}
{% endfor %}
<br>
{% endfor %}