示例#1
0
    def check(self, *package_names):
        package_names, post = package_names[:-1], package_names[-1]
        post.return_value = 'some-github-url'

        nonce = self.start(self.address, *package_names)
        result = self.alice.finish_email_verification(self.address, nonce)

        # email?
        packages = [Package.from_names(NPM, name) for name in package_names]
        assert result == (_email.VERIFICATION_SUCCEEDED, packages,
                          True if packages else None)
        assert self.alice.email_address == P(
            'alice').email_address == self.address

        # database?
        for name in package_names:
            package = Package.from_names(NPM, name)
            assert package.team.package == package
            assert package.team.review_url == 'some-github-url'

        # GitHub issue?
        npackages = len(package_names)
        if npackages == 0:
            assert not post.called
        else:
            assert post.call_count == 1
            posted = json.loads(post.mock_calls[0][1][0])
            if npackages == 1:
                assert posted['title'] == 'foo'
                assert 'for at least a week' in posted['body']
            else:
                assert posted['title'] == 'bar and foo'
                assert 'for at least a week' in posted['body']
            assert self.db.all('select review_url from teams'
                               ) == ['some-github-url'] * npackages
    def check(self, *package_names):
        package_names, post = package_names[:-1], package_names[-1]
        post.return_value = 'some-github-url'

        nonce = self.start(self.address, *package_names)
        result = self.alice.finish_email_verification(self.address, nonce)

        # email?
        packages = [Package.from_names(NPM, name) for name in package_names]
        assert result == (_email.VERIFICATION_SUCCEEDED, packages, True if packages else None)
        assert self.alice.email_address == P('alice').email_address == self.address

        # database?
        for name in package_names:
            package = Package.from_names(NPM, name)
            assert package.team.package == package
            assert package.team.review_url == 'some-github-url'

        # GitHub issue?
        npackages = len(package_names)
        if npackages == 0:
            assert not post.called
        else:
            assert post.call_count == 1
            posted = json.loads(post.mock_calls[0][1][0])
            if npackages == 1:
                assert posted['title'] == 'foo'
                assert 'for at least a week' in posted['body']
            else:
                assert posted['title'] == 'bar and foo'
                assert 'for at least a week' in posted['body']
            assert self.db.all('select review_url from teams') == ['some-github-url'] * npackages
示例#3
0
 def test_deleting_package_removes_open_claims(self):
     self.add_and_verify_email(self.alice, self.address)
     self.alice.set_paypal_address(self.address)
     self.start(self.address, 'foo')
     load = lambda: self.db.one('select * from claims')
     assert load() is not None
     Package.from_names('npm', 'foo').delete()
     assert load() is None
 def test_deleting_package_removes_open_claims(self):
     self.add_and_verify_email(self.alice, self.address)
     self.alice.set_paypal_address(self.address)
     self.start(self.address, 'foo')
     _load = lambda: self.db.one('select * from claims')
     assert _load() is not None
     Package.from_names('npm', 'foo').delete()
     assert _load() is None
    def test_while_we_are_at_it_that_packages_have_unique_teams_that_survive_comparison(self):
        self.test_verified_address_and_multiple_packages_succeeds()

        foo = Package.from_names('npm', 'foo')
        bar = Package.from_names('npm', 'bar')

        assert foo.team == foo.team
        assert bar.team == bar.team
        assert foo.team != bar.team
示例#6
0
    def test_while_we_are_at_it_that_packages_have_unique_teams_that_survive_comparison(
            self):
        self.test_verified_address_and_multiple_packages_succeeds()

        foo = Package.from_names('npm', 'foo')
        bar = Package.from_names('npm', 'bar')

        assert foo.team == foo.team
        assert bar.team == bar.team
        assert foo.team != bar.team
示例#7
0
 def test_can_be_upserted_in_a_transaction(self):
     self.make_package(description='Before')
     with self.db.get_cursor() as cursor:
         Package.upsert(NPM,
                        name='foo',
                        description='After',
                        emails=[],
                        cursor=cursor)
         assert Foo().description == 'Before'
     assert Foo().description == 'After'
 def test_finishing_email_verification_with_preexisting_paypal_doesnt_update_paypal(self):
     self.add_and_verify_email(self.alice, self.address)
     self.alice.set_paypal_address(self.address)
     nonce = self.start(self.address, 'foo')
     result = self.alice.finish_email_verification(self.address, nonce)
     foo = Package.from_names('npm', 'foo')
     assert result == (_email.VERIFICATION_SUCCEEDED, [foo], False)
示例#9
0
def consume_change_stream(stream, db):
    """Given an iterable of CouchDB change notifications and a
    :py:class:`~GratipayDB`, read from the stream and write to the db.

    The npm registry is a CouchDB app, which means we get a change stream from
    it that allows us to follow registry updates in near-realtime. Our strategy
    here is to maintain open connections to both the registry and our own
    database, and write as we read.

    """
    with db.get_connection() as connection:
        for change in stream:

            # Decide what to do.
            if change.get('deleted'):
                package = Package.from_names(NPM, change['id'])
                if not package:
                    # As a result of CouchDB's compaction algorithm, we might
                    # receive 'deleted' events for docs even if we haven't seen
                    # the corresponding events for when the doc was created
                    continue
                op, kw = package.delete, {}
            else:
                op = Package.upsert
                kw = process_doc(change['doc'])
                if not kw:
                    continue
                kw['package_manager'] = NPM

            # Do it.
            cursor = connection.cursor()
            kw['cursor'] = cursor
            op(**kw)
            cursor.run('UPDATE worker_coordination SET npm_last_seq=%(seq)s', change)
            connection.commit()
示例#10
0
 def test_finishing_email_verification_with_preexisting_paypal_doesnt_update_paypal(
         self):
     self.add_and_verify_email(self.alice, self.address)
     self.alice.set_paypal_address(self.address)
     nonce = self.start(self.address, 'foo')
     result = self.alice.finish_email_verification(self.address, nonce)
     foo = Package.from_names('npm', 'foo')
     assert result == (_email.VERIFICATION_SUCCEEDED, [foo], False)
示例#11
0
 def claim_package(self, participant, package):
     """Given a participant and a package, claim the package for the participant.
     """
     if participant.__class__ is not Participant:
         participant = P(participant)
     if package.__class__ is not Package:
         package = Package.from_names(NPM, package)
     package.get_or_create_linked_team(self.db, participant)
示例#12
0
 def claim_package(self, participant, package):
     """Given a participant and a package, claim the package for the participant.
     """
     if participant.__class__ is not Participant:
         participant = P(participant)
     if package.__class__ is not Package:
         package = Package.from_names(NPM, package)
     package.get_or_create_linked_team(self.db, participant)
 def test_but_once_claimed_then_team_persists(self):
     self.make_package()
     self.check()
     foo = Package.from_names(NPM, 'foo')
     assert self.finish_claiming() == (email.VERIFICATION_SUCCEEDED, [foo], True)
     foo.delete()
     self.visit('/foo/')
     foo = self.css('#content .statement p')
     assert foo.text == 'Foo fooingly.'
 def claim_package(self):
     foo = Package.from_names('npm', 'foo')
     alice = self.make_participant('alice', claimed_time='now')
     alice.start_email_verification('*****@*****.**', foo)
     nonce = alice.get_email('*****@*****.**').nonce
     alice.finish_email_verification('*****@*****.**', nonce)
     team = alice.get_teams()[0]
     assert team.package == foo
     return team.slug
示例#15
0
 def claim_package(self):
     foo = Package.from_names('npm', 'foo')
     alice = self.make_participant('alice', claimed_time='now')
     alice.start_email_verification('*****@*****.**', foo)
     nonce = alice.get_email('*****@*****.**').nonce
     alice.finish_email_verification('*****@*****.**', nonce)
     team = alice.get_teams()[0]
     assert team.package == foo
     return team.slug
示例#16
0
 def test_but_once_claimed_then_team_persists(self):
     self.make_package()
     self.check()
     foo = Package.from_names(NPM, 'foo')
     assert self.finish_claiming() == (email.VERIFICATION_SUCCEEDED, [foo], True)
     foo.delete()
     self.visit('/foo/')
     foo = self.css('#content .statement p')
     assert foo.text == 'Foo fooingly.'
示例#17
0
 def make_package(self, package_manager=NPM, name='foo', description='Foo fooingly.',
                                                 emails=['*****@*****.**'], claimed_by=None):
     """Factory for packages.
     """
     self.db.run( 'INSERT INTO packages (package_manager, name, description, emails) '
                  'VALUES (%s, %s, %s, %s) RETURNING *'
                , (package_manager, name, description, emails)
                 )
     package = Package.from_names(NPM, name)
     if claimed_by:  # either a username (existing or not) or a Participant object
         if type(claimed_by) is unicode:
             maybe = P(claimed_by)
             claimed_by = maybe if maybe is not None else self.make_owner(claimed_by)
         admin = self.make_admin()
         team = package.get_or_create_linked_team(self.db, claimed_by)
         team.update_review_status('approved', admin)
     return package
示例#18
0
 def make_package(self, package_manager=NPM, name='foo', description='Foo fooingly.',
                                                 emails=['*****@*****.**'], claimed_by=None):
     """Factory for packages.
     """
     self.db.run( 'INSERT INTO packages (package_manager, name, description, emails) '
                  'VALUES (%s, %s, %s, %s) RETURNING *'
                , (package_manager, name, description, emails)
                 )
     package = Package.from_names(NPM, name)
     if claimed_by:  # either a username (existing or not) or a Participant object
         if type(claimed_by) is unicode:
             maybe = P(claimed_by)
             claimed_by = maybe if maybe is not None else self.make_owner(claimed_by)
         admin = self.make_admin()
         team = package.get_or_create_linked_team(self.db, claimed_by)
         team.update_review_status('approved', admin)
     return package
示例#19
0
def consume_change_stream(stream, db):
    """Given an iterable of CouchDB change notifications and a
    :py:class:`~GratipayDB`, read from the stream and write to the db.

    The npm registry is a CouchDB app, which means we get a change stream from
    it that allows us to follow registry updates in near-realtime. Our strategy
    here is to maintain open connections to both the registry and our own
    database, and write as we read.

    """
    with db.get_connection() as connection:
        for change in stream:

            # Decide what to do.
            if change.get('deleted'):
                package = Package.from_names(NPM, change['id'])
                if not package:
                    # As a result of CouchDB's compaction algorithm, we might
                    # receive 'deleted' events for docs even if we haven't seen
                    # the corresponding events for when the doc was created
                    continue
                op, kw = package.delete, {}
            else:
                op = Package.upsert
                doc = change.get('doc')
                if not doc:
                    continue    # We've seen this in the wild.
                kw = process_doc(doc)
                if not kw:
                    continue
                kw['package_manager'] = NPM

            # Do it.
            cursor = connection.cursor()
            kw['cursor'] = cursor
            op(**kw)
            cursor.run('UPDATE worker_coordination SET npm_last_seq=%(seq)s', change)
            connection.commit()
 def test_deleted_packages_are_404(self):
     self.make_package()
     Package.from_names(NPM, 'foo').delete()
     self.visit('/on/npm/foo')
     assert self.css('#content h1').text == '404'
示例#21
0
 def test_can_be_upserted_in_a_transaction(self):
     self.make_package(description='Before')
     with self.db.get_cursor() as cursor:
         Package.upsert(NPM, name='foo', description='After', emails=[], cursor=cursor)
         assert Foo().description == 'Before'
     assert Foo().description == 'After'
示例#22
0
 def test_can_be_inserted_via_upsert(self):
     Package.upsert(NPM, name='foo', description='Foo!', emails=[])
     assert Foo().name == 'foo'
示例#23
0
 def test_can_be_updated_via_upsert(self):
     self.make_package()
     Package.upsert(NPM, name='foo', description='Bar!', emails=[])
     assert Foo().description == 'Bar!'
示例#24
0
 def test_can_be_instantiated_from_names(self):
     self.make_package()
     assert Package.from_names(NPM, 'foo').name == 'foo'
示例#25
0
 def test_from_names_can_use_a_cursor(self):
     self.make_package()
     with self.db.get_cursor() as cursor:
         assert Package.from_names(NPM, 'foo', cursor).name == 'foo'
示例#26
0
 def test_from_id_can_use_a_cursor(self):
     package = self.make_package()
     with self.db.get_cursor() as cursor:
         assert Package.from_id(package.id, cursor).id == package.id
示例#27
0
 def test_can_be_instantiated_from_id(self):
     package = self.make_package()
     assert Package.from_id(package.id).id == package.id
示例#28
0
 def test_closing_team_unlinks_package(self):
     _, _, team = self.link()
     team.close()
     assert Package.from_names('npm', 'foo').team is None
示例#29
0
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals

import mock
from gratipay.models.package import Package, NPM
from gratipay.models.package.emails import PRIMARY, VERIFIED, UNVERIFIED, UNLINKED, OTHER
from gratipay.testing import Harness
from psycopg2 import IntegrityError
from pytest import raises


Foo = lambda cursor=None: Package.from_names(NPM, 'foo', cursor)


class Basics(Harness):

    def test_can_be_instantiated_from_id(self):
        package = self.make_package()
        assert Package.from_id(package.id).id == package.id

    def test_from_id_can_use_a_cursor(self):
        package = self.make_package()
        with self.db.get_cursor() as cursor:
            assert Package.from_id(package.id, cursor).id == package.id

    def test_can_be_instantiated_from_names(self):
        self.make_package()
        assert Package.from_names(NPM, 'foo').name == 'foo'

    def test_from_names_can_use_a_cursor(self):
        self.make_package()
示例#30
0
 def test_deleted_packages_are_404(self):
     self.make_package()
     Package.from_names(NPM, 'foo').delete()
     self.visit('/on/npm/foo')
     assert self.css('#content h1').text == '404'
示例#31
0
 def test_claiming_deleted_packages_is_a_noop(self):
     self.make_package()
     self.check()
     Package.from_names(NPM, 'foo').delete()
     assert self.finish_claiming() == (email.VERIFICATION_SUCCEEDED, [], None)
 def test_claiming_deleted_packages_is_a_noop(self):
     self.make_package()
     self.check()
     Package.from_names(NPM, 'foo').delete()
     assert self.finish_claiming() == (email.VERIFICATION_SUCCEEDED, [], None)