Exemplo n.º 1
0
 def test_email_login_bad_email(self):
     data = {'log-in.id': '*****@*****.**'}
     r = self.client.POST('/sign-in', data, raise_immediately=False)
     assert r.code != 302
     assert SESSION not in r.headers.cookie
     Participant.dequeue_emails()
     assert not self.get_emails()
Exemplo n.º 2
0
 def test_emails_are_not_sent_went_database_is_read_only(self):
     larry = self.make_participant('larry')
     self.queue_email(larry, 'team_invite', team='team', team_url='fake_url', inviter='bob')
     with postgres_readonly(self.db):
         Participant.dequeue_emails()
         assert self.mailer.call_count == 0
         assert self.db.one("SELECT email_status FROM notifications") == 'queued'
Exemplo n.º 3
0
 def test_email_login_bad_email(self):
     data = {'log-in.id': '*****@*****.**'}
     r = self.client.POST('/sign-in', data, raise_immediately=False)
     assert r.code != 302
     assert SESSION not in r.headers.cookie
     Participant.dequeue_emails()
     assert not self.get_emails()
Exemplo n.º 4
0
    def test_dequeueing_an_email_without_address_just_skips_it(self):
        larry = self.make_participant('larry')
        self.queue_email(larry, 'team_invite', team='team', team_url='fake_url', inviter='bob')

        Participant.dequeue_emails()
        assert self.mailer.call_count == 0
        assert self.db.one("SELECT email_sent FROM notifications") is False
Exemplo n.º 5
0
 def test_participant_with_long_email_address_can_receive_messages(self):
     email = 'a' * 200 + '@example.org'
     fred = self.make_participant(None, email=email)
     fred.insert_identity({'name': "You don't need to know my legal name"})
     fred.notify('team_invite', team='team', team_url='fake_url', inviter='bob')
     Participant.dequeue_emails()
     assert self.db.one("SELECT email_status FROM notifications") == 'sent'
Exemplo n.º 6
0
 def test_sign_in(self):
     r = self.client.PxST('/sign-in', good_data)
     assert r.code == 302, r.text
     assert SESSION in r.headers.cookie
     Participant.dequeue_emails()
     assert self.get_last_email()
     p = Participant.from_username(good_data['sign-in.username'])
     assert p.avatar_url
Exemplo n.º 7
0
    def test_dequeueing_an_email_without_address_just_skips_it(self):
        larry = self.make_participant('larry')
        larry.queue_email("verification")

        assert self.db.one("SELECT spt_name FROM email_queue") == "verification"
        Participant.dequeue_emails()
        assert self.mailer.call_count == 0
        assert self.db.one("SELECT spt_name FROM email_queue") is None
Exemplo n.º 8
0
    def test_dequeueing_an_email_without_address_just_skips_it(self):
        larry = self.make_participant('larry')
        larry.queue_email("verification")

        assert self.db.one("SELECT spt_name FROM email_queue") == "verification"
        Participant.dequeue_emails()
        assert self.mailer.call_count == 0
        assert self.db.one("SELECT spt_name FROM email_queue") is None
Exemplo n.º 9
0
 def test_email_login_team_account(self):
     email = '*****@*****.**'
     self.make_participant('team', email=email, kind='group')
     data = {'log-in.id': email}
     r = self.client.POST('/log-in', data, raise_immediately=False)
     assert SESSION not in r.headers.cookie
     Participant.dequeue_emails()
     assert not self.get_emails()
Exemplo n.º 10
0
    def test_dequeueing_an_email_without_address_just_skips_it(self):
        larry = self.make_participant('larry')
        self.queue_email(larry, "verification")

        assert self.db.one("SELECT event FROM notifications") == "verification"
        Participant.dequeue_emails()
        assert self.mailer.call_count == 0
        assert self.db.one("SELECT event FROM notifications") is None
Exemplo n.º 11
0
 def test_sign_in(self):
     r = self.client.PxST('/sign-in', good_data)
     assert r.code == 302, r.text
     assert SESSION in r.headers.cookie
     Participant.dequeue_emails()
     assert self.get_last_email()
     p = Participant.from_username(good_data['sign-in.username'])
     assert p.avatar_url
Exemplo n.º 12
0
 def test_email_login_team_account(self):
     email = '*****@*****.**'
     self.make_participant('team', email=email, kind='group')
     data = {'log-in.id': email}
     r = self.client.POST('/log-in', data, raise_immediately=False)
     assert SESSION not in r.headers.cookie
     Participant.dequeue_emails()
     assert not self.get_emails()
Exemplo n.º 13
0
    def test_can_dequeue_an_email(self):
        larry = self.make_participant('larry', email='*****@*****.**')
        self.queue_email(larry, 'team_invite', team='team', team_url='fake_url', inviter='bob')

        Participant.dequeue_emails()
        assert self.mailer.call_count == 1
        last_email = self.get_last_email()
        assert last_email['to'][0] == 'larry <*****@*****.**>'
        assert self.db.one("SELECT email_sent FROM notifications") is True
Exemplo n.º 14
0
 def test_participant_with_long_nonascii_name_can_receive_emails(self):
     fred = self.make_participant(None, email='*****@*****.**')
     fred.insert_identity(
         {'name': "Frédéric d'Arundel d'Esquincourt de Condé"})
     fred.notify('team_invite',
                 team='team',
                 team_url='fake_url',
                 inviter='bob')
     Participant.dequeue_emails()
     assert self.db.one("SELECT email_status FROM notifications") == 'sent'
Exemplo n.º 15
0
    def test_can_dequeue_an_email(self):
        larry = self.make_participant('larry', email='*****@*****.**')
        larry.queue_email("verification", link='https://example.com/larry')

        assert self.db.one("SELECT spt_name FROM email_queue") == "verification"
        Participant.dequeue_emails()
        assert self.mailer.call_count == 1
        last_email = self.get_last_email()
        assert last_email['to'][0] == 'larry <*****@*****.**>'
        expected = "connect larry"
        assert expected in last_email['text']
        assert self.db.one("SELECT spt_name FROM email_queue") is None
Exemplo n.º 16
0
    def test_can_dequeue_an_email(self):
        larry = self.make_participant('larry', email='*****@*****.**')
        larry.queue_email("verification", link='https://example.com/larry')

        assert self.db.one("SELECT spt_name FROM email_queue") == "verification"
        Participant.dequeue_emails()
        assert self.mailer.call_count == 1
        last_email = self.get_last_email()
        assert last_email['to'][0] == 'larry <*****@*****.**>'
        expected = "connect larry"
        assert expected in last_email['text']
        assert self.db.one("SELECT spt_name FROM email_queue") is None
Exemplo n.º 17
0
 def test_sign_in(self):
     r = self.sign_in(HTTP_ACCEPT_LANGUAGE='fr')
     assert r.code == 302, r.text
     assert SESSION in r.headers.cookie
     # Check that an email was sent, in the user's preferred language
     Participant.dequeue_emails()
     last_email = self.get_last_email()
     username = good_data['sign-in.username']
     expected_subject = 'Lier à %s sur Liberapay ?' % username
     assert last_email['subject'] == expected_subject
     # Check that the new user has an avatar
     p = Participant.from_username(username)
     assert p.avatar_url
Exemplo n.º 18
0
    def test_can_dequeue_an_email(self):
        larry = self.make_participant('larry', email='*****@*****.**')
        larry.queue_email("verification", link='https://example.com/larry')

        assert self.db.one(
            "SELECT spt_name FROM email_queue") == "verification"
        Participant.dequeue_emails()
        assert self.mailer.call_count == 1
        last_email = self.get_last_email()
        assert last_email['to'][0] == 'larry <*****@*****.**>'
        assert last_email[
            'subject'] == "Email address verification - Liberapay"
        assert self.db.one("SELECT spt_name FROM email_queue") is None
Exemplo n.º 19
0
 def test_sign_in(self):
     fake_msg = Message('Email address verification - Liberapay', 'Vous avez du pain ?')
     LOCALES['fr'].catalog[fake_msg.id].string = fake_msg.string
     r = self.sign_in(HTTP_ACCEPT_LANGUAGE='fr')
     assert r.code == 302, r.text
     assert SESSION in r.headers.cookie
     # Check that an email was sent, in the user's preferred language
     Participant.dequeue_emails()
     last_email = self.get_last_email()
     username = good_data['sign-in.username']
     assert last_email['subject'] == fake_msg.string
     # Check that the new user has an avatar
     p = Participant.from_username(username)
     assert p.avatar_url
Exemplo n.º 20
0
 def test_sign_in(self):
     fake_msg = Message('Email address verification - Liberapay', 'Vous avez du pain ?')
     LOCALES['fr'].catalog[fake_msg.id].string = fake_msg.string
     r = self.sign_in(HTTP_ACCEPT_LANGUAGE='fr')
     assert r.code == 302, r.text
     assert SESSION in r.headers.cookie
     # Check that an email was sent, in the user's preferred language
     Participant.dequeue_emails()
     last_email = self.get_last_email()
     username = good_data['sign-in.username']
     assert last_email['subject'] == fake_msg.string
     # Check that the new user has an avatar
     p = Participant.from_username(username)
     assert p.avatar_url
Exemplo n.º 21
0
    def test_take_over_sends_notifications_to_patrons(self):
        dan_twitter = self.make_elsewhere('twitter', 1, 'dan')

        self.alice.set_tip_to(self.dan, '100') # Alice shouldn't receive an email.
        self.bob.set_tip_to(dan_twitter, '100') # Bob should receive an email.

        self.dan.take_over(dan_twitter, have_confirmation=True)

        Participant.dequeue_emails()
        assert self.mailer.call_count == 1
        last_email = self.get_last_email()
        assert last_email['to'][0] == 'bob <*****@*****.**>'
        assert "to dan" in last_email['text']
        assert "Change your email settings" in last_email['text']
Exemplo n.º 22
0
    def test_email_login(self):
        email = '*****@*****.**'
        alice = self.make_participant('alice')
        alice.add_email(email)
        alice.close(None)

        data = {'log-in.id': email.upper()}
        r = self.client.POST('/', data, raise_immediately=False)
        session = self.db.one(
            "SELECT * FROM user_secrets WHERE participant = %s", (alice.id, ))
        assert session.secret not in r.headers.raw.decode('ascii')
        assert session.secret not in r.body.decode('utf8')

        Participant.dequeue_emails()
        last_email = self.get_last_email()
        assert last_email and last_email['subject'] == 'Log in to Liberapay'
        qs = 'log-in.id=%i&log-in.key=%i&log-in.token=%s' % (
            alice.id, session.id, session.secret)
        assert qs in last_email['text']

        r = self.client.GxT('/alice/?foo=bar&' + qs)
        assert r.code == 302
        assert r.headers[b'Location'] == b'http://localhost/alice/?foo=bar'
        # ↑ checks that original path and query are preserved

        old_secret = self.db.one(
            """
            SELECT secret
              FROM user_secrets
             WHERE participant = %s
               AND id = %s
               AND secret = %s
        """, (alice.id, session.id, session.secret))
        assert old_secret is None
        # ↑ this means that the link is only valid once

        # Check that we can change our password
        password = '******'
        r = self.client.POST(
            '/alice/settings/edit',
            {'new-password': password},
            cookies=r.headers.cookie,
            raise_immediately=False,
        )
        assert r.code == 302
        alice2 = Participant.authenticate(alice.id, 0, password)
        assert alice2 and alice2 == alice
Exemplo n.º 23
0
    def test_email_login(self):
        email = '*****@*****.**'
        alice = self.make_participant('alice')
        alice.add_email(email)
        alice.close(None)

        data = {'log-in.id': email.upper()}
        r = self.client.POST('/', data, raise_immediately=False)
        session = self.db.one("SELECT * FROM user_secrets WHERE participant = %s", (alice.id,))
        assert session.secret not in r.headers.raw.decode('ascii')
        assert session.secret not in r.body.decode('utf8')

        Participant.dequeue_emails()
        last_email = self.get_last_email()
        assert last_email and last_email['subject'] == 'Log in to Liberapay'
        qs = 'log-in.id=%i&log-in.key=%i&log-in.token=%s' % (
            alice.id, session.id, session.secret
        )
        assert qs in last_email['text']

        r = self.client.GxT('/alice/?foo=bar&' + qs)
        assert r.code == 302
        assert r.headers[b'Location'] == b'http://localhost/alice/?foo=bar'
        # ↑ checks that original path and query are preserved

        old_secret = self.db.one("""
            SELECT secret
              FROM user_secrets
             WHERE participant = %s
               AND id = %s
               AND secret = %s
        """, (alice.id, session.id, session.secret))
        assert old_secret is None
        # ↑ this means that the link is only valid once

        # Check that we can change our password
        password = '******'
        r = self.client.POST(
            '/alice/settings/edit',
            {'new-password': password},
            cookies=r.headers.cookie,
            raise_immediately=False,
        )
        assert r.code == 302
        alice2 = Participant.authenticate(alice.id, 0, password)
        assert alice2 and alice2 == alice
Exemplo n.º 24
0
    def test_patrons_are_notified_after_pledgee_joins(self):
        self.bob = self.make_participant('bob', email='*****@*****.**')
        self.dan = self.make_participant('dan', email='*****@*****.**')
        self.alice = self.make_participant('alice', email='*****@*****.**')

        dan_twitter = self.make_elsewhere('twitter', 1, 'dan')

        self.alice.set_tip_to(self.dan, EUR('100'))  # Alice shouldn't receive an email.
        self.bob.set_tip_to(dan_twitter, EUR('100'))  # Bob should receive an email.

        self.dan.take_over(dan_twitter, have_confirmation=True)

        # dan hasn't connected any payment account yet, so there shouldn't be a notification
        Participant.notify_patrons()
        Participant.dequeue_emails()
        assert self.mailer.call_count == 0

        # add a payment account and check again
        self.add_payment_account(self.dan, 'stripe')
        Participant.notify_patrons()
        Participant.dequeue_emails()
        assert self.mailer.call_count == 1
        last_email = self.get_last_email()
        assert last_email['to'][0] == 'bob <*****@*****.**>'
        assert "to dan" in last_email['text']
        assert "Change your email settings" in last_email['text']

        # check that the notification isn't sent again
        self.mailer.reset_mock()
        Participant.notify_patrons()
        Participant.dequeue_emails()
        assert self.mailer.call_count == 0
Exemplo n.º 25
0
    def test_patrons_are_notified_after_pledgee_joins(self):
        self.bob = self.make_participant('bob', email='*****@*****.**')
        self.dan = self.make_participant('dan', email='*****@*****.**')
        self.alice = self.make_participant('alice', email='*****@*****.**')

        dan_twitter = self.make_elsewhere('twitter', 1, 'dan')

        self.alice.set_tip_to(self.dan,
                              EUR('100'))  # Alice shouldn't receive an email.
        self.bob.set_tip_to(dan_twitter,
                            EUR('100'))  # Bob should receive an email.

        self.dan.take_over(dan_twitter, have_confirmation=True)

        # dan hasn't connected any payment account yet, so there shouldn't be a notification
        Participant.notify_patrons()
        Participant.dequeue_emails()
        assert self.mailer.call_count == 0

        # add a payment account and check again
        self.add_payment_account(self.dan, 'stripe')
        Participant.notify_patrons()
        Participant.dequeue_emails()
        assert self.mailer.call_count == 1
        last_email = self.get_last_email()
        assert last_email['to'][0] == 'bob <*****@*****.**>'
        assert "to dan" in last_email['text']
        assert "Change your email settings" in last_email['text']

        # check that the notification isn't sent again
        self.mailer.reset_mock()
        Participant.notify_patrons()
        Participant.dequeue_emails()
        assert self.mailer.call_count == 0
Exemplo n.º 26
0
    def test_email_login(self):
        email = '*****@*****.**'
        alice = self.make_participant('alice')
        alice.add_email(email)
        alice.close(None)

        data = {'log-in.id': email.upper()}
        r = self.client.POST('/', data, raise_immediately=False)
        alice = alice.refetch()
        assert alice.session_token not in r.headers.raw.decode('ascii')
        assert alice.session_token not in r.body.decode('utf8')

        Participant.dequeue_emails()
        last_email = self.get_last_email()
        assert last_email and last_email['subject'] == 'Log in to Liberapay'
        assert 'log-in.token='+alice.session_token in last_email['text']

        url = '/alice/?foo=bar&log-in.id=%s&log-in.token=%s'
        r = self.client.GxT(url % (alice.id, alice.session_token))
        alice2 = alice.refetch()
        assert alice2.session_token != alice.session_token
        # ↑ this means that the link is only valid once
        assert r.code == 302
        assert r.headers[b'Location'] == b'http://localhost/alice/?foo=bar'
        # ↑ checks that original path and query are preserved

        # Check that we can change our password
        password = '******'
        r = self.client.POST(
            '/alice/settings/edit',
            {'new-password': password},
            cookies=r.headers.cookie,
            raise_immediately=False,
        )
        assert r.code == 302
        alice2 = Participant.authenticate('id', 'password', alice.id, password)
        assert alice2 and alice2 == alice
Exemplo n.º 27
0
    def test_email_login_with_old_unverified_address(self):
        email = '*****@*****.**'
        alice = self.make_participant('alice', email=None)
        alice.add_email(email)
        Participant.dequeue_emails()
        self.db.run("UPDATE emails SET nonce = null")

        # Initiate email log-in
        data = {'log-in.id': email.upper()}
        r = self.client.POST('/', data, raise_immediately=False)
        session = self.db.one(
            "SELECT * FROM user_secrets WHERE participant = %s", (alice.id, ))
        assert session.secret not in r.headers.raw.decode('ascii')
        assert session.secret not in r.body.decode('utf8')

        # Check the email message
        Participant.dequeue_emails()
        last_email = self.get_last_email()
        assert last_email and last_email['subject'] == 'Log in to Liberapay'
        email_row = alice.get_email(email)
        assert email_row.verified is None
        assert email_row.nonce
        qs = 'log-in.id=%i&log-in.key=%i&log-in.token=%s&email.id=%s&email.nonce=%s' % (
            alice.id, session.id, session.secret, email_row.id,
            email_row.nonce)
        assert qs in last_email['text']

        # Log in
        r = self.client.GxT('/alice/?' + qs)
        assert r.code == 302
        assert r.headers[b'Location'].startswith(b'http://localhost/alice/')

        # Check that the email address is now verified
        email_row = alice.get_email(email)
        assert email_row.verified
        alice = alice.refetch()
        assert alice.email == email
Exemplo n.º 28
0
    def test_email_login(self):
        email = '*****@*****.**'
        alice = self.make_participant('alice')
        alice.add_email(email)
        alice.close(None)

        data = {'log-in.id': email.upper()}
        r = self.client.POST('/', data, raise_immediately=False)
        alice = alice.refetch()
        assert alice.session_token not in r.headers.raw.decode('ascii')
        assert alice.session_token not in r.body.decode('utf8')

        Participant.dequeue_emails()
        last_email = self.get_last_email()
        assert last_email and last_email['subject'] == 'Log in to Liberapay'
        assert 'log-in.token=' + alice.session_token in last_email['text']

        url = '/alice/?foo=bar&log-in.id=%s&log-in.token=%s'
        r = self.client.GxT(url % (alice.id, alice.session_token))
        alice2 = alice.refetch()
        assert alice2.session_token != alice.session_token
        # ↑ this means that the link is only valid once
        assert r.code == 302
        assert r.headers[b'Location'] == b'http://localhost/alice/?foo=bar'
        # ↑ checks that original path and query are preserved

        # Check that we can change our password
        password = '******'
        r = self.client.POST(
            '/alice/settings/edit',
            {'new-password': password},
            cookies=r.headers.cookie,
            raise_immediately=False,
        )
        assert r.code == 302
        alice2 = Participant.authenticate('id', 'password', alice.id, password)
        assert alice2 and alice2 == alice
Exemplo n.º 29
0
    def test_patrons_are_charged_after_pledgee_joins(self):
        bob = self.make_participant('bob', email='*****@*****.**')
        dan = self.make_participant('dan', email='*****@*****.**')
        alice = self.make_participant('alice', email='*****@*****.**')
        dan_twitter = self.make_elsewhere('twitter', 1, 'dan')
        alice.set_tip_to(dan, EUR('100'), renewal_mode=2)
        bob.set_tip_to(dan_twitter, EUR('100'), renewal_mode=2)
        dan.take_over(dan_twitter, have_confirmation=True)

        # dan hasn't connected any payment account yet, so nothing should happen
        Participant.notify_patrons()
        Participant.dequeue_emails()
        assert self.mailer.call_count == 0

        # add a payment account and check again, but it's still too early
        self.add_payment_account(dan, 'stripe')
        Participant.notify_patrons()
        Participant.dequeue_emails()
        assert self.mailer.call_count == 0

        # simulate skipping one day ahead, now there should be a notification
        # and a scheduled payin
        self.db.run("UPDATE events SET ts = ts - interval '24 hours'")
        Participant.notify_patrons()
        Participant.dequeue_emails()
        assert self.mailer.call_count == 1
        last_email = self.get_last_email()
        assert last_email['to'][0] == 'bob <*****@*****.**>'
        assert last_email[
            'subject'] == "dan from Twitter has joined Liberapay!"
        scheduled_payins = self.db.all(
            "SELECT * FROM scheduled_payins WHERE payer = %s", (bob.id, ))
        assert len(scheduled_payins) == 1
        assert scheduled_payins[0].amount == EUR('400.00')
        assert scheduled_payins[0].automatic is True

        # check that the notification isn't sent again
        self.mailer.reset_mock()
        Participant.notify_patrons()
        Participant.dequeue_emails()
        assert self.mailer.call_count == 0
Exemplo n.º 30
0
 def test_sign_in(self):
     r = self.client.PxST('/sign-in', good_data)
     assert r.code == 302, r.text
     assert SESSION in r.headers.cookie
     Participant.dequeue_emails()
     assert self.get_last_email()
Exemplo n.º 31
0
 def test_sign_in(self):
     r = self.client.PxST('/sign-in', good_data)
     assert r.code == 302, r.text
     assert SESSION in r.headers.cookie
     Participant.dequeue_emails()
     assert self.get_last_email()
Exemplo n.º 32
0
    def test_email_login(self):
        email = '*****@*****.**'
        alice = self.make_participant('alice')
        alice.add_email(email)
        alice.close(None)

        # Sanity checks
        email_row = alice.get_email(email)
        assert email_row.verified is None
        assert alice.email is None

        # Initiate email log-in
        data = {'log-in.id': email.upper()}
        r = self.client.POST('/', data, raise_immediately=False)
        session = self.db.one(
            "SELECT * FROM user_secrets WHERE participant = %s", (alice.id, ))
        assert session.secret not in r.headers.raw.decode('ascii')
        assert session.secret not in r.body.decode('utf8')

        # Check the email message
        Participant.dequeue_emails()
        last_email = self.get_last_email()
        assert last_email and last_email['subject'] == 'Log in to Liberapay'
        qs = 'log-in.id=%i&log-in.key=%i&log-in.token=%s&email.id=%s&email.nonce=%s' % (
            alice.id, session.id, session.secret, email_row.id,
            email_row.nonce)
        assert qs in last_email['text']

        # Log in
        r = self.client.GxT('/alice/?foo=bar&' + qs)
        assert r.code == 302
        assert r.headers[b'Location'] == b'http://localhost/alice/?foo=bar'
        # ↑ checks that original path and query are preserved

        old_secret = self.db.one(
            """
            SELECT secret
              FROM user_secrets
             WHERE participant = %s
               AND id = %s
               AND secret = %s
        """, (alice.id, session.id, session.secret))
        assert old_secret is None
        # ↑ this means that the link is only valid once

        # Check that the email address is now verified
        email_row = alice.get_email(email)
        assert email_row.verified
        alice = alice.refetch()
        assert alice.email == email

        # Check what happens if the user clicks the login link a second time
        cookies = r.headers.cookie
        r = self.client.GxT('/alice/?foo=bar&' + qs, cookies=cookies)
        assert r.code == 400
        assert " already logged in," in r.text, r.text

        # Check that we can change our password
        password = '******'
        r = self.client.POST(
            '/alice/settings/edit',
            {'new-password': password},
            cookies=cookies,
            raise_immediately=False,
        )
        assert r.code == 302
        alice2 = Participant.authenticate(alice.id, 0, password)
        assert alice2 and alice2 == alice
Exemplo n.º 33
0
 def get_emails(self):
     Participant.dequeue_emails()
     return [a[1] for a in self.mailer.call_args_list]
Exemplo n.º 34
0
 def get_emails(self):
     Participant.dequeue_emails()
     return [a[1] for a in self.mailer.call_args_list]
Exemplo n.º 35
0
 def get_emails(self):
     Participant.dequeue_emails()
     emails = [a[1] for a in self.mailer.call_args_list]
     self.mailer.reset_mock()
     return emails
Exemplo n.º 36
0
 def get_emails(self):
     Participant.dequeue_emails()
     emails = [a[1] for a in self.mailer.call_args_list]
     self.mailer.reset_mock()
     return emails
Exemplo n.º 37
0
    def test_email_login(self):
        email = '*****@*****.**'
        alice = self.make_participant('alice', email=None)
        alice.add_email(email)
        alice.close(None)

        # Sanity checks
        email_row = alice.get_email(email)
        assert email_row.verified is None
        assert alice.email is None

        # Initiate email log-in
        data = {'log-in.id': email.upper()}
        r = self.client.POST('/', data, raise_immediately=False)
        session = self.db.one(
            "SELECT * FROM user_secrets WHERE participant = %s", (alice.id, ))
        assert session.secret not in r.headers.raw.decode('ascii')
        assert session.secret not in r.body.decode('utf8')

        # Check the email message
        Participant.dequeue_emails()
        last_email = self.get_last_email()
        assert last_email and last_email['subject'] == 'Log in to Liberapay'
        qs = 'log-in.id=%i&log-in.key=%i&log-in.token=%s&email.id=%s&email.nonce=%s' % (
            alice.id, session.id, session.secret, email_row.id,
            email_row.nonce)
        assert qs in last_email['text']

        # Attempt to use the URL in a new browser session (no anti-CSRF cookie yet)
        r = self.client.GxT('/alice/?foo=bar&' + qs, csrf_token=None)
        assert r.code == 200
        refresh_qs = '?foo=bar&' + qs + '&cookie_sent=true'
        assert r.headers[b'Refresh'] == b"0;url=" + refresh_qs.encode()
        assert CSRF_TOKEN in r.headers.cookie

        # Follow the redirect, still without cookies
        r = self.client.GxT('/alice/' + refresh_qs, csrf_token=None)
        assert r.code == 403, r.text
        assert "Please make sure your browser is configured to allow cookies" in r.text

        # Log in
        csrf_token = '_ThisIsAThirtyTwoBytesLongToken_'
        confirmation_token = b64encode_s(
            blake2b(
                session.secret.encode(),
                key=csrf_token.encode(),
                digest_size=48,
            ).digest())
        r = self.client.GxT('/alice/' + refresh_qs, csrf_token=csrf_token)
        assert r.code == 200
        assert SESSION not in r.headers.cookie
        assert confirmation_token in r.text
        r = self.client.GxT(
            '/alice/' + refresh_qs + '&log-in.confirmation=' +
            confirmation_token,
            csrf_token=csrf_token,
        )
        assert r.code == 302
        assert SESSION in r.headers.cookie
        assert r.headers[b'Location'].startswith(
            b'http://localhost/alice/?foo=bar&success=')
        # ↑ checks that original path and query are preserved

        old_secret = self.db.one(
            """
            SELECT secret
              FROM user_secrets
             WHERE participant = %s
               AND id = %s
               AND secret = %s
        """, (alice.id, session.id, session.secret))
        assert old_secret is None
        # ↑ this means that the link is only valid once

        # Check that the email address is now verified
        email_row = alice.get_email(email)
        assert email_row.verified
        alice = alice.refetch()
        assert alice.email == email

        # Check what happens if the user clicks the login link a second time
        cookies = r.headers.cookie
        r = self.client.GxT('/alice/?foo=bar&' + qs, cookies=cookies)
        assert r.code == 400
        assert " already logged in," in r.text, r.text

        # Check that we can change our password
        password = '******'
        r = self.client.POST(
            '/alice/settings/edit',
            {'new-password': password},
            cookies=cookies,
            raise_immediately=False,
        )
        assert r.code == 302
        alice2 = Participant.authenticate(alice.id, 0, password)
        assert alice2 and alice2 == alice
Exemplo n.º 38
0
    def test_email_login_with_old_unverified_address(self):
        email = '*****@*****.**'
        alice = self.make_participant('alice', email=None)
        alice.add_email(email)
        Participant.dequeue_emails()
        self.db.run("UPDATE emails SET nonce = null")

        # Initiate email log-in
        data = {'log-in.id': email.upper()}
        r = self.client.POST('/', data, raise_immediately=False)
        session = self.db.one(
            "SELECT * FROM user_secrets WHERE participant = %s", (alice.id, ))
        assert session.secret not in r.headers.raw.decode('ascii')
        assert session.secret not in r.body.decode('utf8')

        # Check the email message
        Participant.dequeue_emails()
        last_email = self.get_last_email()
        assert last_email and last_email['subject'] == 'Log in to Liberapay'
        email_row = alice.get_email(email)
        assert email_row.verified is None
        assert email_row.nonce
        qs = 'log-in.id=%i&log-in.key=%i&log-in.token=%s&email.id=%s&email.nonce=%s' % (
            alice.id, session.id, session.secret, email_row.id,
            email_row.nonce)
        assert qs in last_email['text']

        # Try to log in without a confirmation code
        csrf_token = '_ThisIsAThirtyTwoBytesLongToken_'
        confirmation_token = b64encode_s(
            blake2b(
                session.secret.encode(),
                key=csrf_token.encode(),
                digest_size=48,
            ).digest())
        r = self.client.GxT('/alice/?' + qs, csrf_token=csrf_token)
        assert r.code == 200
        assert SESSION not in r.headers.cookie
        assert confirmation_token in r.text

        # Try to log in with an incorrect confirmation code
        r = self.client.GxT(
            '/alice/?' + qs + '&log-in.confirmation=' + ('~' * 64),
            csrf_token=csrf_token,
        )
        assert r.code == 400
        assert SESSION not in r.headers.cookie
        assert confirmation_token not in r.text

        # Log in with the correct confirmation code
        r = self.client.GxT(
            '/alice/?' + qs + '&log-in.confirmation=' + confirmation_token,
            csrf_token=csrf_token,
        )
        assert r.code == 302
        assert SESSION in r.headers.cookie
        assert r.headers[b'Location'].startswith(b'http://localhost/alice/')

        # Check that the email address is now verified
        email_row = alice.get_email(email)
        assert email_row.verified
        alice = alice.refetch()
        assert alice.email == email