예제 #1
0
 def test_email_address_is_encoded_in_sent_verification_link(self):
     address = '*****@*****.**'
     encoded = encode_for_querystring(address)
     self.hit_email_spt('add-email', address)
     last_email = self.get_last_email()
     assert "~alice/emails/verify.html?email2=" + encoded in last_email[
         'body_text']
예제 #2
0
    def get_email_verification_link(self, c, email, *packages):
        """Get a link to complete an email verification workflow.

        :param Cursor c: the cursor to use
        :param unicode email: the email address to be verified

        :param packages: :py:class:`~gratipay.models.package.Package` objects
            for which a successful verification will also entail verification of
            ownership of the package

        :returns: a URL by which to complete the verification process

        """
        self.app.add_event( c
                          , 'participant'
                          , dict(id=self.id, action='add', values=dict(email=email))
                           )
        nonce = self.get_email_verification_nonce(c, email)
        if packages:
            self.start_package_claims(c, nonce, *packages)
        link = "{base_url}/~{username}/emails/verify.html?email={encoded_email}&nonce={nonce}"
        return link.format( base_url=gratipay.base_url
                          , username=self.username_lower
                          , encoded_email=encode_for_querystring(email)
                          , nonce=nonce
                           )
예제 #3
0
 def hit_verify_spt(self,
                    email,
                    nonce,
                    username='******',
                    should_fail=False):
     # Email address is encoded in url.
     url = '/~%s/emails/verify.html?email2=%s&nonce=%s'
     url %= (username, encode_for_querystring(email), nonce)
     f = self.client.GxT if should_fail else self.client.GET
     return f(url, auth_as=username)
 def test_email_verification_is_backwards_compatible(self):
     """Test email verification still works with 'email2' field in verification link.
     """
     username = '******'
     email = '*****@*****.**'
     self.hit_email_spt('add-email', email)
     nonce = self.alice.get_email(email).nonce
     url = '/~%s/emails/verify.html?email2=%s&nonce=%s'
     url %= (username, encode_for_querystring(email), nonce)
     self.client.GET(url, auth_as=username)
     expected = email
     actual = P(username).email_address
     assert expected == actual
예제 #5
0
    def get_email_verification_link(self, c, email, *packages):
        """Get a link to complete an email verification workflow.

        :param Cursor c: the cursor to use
        :param unicode email: the email address to be verified

        :param packages: :py:class:`~gratipay.models.package.Package` objects
            for which a successful verification will also entail verification of
            ownership of the package

        :returns: a URL by which to complete the verification process

        """
        self.app.add_event(
            c, 'participant',
            dict(id=self.id, action='add', values=dict(email=email)))
        nonce = self.get_email_verification_nonce(c, email)
        if packages:
            self.start_package_claims(c, nonce, *packages)
        link = "{base_url}/~{username}/emails/verify.html?email2={encoded_email}&nonce={nonce}"
        return link.format(base_url=gratipay.base_url,
                           username=self.username_lower,
                           encoded_email=encode_for_querystring(email),
                           nonce=nonce)
예제 #6
0
 def test_email_address_is_encoded_in_sent_verification_link(self):
     address = '*****@*****.**'
     encoded = encode_for_querystring(address)
     self.hit_email_spt('add-email', address)
     last_email = self.get_last_email()
     assert "~alice/emails/verify.html?email2="+encoded in last_email['body_text']
예제 #7
0
 def verify_email(self, email, nonce, username='******', should_fail=False):
     # Email address is encoded in url.
     url = '/~%s/emails/verify.html?email2=%s&nonce=%s'
     url %= (username, encode_for_querystring(email), nonce)
     f = self.client.GxT if should_fail else self.client.GET
     return f(url, auth_as=username)
예제 #8
0
 def test_efq_doesnt_accept_bytes(self):
     with self.assertRaises(TypeError):
         encode_for_querystring(b'TheEnterprise')
예제 #9
0
 def test_efq_replaces_equals_with_tilde(self):
     assert encode_for_querystring('TheEnterprise') == 'VGhlRW50ZXJwcmlzZQ~~'
예제 #10
0
 def test_efq_replaces_slash_with_underscore(self):
     # TheEnter?prise => VGhlRW50ZXI/cHJpc2U=
     assert encode_for_querystring('TheEnter?prise') == 'VGhlRW50ZXI_cHJpc2U~'
예제 #11
0
 def test_efq_doesnt_accept_bytes(self):
     with self.assertRaises(TypeError):
         encode_for_querystring(b'TheEnterprise')
예제 #12
0
 def test_efq_replaces_equals_with_tilde(self):
     assert encode_for_querystring('TheEnterprise') == 'VGhlRW50ZXJwcmlzZQ~~'
예제 #13
0
 def test_efq_replaces_slash_with_underscore(self):
     # TheEnter?prise => VGhlRW50ZXI/cHJpc2U=
     assert encode_for_querystring('TheEnter?prise') == 'VGhlRW50ZXI_cHJpc2U~'
예제 #14
0
    def add_email(self, email):
        """Add an email address for a participant.

        This is called when adding a new email address, and when resending the
        verification email for an unverified email address.

        :param unicode email: the email address to add

        :returns: ``None``

        :raises EmailAlreadyVerified: if the email is already verified for
            this participant
        :raises EmailTaken: if the email is verified for a different participant
        :raises TooManyEmailAddresses: if the participant already has 10 emails
        :raises Throttled: if the participant adds too many emails too quickly

        """

        # Check that this address isn't already verified
        owner = self.db.one(
            """
            SELECT p.username
              FROM emails e INNER JOIN participants p
                ON e.participant_id = p.id
             WHERE e.address = %(email)s
               AND e.verified IS true
        """, locals())
        if owner:
            if owner == self.username:
                raise EmailAlreadyVerified(email)
            else:
                raise EmailTaken(email)

        if len(self.get_emails()) > 9:
            raise TooManyEmailAddresses(email)

        nonce = str(uuid.uuid4())
        verification_start = utcnow()

        try:
            with self.db.get_cursor() as c:
                self.app.add_event(
                    c, 'participant',
                    dict(id=self.id, action='add', values=dict(email=email)))
                c.run(
                    """
                    INSERT INTO emails
                                (address, nonce, verification_start, participant_id)
                         VALUES (%s, %s, %s, %s)
                """, (email, nonce, verification_start, self.id))
        except IntegrityError:
            nonce = self.db.one(
                """
                UPDATE emails
                   SET verification_start=%s
                 WHERE participant_id=%s
                   AND address=%s
                   AND verified IS NULL
             RETURNING nonce
            """, (verification_start, self.id, email))
            if not nonce:
                return self.add_email(email)

        base_url = gratipay.base_url
        username = self.username_lower
        encoded_email = encode_for_querystring(email)
        link = "{base_url}/~{username}/emails/verify.html?email2={encoded_email}&nonce={nonce}"
        self.app.email_queue.put(self,
                                 'verification',
                                 email=email,
                                 link=link.format(**locals()),
                                 include_unsubscribe=False)
        if self.email_address:
            self.app.email_queue.put(
                self,
                'verification_notice',
                new_email=email,
                include_unsubscribe=False

                # Don't count this one against their sending quota.
                # It's going to their own verified address, anyway.
                ,
                _user_initiated=False)