Skip to content

Commit

Permalink
Report the participant's name too
Browse files Browse the repository at this point in the history
The API endpoint `data/other_verified_users` is something of a misnomer.
It is primarily used to report information we can confirm to have for a
given email address (to be consumed by the membership-processing
pipeline).

Accordingly, we can report a name which we have on file for the user.
This will prove useful when trying to record a membership payment (which
we have previously just assumed should match the first & last name of
whoever has made the payment).
  • Loading branch information
DavidCain committed Jun 1, 2022
1 parent 29d1f4d commit 10cbc69
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 2 deletions.
9 changes: 7 additions & 2 deletions ws/api_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,14 +601,19 @@ def get(self, request, *args, **kwargs):

addr = EmailAddress.objects.filter(email=email, verified=True).first()
if not addr: # Not in our system, so just return the original
return JsonResponse({'primary': email, 'emails': [email]})
# This API endpoint is for trusted entities; it's okay to give a null name.
# (in other words, there's no user enumeration vulnerability here)
return JsonResponse({'name': None, 'primary': email, 'emails': [email]})

# Normal case: Email is verified. Return all other verified emails
verifed_emails = addr.user.emailaddress_set.filter(verified=True)
participant = models.Participant.objects.filter(user=addr.user).first()
return JsonResponse(
{
'name': participant and participant.name,
'primary': addr.user.email,
'emails': list(verifed_emails.values_list('email', flat=True)),
# No real reason to sort these, apart from making return order deterministic)
'emails': sorted(verifed_emails.values_list('email', flat=True)),
}
)

Expand Down
72 changes: 72 additions & 0 deletions ws/tests/views/test_api_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,78 @@ def test_attempted_attack_fails(self):
self.assertEqual(response.json(), {'message': 'invalid algorithm'})


class OtherVerifiedEmailsTest(TestCase):
"""We report what we know about a MITOCer to authenticated APIS."""

def _query_for(self, email: str):
real_token = jwt.encode(
{'exp': time.time() + 60, 'email': email},
algorithm='HS512',
key=settings.MEMBERSHIP_SECRET_KEY,
)
return self.client.get(
'/data/verified_emails/', HTTP_AUTHORIZATION=f'Bearer: {real_token}'
)

def test_unknown_user(self):
"""We just report back the same email if we don't find a match."""
response = self._query_for('barry.o@whitehouse.gov')
self.assertEqual(
response.json(),
{
'name': None,
'primary': 'barry.o@whitehouse.gov',
'emails': ['barry.o@whitehouse.gov'],
},
)

def test_normal_participant(self):
"""We handle the case of a participant with some verified & unverified emails."""
tim = factories.ParticipantFactory.create(
name='Tim Beaver', email='tim@example.com'
)

factories.EmailFactory.create(
user_id=tim.user_id,
verified=False,
primary=False,
# Tim clearly doesn't own this email
email='tim@whitehouse.gov',
)
factories.EmailFactory.create(
user_id=tim.user_id, verified=True, primary=False, email='tim@mit.edu'
)

response = self._query_for('tim@mit.edu')

self.assertEqual(response.status_code, 200)
self.assertEqual(
response.json(),
{
'name': 'Tim Beaver',
'primary': 'tim@example.com',
'emails': ['tim@example.com', 'tim@mit.edu'],
},
)
# We get the same result when querying under a different known email!
self.assertEqual(response.json(), self._query_for('tim@example.com').json())

def test_user_without_participant(self):
"""We handle the case of a user who never completed a participant record."""

factories.UserFactory.create(email='tim@mit.edu')
response = self._query_for('tim@mit.edu')
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.json(),
{
'name': None,
'primary': 'tim@mit.edu',
'emails': ['tim@mit.edu'],
},
)


class JsonProgramLeadersViewTest(TestCase):
def setUp(self):
super().setUp()
Expand Down

0 comments on commit 10cbc69

Please sign in to comment.