Exemple #1
0
def test_email_address_get(clean_db):
    """Email addresses can be loaded using EmailAddress.get"""
    db = clean_db
    ea1 = EmailAddress('*****@*****.**')
    ea2 = EmailAddress('*****@*****.**')
    ea3 = EmailAddress('*****@*****.**')
    db.session.add_all([ea1, ea2, ea3])
    db.session.commit()

    get1 = EmailAddress.get('*****@*****.**')
    assert get1 == ea1
    get2 = EmailAddress.get('*****@*****.**')
    assert get2 == ea2
    # Can also get by hash
    get3 = EmailAddress.get(blake2b160=hash_map['*****@*****.**'])
    assert get3 == ea1
    # Or by Base58 representation of hash
    get4 = EmailAddress.get(email_hash='2EGz72jxcsYjvXxF7r5rqfAgikor')
    assert get4 == ea1

    # Will return nothing if given garbage input, or a non-existent email address
    assert EmailAddress.get('invalid') is None
    assert EmailAddress.get('*****@*****.**') is None
Exemple #2
0
def test_email_address_mixin(email_models, clean_mixin_db):
    """The EmailAddressMixin class adds safety checks for using an email address"""
    db = clean_mixin_db
    models = email_models

    blocked_email = EmailAddress('*****@*****.**')

    user1 = models.EmailUser()
    user2 = models.EmailUser()

    doc1 = models.EmailDocument()
    doc2 = models.EmailDocument()

    db.session.add_all([user1, user2, doc1, doc2, blocked_email])

    EmailAddress.mark_blocked('*****@*****.**')

    # Mixin-based classes can simply specify an email parameter to link to an
    # EmailAddress instance
    link1 = models.EmailLink(emailuser=user1, email='*****@*****.**')
    db.session.add(link1)
    ea1 = EmailAddress.get('*****@*****.**')
    assert link1.email == '*****@*****.**'
    assert link1.email_address == ea1
    assert link1.transport_hash == ea1.transport_hash
    assert bool(link1.transport_hash)

    # Link an unrelated email address to another user to demonstrate that it works
    link2 = models.EmailLink(emailuser=user2, email='*****@*****.**')
    db.session.add(link2)
    ea2 = EmailAddress.get('*****@*****.**')
    assert link2.email == '*****@*****.**'
    assert link2.email_address == ea2
    assert link2.transport_hash == ea2.transport_hash
    assert bool(link1.transport_hash)

    db.session.commit()

    # '*****@*****.**' is now exclusive to user2. Attempting it to assign it to
    # user1 will raise an exception, even if the case is changed.
    with pytest.raises(EmailAddressInUseError):
        models.EmailLink(emailuser=user1, email='*****@*****.**')

    # This safety catch works even if the email_address column is used:
    with pytest.raises(EmailAddressInUseError):
        models.EmailLink(emailuser=user1, email_address=ea2)

    db.session.rollback()

    # Blocked addresses cannot be used either
    with pytest.raises(EmailAddressBlockedError):
        models.EmailLink(emailuser=user1, email='*****@*****.**')

    with pytest.raises(EmailAddressBlockedError):
        models.EmailLink(emailuser=user1, email_address=blocked_email)

    db.session.rollback()

    # Attempting to assign '*****@*****.**' to user2 a second time will cause a
    # SQL integrity error because EmailLink.__email_unique__ is True.
    link3 = models.EmailLink(emailuser=user2, email='*****@*****.**')
    db.session.add(link3)
    with pytest.raises(IntegrityError):
        db.session.flush()

    del link3
    db.session.rollback()

    # The EmailDocument model, in contrast, has no requirement of availability to a
    # specific user, so it won't be blocked here despite being exclusive to user1
    assert doc1.email is None
    assert doc2.email is None
    assert doc1.email_address is None
    assert doc2.email_address is None

    doc1.email = '*****@*****.**'
    doc2.email = '*****@*****.**'

    assert doc1.email == '*****@*****.**'
    assert doc2.email == '*****@*****.**'
    assert doc1.email_address == ea1
    assert doc2.email_address == ea1

    # ea1 now has three references, while ea2 has 1
    assert ea1.refcount() == 3
    assert ea2.refcount() == 1

    # Setting the email property on EmailDocument will mutate
    # EmailDocument.email_address and not EmailDocument.email_address.email
    assert ea1.email == '*****@*****.**'
    doc1.email = None
    assert ea1.email == '*****@*****.**'
    assert doc1.email_address is None
    doc2.email = '*****@*****.**'
    assert ea1.email == '*****@*****.**'
    assert doc2.email_address == ea2

    # EmailLinkedDocument takes the complexity up a notch

    # A document linked to a user can use any email linked to that user
    ldoc1 = models.EmailLinkedDocument(emailuser=user1,
                                       email='*****@*****.**')
    db.session.add(ldoc1)
    assert ldoc1.emailuser == user1
    assert ldoc1.email_address == ea1

    # But another user can't use this email address
    with pytest.raises(EmailAddressInUseError):
        models.EmailLinkedDocument(emailuser=user2,
                                   email='*****@*****.**')

    # This restriction also applies when user is not specified. Here, this email is
    # claimed by user2 above
    with pytest.raises(EmailAddressInUseError):
        models.EmailLinkedDocument(emailuser=None, email='*****@*****.**')

    # But it works with an unaffiliated email address
    ldoc2 = models.EmailLinkedDocument(email='*****@*****.**')
    db.session.add(ldoc2)
    assert ldoc2.emailuser is None
    assert ldoc2.email == '*****@*****.**'

    ldoc3 = models.EmailLinkedDocument(emailuser=user2,
                                       email='*****@*****.**')
    db.session.add(ldoc3)
    assert ldoc3.emailuser is user2
    assert ldoc3.email == '*****@*****.**'

    # Setting the email to None on the document removes the link to the EmailAddress,
    # but does not blank out the EmailAddress

    assert ldoc1.email_address == ea1
    assert ea1.email == '*****@*****.**'
    ldoc1.email = None
    assert ldoc1.email_address is None
    assert ea1.email == '*****@*****.**'