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

Commit

Permalink
implement has_verified_identity
Browse files Browse the repository at this point in the history
  • Loading branch information
chadwhitacre committed May 1, 2016
1 parent ba617f5 commit 713fa95
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 0 deletions.
32 changes: 32 additions & 0 deletions sql/branch.sql
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,35 @@ CREATE TABLE participant_identities
, is_verified boolean NOT NULL DEFAULT false
, UNIQUE(participant_id, country_id)
);


-- participants.has_verified_identity

ALTER TABLE participants ADD COLUMN has_verified_identity bool NOT NULL DEFAULT false;

CREATE FUNCTION update_has_verified_identity() RETURNS trigger AS $$
BEGIN
UPDATE participants p
SET has_verified_identity=COALESCE((
SELECT is_verified
FROM participant_identities
WHERE participant_id = OLD.participant_id
AND is_verified
LIMIT 1
), false)
WHERE p.id = OLD.participant_id;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER propagate_is_verified_changes
AFTER UPDATE OF is_verified ON participant_identities
FOR EACH ROW
EXECUTE PROCEDURE update_has_verified_identity();

CREATE TRIGGER propagate_is_verified_removal
AFTER DELETE ON participant_identities
FOR EACH ROW
EXECUTE PROCEDURE update_has_verified_identity();

-- We don't need an INSERT trigger, because of the way the defaults play out.
94 changes: 94 additions & 0 deletions tests/py/test_participant_identities.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from __future__ import absolute_import, division, print_function, unicode_literals

from gratipay.testing import Harness
from gratipay.models.participant import Participant
from gratipay.models.participant.mixins import identity, Identity
from gratipay.models.participant.mixins.identity import _validate_info
from gratipay.models.participant.mixins.identity import ParticipantIdentityInfoInvalid
from gratipay.models.participant.mixins.identity import ParticipantIdentitySchemaUnknown
from postgres.orm import ReadOnly
from pytest import raises


Expand Down Expand Up @@ -256,3 +258,95 @@ def test_ci_still_logs_an_event_when_noop(self):
crusher = self.make_participant('crusher')
crusher.clear_identity(self.TTO)
self.assert_events(crusher.id, [None], [self.TTO], ['clear identity'])


# hvi - has_verified_identity

def test_hvi_defaults_to_false(self):
crusher = self.make_participant('crusher')
assert crusher.has_verified_identity is False

def test_hvi_is_read_only(self):
crusher = self.make_participant('crusher')
with raises(ReadOnly):
crusher.has_verified_identity = True

def test_hvi_becomes_true_when_an_identity_is_verified(self):
crusher = self.make_participant('crusher')
crusher.store_identity_info(self.TTO, 'nothing-enforced', {})
crusher.set_identity_verification(self.TTO, True)
assert Participant.from_username('crusher').has_verified_identity

def test_hvi_becomes_false_when_the_identity_is_unverified(self):
crusher = self.make_participant('crusher')
crusher.store_identity_info(self.TTO, 'nothing-enforced', {})
crusher.set_identity_verification(self.TTO, True)
crusher.set_identity_verification(self.TTO, False)
assert not Participant.from_username('crusher').has_verified_identity

def test_hvi_stays_true_when_a_secondary_identity_is_verified(self):
crusher = self.make_participant('crusher')
crusher.store_identity_info(self.USA, 'nothing-enforced', {})
crusher.set_identity_verification(self.USA, True)
crusher.store_identity_info(self.TTO, 'nothing-enforced', {})
crusher.set_identity_verification(self.TTO, True)
assert Participant.from_username('crusher').has_verified_identity

def test_hvi_stays_true_when_the_secondary_identity_is_unverified(self):
crusher = self.make_participant('crusher')
crusher.store_identity_info(self.USA, 'nothing-enforced', {})
crusher.set_identity_verification(self.USA, True)
crusher.store_identity_info(self.TTO, 'nothing-enforced', {})
crusher.set_identity_verification(self.TTO, True)
crusher.set_identity_verification(self.TTO, False)
assert Participant.from_username('crusher').has_verified_identity

def test_hvi_goes_back_to_false_when_both_are_unverified(self):
crusher = self.make_participant('crusher')
crusher.store_identity_info(self.USA, 'nothing-enforced', {})
crusher.store_identity_info(self.TTO, 'nothing-enforced', {})
crusher.set_identity_verification(self.TTO, True)
crusher.set_identity_verification(self.USA, True)
crusher.set_identity_verification(self.TTO, False)
crusher.set_identity_verification(self.USA, False)
assert not Participant.from_username('crusher').has_verified_identity

def test_hvi_changes_are_scoped_to_a_participant(self):
crusher = self.make_participant('crusher')
crusher.store_identity_info(self.USA, 'nothing-enforced', {})

bruiser = self.make_participant('bruiser')
bruiser.store_identity_info(self.USA, 'nothing-enforced', {})

crusher.set_identity_verification(self.USA, True)

assert Participant.from_username('crusher').has_verified_identity
assert not Participant.from_username('bruiser').has_verified_identity

def test_hvi_resets_when_identity_is_cleared(self):
crusher = self.make_participant('crusher')
crusher.store_identity_info(self.TTO, 'nothing-enforced', {})
crusher.set_identity_verification(self.TTO, True)
crusher.clear_identity(self.TTO)
assert not Participant.from_username('crusher').has_verified_identity

def test_hvi_doesnt_reset_when_penultimate_identity_is_cleared(self):
crusher = self.make_participant('crusher')
crusher.store_identity_info(self.USA, 'nothing-enforced', {})
crusher.set_identity_verification(self.USA, True)
crusher.store_identity_info(self.TTO, 'nothing-enforced', {})
crusher.set_identity_verification(self.TTO, True)
crusher.set_identity_verification(self.TTO, False)
crusher.clear_identity(self.TTO)
assert Participant.from_username('crusher').has_verified_identity

def test_hvi_does_reset_when_both_identities_are_cleared(self):
crusher = self.make_participant('crusher')
crusher.store_identity_info(self.USA, 'nothing-enforced', {})
crusher.store_identity_info(self.TTO, 'nothing-enforced', {})
crusher.set_identity_verification(self.USA, True)
crusher.set_identity_verification(self.TTO, True)
crusher.set_identity_verification(self.TTO, False)
crusher.set_identity_verification(self.USA, False)
crusher.clear_identity(self.TTO)
assert not Participant.from_username('crusher').has_verified_identity

0 comments on commit 713fa95

Please sign in to comment.