Exemplo n.º 1
0
def populate(db):
    """
    Create some data for tests to use.

    Args:
        db (sqlalchemy.orm.session.Session): The database session.
    """
    user = User(name=u'guest')
    db.add(user)
    anonymous = User(name=u'anonymous')
    db.add(anonymous)
    provenpackager = Group(name=u'provenpackager')
    db.add(provenpackager)
    packager = Group(name=u'packager')
    db.add(packager)
    user.groups.append(packager)
    release = Release(name=u'F17',
                      long_name=u'Fedora 17',
                      id_prefix=u'FEDORA',
                      version=u'17',
                      dist_tag=u'f17',
                      stable_tag=u'f17-updates',
                      testing_tag=u'f17-updates-testing',
                      candidate_tag=u'f17-updates-candidate',
                      pending_signing_tag=u'f17-updates-testing-signing',
                      pending_testing_tag=u'f17-updates-testing-pending',
                      pending_stable_tag=u'f17-updates-pending',
                      override_tag=u'f17-override',
                      branch=u'f17',
                      state=ReleaseState.current)
    db.add(release)
    db.flush()
    update = create_update(db, [u'bodhi-2.0-1.fc17'])
    update.type = UpdateType.bugfix
    update.severity = UpdateSeverity.medium
    bug = Bug(bug_id=12345)
    db.add(bug)
    update.bugs.append(bug)
    cve = CVE(cve_id=u"CVE-1985-0110")
    db.add(cve)
    update.cves.append(cve)

    comment = Comment(karma=1, text=u"wow. amaze.")
    db.add(comment)
    comment.user = user
    update.comments.append(comment)

    comment = Comment(karma=0, text=u"srsly.  pretty good.", anonymous=True)
    comment.user = anonymous
    db.add(comment)
    update.comments.append(comment)

    with mock.patch(target='uuid.uuid4', return_value='wat'):
        update.assign_alias()
    db.add(update)

    db.commit()
Exemplo n.º 2
0
def populate(db):
    """
    Create some data for tests to use.

    Args:
        db (sqlalchemy.orm.session.Session): The database session.
    """
    user = User(name='guest')
    db.add(user)
    anonymous = User(name='anonymous')
    db.add(anonymous)
    provenpackager = Group(name='provenpackager')
    db.add(provenpackager)
    packager = Group(name='packager')
    db.add(packager)
    user.groups.append(packager)
    release = Release(name='F17',
                      long_name='Fedora 17',
                      id_prefix='FEDORA',
                      version='17',
                      dist_tag='f17',
                      stable_tag='f17-updates',
                      testing_tag='f17-updates-testing',
                      candidate_tag='f17-updates-candidate',
                      pending_signing_tag='f17-updates-signing-pending',
                      pending_testing_tag='f17-updates-testing-pending',
                      pending_stable_tag='f17-updates-pending',
                      override_tag='f17-override',
                      branch='f17',
                      state=ReleaseState.current,
                      create_automatic_updates=True,
                      package_manager=PackageManager.unspecified,
                      testing_repository=None)
    db.add(release)
    db.flush()
    # This mock will help us generate a consistent update alias.
    with mock.patch(target='uuid.uuid4', return_value='wat'):
        update = create_update(db, ['bodhi-2.0-1.fc17'])
    update.type = UpdateType.bugfix
    update.severity = UpdateSeverity.medium
    bug = Bug(bug_id=12345)
    db.add(bug)
    update.bugs.append(bug)

    comment = Comment(karma=1, text="wow. amaze.")
    db.add(comment)
    comment.user = user
    update.comments.append(comment)

    comment = Comment(karma=0, text="srsly.  pretty good.")
    comment.user = anonymous
    db.add(comment)
    update.comments.append(comment)

    db.add(update)

    db.commit()
Exemplo n.º 3
0
    def test_list_comments_with_multiple_ignore_user(self):
        another_user = User(name='aUser')
        self.db.add(another_user)
        update = Update(
            user=another_user,
            request=UpdateRequest.testing,
            type=UpdateType.enhancement,
            notes='Just another update.',
            date_submitted=datetime(1981, 10, 11),
            requirements='rpmlint',
            stable_karma=3,
            unstable_karma=-3,
            release=Release.query.one()
        )
        self.db.add(update)

        comment = Comment(karma=1, text='Cool! 😃')
        comment.user = another_user
        self.db.add(comment)
        update.comments.append(comment)
        self.db.flush()

        res = self.app.get('/comments/', {"ignore_user": "******"})
        body = res.json_body
        self.assertEqual(len(body['comments']), 1)
        self.assertNotIn('errors', body)
        self.assertEqual(body['comments'][0]['text'], 'Cool! 😃')
Exemplo n.º 4
0
    def test_list_comments_by_multiple_usernames(self):
        nvr = u'just-testing-1.0-2.fc17'
        update = Update(
            title=nvr,
            request=UpdateRequest.testing,
            type=UpdateType.enhancement,
            notes=u'Just another update.',
            date_submitted=datetime(1981, 10, 11),
            requirements=u'rpmlint',
            stable_karma=3,
            unstable_karma=-3,
        )
        update.release = Release.query.one()
        self.db.add(update)

        another_user = User(name=u'aUser')
        self.db.add(another_user)

        comment = Comment(karma=1, text=u'Cool! 😃')
        comment.user = another_user
        self.db.add(comment)
        update.comments.append(comment)
        self.db.flush()

        res = self.app.get('/comments/', {"user": "******"})
        body = res.json_body
        self.assertEqual(len(body['comments']), 2)
        self.assertEqual(body['comments'][0]['text'], u'Cool! 😃')
        self.assertEqual(body['comments'][1]['text'], u'wow. amaze.')
Exemplo n.º 5
0
def get_user(request):
    """
    Return a user given by username.

    Args:
        request (pyramid.request): The current request.
    Returns:
        dict: A dictionary with two keys. "user" maps to a dictionary representation of the User
            object. "urls" maps to various URLs that describe various other objects related to the
            user.
    """
    id = request.matchdict.get('name')
    user = User.get(id)

    if not user:
        request.errors.add('body', 'name', 'No such user')
        request.errors.status = HTTPNotFound.code
        return

    user = user.__json__(request)

    # Throw some extra information in there
    rurl = request.route_url  # Just shorthand
    urls = {
        'comments_by': rurl('comments') + '?user=%s' % id,
        'comments_on': rurl('comments') + '?update_owner=%s' % id,
        'recent_updates': rurl('updates') + '?user=%s' % id,
        'recent_overrides': rurl('overrides') + '?user=%s' % id,
        'comments_by_rss': rurl('comments_rss') + '?user=%s' % id,
        'comments_on_rss': rurl('comments_rss') + '?update_owner=%s' % id,
        'recent_updates_rss': rurl('updates_rss') + '?user=%s' % id,
        'recent_overrides_rss': rurl('overrides_rss') + '?user=%s' % id,
    }

    return dict(user=user, urls=urls)
Exemplo n.º 6
0
    def test_remember_me_with_bad_endpoint(self):
        """Test the post-login hook with a bad openid endpoint"""
        req = DummyRequest(params={
            'openid.op_endpoint': 'bad_endpoint',
        })
        req.db = self.db

        def flash(msg):
            pass

        req.session.flash = flash
        info = {
            'identity_url': 'http://lmacken.id.fedoraproject.org',
            'groups': [u'releng'],
        }
        req.registry.settings = self.app_settings

        try:
            remember_me(None, req, info)
            assert False, 'remember_me should have thrown an exception'
        except Exception:
            # A ComponentLookupError is thrown because we're doing this outside
            # of the webapp
            pass

        # The user should not exist
        self.assertIsNone(User.get(u'lmacken', self.db))
Exemplo n.º 7
0
    def test_list_overrides_by_multiple_usernames(self):
        release = Release.get('F17')

        package = RpmPackage(name='just-testing')
        self.db.add(package)
        build = RpmBuild(nvr='just-testing-1.0-2.fc17', package=package, release=release)
        self.db.add(build)
        another_user = User(name='aUser')
        self.db.add(another_user)

        expiration_date = datetime.utcnow() + timedelta(days=1)

        override = BuildrootOverride(build=build, submitter=another_user,
                                     notes='Crazy! 😱',
                                     expiration_date=expiration_date)
        self.db.add(override)
        self.db.flush()

        res = self.app.get('/overrides/', {"user": "******"})
        body = res.json_body
        self.assertEqual(len(body['overrides']), 2)

        override_fake = body['overrides'][0]
        self.assertEqual(override_fake['build']['nvr'], 'just-testing-1.0-2.fc17')
        self.assertEqual(override_fake['submitter']['name'], 'aUser')
        self.assertEqual(override_fake['notes'], 'Crazy! 😱')

        override_orig = body['overrides'][1]
        self.assertEqual(override_orig['build']['nvr'], 'bodhi-2.0-1.fc17')
        self.assertEqual(override_orig['submitter']['name'], 'guest')
        self.assertEqual(override_orig['notes'], 'blah blah blah')
Exemplo n.º 8
0
    def setUp(self, *args, **kwargs):
        super(TestCommentsService, self).setUp(*args, **kwargs)

        # Add a second update owned by somebody else so we can test karma
        # policy stuff
        user2 = User(name='lmacken')
        self.db.flush()
        self.db.add(user2)
        release = self.db.query(Release).filter_by(name='F17').one()
        update = Update(
            user=user2,
            request=UpdateRequest.testing,
            type=UpdateType.enhancement,
            notes='Useful details!',
            release=release,
            date_submitted=datetime(1984, 11, 2),
            requirements='rpmlint',
            stable_karma=3,
            unstable_karma=-3,
        )
        self.db.add(update)
        build = RpmBuild(nvr=up2, update=update,
                         package=RpmPackage.query.filter_by(name='bodhi').one())
        self.db.add(build)
        self.db.flush()
Exemplo n.º 9
0
    def test_list_comments_by_multiple_usernames(self):
        update = Update(request=UpdateRequest.testing,
                        type=UpdateType.enhancement,
                        notes='Just another update.',
                        date_submitted=datetime(1981, 10, 11),
                        requirements='rpmlint',
                        stable_karma=3,
                        unstable_karma=-3,
                        release=Release.query.one())
        self.db.add(update)

        another_user = User(name='aUser')
        self.db.add(another_user)

        comment = Comment(karma=1, text='Cool! 😃')
        comment.user = another_user
        self.db.add(comment)
        update.comments.append(comment)
        self.db.flush()

        res = self.app.get('/comments/', {"user": "******"})
        body = res.json_body
        assert len(body['comments']) == 2
        assert body['comments'][0]['text'] == 'Cool! 😃'
        assert body['comments'][1]['text'] == 'wow. amaze.'
Exemplo n.º 10
0
    def test_list_comments_by_multiple_update_owners(self):
        another_user = User(name='aUser')
        self.db.add(another_user)
        update = Update(
            user=another_user,
            request=UpdateRequest.testing,
            type=UpdateType.enhancement,
            notes='Just another update.',
            date_submitted=datetime(1981, 10, 11),
            requirements='rpmlint',
            stable_karma=3,
            unstable_karma=-3,
            release=Release.query.one()
        )
        self.db.add(update)

        comment = Comment(karma=1, text='Cool! 😃')
        comment.user = another_user
        self.db.add(comment)
        update.comments.append(comment)
        self.db.flush()

        res = self.app.get('/comments/', {"update_owner": "guest,aUser"})
        body = res.json_body
        self.assertEqual(len(body['comments']), 3)

        comment = body['comments'][0]
        self.assertEqual(comment['text'], 'Cool! 😃')
        comment = body['comments'][1]
        self.assertEqual(comment['text'], 'srsly.  pretty good.')
Exemplo n.º 11
0
    def test_get_single_user_with_nonstandard_characters(self):
        """Test that we don't receive a 404 page with bot usernames."""
        user = User(name='bot/a.bad.name')
        self.db.add(user)
        self.db.flush()

        res = self.app.get('/users/bot/a.bad.name')
        assert res.json_body['user']['name'] == 'bot/a.bad.name'
Exemplo n.º 12
0
def create_or_update_user(db, username, email, groups):
    """Create or update a user in the database.

    Args:
        db (sqlalchemy.orm.session.Session): The database session.
        username (str): The username to create or update
        email (str): The user's email address
        groups (list(str)): A list of group names the user belongs to, that will be synced.

    Returns:
        bodhi.server.models.User: The user instance.
    """
    # Find the user in our database. Create it if it doesn't exist.
    user = db.query(User).filter_by(name=username).first()
    if not user:
        user = User(name=username, email=email)
        db.add(user)
        db.flush()
    else:
        # Update email address if the address changed
        if user.email != email:
            user.email = email
            db.flush()

    # Keep track of what groups the user is a member of
    for group_name in groups:
        # Drop empty group names https://github.com/fedora-infra/bodhi/issues/306
        if not group_name.strip():
            continue

        group = db.query(Group).filter_by(name=group_name).first()
        if not group:
            group = Group(name=group_name)
            db.add(group)
            db.flush()
        if group not in user.groups:
            log.info('Adding %s to %s group', user.name, group.name)
            user.groups.append(group)

    # See if the user was removed from any groups
    for group in user.groups:
        if group.name not in groups:
            log.info('Removing %s from %s group', user.name, group.name)
            user.groups.remove(group)

    return user
Exemplo n.º 13
0
    def test_list_overrides_by_username_without_override(self):
        self.db.add(User(name='bochecha'))
        self.db.flush()

        res = self.app.get('/overrides/', {'user': '******'})

        body = res.json_body
        self.assertEqual(len(body['overrides']), 0)
Exemplo n.º 14
0
 def test_list_comments_by_update_owner_with_none(self):
     user = User(name='ralph')
     self.db.add(user)
     self.db.flush()
     res = self.app.get('/comments/', {"update_owner": "ralph"})
     body = res.json_body
     self.assertEqual(len(body['comments']), 0)
     self.assertNotIn('errors', body)
Exemplo n.º 15
0
 def test_list_comments_by_update_owner_with_none(self):
     user = User(name='ralph')
     self.db.add(user)
     self.db.flush()
     res = self.app.get('/comments/', {"update_owner": "ralph"})
     body = res.json_body
     assert len(body['comments']) == 0
     assert 'errors' not in body
Exemplo n.º 16
0
    def test_remember_me(self):
        """Test the post-login hook"""
        req = DummyRequest(
            params={
                'openid.op_endpoint': self.app_settings['openid.provider'],
            })
        req.db = self.db
        req.session = {'came_from': '/'}
        info = {
            'identity_url': 'http://lmacken.id.fedoraproject.org',
            'groups': [u'releng'],
            'sreg': {
                'email': u'[email protected]'
            },
        }
        req.registry.settings = self.app_settings

        # Ensure the user doesn't exist yet
        self.assertIsNone(User.get(u'lmacken', self.db))
        self.assertIsNone(Group.get(u'releng', self.db))

        remember_me(None, req, info)

        # The user should now exist, and be a member of the releng group
        user = User.get(u'lmacken', self.db)
        self.assertEquals(user.name, u'lmacken')
        self.assertEquals(user.email, u'[email protected]')
        self.assertEquals(len(user.groups), 1)
        self.assertEquals(user.groups[0].name, u'releng')

        # Pretend the user has been removed from the releng group
        info['groups'] = []
        req.session = {'came_from': '/'}

        remember_me(None, req, info)

        user = User.get(u'lmacken', self.db)
        self.assertEquals(len(user.groups), 0)
        self.assertEquals(len(Group.get(u'releng', self.db).users), 0)
Exemplo n.º 17
0
 def test_edit_stack_with_no_user_privs(self, *args):
     user = User(name=u'bob')
     self.db.add(user)
     self.db.add(RpmPackage(name=u'gnome-music'))
     self.db.commit()
     self.stack.users.append(user)
     self.db.commit()
     attrs = {'name': 'GNOME', 'packages': 'gnome-music gnome-shell',
              'csrf_token': self.get_csrf_token()}
     res = self.app.post("/stacks/", attrs, status=403)
     body = res.json_body
     self.assertEquals(body['status'], 'error')
     self.assertEquals(body['errors'][0]['description'],
                       'guest does not have privileges to modify the GNOME stack')
Exemplo n.º 18
0
    def test_existing_user(self, caplog):
        """Test Koji build user existing in DB."""
        caplog.set_level(logging.DEBUG)

        expected_username = base.buildsys.DevBuildsys._build_data['owner_name']

        # ensure user with expected name exists
        user = self.db.query(User).filter_by(name=expected_username).first()
        if not user:
            user = User(name=expected_username)
            self.db.add(user)
        self.db.flush()

        assert (f"Creating bodhi user for '{expected_username}'."
                not in caplog.messages)
Exemplo n.º 19
0
    def test_existing_user(self, caplog):
        """Test Koji build user existing in DB."""
        caplog.set_level(logging.DEBUG)

        expected_username = base.buildsys.DevBuildsys._build_data['owner_name']

        # ensure user with expected name exists
        user = self.db.query(User).filter_by(name=expected_username).first()
        if not user:
            user = User(name=expected_username)
            self.db.add(user)
        self.db.flush()

        with mock.patch('bodhi.server.models.handle_update'):
            with mock_sends(update_schemas.UpdateReadyForTestingV1):
                self.handler(self.sample_message)

        assert (f"Creating bodhi user for '{expected_username}'."
                not in caplog.messages)
Exemplo n.º 20
0
def groupfinder(userid, request):
    """
    Return a list of strings describing the groups the request's user is a member of.

    The strings are of the format group:<group_name>, so this might return something like this as
    an example:

        ['group:packager', 'group:bodhiadmin']

    Args:
        userid (str): The user's id.
        request (pyramid.request.Request): The current web request.
    Returns:
        list or None: A list of the user's groups, or None if the user is not authenticated.
    """
    from bodhi.server.models import User
    if request.user:
        user = User.get(request.user.name)
        return ['group:' + group.name for group in user.groups]
Exemplo n.º 21
0
def save_stack(request):
    """
    Save a stack.

    Args:
        request (pyramid.request): The current web request.
    Returns:
        dict: A dictionary with key "stack" that indexes the newly created Stack.
    """
    data = request.validated
    db = request.db
    user = User.get(request.user.name)

    # Fetch or create the stack
    stack = Stack.get(data['name'])
    if not stack:
        stack = Stack(name=data['name'], users=[user])
        db.add(stack)
        db.flush()

    if stack.users or stack.groups:
        if user in stack.users:
            log.info('%s is an owner of the %s', user.name, stack.name)
        else:
            for group in user.groups:
                if group in stack.groups:
                    log.info('%s is a member of the %s group', user.name, stack.name)
                    break
            else:
                log.warning('%s is not an owner of the %s stack',
                            user.name, stack.name)
                log.debug('owners = %s; groups = %s', stack.users, stack.groups)
                request.errors.add('body', 'name', '%s does not have privileges'
                                   ' to modify the %s stack' % (user.name, stack.name))
                request.errors.status = HTTPForbidden.code
                return

    # Update the stack description
    desc = data['description']
    if desc:
        stack.description = desc

    # Update the stack requirements
    # If the user passed in no value at all for requirements, then use
    # the site defaults.  If, however, the user passed in the empty string, we
    # assume they mean *really*, no requirements so we leave the value null.
    reqs = data['requirements']
    if reqs is None:
        stack.requirements = config.get('site_requirements')
    elif reqs:
        stack.requirements = reqs

    stack.update_relationship('users', User, data, db)
    stack.update_relationship('groups', Group, data, db)

    # We make a special case out of packages here, since when a package is
    # added to a stack, we want to give it the same requirements as the stack
    # has. See https://github.com/fedora-infra/bodhi/issues/101
    new, same, rem = stack.update_relationship('packages', Package, data, db)
    if stack.requirements:
        additional = list(tokenize(stack.requirements))

        for name in new:
            package = Package.get(name)
            original = package.requirements
            original = [] if not original else list(tokenize(original))
            package.requirements = " ".join(list(set(original + additional)))

    log.info('Saved %s stack', data['name'])
    notifications.publish(topic='stack.save', msg=dict(
        stack=stack, agent=user.name))

    return dict(stack=stack)
Exemplo n.º 22
0
def save_override(request):
    """
    Create or edit a buildroot override.

    This entails either creating a new buildroot override, or editing an
    existing one. To edit an existing buildroot override, the buildroot
    override's original id needs to be specified in the ``edited`` parameter.

    Args:
        request (pyramid.request): The current web request.
    Returns:
        dict: The new or edited override.
    """
    data = request.validated

    edited = data.pop("edited")

    caveats = []
    try:
        submitter = User.get(request.user.name)
        if edited is None:
            builds = data['builds']
            overrides = []
            if len(builds) > 1:
                caveats.append({
                    'name':
                    'nvrs',
                    'description':
                    'Your override submission was '
                    'split into %i.' % len(builds)
                })
            for build in builds:
                log.info("Creating a new buildroot override: %s" % build.nvr)
                existing_override = BuildrootOverride.get(build.id)
                if existing_override:
                    if not existing_override.expired_date:
                        data['expiration_date'] = max(
                            existing_override.expiration_date,
                            data['expiration_date'])

                    new_notes = f"""{data['notes']}
_____________
_@{existing_override.submitter.name} ({existing_override.submission_date.strftime('%b %d, %Y')})_
{existing_override.notes}"""
                    # Truncate notes at 2000 chars
                    if len(new_notes) > 2000:
                        new_notes = new_notes[:1972] + '(...)\n___Notes truncated___'

                    overrides.append(
                        BuildrootOverride.edit(
                            request,
                            edited=build,
                            submitter=submitter,
                            submission_date=datetime.now(),
                            notes=new_notes,
                            expiration_date=data['expiration_date'],
                            expired=None,
                        ))
                else:
                    overrides.append(
                        BuildrootOverride.new(
                            request,
                            build=build,
                            submitter=submitter,
                            notes=data['notes'],
                            expiration_date=data['expiration_date'],
                        ))

            if len(builds) > 1:
                result = dict(overrides=overrides)
            else:
                result = overrides[0]
        else:
            log.info("Editing buildroot override: %s" % edited)

            edited = Build.get(edited)

            if edited is None:
                request.errors.add('body', 'edited', 'No such build')
                return

            result = BuildrootOverride.edit(
                request,
                edited=edited,
                submitter=submitter,
                notes=data["notes"],
                expired=data["expired"],
                expiration_date=data["expiration_date"])

            if not result:
                # Some error inside .edit(...)
                return

    except Exception as e:
        log.exception(e)
        request.errors.add('body', 'override',
                           'Unable to save buildroot override: %s' % e)
        return

    if not isinstance(result, dict):
        result = result.__json__()

    result['caveats'] = caveats

    return result
Exemplo n.º 23
0
    def setUp(self, *args, **kwargs):
        super(TestFrontpageView, self).setUp(*args, **kwargs)

        def _add_updates(updateslist, user, release, packagesuffix):
            """Private method that adds updates to the database for testing

            """
            count = 0
            for i in updateslist:
                for j in i[1]:
                    for k in range(0, j[1]):
                        update = Update(
                            title=u'bodhi-2.0-1%s.%s' %
                            (str(count), packagesuffix),
                            user=user,
                            status=i[0],
                            type=j[0],
                            notes=u'Useful details!',
                            release=release,
                            date_submitted=datetime(1984, 11, 2),
                            requirements=u'rpmlint',
                            stable_karma=3,
                            unstable_karma=-3,
                        )
                        self.db.add(update)
                        self.db.flush()
                        count = count + 1

        user2 = User(name=u'dudemcpants')
        self.db.flush()
        self.db.add(user2)

        release = Release(name=u'F18',
                          long_name=u'Fedora 18',
                          id_prefix=u'FEDORA',
                          version=u'18',
                          dist_tag=u'f18',
                          stable_tag=u'f18-updates',
                          testing_tag=u'f18-updates-testing',
                          candidate_tag=u'f18-updates-candidate',
                          pending_signing_tag=u'f18-updates-testing-signing',
                          pending_testing_tag=u'f18-updates-testing-pending',
                          pending_stable_tag=u'f18-updates-pending',
                          override_tag=u'f18-override',
                          branch=u'f18',
                          state=ReleaseState.pending)
        self.db.add(release)

        currentrelease = self.db.query(Release).filter_by(name=u'F17').one()
        addedupdates = [[
            UpdateStatus.pending,
            [[UpdateType.security, 5], [UpdateType.bugfix, 4],
             [UpdateType.enhancement, 3], [UpdateType.newpackage, 2]]
        ],
                        [
                            UpdateStatus.testing,
                            [[UpdateType.security, 15],
                             [UpdateType.bugfix, 14],
                             [UpdateType.enhancement, 13],
                             [UpdateType.newpackage, 12]]
                        ],
                        [
                            UpdateStatus.stable,
                            [[UpdateType.security, 25],
                             [UpdateType.bugfix, 24],
                             [UpdateType.enhancement, 23],
                             [UpdateType.newpackage, 22]]
                        ]]
        _add_updates(addedupdates, user2, currentrelease, "fc17")

        pendingrelease = self.db.query(Release).filter_by(name=u'F18').one()
        addedupdates2 = [[
            UpdateStatus.pending,
            [[UpdateType.security, 2], [UpdateType.bugfix, 2],
             [UpdateType.enhancement, 2], [UpdateType.newpackage, 2]]
        ],
                         [
                             UpdateStatus.testing,
                             [[UpdateType.security, 3], [UpdateType.bugfix, 3],
                              [UpdateType.enhancement, 3],
                              [UpdateType.newpackage, 3]]
                         ],
                         [
                             UpdateStatus.stable,
                             [[UpdateType.security, 4], [UpdateType.bugfix, 4],
                              [UpdateType.enhancement, 4],
                              [UpdateType.newpackage, 4]]
                         ]]
        _add_updates(addedupdates2, user2, pendingrelease, "fc18")
        self.db.flush()
        Release._tag_cache = None
Exemplo n.º 24
0
    def setup_method(self, method):
        super(TestUsersService, self).setup_method(method)

        user = User(name='bodhi')
        self.db.add(user)
        self.db.flush()
Exemplo n.º 25
0
    def __call__(self, message: fedora_messaging.api.Message) -> None:
        """Create updates from appropriately tagged builds.

        Args:
            message: The message we are processing.
        """
        body = message.body

        missing = []
        for mandatory in ('tag', 'build_id', 'name', 'version', 'release'):
            if mandatory not in body:
                missing.append(mandatory)
        if missing:
            log.debug(
                f"Received incomplete tag message. Missing: {', '.join(missing)}"
            )
            return

        btag = body['tag']
        bnvr = '{name}-{version}-{release}'.format(**body)

        koji = buildsys.get_session()

        kbuildinfo = koji.getBuild(bnvr)
        if not kbuildinfo:
            log.debug(f"Can't find Koji build for {bnvr}.")
            return

        if 'nvr' not in kbuildinfo:
            log.debug(f"Koji build info for {bnvr} doesn't contain 'nvr'.")
            return

        if 'owner_name' not in kbuildinfo:
            log.debug(
                f"Koji build info for {bnvr} doesn't contain 'owner_name'.")
            return

        if kbuildinfo['owner_name'] in config.get(
                'automatic_updates_blacklist'):
            log.debug(
                f"{bnvr} owned by {kbuildinfo['owner_name']} who is listed in "
                "automatic_updates_blacklist, skipping.")
            return

        # some APIs want the Koji build info, some others want the same
        # wrapped in a larger (request?) structure
        rbuildinfo = {
            'info': kbuildinfo,
            'nvr': kbuildinfo['nvr'].rsplit('-', 2),
        }

        with self.db_factory() as dbsession:
            rel = dbsession.query(Release).filter_by(
                create_automatic_updates=True, candidate_tag=btag).first()
            if not rel:
                log.debug(
                    f"Ignoring build being tagged into {btag!r}, no release configured for "
                    "automatic updates for it found.")
                return

            bcls = ContentType.infer_content_class(Build, kbuildinfo)
            build = bcls.get(bnvr)
            if build and build.update:
                log.info(
                    f"Build, active update for {bnvr} exists already, skipping."
                )
                return

            if not build:
                log.debug(f"Build for {bnvr} doesn't exist yet, creating.")

                # Package.get_or_create() infers content type already
                log.debug("Getting/creating related package object.")
                pkg = Package.get_or_create(dbsession, rbuildinfo)

                log.debug("Creating build object, adding it to the DB.")
                build = bcls(nvr=bnvr, package=pkg, release=rel)
                dbsession.add(build)

            owner_name = kbuildinfo['owner_name']
            user = User.get(owner_name)
            if not user:
                log.debug(f"Creating bodhi user for '{owner_name}'.")
                # Leave email, groups blank, these will be filled
                # in or updated when they log into Bodhi next time, see
                # bodhi.server.security:remember_me().
                user = User(name=owner_name)
                dbsession.add(user)

            log.debug(f"Creating new update for {bnvr}.")
            changelog = build.get_changelog(lastupdate=True)
            if changelog:
                notes = f"""Automatic update for {bnvr}.

##### **Changelog**

```
{changelog}
```"""
            else:
                notes = f"Automatic update for {bnvr}."
            update = Update(
                release=rel,
                builds=[build],
                notes=notes,
                type=UpdateType.unspecified,
                stable_karma=3,
                unstable_karma=-3,
                autokarma=False,
                user=user,
                status=UpdateStatus.pending,
            )

            # Comment on the update that it was automatically created.
            update.comment(
                dbsession,
                str("This update was automatically created"),
                author="bodhi",
            )

            update.add_tag(update.release.pending_signing_tag)

            log.debug("Adding new update to the database.")
            dbsession.add(update)

            log.debug("Committing changes to the database.")
            dbsession.commit()
Exemplo n.º 26
0
def query_comments(request):
    """
    Search for comments matching given search parameters.

    Args:
        request (pyramid.request): The current request.
    Return:
        dict: A dictionary with the following key-value pairs:
            comments: An iterable with the current page of matched comments.
            page: The current page number.
            pages: The total number of pages.
            rows_per_page: The number of rows per page.
            total: The number of items matching the search terms.
            chrome: A boolean indicating whether to paginate or not.
    """
    db = request.db
    data = request.validated
    query = db.query(Comment)

    like = data.get('like')
    if like is not None:
        query = query.filter(or_(*[Comment.text.like('%%%s%%' % like)]))

    packages = data.get('packages')
    if packages is not None:
        query = query\
            .join(Comment.update)\
            .join(Update.builds)\
            .join(Build.package)
        query = query.filter(or_(*[Build.package == pkg for pkg in packages]))

    since = data.get('since')
    if since is not None:
        query = query.filter(Comment.timestamp >= since)

    updates = data.get('updates')
    if updates is not None:
        query = query.filter(or_(*[Comment.update == u for u in updates]))

    update_owner = data.get('update_owner')
    if update_owner is not None:
        query = query.join(Comment.update)
        query = query.filter(or_(*[Update.user == u for u in update_owner]))

    ignore_user = data.get('ignore_user')
    if ignore_user is not None:
        query = query.filter(and_(*[Comment.user != u for u in ignore_user]))

    # don't show bodhi user comments in the web interface
    if data.get("chrome"):
        query = query.filter(and_(*[Comment.user != User.get('bodhi')]))

    user = data.get('user')
    if user is not None:
        query = query.filter(or_(*[Comment.user == u for u in user]))

    query = query.order_by(Comment.timestamp.desc())

    # We can't use ``query.count()`` here because it is naive with respect to
    # all the joins that we're doing above.
    count_query = query.with_labels().statement\
        .with_only_columns([func.count(distinct(Comment.id))])\
        .order_by(None)
    total = db.execute(count_query).scalar()

    page = data.get('page')
    rows_per_page = data.get('rows_per_page')
    pages = int(math.ceil(total / float(rows_per_page)))
    query = query.offset(rows_per_page * (page - 1)).limit(rows_per_page)

    return dict(
        comments=query.all(),
        page=page,
        pages=pages,
        rows_per_page=rows_per_page,
        total=total,
        chrome=data.get('chrome'),
    )
Exemplo n.º 27
0
    def __call__(self, message: fedora_messaging.api.Message) -> None:
        """Create updates from appropriately tagged builds.

        Args:
            message: The message we are processing.
        """
        body = message.body

        missing = []
        for mandatory in ('tag', 'build_id', 'name', 'version', 'release'):
            if mandatory not in body:
                missing.append(mandatory)
        if missing:
            log.debug(
                f"Received incomplete tag message. Missing: {', '.join(missing)}"
            )
            return

        btag = body['tag']
        bnvr = '{name}-{version}-{release}'.format(**body)

        koji = buildsys.get_session()

        kbuildinfo = koji.getBuild(bnvr)
        if not kbuildinfo:
            log.debug(f"Can't find Koji build for {bnvr}.")
            return

        if 'nvr' not in kbuildinfo:
            log.debug(f"Koji build info for {bnvr} doesn't contain 'nvr'.")
            return

        if 'owner_name' not in kbuildinfo:
            log.debug(
                f"Koji build info for {bnvr} doesn't contain 'owner_name'.")
            return

        if kbuildinfo['owner_name'] in config.get(
                'automatic_updates_blacklist'):
            log.debug(
                f"{bnvr} owned by {kbuildinfo['owner_name']} who is listed in "
                "automatic_updates_blacklist, skipping.")
            return

        # some APIs want the Koji build info, some others want the same
        # wrapped in a larger (request?) structure
        rbuildinfo = {
            'info': kbuildinfo,
            'nvr': kbuildinfo['nvr'].rsplit('-', 2),
        }

        with self.db_factory() as dbsession:
            rel = dbsession.query(Release).filter_by(
                create_automatic_updates=True, candidate_tag=btag).first()
            if not rel:
                log.debug(
                    f"Ignoring build being tagged into {btag!r}, no release configured for "
                    "automatic updates for it found.")
                return

            bcls = ContentType.infer_content_class(Build, kbuildinfo)
            build = bcls.get(bnvr)
            if build and build.update:
                log.info(
                    f"Build, active update for {bnvr} exists already, skipping."
                )
                return

            if not build:
                log.debug(f"Build for {bnvr} doesn't exist yet, creating.")

                # Package.get_or_create() infers content type already
                log.debug("Getting/creating related package object.")
                pkg = Package.get_or_create(dbsession, rbuildinfo)

                log.debug("Creating build object, adding it to the DB.")
                build = bcls(nvr=bnvr, package=pkg, release=rel)
                dbsession.add(build)

            owner_name = kbuildinfo['owner_name']
            user = User.get(owner_name)
            if not user:
                log.debug(f"Creating bodhi user for '{owner_name}'.")
                # Leave email, groups blank, these will be filled
                # in or updated when they log into Bodhi next time, see
                # bodhi.server.security:remember_me().
                user = User(name=owner_name)
                dbsession.add(user)

            log.debug(f"Creating new update for {bnvr}.")
            try:
                changelog = build.get_changelog(lastupdate=True)
            except ValueError:
                # Often due to bot-generated builds
                # https://github.com/fedora-infra/bodhi/issues/4146
                changelog = None
            except Exception:
                # Re-raise exception, so that the message can be re-queued
                raise
            closing_bugs = []
            if changelog:
                log.debug("Adding changelog to update notes.")
                notes = f"""Automatic update for {bnvr}.

##### **Changelog**

```
{changelog}
```"""

                if rel.name not in config.get('bz_exclude_rels'):
                    for b in re.finditer(config.get('bz_regex'), changelog,
                                         re.IGNORECASE):
                        idx = int(b.group(1))
                        log.debug(f'Adding bug #{idx} to the update.')
                        bug = Bug.get(idx)
                        if bug is None:
                            bug = Bug(bug_id=idx)
                            dbsession.add(bug)
                            dbsession.flush()
                        if bug not in closing_bugs:
                            closing_bugs.append(bug)
            else:
                notes = f"Automatic update for {bnvr}."
            update = Update(
                release=rel,
                builds=[build],
                bugs=closing_bugs,
                notes=notes,
                type=UpdateType.unspecified,
                stable_karma=3,
                unstable_karma=-3,
                autokarma=False,
                user=user,
                status=UpdateStatus.pending,
                critpath=Update.contains_critpath_component([build],
                                                            rel.branch),
            )

            # Comment on the update that it was automatically created.
            update.comment(
                dbsession,
                str("This update was automatically created"),
                author="bodhi",
            )

            update.add_tag(update.release.pending_signing_tag)

            log.debug("Adding new update to the database.")
            dbsession.add(update)

            log.debug("Flushing changes to the database.")
            dbsession.flush()

            # Obsolete older updates which may be stuck in testing due to failed gating
            try:
                update.obsolete_older_updates(dbsession)
            except Exception as e:
                log.error(f'Problem obsoleting older updates: {e}')

            alias = update.alias
            buglist = [b.bug_id for b in update.bugs]

        # This must be run after dbsession is closed so changes are committed to db
        work_on_bugs_task.delay(alias, buglist)
Exemplo n.º 28
0
def save_override(request):
    """
    Create or edit a buildroot override.

    This entails either creating a new buildroot override, or editing an
    existing one. To edit an existing buildroot override, the buildroot
    override's original id needs to be specified in the ``edited`` parameter.

    Args:
        request (pyramid.request): The current web request.
    Returns:
        dict: The new or edited override.
    """
    data = request.validated

    edited = data.pop("edited")

    caveats = []
    try:
        submitter = User.get(request.user.name)
        if edited is None:
            builds = data['builds']
            overrides = []
            if len(builds) > 1:
                caveats.append({
                    'name': 'nvrs',
                    'description': 'Your override submission was '
                    'split into %i.' % len(builds)
                })
            for build in builds:
                log.info("Creating a new buildroot override: %s" % build.nvr)
                if BuildrootOverride.get(build.id):
                    request.errors.add('body', 'builds',
                                       'Buildroot override for %s already exists' % build.nvr)
                    return
                else:
                    overrides.append(BuildrootOverride.new(
                        request,
                        build=build,
                        submitter=submitter,
                        notes=data['notes'],
                        expiration_date=data['expiration_date'],
                    ))

            if len(builds) > 1:
                result = dict(overrides=overrides)
            else:
                result = overrides[0]
        else:
            log.info("Editing buildroot override: %s" % edited)

            edited = Build.get(edited)

            if edited is None:
                request.errors.add('body', 'edited', 'No such build')
                return

            result = BuildrootOverride.edit(
                request, edited=edited, submitter=submitter,
                notes=data["notes"], expired=data["expired"],
                expiration_date=data["expiration_date"])

            if not result:
                # Some error inside .edit(...)
                return

    except Exception as e:
        log.exception(e)
        request.errors.add('body', 'override',
                           'Unable to save buildroot override: %s' % e)
        return

    if not isinstance(result, dict):
        result = result.__json__()

    result['caveats'] = caveats

    return result
Exemplo n.º 29
0
    def setUp(self, *args, **kwargs):
        super(TestReleasesHTML, self).setUp(*args, **kwargs)

        def _add_updates(updateslist, user, release, packagesuffix):
            """Private method that adds updates to the database for testing

            """
            count = 0
            for i in updateslist:
                for j in i[1]:
                    for k in range(0, j[1]):
                        update = Update(
                            user=user,
                            status=i[0],
                            type=j[0],
                            notes='Useful details!',
                            release=release,
                            date_submitted=datetime(1984, 11, 2),
                            requirements='rpmlint',
                            stable_karma=3,
                            unstable_karma=-3,
                        )
                        self.db.add(update)
                        self.db.commit()
                        count = count + 1

        user2 = User(name='dudemcpants')
        self.db.flush()
        self.db.add(user2)

        release = Release(name='F18',
                          long_name='Fedora 18',
                          id_prefix='FEDORA',
                          version='18',
                          dist_tag='f18',
                          stable_tag='f18-updates',
                          testing_tag='f18-updates-testing',
                          candidate_tag='f18-updates-candidate',
                          pending_signing_tag='f18-updates-testing-signing',
                          pending_testing_tag='f18-updates-testing-pending',
                          pending_stable_tag='f18-updates-pending',
                          override_tag='f18-override',
                          branch='f18',
                          state=ReleaseState.pending)
        self.db.add(release)

        currentrelease = self.db.query(Release).filter_by(name='F17').one()
        addedupdates = [[
            UpdateStatus.pending,
            [[UpdateType.security, 5], [UpdateType.bugfix, 4],
             [UpdateType.enhancement, 3], [UpdateType.newpackage, 2]]
        ],
                        [
                            UpdateStatus.testing,
                            [[UpdateType.security, 15],
                             [UpdateType.bugfix, 14],
                             [UpdateType.enhancement, 13],
                             [UpdateType.newpackage, 12]]
                        ],
                        [
                            UpdateStatus.stable,
                            [[UpdateType.security, 25],
                             [UpdateType.bugfix, 24],
                             [UpdateType.enhancement, 23],
                             [UpdateType.newpackage, 22]]
                        ]]

        with fml_testing.mock_sends(*[api.Message] * 54):
            _add_updates(addedupdates, user2, currentrelease, "fc17")

        pendingrelease = self.db.query(Release).filter_by(name='F18').one()
        addedupdates2 = [[
            UpdateStatus.pending,
            [[UpdateType.security, 2], [UpdateType.bugfix, 2],
             [UpdateType.enhancement, 2], [UpdateType.newpackage, 2]]
        ],
                         [
                             UpdateStatus.testing,
                             [[UpdateType.security, 3], [UpdateType.bugfix, 3],
                              [UpdateType.enhancement, 3],
                              [UpdateType.newpackage, 3]]
                         ],
                         [
                             UpdateStatus.stable,
                             [[UpdateType.security, 4], [UpdateType.bugfix, 4],
                              [UpdateType.enhancement, 4],
                              [UpdateType.newpackage, 4]]
                         ]]
        with fml_testing.mock_sends(*[api.Message] * 12):
            _add_updates(addedupdates2, user2, pendingrelease, "fc18")
        self.db.flush()
        # Clear the caches
        Release._tag_cache = None
        generic._generate_home_page_stats.invalidate()
Exemplo n.º 30
0
    def setUp(self):
        super(TestUsersService, self).setUp()

        user = User(name=u'bodhi')
        self.db.add(user)
        self.db.flush()