def list_packages(motif=None, orphaned=False, status='Approved', origin='list_packages'): ''' Display the list of packages corresponding to the motif. ''' pattern = flask.request.args.get('motif', motif) or '*' branches = flask.request.args.get('branches', None) owner = flask.request.args.get('owner', None) orphaned = bool(flask.request.args.get('orphaned', orphaned)) status = flask.request.args.get('status', status) limit = flask.request.args.get('limit', APP.config['ITEMS_PER_PAGE']) page = flask.request.args.get('page', 1) try: page = int(page) except ValueError: page = 1 try: int(limit) except ValueError: limit = APP.config['ITEMS_PER_PAGE'] flask.flash('Incorrect limit provided, using default', 'errors') packages = pkgdblib.search_package( SESSION, pkg_name=pattern, pkg_branch=branches, pkg_poc=owner, orphaned=orphaned, status=status, page=page, limit=limit, ) packages_count = pkgdblib.search_package( SESSION, pkg_name=pattern, pkg_branch=branches, pkg_poc=owner, orphaned=orphaned, status=status, page=page, limit=limit, count=True ) total_page = int(ceil(packages_count / float(limit))) return flask.render_template( 'list_packages.html', origin=origin, packages=packages, motif=motif, total_page=total_page, packages_count=packages_count, page=page )
def list_packages(motif=None, orphaned=False, status='Approved', origin='list_packages'): ''' Display the list of packages corresponding to the motif. ''' pattern = flask.request.args.get('motif', motif) or '*' branches = flask.request.args.get('branches', None) owner = flask.request.args.get('owner', None) orphaned = bool(flask.request.args.get('orphaned', orphaned)) status = flask.request.args.get('status', status) limit = flask.request.args.get('limit', APP.config['ITEMS_PER_PAGE']) page = flask.request.args.get('page', 1) try: page = int(page) except ValueError: page = 1 try: int(limit) except ValueError: limit = APP.config['ITEMS_PER_PAGE'] flask.flash('Incorrect limit provided, using default', 'errors') packages = pkgdblib.search_package( SESSION, pkg_name=pattern, pkg_branch=branches, pkg_poc=owner, orphaned=orphaned, status=status, page=page, limit=limit, ) packages_count = pkgdblib.search_package(SESSION, pkg_name=pattern, pkg_branch=branches, pkg_poc=owner, orphaned=orphaned, status=status, page=page, limit=limit, count=True) total_page = int(ceil(packages_count / float(limit))) return flask.render_template('list_packages.html', origin=origin, packages=packages, motif=motif, total_page=total_page, packages_count=packages_count, page=page)
def package_retire(package, collection): ''' Gives the possibility to orphan or take a package. ''' packagename = package package = None try: package_acl = pkgdblib.get_acl_package(SESSION, packagename) package = pkgdblib.search_package(SESSION, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') for acl in package_acl: if acl.collection.branchname == collection: if acl.point_of_contact == 'orphan': try: pkgdblib.update_pkg_status( session=SESSION, pkg_name=package.name, pkg_branch=acl.collection.branchname, status='Retired', user=flask.g.fas_user) flask.flash('This package has been retired on branch: %s' % collection) except pkgdblib.PkgdbException, err: flask.flash(str(err), 'error') SESSION.rollback() break else: flask.flash('This package has not been orphaned on ' 'branch: %s' % collection)
def package_orphan(package, collection): ''' Gives the possibility to orphan or take a package. ''' packagename = package package = None try: package_acl = pkgdblib.get_acl_package(SESSION, packagename) package = pkgdblib.search_package(SESSION, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') for acl in package_acl: if acl.collection.branchname == collection: try: pkgdblib.update_pkg_poc(session=SESSION, pkg_name=package.name, pkg_branch=acl.collection.branchname, pkg_poc='orphan', user=flask.g.fas_user) flask.flash( 'You are no longer point of contact on branch: %s' % collection) except pkgdblib.PkgdbException, err: flask.flash(str(err), 'error') SESSION.rollback() break
def package_request_branch(namespace, package, full=True): ''' Gives the possibility to request a new branch for this package. ''' if not bool(full) or str(full) in ['0', 'False']: full = False try: package_acl = pkgdblib.get_acl_package( SESSION, namespace, package) package = pkgdblib.search_package( SESSION, namespace, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') branches = [ pkg.collection.branchname for pkg in package_acl if pkg.collection.status != 'EOL' ] collections = pkgdb2.lib.search_collection( SESSION, '*', 'Under Development') collections.extend(pkgdb2.lib.search_collection(SESSION, '*', 'Active')) # List the possible branches that this package does not already have. branches_possible = [ collec.branchname for collec in collections if collec.branchname not in branches] # Further limit that list to only the branches allowed for this namespace. namespace_policy = APP.config.get('PKGDB2_NAMESPACE_POLICY') policy = namespace_policy.get(pkg.package.namespace) if policy: branches_possible = [b for b in branches_possible if b in policy] form = pkgdb2.forms.BranchForm(collections=branches_possible) if form.validate_on_submit(): for branch in form.branches.data: try: msg = pkgdblib.add_new_branch_request( session=SESSION, namespace=package.namespace, pkg_name=package.name, clt_to=branch, user=flask.g.fas_user) SESSION.commit() flask.flash(msg) except pkgdblib.PkgdbException, err: # pragma: no cover flask.flash(str(err), 'error') SESSION.rollback() except SQLAlchemyError, err: # pragma: no cover APP.logger.exception(err) flask.flash( 'Could not save the request to the database for ' 'branch: %s' % branch, 'error') SESSION.rollback()
def package_anitya(namespace, package, full=True): """ Return information anitya integration about this package. """ if str(full).lower() in ['0', 'false']: full = False pkg = None try: pkg = pkgdblib.search_package( SESSION, namespace, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') url = '%s/api/project/%s/%s' % ( APP.config['PKGDB2_ANITYA_URL'], APP.config['PKGDB2_ANITYA_DISTRO'], package ) data = {} try: req = requests.get(url) if req.status_code != 200: raise pkgdblib.PkgdbException( 'Querying anitya returned a status %s' % req.status_code) else: data = req.json() except Exception, err: flask.flash(err.message, 'error') pass
def package_orphan(package, collection): ''' Gives the possibility to orphan or take a package. ''' packagename = package package = None try: package_acl = pkgdblib.get_acl_package(SESSION, packagename) package = pkgdblib.search_package(SESSION, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') for acl in package_acl: if acl.collection.branchname == collection: try: pkgdblib.update_pkg_poc( session=SESSION, pkg_name=package.name, pkg_branch=acl.collection.branchname, pkg_poc='orphan', user=flask.g.fas_user ) flask.flash( 'You are no longer point of contact on branch: %s' % collection) except pkgdblib.PkgdbException, err: flask.flash(str(err), 'error') SESSION.rollback() break
def package_retire(package, collection): ''' Gives the possibility to orphan or take a package. ''' packagename = package package = None try: package_acl = pkgdblib.get_acl_package(SESSION, packagename) package = pkgdblib.search_package(SESSION, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') for acl in package_acl: if acl.collection.branchname == collection: if acl.point_of_contact == 'orphan': try: pkgdblib.update_pkg_status( session=SESSION, pkg_name=package.name, pkg_branch=acl.collection.branchname, status='Retired', user=flask.g.fas_user ) flask.flash( 'This package has been retired on branch: %s' % collection) except pkgdblib.PkgdbException, err: flask.flash(str(err), 'error') SESSION.rollback() break else: flask.flash( 'This package has not been orphaned on ' 'branch: %s' % collection)
def package_anitya(package, full=True): """ Return information anitya integration about this package. """ if str(full).lower() in ['0', 'false']: full = False pkg = None try: pkg = pkgdblib.search_package(SESSION, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') url = '%s/api/project/%s/%s' % (APP.config['PKGDB2_ANITYA_URL'], APP.config['PKGDB2_ANITYA_DISTRO'], package) data = {} try: req = requests.get(url) if req.status_code != 200: raise pkgdblib.PkgdbException( 'Querying anitya returned a status %s' % req.status_code) else: data = req.json() except Exception, err: flask.flash(err.message, 'error') pass
def package_retire(package, full=True): ''' Gives the possibility to orphan or take a package. ''' if not bool(full) or str(full) in ['0', 'False']: full = False try: package_acl = pkgdblib.get_acl_package(SESSION, package) package = pkgdblib.search_package(SESSION, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') if not is_pkgdb_admin(flask.g.fas_user): flask.flash( 'Only Admins are allowed to retire package here, ' 'you should use `fedpkg retire`.', 'errors') return flask.redirect( flask.url_for('.package_info', package=package.name)) collections = [ acl.collection.branchname for acl in package_acl if acl.collection.status in ['Active', 'Under Development'] and acl.status == 'Orphaned' ] form = pkgdb2.forms.BranchForm(collections=collections) if form.validate_on_submit(): for acl in package_acl: if acl.collection.branchname in form.branches.data: if acl.point_of_contact == 'orphan': try: pkgdblib.update_pkg_status( session=SESSION, pkg_name=package.name, pkg_branch=acl.collection.branchname, status='Retired', user=flask.g.fas_user) flask.flash( 'This package has been retired on branch: %s' % acl.collection.branchname) except pkgdblib.PkgdbException, err: # pragma: no cover # We should never hit this flask.flash(str(err), 'error') SESSION.rollback() APP.logger.exception(err) else: # pragma: no cover flask.flash('This package has not been orphaned on ' 'branch: %s' % acl.collection.branchname) try: SESSION.commit() # Keep it in, but normally we shouldn't hit this except pkgdblib.PkgdbException, err: # pragma: no cover # We should never hit this SESSION.rollback() APP.logger.exception(err) flask.flash(str(err), 'error')
def watch_package(package): ''' Request watch* ACLs on a package. Anyone can request these ACLs, no need to be a packager. ''' try: pkg = pkgdblib.search_package(SESSION, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect(flask.url_for('.package_info', package=package)) pkg_acls = ['watchcommits', 'watchbugzilla'] pkg_branchs = [pkglist.collection.branchname for pkglist in pkg.listings] try: for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): pkgdblib.set_acl_package( SESSION, pkg_name=package, pkg_branch=collec, pkg_user=flask.g.fas_user.username, acl=acl, status='Approved', user=flask.g.fas_user, ) SESSION.commit() flask.flash('ACLs updated') # Let's keep this in although we should never see it except pkgdblib.PkgdbException, err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error')
def watch_package(package): ''' Request watch* ACLs on a package. Anyone can request these ACLs, no need to be a packager. ''' try: pkg = pkgdblib.search_package(SESSION, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect( flask.url_for('.package_info', package=package)) pkg_acls = ['watchcommits', 'watchbugzilla'] pkg_branchs = [pkglist.collection.branchname for pkglist in pkg.listings] try: for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): pkgdblib.set_acl_package( SESSION, pkg_name=package, pkg_branch=collec, pkg_user=flask.g.fas_user.username, acl=acl, status='Approved', user=flask.g.fas_user, ) SESSION.commit() flask.flash('ACLs updated') # Let's keep this in although we should never see it except pkgdblib.PkgdbException, err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error')
def package_anitya(package, full=True): """ Return information anitya integration about this package. """ if str(full).lower() in ['0', 'false']: full = False pkg = None try: pkg = pkgdblib.search_package(SESSION, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') url = '%s/api/project/%s/%s' % ( APP.config['PKGDB2_ANITYA_URL'], APP.config['PKGDB2_ANITYA_DISTRO'], package ) req = requests.get(url) data = req.json() return flask.render_template( 'package_anitya.html', full=full, package=package, pkg=pkg, data=data, )
def package_give_acls(namespace, package): ''' Give acls to a specified user for a specific package. ''' try: pkg = pkgdblib.search_package(SESSION, namespace=namespace, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect(flask.url_for('.list_packages')) collections = [ pkglist.collection for pkglist in pkg.listings if pkglist.collection.status != 'EOL' ] acls = pkgdblib.get_status(SESSION) form = pkgdb2.forms.SetAclPackageForm( collections_obj=collections, pkg_acl=acls['pkg_acl'], acl_status=acls['acl_status'], namespaces=acls['namespaces'], ) form.pkgname.data = package if str(form.namespace.data) in ['None', '']: form.namespace.data = 'rpms' if form.validate_on_submit(): pkg_branchs = form.branches.data pkg_acls = form.acl.data pkg_user = form.user.data acl_status = form.acl_status.data try: for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): if acl in APP.config['AUTO_APPROVE']: acl_status = 'Approved' pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=package, pkg_branch=collec, pkg_user=pkg_user, acl=acl, status=acl_status, user=flask.g.fas_user, ) SESSION.commit() flask.flash('ACLs updated') return flask.redirect( flask.url_for('.package_info', namespace=namespace, package=package)) except pkgdblib.PkgdbException, err: SESSION.rollback() flask.flash(str(err), 'error')
def giveup_acl(namespace, package, acl): ''' Request acls for a specific package. ''' form = pkgdb2.forms.ConfirmationForm() if form.validate_on_submit(): pkg_acl = pkgdblib.get_status(SESSION, 'pkg_acl')['pkg_acl'] if acl not in pkg_acl: flask.flash('Invalid ACL provided %s.' % acl, 'errors') return flask.render_template('msg.html') try: pkg = pkgdblib.search_package( SESSION, namespace=namespace, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect(flask.url_for( '.package_info', namespace=namespace, package=package)) pkg_branchs = set([ pkglist.collection.branchname for pkglist in pkg.listings if pkglist.collection.status in ['Active', 'Under Development'] and flask.g.fas_user.username in [tmpacl.fas_name for tmpacl in pkglist.acls] ]) if not pkg_branchs: flask.flash( 'No active branches found for you for the ACL: %s' % acl, 'error') return flask.redirect(flask.url_for( '.package_info', namespace=namespace, package=package)) for branch in pkg_branchs: print package, namespace, branch, acl, flask.g.fas_user.username try: pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=package, pkg_branch=branch, pkg_user=flask.g.fas_user.username, acl=acl, status='Obsolete', user=flask.g.fas_user, ) flask.flash( 'Your ACL %s is obsoleted on branch %s of package %s' % (acl, branch, package)) except pkgdblib.PkgdbException, err: # pragma: no cover flask.flash(str(err), 'error') SESSION.rollback() try: SESSION.commit() # Keep it in, but normally we shouldn't hit this except pkgdblib.PkgdbException, err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error')
def comaintain_package(package): ''' Asks for ACLs to co-maintain a package. You need to be a packager to request co-maintainership. ''' # This is really wearing belt and suspenders, the decorator above # should take care of this if not 'packager' in flask.g.fas_user.groups: # pragma: no cover flask.flash( 'You must be a packager to apply to be a comaintainer', 'errors') return flask.redirect(flask.url_for( '.package_info', package=package)) try: pkg = pkgdblib.search_package(SESSION, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect( flask.url_for('.package_info', package=package)) pkg_acls = ['commit', 'watchcommits', 'watchbugzilla'] pkg_branchs = [pkglist.collection.branchname for pkglist in pkg.listings] # Make sure the requester does not already have commit pkg_branchs2 = [] for pkg_branch in pkg_branchs: if pkgdblib.has_acls(SESSION, flask.g.fas_user.username, pkg.name, pkg_branch, 'commit'): flask.flash( 'You are already a co-maintainer on %s' % pkg_branch, 'error') else: pkg_branchs2.append(pkg_branch) pkg_branchs = pkg_branchs2 if not pkg_branchs: return flask.redirect(flask.url_for('.package_info', package=package)) try: for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): acl_status = 'Awaiting Review' if acl in APP.config['AUTO_APPROVE']: acl_status = 'Approved' pkgdblib.set_acl_package( SESSION, pkg_name=package, pkg_branch=collec, pkg_user=flask.g.fas_user.username, acl=acl, status=acl_status, user=flask.g.fas_user, ) SESSION.commit() flask.flash('ACLs updated') # Let's keep this in although we should never see it except pkgdblib.PkgdbException, err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error')
def delete_package(namespace, package): ''' Delete the specified package. ''' form = pkgdb2.forms.ConfirmationForm() if not form.validate_on_submit(): flask.flash('Invalid input', 'error') return flask.redirect(flask.url_for( '.package_info', namespace=namespace, package=package)) packagename = package package = None try: package = pkgdblib.search_package( SESSION, namespace, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') for pkglist in package.listings: for acl in pkglist.acls: pkgdb2.lib.utils.log(SESSION, None, 'acl.delete', dict( agent=flask.g.fas_user.username, acl=acl.to_json(), )) SESSION.delete(acl) pkgdb2.lib.utils.log(SESSION, None, 'package.branch.delete', dict( agent=flask.g.fas_user.username, package_listing=pkglist.to_json(), )) SESSION.delete(pkglist) pkgdb2.lib.utils.log(SESSION, None, 'package.delete', dict( agent=flask.g.fas_user.username, package=package.to_json(), )) SESSION.delete(package) try: SESSION.commit() flask.flash('Package %s deleted' % packagename) except SQLAlchemyError as err: # pragma: no cover SESSION.rollback() flask.flash( 'An error occured while trying to delete the package %s' % packagename, 'error') APP.logger.debug('Could not delete package: %s', packagename) APP.logger.exception(err) return flask.redirect(flask.url_for( '.package_info', namespace=package.namespace, package=package.name) ) return flask.redirect( flask.url_for('.list_packages'))
def giveup_acl(package, acl): ''' Request acls for a specific package. ''' form = pkgdb2.forms.ConfirmationForm() if form.validate_on_submit(): pkg_acl = pkgdblib.get_status(SESSION, 'pkg_acl')['pkg_acl'] if acl not in pkg_acl: flask.flash('Invalid ACL provided %s.' % acl, 'errors') return flask.render_template('msg.html') try: pkg = pkgdblib.search_package( SESSION, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect( flask.url_for('.package_info', package=package)) pkg_branchs = set([ pkglist.collection.branchname for pkglist in pkg.listings if pkglist.collection.status in ['Active', 'Under Development'] and flask.g.fas_user.username in [tmpacl.fas_name for tmpacl in pkglist.acls] ]) if not pkg_branchs: flask.flash( 'No active branches found for you for the ACL: %s' % acl, 'error') return flask.redirect( flask.url_for('.package_info', package=package)) for branch in pkg_branchs: try: pkgdblib.set_acl_package( SESSION, pkg_name=package, pkg_branch=branch, pkg_user=flask.g.fas_user.username, acl=acl, status='Obsolete', user=flask.g.fas_user, ) flask.flash( 'Your ACL %s is obsoleted on branch %s of package %s' % (acl, branch, package)) except pkgdblib.PkgdbException, err: flask.flash(str(err), 'error') SESSION.rollback() try: SESSION.commit() # Keep it in, but normally we shouldn't hit this except pkgdblib.PkgdbException, err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error')
def package_orphan(namespace, package, full=True): ''' Gives the possibility to orphan or take a package. ''' if not bool(full) or str(full) in ['0', 'False']: full = False try: package_acl = pkgdblib.get_acl_package( SESSION, namespace, package) package = pkgdblib.search_package( SESSION, namespace, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') collections = [ acl.collection.branchname for acl in package_acl if acl.collection.status in ['Active', 'Under Development'] and acl.status == 'Approved' and ( is_pkgdb_admin(flask.g.fas_user) or acl.point_of_contact == flask.g.fas_user.username or ( acl.point_of_contact.startswith('group::') and is_pkg_admin( SESSION, flask.g.fas_user, namespace, package.name) ) ) ] form = pkgdb2.forms.BranchForm(collections=collections) if form.validate_on_submit(): for branch in form.branches.data: try: pkgdblib.update_pkg_poc( session=SESSION, namespace=namespace, pkg_name=package.name, pkg_branch=branch, pkg_poc='orphan', user=flask.g.fas_user ) flask.flash( 'You are no longer point of contact on branch: %s' % branch) except pkgdblib.PkgdbBugzillaException, err: # pragma: no cover APP.logger.exception(err) flask.flash(str(err), 'error') SESSION.rollback() except pkgdblib.PkgdbException, err: # pragma: no cover flask.flash(str(err), 'error') SESSION.rollback()
def package_give_acls(namespace, package): ''' Give acls to a specified user for a specific package. ''' try: pkg = pkgdblib.search_package( SESSION, namespace=namespace, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect( flask.url_for('.list_packages')) collections = [ pkglist.collection for pkglist in pkg.listings if pkglist.collection.status != 'EOL'] acls = pkgdblib.get_status(SESSION) form = pkgdb2.forms.SetAclPackageForm( collections_obj=collections, pkg_acl=acls['pkg_acl'], acl_status=acls['acl_status'], namespaces=acls['namespaces'], ) form.pkgname.data = package if str(form.namespace.data) in ['None', '']: form.namespace.data = 'rpms' if form.validate_on_submit(): pkg_branchs = form.branches.data pkg_acls = form.acl.data pkg_user = form.user.data acl_status = form.acl_status.data try: for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): if acl in APP.config['AUTO_APPROVE']: acl_status = 'Approved' pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=package, pkg_branch=collec, pkg_user=pkg_user, acl=acl, status=acl_status, user=flask.g.fas_user, ) SESSION.commit() flask.flash('ACLs updated') return flask.redirect(flask.url_for( '.package_info', namespace=namespace, package=package)) except pkgdblib.PkgdbException, err: SESSION.rollback() flask.flash(str(err), 'error')
def request_acl(namespace, package): ''' Request acls for a specific package. ''' try: package_acl = pkgdblib.get_acl_package(SESSION, namespace, package) package = pkgdblib.search_package(SESSION, namespace, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') collections = [ acl.collection for acl in package_acl if acl.collection.status in ['Active', 'Under Development'] ] pkg_acl = pkgdblib.get_status(SESSION, 'pkg_acl')['pkg_acl'] form = pkgdb2.forms.RequestAclPackageForm(collections=collections, pkg_acl_list=pkg_acl) if form.validate_on_submit(): pkg_branchs = form.branches.data pkg_acls = form.acl.data try: for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): acl_status = 'Awaiting Review' if acl in APP.config['AUTO_APPROVE']: acl_status = 'Approved' elif 'packager' not in flask.g.fas_user.groups: flask.flash( 'You must be a packager to apply to the' ' ACL: %s on %s' % (acl, collec), 'errors') continue pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=package.name, pkg_branch=collec, pkg_user=flask.g.fas_user.username, acl=acl, status=acl_status, user=flask.g.fas_user, ) SESSION.commit() flask.flash('ACLs updated') return flask.redirect( flask.url_for('.package_info', namespace=package.namespace, package=package.name)) except pkgdblib.PkgdbException, err: SESSION.rollback() flask.flash(str(err), 'error')
def delete_package(package): ''' Delete the specified package. ''' form = pkgdb2.forms.ConfirmationForm() if not form.validate_on_submit(): flask.flash('Invalid input', 'error') return flask.redirect(flask.url_for('.package_info', package=package)) packagename = package package = None try: package = pkgdblib.search_package(SESSION, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') for pkglist in package.listings: for acl in pkglist.acls: pkgdb2.lib.utils.log( SESSION, None, 'acl.delete', dict( agent=flask.g.fas_user.username, acl=acl.to_json(), )) SESSION.delete(acl) pkgdb2.lib.utils.log( SESSION, None, 'package.branch.delete', dict( agent=flask.g.fas_user.username, package_listing=pkglist.to_json(), )) SESSION.delete(pkglist) pkgdb2.lib.utils.log( SESSION, None, 'package.delete', dict( agent=flask.g.fas_user.username, package=package.to_json(), )) SESSION.delete(package) try: SESSION.commit() flask.flash('Package %s deleted' % packagename) except SQLAlchemyError, err: # pragma: no cover SESSION.rollback() flask.flash( 'An error occured while trying to delete the package %s' % packagename, 'error') APP.logger.debug('Could not delete package: %s', packagename) APP.logger.exception(err) return flask.redirect( flask.url_for('.package_info', package=package.name))
def request_acl(package): ''' Request acls for a specific package. ''' try: package_acl = pkgdblib.get_acl_package(SESSION, package) package = pkgdblib.search_package(SESSION, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') collections = [ acl.collection for acl in package_acl if acl.collection.status in ['Active', 'Under Development'] ] pkg_acl = pkgdblib.get_status(SESSION, 'pkg_acl')['pkg_acl'] form = pkgdb2.forms.RequestAclPackageForm( collections=collections, pkg_acl_list=pkg_acl ) if form.validate_on_submit(): pkg_branchs = form.branches.data pkg_acls = form.acl.data try: for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): acl_status = 'Awaiting Review' if acl in APP.config['AUTO_APPROVE']: acl_status = 'Approved' elif 'packager' not in flask.g.fas_user.groups: flask.flash( 'You must be a packager to apply to the' ' ACL: %s on %s' % (acl, collec), 'errors') continue pkgdblib.set_acl_package( SESSION, pkg_name=package.name, pkg_branch=collec, pkg_user=flask.g.fas_user.username, acl=acl, status=acl_status, user=flask.g.fas_user, ) SESSION.commit() flask.flash('ACLs updated') return flask.redirect( flask.url_for('.package_info', package=package.name)) except pkgdblib.PkgdbException, err: SESSION.rollback() flask.flash(str(err), 'error')
def request_acl_all_branch(namespace, package, acl): ''' Request the specified ACL on all branches of the specified package. ''' form = pkgdb2.forms.ConfirmationForm() if form.validate_on_submit(): pkg_acl = pkgdblib.get_status(SESSION, 'pkg_acl')['pkg_acl'] if acl not in pkg_acl: flask.flash('Invalid ACL provided %s.' % acl, 'errors') return flask.render_template('msg.html') try: pkg = pkgdblib.search_package( SESSION, namespace=namespace, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.render_template('msg.html') pkg_branchs = set([ pkglist.collection.branchname for pkglist in pkg.listings if pkglist.collection.status in ['Active', 'Under Development'] and pkglist.status == 'Approved' ]) for branch in pkg_branchs: acl_status = 'Awaiting Review' pkger_grp = APP.config.get('PKGER_GROUP', 'packager') if acl in APP.config['AUTO_APPROVE']: acl_status = 'Approved' elif pkger_grp not in flask.g.fas_user.groups: flask.flash( 'You must be a %s to apply to the ACL: %s on %s' % ( pkger_grp, acl, package), 'error') try: pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=package, pkg_branch=branch, pkg_user=flask.g.fas_user.username, acl=acl, status=acl_status, user=flask.g.fas_user, ) flask.flash( 'ACL %s requested on branch %s' % (acl, branch)) SESSION.commit() except PkgdbException as err: SESSION.rollback() flask.flash(str(err), 'error') return flask.redirect(flask.url_for( '.package_info', namespace=namespace, package=package))
def request_acl_all_branch(namespace, package, acl): ''' Request the specified ACL on all branches of the specified package. ''' form = pkgdb2.forms.ConfirmationForm() if form.validate_on_submit(): pkg_acl = pkgdblib.get_status(SESSION, 'pkg_acl')['pkg_acl'] if acl not in pkg_acl: flask.flash('Invalid ACL provided %s.' % acl, 'errors') return flask.render_template('msg.html') try: pkg = pkgdblib.search_package(SESSION, namespace=namespace, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.render_template('msg.html') pkg_branchs = set([ pkglist.collection.branchname for pkglist in pkg.listings if pkglist.collection.status in ['Active', 'Under Development'] and pkglist.status == 'Approved' ]) for branch in pkg_branchs: acl_status = 'Awaiting Review' pkger_grp = APP.config.get('PKGER_GROUP', 'packager') if acl in APP.config['AUTO_APPROVE']: acl_status = 'Approved' elif pkger_grp not in flask.g.fas_user.groups: flask.flash( 'You must be a %s to apply to the ACL: %s on %s' % (pkger_grp, acl, package), 'error') try: pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=package, pkg_branch=branch, pkg_user=flask.g.fas_user.username, acl=acl, status=acl_status, user=flask.g.fas_user, ) flask.flash('ACL %s requested on branch %s' % (acl, branch)) SESSION.commit() except PkgdbException as err: SESSION.rollback() flask.flash(str(err), 'error') return flask.redirect( flask.url_for('.package_info', namespace=namespace, package=package))
def comaintain_package(package): ''' Asks for ACLs to co-maintain a package. You need to be a packager to request co-maintainership. ''' # This is really wearing belt and suspenders, the decorator above # should take care of this if not 'packager' in flask.g.fas_user.groups: # pragma: no cover flask.flash('You must be a packager to apply to be a comaintainer', 'errors') return flask.redirect(flask.url_for('.package_info', package=package)) try: pkg = pkgdblib.search_package(SESSION, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect(flask.url_for('.package_info', package=package)) pkg_acls = ['commit', 'watchcommits', 'watchbugzilla'] pkg_branchs = [pkglist.collection.branchname for pkglist in pkg.listings] # Make sure the requester does not already have commit pkg_branchs2 = [] for pkg_branch in pkg_branchs: if pkgdblib.has_acls(SESSION, flask.g.fas_user.username, pkg.name, pkg_branch, 'commit'): flask.flash('You are already a co-maintainer on %s' % pkg_branch, 'error') else: pkg_branchs2.append(pkg_branch) pkg_branchs = pkg_branchs2 if not pkg_branchs: return flask.redirect(flask.url_for('.package_info', package=package)) try: for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): acl_status = 'Awaiting Review' if acl in APP.config['AUTO_APPROVE']: acl_status = 'Approved' pkgdblib.set_acl_package( SESSION, pkg_name=package, pkg_branch=collec, pkg_user=flask.g.fas_user.username, acl=acl, status=acl_status, user=flask.g.fas_user, ) SESSION.commit() flask.flash('ACLs updated') # Let's keep this in although we should never see it except pkgdblib.PkgdbException, err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error')
def package_take(namespace, package, full=True): ''' Make someone Point of contact of an orphaned package. ''' if not bool(full) or str(full) in ['0', 'False']: full = False try: package_acl = pkgdblib.get_acl_package( SESSION, namespace, package) package = pkgdblib.search_package( SESSION, namespace, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') collections = [ acl.collection.branchname for acl in package_acl if acl.collection.status in ['Active', 'Under Development'] and acl.status == 'Orphaned' ] if not collections: flask.flash('No branches orphaned found', 'error') return flask.redirect(flask.url_for( '.package_info', namespace=package.namespace, package=package.name) ) form = pkgdb2.forms.BranchForm(collections=collections) if form.validate_on_submit(): for branch in form.branches.data: try: pkgdblib.unorphan_package( session=SESSION, namespace=package.namespace, pkg_name=package.name, pkg_branch=branch, pkg_user=flask.g.fas_user.username, user=flask.g.fas_user ) SESSION.commit() flask.flash('You have taken the package %s on branch %s' % ( package.name, branch)) except pkgdblib.PkgdbBugzillaException, err: # pragma: no cover APP.logger.exception(err) flask.flash(str(err), 'error') SESSION.rollback() except pkgdblib.PkgdbException, err: # pragma: no cover flask.flash(str(err), 'error') SESSION.rollback()
def package_unretire(package, full=True): ''' Asks an admin to unretire the package. ''' if not bool(full) or str(full) in ['0', 'False']: full = False try: package_acl = pkgdblib.get_acl_package(SESSION, package) package = pkgdblib.search_package(SESSION, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') collections = [ acl.collection.branchname for acl in package_acl if acl.collection.status in ['Active', 'Under Development'] and acl.status == 'Retired' ] form = pkgdb2.forms.BranchForm(collections=collections) if form.validate_on_submit(): for acl in package_acl: if acl.collection.branchname in form.branches.data: if acl.point_of_contact == 'orphan': try: pkgdblib.add_unretire_request( session=SESSION, pkg_name=package.name, pkg_branch=acl.collection.branchname, user=flask.g.fas_user, ) flask.flash( 'Admins have been asked to un-retire branch: %s' % acl.collection.branchname) except pkgdblib.PkgdbException, err: # pragma: no cover # We should never hit this flask.flash(str(err), 'error') SESSION.rollback() except SQLAlchemyError, err: SESSION.rollback() flask.flash( 'Could not save the request for branch: %s, has ' 'it already been requested?' % acl.collection.branchname, 'error') else: # pragma: no cover flask.flash( 'This package is not orphaned on branch: %s' % acl.collection.branchname)
def package_request_branch(namespace, package, full=True): ''' Gives the possibility to request a new branch for this package. ''' if not bool(full) or str(full) in ['0', 'False']: full = False try: package_acl = pkgdblib.get_acl_package(SESSION, namespace, package) package = pkgdblib.search_package(SESSION, namespace, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') branches = [ pkg.collection.branchname for pkg in package_acl if pkg.collection.status != 'EOL' ] collections = pkgdb2.lib.search_collection(SESSION, '*', 'Under Development') collections.extend(pkgdb2.lib.search_collection(SESSION, '*', 'Active')) branches_possible = [ collec.branchname for collec in collections if collec.branchname not in branches ] form = pkgdb2.forms.BranchForm(collections=branches_possible) if form.validate_on_submit(): for branch in form.branches.data: try: msg = pkgdblib.add_new_branch_request( session=SESSION, namespace=package.namespace, pkg_name=package.name, clt_to=branch, user=flask.g.fas_user) SESSION.commit() flask.flash(msg) except pkgdblib.PkgdbException, err: # pragma: no cover flask.flash(str(err), 'error') SESSION.rollback() except SQLAlchemyError, err: # pragma: no cover APP.logger.exception(err) flask.flash( 'Could not save the request to the database for ' 'branch: %s' % branch, 'error') SESSION.rollback()
def package_take(namespace, package, full=True): ''' Make someone Point of contact of an orphaned package. ''' if not bool(full) or str(full) in ['0', 'False']: full = False try: package_acl = pkgdblib.get_acl_package(SESSION, namespace, package) package = pkgdblib.search_package(SESSION, namespace, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') collections = [ acl.collection.branchname for acl in package_acl if acl.collection.status in ['Active', 'Under Development'] and acl.status == 'Orphaned' ] if not collections: flask.flash('No branches orphaned found', 'error') return flask.redirect( flask.url_for('.package_info', namespace=package.namespace, package=package.name)) form = pkgdb2.forms.BranchForm(collections=collections) if form.validate_on_submit(): for branch in form.branches.data: try: pkgdblib.unorphan_package(session=SESSION, namespace=package.namespace, pkg_name=package.name, pkg_branch=branch, pkg_user=flask.g.fas_user.username, user=flask.g.fas_user) SESSION.commit() flask.flash('You have taken the package %s on branch %s' % (package.name, branch)) except pkgdblib.PkgdbBugzillaException, err: # pragma: no cover APP.logger.exception(err) flask.flash(str(err), 'error') SESSION.rollback() except pkgdblib.PkgdbException, err: # pragma: no cover flask.flash(str(err), 'error') SESSION.rollback()
def package_unretire(package, full=True): ''' Asks an admin to unretire the package. ''' if not bool(full) or str(full) in ['0', 'False']: full = False try: package_acl = pkgdblib.get_acl_package(SESSION, package) package = pkgdblib.search_package(SESSION, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') collections = [ acl.collection.branchname for acl in package_acl if acl.collection.status in ['Active', 'Under Development'] and acl.status == 'Retired' ] form = pkgdb2.forms.BranchForm(collections=collections) if form.validate_on_submit(): for acl in package_acl: if acl.collection.branchname in form.branches.data: if acl.point_of_contact == 'orphan': try: pkgdblib.add_unretire_request( session=SESSION, pkg_name=package.name, pkg_branch=acl.collection.branchname, user=flask.g.fas_user, ) flask.flash( 'Admins have been asked to un-retire branch: %s' % acl.collection.branchname) except pkgdblib.PkgdbException, err: # pragma: no cover # We should never hit this flask.flash(str(err), 'error') SESSION.rollback() except SQLAlchemyError, err: SESSION.rollback() flask.flash( 'Could not save the request for branch: %s, has ' 'it already been requested?' % acl.collection.branchname, 'error') else: # pragma: no cover flask.flash('This package is not orphaned on branch: %s' % acl.collection.branchname)
def dropcommit_package(namespace, package): ''' Obsolete commit ACLs on a package. This method can only be used for the user itself. ''' form = pkgdb2.forms.ConfirmationForm() if form.validate_on_submit(): try: pkg = pkgdblib.search_package(SESSION, namespace=namespace, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect( flask.url_for('.package_info', namespace=namespace, package=package)) pkg_acls = ['commit'] pkg_branchs = set() for pkglist in pkg.listings: if pkglist.collection.status in ['Active', 'Under Development']: for acl in pkglist.acls: if acl.fas_name == flask.g.fas_user.username and \ acl.acl == 'commit' and acl.status == 'Approved': pkg_branchs.add(pkglist.collection.branchname) try: for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=package, pkg_branch=collec, pkg_user=flask.g.fas_user.username, acl=acl, status='Obsolete', user=flask.g.fas_user, ) SESSION.commit() flask.flash('ACLs updated') # Let's keep this in although we should never see it except PkgdbException as err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error') return flask.redirect( flask.url_for('.package_info', namespace=namespace, package=package))
def package_orphan(namespace, package, full=True): ''' Gives the possibility to orphan or take a package. ''' if not bool(full) or str(full) in ['0', 'False']: full = False try: package_acl = pkgdblib.get_acl_package(SESSION, namespace, package) package = pkgdblib.search_package(SESSION, namespace, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') collections = [ acl.collection.branchname for acl in package_acl if acl.collection.status in ['Active', 'Under Development'] and acl.status == 'Approved' and ( is_pkgdb_admin(flask.g.fas_user) or acl.point_of_contact == flask.g.fas_user.username or (acl.point_of_contact.startswith('group::') and is_pkg_admin( SESSION, flask.g.fas_user, namespace, package.name))) ] form = pkgdb2.forms.BranchForm(collections=collections) if form.validate_on_submit(): for branch in form.branches.data: try: pkgdblib.update_pkg_poc(session=SESSION, namespace=namespace, pkg_name=package.name, pkg_branch=branch, pkg_poc='orphan', user=flask.g.fas_user) flask.flash( 'You are no longer point of contact on branch: %s' % branch) except pkgdblib.PkgdbBugzillaException, err: # pragma: no cover APP.logger.exception(err) flask.flash(str(err), 'error') SESSION.rollback() except pkgdblib.PkgdbException, err: # pragma: no cover flask.flash(str(err), 'error') SESSION.rollback()
def dropcommit_package(namespace, package): ''' Obsolete commit ACLs on a package. This method can only be used for the user itself. ''' form = pkgdb2.forms.ConfirmationForm() if form.validate_on_submit(): try: pkg = pkgdblib.search_package( SESSION, namespace=namespace, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect(flask.url_for( '.package_info', namespace=namespace, package=package)) pkg_acls = ['commit'] pkg_branchs = set() for pkglist in pkg.listings: if pkglist.collection.status in [ 'Active', 'Under Development']: for acl in pkglist.acls: if acl.fas_name == flask.g.fas_user.username and \ acl.acl == 'commit' and acl.status == 'Approved': pkg_branchs.add(pkglist.collection.branchname) try: for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=package, pkg_branch=collec, pkg_user=flask.g.fas_user.username, acl=acl, status='Obsolete', user=flask.g.fas_user, ) SESSION.commit() flask.flash('ACLs updated') # Let's keep this in although we should never see it except PkgdbException as err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error') return flask.redirect(flask.url_for( '.package_info', namespace=namespace, package=package))
def watch_package(namespace, package): ''' Request watch* ACLs on a package. Anyone can request these ACLs, no need to be a packager. ''' form = pkgdb2.forms.ConfirmationForm() if form.validate_on_submit(): try: pkg = pkgdblib.search_package(SESSION, namespace=namespace, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect( flask.url_for('.package_info', namespace=namespace, package=package)) pkg_acls = ['watchcommits', 'watchbugzilla'] pkg_branchs = set([ pkglist.collection.branchname for pkglist in pkg.listings if pkglist.collection.status in ['Active', 'Under Development'] and pkglist.status == 'Approved' ]) try: for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=package, pkg_branch=collec, pkg_user=flask.g.fas_user.username, acl=acl, status='Approved', user=flask.g.fas_user, ) SESSION.commit() flask.flash('ACLs updated') # Let's keep this in although we should never see it except PkgdbException as err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error') return flask.redirect( flask.url_for('.package_info', namespace=namespace, package=package))
def watch_package(namespace, package): ''' Request watch* ACLs on a package. Anyone can request these ACLs, no need to be a packager. ''' form = pkgdb2.forms.ConfirmationForm() if form.validate_on_submit(): try: pkg = pkgdblib.search_package( SESSION, namespace=namespace, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect(flask.url_for( '.package_info', namespace=namespace, package=package)) pkg_acls = ['watchcommits', 'watchbugzilla'] pkg_branchs = set([ pkglist.collection.branchname for pkglist in pkg.listings if pkglist.collection.status in ['Active', 'Under Development'] and pkglist.status == 'Approved' ]) try: for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=package, pkg_branch=collec, pkg_user=flask.g.fas_user.username, acl=acl, status='Approved', user=flask.g.fas_user, ) SESSION.commit() flask.flash('ACLs updated') # Let's keep this in although we should never see it except PkgdbException as err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error') return flask.redirect(flask.url_for( '.package_info', namespace=namespace, package=package))
def unwatch_package(package): ''' Obsolete watch* ACLs on a package. This method can only be used for the user itself. ''' form = pkgdb2.forms.ConfirmationForm() if form.validate_on_submit(): try: pkg = pkgdblib.search_package( SESSION, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect( flask.url_for('.package_info', package=package)) pkg_acls = ['watchcommits', 'watchbugzilla'] pkg_branchs = set([ pkglist.collection.branchname for pkglist in pkg.listings if pkglist.collection.status in ['Active', 'Under Development']]) try: for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): pkgdblib.set_acl_package( SESSION, pkg_name=package, pkg_branch=collec, pkg_user=flask.g.fas_user.username, acl=acl, status='Obsolete', user=flask.g.fas_user, ) SESSION.commit() flask.flash('ACLs updated') # Let's keep this in although we should never see it except pkgdblib.PkgdbException, err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error')
def update_acl(package, update_acl): ''' Update the acls of a package. ''' packagename = package package = None try: package_acl = pkgdblib.get_acl_package(SESSION, packagename) package = pkgdblib.search_package(SESSION, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') statues = pkgdblib.get_status(SESSION) planned_acls = set(statues['pkg_acl']) acl_status = list(set(statues['acl_status'])) acl_status.insert(0, '') if update_acl not in planned_acls: flask.flash('Invalid ACL to update.', 'errors') return flask.redirect( flask.url_for('.package_info', package=package.name)) branches = {} branches_inv = {} commit_acls = {} admins = {} committers = [] for pkg in package_acl: if pkg.collection.status == 'EOL': # pragma: no cover continue collection_name = '%s %s' % (pkg.collection.name, pkg.collection.version) if collection_name not in branches: branches[collection_name] = pkg.collection.branchname if pkg.collection.branchname not in branches_inv: branches_inv[pkg.collection.branchname] = collection_name for acl in pkg.acls: if acl.acl == 'approveacls' and acl.status == 'Approved': if acl.fas_name not in admins: admins[acl.fas_name] = set() admins[acl.fas_name].add(collection_name) if acl.acl != update_acl: continue committers.append(acl.fas_name) if acl.fas_name not in commit_acls: commit_acls[acl.fas_name] = {} if collection_name not in commit_acls[acl.fas_name]: commit_acls[acl.fas_name][collection_name] = {} commit_acls[acl.fas_name][collection_name][acl.acl] = \ acl.status for aclname in planned_acls: for user in commit_acls: if collection_name in commit_acls[user] and \ aclname not in commit_acls[user][collection_name]: commit_acls[user][collection_name][aclname] = None # If the user is not an admin, he/she can only access his/her ACLs username = flask.g.fas_user.username if username not in admins and not is_pkgdb_admin(flask.g.fas_user): tmp = {username: []} if username in commit_acls: tmp = {username: commit_acls[username]} commit_acls = tmp form = pkgdb2.forms.ConfirmationForm() if form.validate_on_submit(): sub_acls = flask.request.values.getlist('acls') sub_users = flask.request.values.getlist('user') sub_branches = flask.request.values.getlist('branch') changed = False if sub_acls and len(sub_acls) == (len(sub_users) * len(sub_branches)): cnt = 0 for cnt_u in range(len(sub_users)): for cnt_b in range(len(sub_branches)): lcl_acl = sub_acls[cnt] lcl_user = sub_users[cnt_u] lcl_branch = sub_branches[cnt_b] if lcl_acl not in acl_status: flask.flash('Invalid ACL: %s' % lcl_acl, 'error') cnt += 1 continue if lcl_user not in commit_acls: flask.flash('Invalid user: %s' % lcl_user, 'error') cnt += 1 continue if lcl_branch not in branches_inv or ( branches_inv[lcl_branch] in commit_acls[lcl_user] and commit_acls[lcl_user][branches_inv[lcl_branch]] [update_acl] == lcl_acl): cnt += 1 continue if not lcl_acl: if branches_inv[lcl_branch] \ not in commit_acls[lcl_user]: cnt += 1 continue elif branches_inv[lcl_branch] \ in commit_acls[lcl_user] \ and username != lcl_user: flask.flash('Only the user can remove his/her ACL', 'error') cnt += 1 continue try: pkgdblib.set_acl_package( SESSION, pkg_name=package.name, pkg_branch=lcl_branch, pkg_user=lcl_user, acl=update_acl, status=lcl_acl, user=flask.g.fas_user, ) SESSION.commit() flask.flash("%s's %s ACL updated on %s" % (lcl_user, update_acl, lcl_branch)) changed = True except pkgdblib.PkgdbException, err: SESSION.rollback() flask.flash(str(err), 'error') cnt += 1 SESSION.commit() if not changed: flask.flash('Nothing to update') return flask.redirect( flask.url_for('.package_info', package=package.name)) else: flask.flash('Invalid input submitted', 'error')
def package_info(package): ''' Display the information about the specified package. ''' packagename = package package = None try: package_acl = pkgdblib.get_acl_package(SESSION, packagename) package = pkgdblib.search_package(SESSION, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') package_acls = [] branch_admin = [] is_poc = False for pkg in package_acl: if pkg.collection.status == 'EOL': # pragma: no cover continue tmp = {} tmp['collection'] = '%s %s' % (pkg.collection.name, pkg.collection.version) tmp['branchname'] = pkg.collection.branchname tmp['point_of_contact'] = pkg.point_of_contact tmp['status'] = pkg.status if hasattr(flask.g, 'fas_user') and flask.g.fas_user and \ pkg.point_of_contact == flask.g.fas_user.username: is_poc = True acls = {} for acl in pkg.acls: tmp2 = {'acl': acl.acl, 'status': acl.status} if acl.fas_name in acls: acls[acl.fas_name].append(tmp2) else: acls[acl.fas_name] = [tmp2] ## This list is a little hacky, but we would have to save ACLs ## in their own table otherwise. planned_acls = set(['approveacls', 'commit', 'watchbugzilla', 'watchcommits']) for fas_name in acls: seen_acls = set([acl['acl'] for acl in acls[fas_name]]) for aclname in planned_acls - seen_acls: acls[fas_name].append({'acl': aclname, 'status': ''}) tmp['acls'] = acls package_acls.append(tmp) if is_pkg_admin(SESSION, flask.g.fas_user, package.name, pkg.collection.branchname): branch_admin.append(pkg.collection.branchname) package_acls.reverse() if package_acls: package_acls.insert(0, package_acls.pop()) return flask.render_template( 'package.html', package=package, package_acl=package_acls, branch_admin=branch_admin, is_poc=is_poc, )
def comaintain_package(namespace, package): ''' Asks for ACLs to co-maintain a package. You need to be a packager to request co-maintainership. ''' form = pkgdb2.forms.ConfirmationForm() if form.validate_on_submit(): # This is really wearing belt and suspenders, the decorator above # should take care of this pkger_grp = APP.config.get('PKGER_GROUP', 'packager') if pkger_grp not in flask.g.fas_user.groups: # pragma: no cover flask.flash( 'You must be a %s to apply to be a comaintainer' % pkger_grp, 'errors') return flask.redirect(flask.url_for( '.package_info', package=package)) try: pkg = pkgdblib.search_package( SESSION, namespace=namespace, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect(flask.url_for( '.package_info', namespace=namespace, package=package)) pkg_acls = ['commit', 'watchcommits', 'watchbugzilla'] pkg_branchs = set([ pkglist.collection.branchname for pkglist in pkg.listings if pkglist.collection.status in ['Active', 'Under Development'] and pkglist.status == 'Approved' ]) # Make sure the requester does not already have commit pkg_branchs2 = [] for pkg_branch in pkg_branchs: if pkgdblib.has_acls( SESSION, flask.g.fas_user.username, pkg.namespace, pkg.name, acl='commit', branch=pkg_branch): flask.flash( 'You are already a co-maintainer on %s' % pkg_branch, 'error') else: pkg_branchs2.append(pkg_branch) pkg_branchs = pkg_branchs2 if not pkg_branchs: return flask.redirect(flask.url_for( '.package_info', namespace=namespace, package=package)) try: msgs = [] for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): acl_status = 'Awaiting Review' if acl in APP.config['AUTO_APPROVE']: acl_status = 'Approved' msg = pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=package, pkg_branch=collec, pkg_user=flask.g.fas_user.username, acl=acl, status=acl_status, user=flask.g.fas_user, ) if msg: msgs.append(msg) SESSION.commit() if msgs: flask.flash('ACLs updated') else: flask.flash('Nothing to update') # Let's keep this in although we should never see it except PkgdbException as err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error') return flask.redirect(flask.url_for( '.package_info', namespace=namespace, package=package))
def package_give(package, full=True): ''' Gives the PoC of a package to someone else. ''' if not bool(full) or str(full) in ['0', 'False']: full = False packagename = package package = None try: package_acl = pkgdblib.get_acl_package(SESSION, packagename) package = pkgdblib.search_package(SESSION, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') # Restrict the branch to the one current user is PoC of (unless admin # or group) collect_name = [] for acl in package_acl: if acl.point_of_contact != flask.g.fas_user.username and \ not is_pkgdb_admin(flask.g.fas_user) and \ not acl.point_of_contact.startswith('group::'): pass else: if acl.point_of_contact.startswith('group::'): group = acl.point_of_contact.split('group::')[0] if group not in flask.g.fas_user.groups: pass elif acl.collection.status != 'EOL': collect_name.append(acl.collection.branchname) form = pkgdb2.forms.GivePoCForm(collections=collect_name) acls = ['commit', 'watchbugzilla', 'watchcommits', 'approveacls'] if form.validate_on_submit(): collections = form.branches.data pkg_poc = form.poc.data if pkg_poc.startswith('group::'): acls = ['commit', 'watchbugzilla', 'watchcommits'] try: for pkg_collection in collections: message = pkgdblib.update_pkg_poc( SESSION, pkg_name=packagename, pkg_branch=pkg_collection, pkg_poc=pkg_poc, user=flask.g.fas_user, ) flask.flash(message) for acl in acls: pkgdblib.set_acl_package(SESSION, pkg_name=packagename, pkg_branch=pkg_collection, pkg_user=pkg_poc, acl=acl, status='Approved', user=flask.g.fas_user) SESSION.commit() except pkgdblib.PkgdbBugzillaException, err: # pragma: no cover APP.logger.exception(err) flask.flash(str(err), 'error') SESSION.rollback() except pkgdblib.PkgdbException, err: SESSION.rollback() flask.flash(str(err), 'error')
def list_packages(motif=None, orphaned=None, status=None, origin='list_packages', case_sensitive=False): ''' Display the list of packages corresponding to the motif. ''' pattern = flask.request.args.get('motif', motif) or '*' branches = flask.request.args.get('branches', None) owner = flask.request.args.get('owner', None) orphaned = flask.request.args.get('orphaned', orphaned) if str(orphaned) in ['False', '0']: orphaned = False status = flask.request.args.get('status', status) limit = flask.request.args.get('limit', APP.config['ITEMS_PER_PAGE']) page = flask.request.args.get('page', 1) case_sensitive = flask.request.args.get('case_sensitive', False) try: page = abs(int(page)) except ValueError: page = 1 try: limit = abs(int(limit)) except ValueError: limit = APP.config['ITEMS_PER_PAGE'] flask.flash('Incorrect limit provided, using default', 'errors') packages = pkgdblib.search_package( SESSION, pkg_name=pattern, pkg_branch=branches, pkg_poc=owner, orphaned=orphaned, status=status, page=page, limit=limit, case_sensitive=case_sensitive, ) packages_count = pkgdblib.search_package( SESSION, pkg_name=pattern, pkg_branch=branches, pkg_poc=owner, orphaned=orphaned, status=status, page=page, limit=limit, count=True, case_sensitive=case_sensitive, ) total_page = int(ceil(packages_count / float(limit))) select = origin.replace('list_', '') if len(packages) == 1: flask.flash('Only one package matching, redirecting you to it') return flask.redirect( flask.url_for('.package_info', package=packages[0].name)) return flask.render_template( 'list_packages.html', origin=origin, select=select, packages=packages, motif=motif, total_page=total_page, packages_count=packages_count, page=page, status=status, owner=owner, branches=branches, )
def comaintain_package(namespace, package): ''' Asks for ACLs to co-maintain a package. You need to be a packager to request co-maintainership. ''' form = pkgdb2.forms.ConfirmationForm() if form.validate_on_submit(): # This is really wearing belt and suspenders, the decorator above # should take care of this pkger_grp = APP.config.get('PKGER_GROUP', 'packager') if pkger_grp not in flask.g.fas_user.groups: # pragma: no cover flask.flash( 'You must be a %s to apply to be a comaintainer' % pkger_grp, 'errors') return flask.redirect( flask.url_for('.package_info', package=package)) try: pkg = pkgdblib.search_package(SESSION, namespace=namespace, pkg_name=package, limit=1)[0] except IndexError: flask.flash('No package found by this name', 'error') return flask.redirect( flask.url_for('.package_info', namespace=namespace, package=package)) pkg_acls = ['commit', 'watchcommits', 'watchbugzilla'] pkg_branchs = set([ pkglist.collection.branchname for pkglist in pkg.listings if pkglist.collection.status in ['Active', 'Under Development'] and pkglist.status == 'Approved' ]) # Make sure the requester does not already have commit pkg_branchs2 = [] for pkg_branch in pkg_branchs: if pkgdblib.has_acls(SESSION, flask.g.fas_user.username, pkg.namespace, pkg.name, acl='commit', branch=pkg_branch): flask.flash( 'You are already a co-maintainer on %s' % pkg_branch, 'error') else: pkg_branchs2.append(pkg_branch) pkg_branchs = pkg_branchs2 if not pkg_branchs: return flask.redirect( flask.url_for('.package_info', namespace=namespace, package=package)) try: msgs = [] for (collec, acl) in itertools.product(pkg_branchs, pkg_acls): acl_status = 'Awaiting Review' if acl in APP.config['AUTO_APPROVE']: acl_status = 'Approved' msg = pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=package, pkg_branch=collec, pkg_user=flask.g.fas_user.username, acl=acl, status=acl_status, user=flask.g.fas_user, ) if msg: msgs.append(msg) SESSION.commit() if msgs: flask.flash('ACLs updated') else: flask.flash('Nothing to update') # Let's keep this in although we should never see it except PkgdbException as err: # pragma: no cover SESSION.rollback() flask.flash(str(err), 'error') return flask.redirect( flask.url_for('.package_info', namespace=namespace, package=package))
def list_packages(namespace=None, motif=None, orphaned=None, status=None, origin='list_packages', case_sensitive=False): ''' Display the list of packages corresponding to the motif. ''' pattern = flask.request.args.get('motif', motif) or '*' branches = flask.request.args.get('branches', None) owner = flask.request.args.get('owner', None) namespace = flask.request.args.get('namespace', namespace) orphaned = flask.request.args.get('orphaned', orphaned) if str(orphaned) in ['False', '0']: orphaned = False status = flask.request.args.get('status', status) limit = flask.request.args.get('limit', APP.config['ITEMS_PER_PAGE']) page = flask.request.args.get('page', 1) case_sensitive = flask.request.args.get('case_sensitive', False) try: page = abs(int(page)) except ValueError: page = 1 try: limit = abs(int(limit)) except ValueError: limit = APP.config['ITEMS_PER_PAGE'] flask.flash('Incorrect limit provided, using default', 'errors') packages = pkgdblib.search_package( SESSION, namespace=namespace, pkg_name=pattern, pkg_branch=branches, pkg_poc=owner, orphaned=orphaned, status=status, page=page, limit=limit, case_sensitive=case_sensitive, ) packages_count = pkgdblib.search_package( SESSION, namespace=namespace, pkg_name=pattern, pkg_branch=branches, pkg_poc=owner, orphaned=orphaned, status=status, page=page, limit=limit, count=True, case_sensitive=case_sensitive, ) total_page = int(ceil(packages_count / float(limit))) select = origin.replace('list_', '') if namespace: select = namespace if len(packages) == 1: flask.flash('Only one package matching, redirecting you to it') return flask.redirect(flask.url_for( '.package_info', namespace=packages[0].namespace, package=packages[0].name) ) return flask.render_template( 'list_packages.html', origin=origin, select=select, packages=packages, motif=pattern, total_page=total_page, packages_count=packages_count, page=page, status=status, owner=owner, branches=branches, namespace=namespace, )
def api_package_edit(): ''' Edit a package -------------- Edit a package. :: /api/package/edit/ Accepts POST queries only. :arg pkgname: String of the package name to be created. :arg summary: String of the summary description of the package. :arg description: String describing the package (same as in the spec file). :arg review_url: the URL of the package review on the bugzilla. :arg status: status of the package can be one of: 'Approved', 'Awaiting Review', 'Denied', 'Obsolete', 'Removed' :arg upstream_url: the URL of the upstream project Sample response: :: { "output": "ok", "messages": ["Package edited"] } { "output": "notok", "error": ["You're not allowed to edit this package"] } ''' httpcode = 200 output = {} pkg_status = pkgdblib.get_status(SESSION, 'pkg_status')['pkg_status'] form = forms.EditPackageForm( csrf_enabled=False, pkg_status_list=pkg_status, ) if form.validate_on_submit(): pkg_name = form.pkgname.data package = None try: package = pkgdblib.search_package(SESSION, pkg_name, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() output['output'] = 'notok' output['error'] = 'No package of this name found' httpcode = 500 if package: pkg_summary = form.summary.data pkg_description = form.description.data pkg_review_url = form.review_url.data pkg_status = form.status.data if pkg_status == 'None': pkg_status = None pkg_upstream_url = form.upstream_url.data try: message = pkgdblib.edit_package( SESSION, package, pkg_name=pkg_name, pkg_summary=pkg_summary, pkg_description=pkg_description, pkg_review_url=pkg_review_url, pkg_upstream_url=pkg_upstream_url, pkg_status=pkg_status, user=flask.g.fas_user) SESSION.commit() output['output'] = 'ok' output['messages'] = [message] except pkgdblib.PkgdbException, err: # pragma: no cover # We can only reach here in two cases: # 1) the user is not an admin, but that's taken care of # by the decorator # 2) we have a SQLAlchemy problem when storing the info # in the DB which we cannot test SESSION.rollback() output['output'] = 'notok' output['error'] = str(err) httpcode = 500
def api_branch_request(package, namespace='rpms'): ''' New branch request ------------------ Request a new branch for package in pkgdb. :: /api/request/branch/<namespace>/<package> Accepts POST queries only. :arg package: The name of the package :arg branches: The list of branches desired for this package. :arg namespace: The namespace of the package (default to ``rpms``). Sample response: :: { 'messages': [ 'Branch f17 created for user pingou', ], 'output': 'ok' } { "messages": [ "Branch el6 requested for user pingou" ], "output": "ok" } { "output": "notok", 'error': 'User "pingou" is not in the packager group', } { "error": "Invalid input submitted", "error_detail": [ "branches: 'foobar' is not a valid choice for this field", ], "output": "notok" } ''' httpcode = 200 output = {} try: package_acl = pkgdblib.get_acl_package(SESSION, namespace, package) package = pkgdblib.search_package( SESSION, namespace, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() output['output'] = 'notok' output['error'] = 'No package found: %s/%s' % (namespace, package) httpcode = 404 else: branches = [ pkg.collection.branchname for pkg in package_acl if pkg.collection.status != 'EOL' ] collections = pkgdblib.search_collection( SESSION, '*', 'Under Development') collections.extend(pkgdblib.search_collection( SESSION, '*', 'Active')) branches_possible = [ collec.branchname for collec in collections if collec.branchname not in branches] form = forms.BranchForm( collections=branches_possible, csrf_enabled=False, ) if form.validate_on_submit(): try: messages = [] for branch in form.branches.data: msg = pkgdblib.add_new_branch_request( session=SESSION, namespace=namespace, pkg_name=package.name, clt_to=branch, user=flask.g.fas_user) if msg: messages.append(msg) SESSION.commit() output['output'] = 'ok' output['messages'] = messages except pkgdblib.PkgdbException, err: # pragma: no cover SESSION.rollback() output['output'] = 'notok' output['error'] = str(err) httpcode = 400 except SQLAlchemyError, err: # pragma: no cover SESSION.rollback() APP.logger.exception(err) output['output'] = 'notok' output['error'] = 'Could not save the request to the '\ 'database for branch: %s' % branch httpcode = 400
def package_unretire(namespace, package, full=True): ''' Asks an admin to unretire the package. ''' if not bool(full) or str(full) in ['0', 'False']: full = False try: package_acl = pkgdblib.get_acl_package(SESSION, namespace, package) package = pkgdblib.search_package(SESSION, namespace, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') # Get the list of retired branches retire_collections = [ acl.collection.branchname for acl in package_acl if acl.collection.status in ['Active', 'Under Development'] and acl.status == 'Retired' ] # Get the list of all the collections active or under development collections = [ collection.branchname for collection in pkgdb2.lib.search_collection( SESSION, '*', 'Under Development') if collection.branchname in retire_collections ] collections.reverse() active_collections = pkgdb2.lib.search_collection(SESSION, '*', 'Active') active_collections.reverse() cnt = 0 # Restrict the Fedora branch to 2 active versions for collection in active_collections: if collection.name.lower() == 'fedora': if cnt >= 2: continue cnt += 1 if collection.branchname not in retire_collections: continue collections.append(collection.branchname) form = pkgdb2.forms.UnretireForm(collections=collections) if form.validate_on_submit(): review_url = form.review_url.data review_url = review_url.strip() if review_url else None checks_ok = True for br in form.branches.data: if br == 'master' and not review_url: checks_ok = False flask.flash( 'You must provide a review URL to un-retire master', 'error') break elif br.startswith( 'e') and 'master' in collections and not review_url: checks_ok = False flask.flash( 'You must provide a review URL to un-retire an EPEL ' 'branch if master is also retired', 'error') break if not checks_ok: return flask.redirect( flask.url_for('.package_info', namespace=package.namespace, package=package.name)) for acl in package_acl: if acl.collection.branchname in form.branches.data: if acl.point_of_contact == 'orphan': try: pkgdblib.add_unretire_request( session=SESSION, namespace=namespace, pkg_name=package.name, pkg_branch=acl.collection.branchname, review_url=form.review_url.data, user=flask.g.fas_user, ) flask.flash( 'Admins have been asked to un-retire branch: %s' % acl.collection.branchname) except pkgdblib.PkgdbException, err: # pragma: no cover # We should never hit this flask.flash(str(err), 'error') SESSION.rollback() except SQLAlchemyError, err: SESSION.rollback() flask.flash( 'Could not save the request for branch: %s, has ' 'it already been requested?' % acl.collection.branchname, 'error') else: # pragma: no cover flask.flash('This package is not orphaned on branch: %s' % acl.collection.branchname)
def package_unretire(namespace, package, full=True): ''' Asks an admin to unretire the package. ''' if not bool(full) or str(full) in ['0', 'False']: full = False try: package_acl = pkgdblib.get_acl_package( SESSION, namespace, package) package = pkgdblib.search_package( SESSION, namespace, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') # Get the list of retired branches retire_collections = [ acl.collection.branchname for acl in package_acl if acl.collection.status in ['Active', 'Under Development'] and acl.status == 'Retired' ] # Get the list of all the collections active or under development collections = [ collection.branchname for collection in pkgdb2.lib.search_collection(SESSION, '*', 'Under Development') if collection.branchname in retire_collections ] collections.reverse() active_collections = pkgdb2.lib.search_collection(SESSION, '*', 'Active') active_collections.reverse() cnt = 0 # Restrict the Fedora branch to 2 active versions for collection in active_collections: if collection.name.lower() == 'fedora': if cnt >= 2: continue cnt += 1 if collection.branchname not in retire_collections: continue collections.append(collection.branchname) form = pkgdb2.forms.UnretireForm(collections=collections) if form.validate_on_submit(): review_url = form.review_url.data review_url = review_url.strip() if review_url else None checks_ok = True # Check the review URL bz = APP.config.get('PKGDB2_BUGZILLA_URL') review_url = pkgdblib.check_bz_url(bz, review_url) for br in form.branches.data: if br.startswith('e') \ and 'master' in collections \ and not review_url: checks_ok = False flask.flash( 'You must provide a valid review URL to un-retire an ' 'EPEL branch if master is also retired', 'error') break if not checks_ok: return flask.redirect(flask.url_for( '.package_info', namespace=package.namespace, package=package.name) ) for acl in package_acl: if acl.collection.branchname in form.branches.data: if acl.point_of_contact == 'orphan': try: pkgdblib.add_unretire_request( session=SESSION, namespace=namespace, pkg_name=package.name, pkg_branch=acl.collection.branchname, review_url=review_url, user=flask.g.fas_user, ) flask.flash( 'Admins have been asked to un-retire branch: %s' % acl.collection.branchname) except PkgdbException as err: # pragma: no cover # We should never hit this flask.flash(str(err), 'error') SESSION.rollback() except SQLAlchemyError as err: APP.logger.exception(err) SESSION.rollback() flask.flash( 'Could not save the request for branch: %s, has ' 'it already been requested?' % acl.collection.branchname, 'error') else: # pragma: no cover flask.flash( 'This package is not orphaned on branch: %s' % acl.collection.branchname) try: SESSION.commit() # Keep it in, but normally we shouldn't hit this except PkgdbException as err: # pragma: no cover # We should never hit this SESSION.rollback() APP.logger.exception(err) flask.flash(str(err), 'error') return flask.redirect(flask.url_for( '.package_info', namespace=package.namespace, package=package.name) ) return flask.render_template( 'request_unretire.html', full=full, package=package, form=form, action='unretire', )
def package_retire(namespace, package, full=True): ''' Gives the possibility to orphan or take a package. ''' if not bool(full) or str(full) in ['0', 'False']: full = False try: package_acl = pkgdblib.get_acl_package( SESSION, namespace, package) package = pkgdblib.search_package( SESSION, namespace, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') if not is_pkgdb_admin(flask.g.fas_user): flask.flash( 'Only Admins are allowed to retire package here, ' 'you should use `fedpkg retire`.', 'errors') return flask.redirect(flask.url_for( '.package_info', namespace=package.namespace, package=package.name) ) collections = [ acl.collection.branchname for acl in package_acl if acl.collection.status in ['Active', 'Under Development'] and acl.status == 'Orphaned' ] form = pkgdb2.forms.BranchForm(collections=collections) if form.validate_on_submit(): for acl in package_acl: if acl.collection.branchname in form.branches.data: if acl.point_of_contact == 'orphan': try: pkgdblib.update_pkg_status( session=SESSION, namespace=namespace, pkg_name=package.name, pkg_branch=acl.collection.branchname, status='Retired', user=flask.g.fas_user ) flask.flash( 'This package has been retired on branch: %s' % acl.collection.branchname) except PkgdbException as err: # pragma: no cover # We should never hit this flask.flash(str(err), 'error') SESSION.rollback() APP.logger.exception(err) else: # pragma: no cover flask.flash( 'This package has not been orphaned on ' 'branch: %s' % acl.collection.branchname) try: SESSION.commit() # Keep it in, but normally we shouldn't hit this except PkgdbException as err: # pragma: no cover # We should never hit this SESSION.rollback() APP.logger.exception(err) flask.flash(str(err), 'error') return flask.redirect(flask.url_for( '.package_info', namespace=package.namespace, package=package.name) ) return flask.render_template( 'branch_selection.html', full=full, package=package, form=form, action='retire', )
def package_give(namespace, package, full=True): ''' Gives the PoC of a package to someone else. ''' if not bool(full) or str(full) in ['0', 'False']: full = False packagename = package package = None try: package_acl = pkgdblib.get_acl_package( SESSION, namespace, packagename) package = pkgdblib.search_package( SESSION, namespace, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') # Restrict the branch to the one current user is PoC of (unless admin # or group) collect_name = [] for acl in package_acl: if acl.point_of_contact != flask.g.fas_user.username and \ not is_pkgdb_admin(flask.g.fas_user) and \ not acl.point_of_contact.startswith('group::'): pass else: if acl.point_of_contact.startswith('group::'): group = acl.point_of_contact.split('group::')[0] if group not in flask.g.fas_user.groups: pass elif acl.collection.status != 'EOL': collect_name.append(acl.collection.branchname) form = pkgdb2.forms.GivePoCForm(collections=collect_name) acls = ['commit', 'watchbugzilla', 'watchcommits', 'approveacls'] if form.validate_on_submit(): collections = form.branches.data pkg_poc = form.poc.data if pkg_poc.startswith('group::'): acls = ['commit', 'watchbugzilla', 'watchcommits'] try: for pkg_collection in collections: message = pkgdblib.update_pkg_poc( SESSION, namespace=namespace, pkg_name=packagename, pkg_branch=pkg_collection, pkg_poc=pkg_poc, user=flask.g.fas_user, ) flask.flash(message) for acl in acls: pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=packagename, pkg_branch=pkg_collection, pkg_user=pkg_poc, acl=acl, status='Approved', user=flask.g.fas_user ) SESSION.commit() except pkgdblib.exceptions.PkgdbBugzillaException as err: # pragma: no cover APP.logger.exception(err) flask.flash(str(err), 'error') SESSION.rollback() except PkgdbException as err: SESSION.rollback() flask.flash(str(err), 'error') return flask.redirect(flask.url_for( '.package_info', namespace=namespace, package=packagename) ) return flask.render_template( 'package_give.html', full=full, form=form, packagename=packagename, namespace=namespace, )
def package_info(package): ''' Display the information about the specified package. ''' packagename = package package = None try: package_acl = pkgdblib.get_acl_package(SESSION, packagename) package = pkgdblib.search_package(SESSION, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') package_acls = [] branch_admin = [] is_poc = False for pkg in package_acl: if pkg.collection.status == 'EOL': # pragma: no cover continue tmp = {} tmp['collection'] = '%s %s' % (pkg.collection.name, pkg.collection.version) tmp['branchname'] = pkg.collection.branchname tmp['point_of_contact'] = pkg.point_of_contact tmp['status'] = pkg.status if hasattr(flask.g, 'fas_user') and flask.g.fas_user and \ pkg.point_of_contact == flask.g.fas_user.username: is_poc = True acls = {} for acl in pkg.acls: tmp2 = {'acl': acl.acl, 'status': acl.status} if acl.fas_name in acls: acls[acl.fas_name].append(tmp2) else: acls[acl.fas_name] = [tmp2] ## This list is a little hacky, but we would have to save ACLs ## in their own table otherwise. planned_acls = set( ['approveacls', 'commit', 'watchbugzilla', 'watchcommits']) for fas_name in acls: seen_acls = set([acl['acl'] for acl in acls[fas_name]]) for aclname in planned_acls - seen_acls: acls[fas_name].append({'acl': aclname, 'status': ''}) tmp['acls'] = acls package_acls.append(tmp) if is_pkg_admin(SESSION, flask.g.fas_user, package.name, pkg.collection.branchname): branch_admin.append(pkg.collection.branchname) package_acls.reverse() if package_acls: package_acls.insert(0, package_acls.pop()) return flask.render_template( 'package.html', package=package, package_acl=package_acls, branch_admin=branch_admin, is_poc=is_poc, )
def api_package_edit(): ''' Edit a package -------------- Edit a package. :: /api/package/edit/ Accept POST queries only. :arg pkgname: String of the package name to be created. :arg summary: String of the summary description of the package. :arg description: String describing the package (same as in the spec file). :arg review_url: the URL of the package review on the bugzilla. :arg status: status of the package can be one of: 'Approved', 'Awaiting Review', 'Denied', 'Obsolete', 'Removed' :arg upstream_url: the URL of the upstream project Sample response: :: { "output": "ok", "messages": ["Package edited"] } { "output": "notok", "error": ["You're not allowed to edit this package"] } ''' httpcode = 200 output = {} pkg_status = pkgdblib.get_status(SESSION, 'pkg_status')['pkg_status'] form = forms.EditPackageForm( csrf_enabled=False, pkg_status_list=pkg_status, ) if form.validate_on_submit(): pkg_name = form.pkgname.data package = None try: package = pkgdblib.search_package(SESSION, pkg_name, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() output['output'] = 'notok' output['error'] = 'No package of this name found' httpcode = 500 if package: pkg_summary = form.summary.data pkg_description = form.description.data pkg_review_url = form.review_url.data pkg_status = form.status.data if pkg_status == 'None': pkg_status = None pkg_upstream_url = form.upstream_url.data try: message = pkgdblib.edit_package( SESSION, package, pkg_name=pkg_name, pkg_summary=pkg_summary, pkg_description=pkg_description, pkg_review_url=pkg_review_url, pkg_upstream_url=pkg_upstream_url, pkg_status=pkg_status, user=flask.g.fas_user ) SESSION.commit() output['output'] = 'ok' output['messages'] = [message] except pkgdblib.PkgdbException, err: # pragma: no cover # We can only reach here in two cases: # 1) the user is not an admin, but that's taken care of # by the decorator # 2) we have a SQLAlchemy problem when storing the info # in the DB which we cannot test SESSION.rollback() output['output'] = 'notok' output['error'] = str(err) httpcode = 500
def package_info(package): ''' Display the information about the specified package. ''' packagename = package package = None try: package_acl = pkgdblib.get_acl_package(SESSION, packagename) package = pkgdblib.search_package(SESSION, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') planned_acls = set(pkgdblib.get_status(SESSION, 'pkg_acl')['pkg_acl']) branches = set() commit_acls = {} watch_acls = {} admins = {} pending_admins = {} pocs = {} committers = [] for pkg in package_acl: if pkg.collection.status == 'EOL': # pragma: no cover continue collection_name = '%s %s' % (pkg.collection.name, pkg.collection.version) branches.add(collection_name) if pkg.point_of_contact not in pocs: pocs[pkg.point_of_contact] = set() pocs[pkg.point_of_contact].add(collection_name) for acl in pkg.acls: if acl.acl == 'approveacls' and acl.status == 'Approved': if acl.fas_name not in admins: admins[acl.fas_name] = set() admins[acl.fas_name].add(collection_name) elif acl.acl == 'approveacls' and acl.status == 'Awaiting Review': if acl.fas_name not in pending_admins: pending_admins[acl.fas_name] = set() pending_admins[acl.fas_name].add(collection_name) if acl.acl == 'commit': dic = commit_acls if acl.status == 'Approved': committers.append(acl.fas_name) elif acl.acl.startswith('watch') and acl.status == 'Approved': dic = watch_acls else: # pragma: no cover -- pass isn't `covered` by coverage # We managed approveacls earlier continue if acl.fas_name not in dic: dic[acl.fas_name] = {} if collection_name not in dic[acl.fas_name]: dic[acl.fas_name][collection_name] = {} dic[acl.fas_name][collection_name][acl.acl] = \ acl.status for aclname in planned_acls: for user in commit_acls: if collection_name in commit_acls[user] and \ aclname not in commit_acls[user][collection_name]: commit_acls[user][collection_name][aclname] = None for aclname in planned_acls: for user in watch_acls: if collection_name in watch_acls[user] and \ aclname not in watch_acls[user][collection_name]: watch_acls[user][collection_name][aclname] = None statuses = set([ listing.status for listing in package.sorted_listings if listing.collection.status != 'EOL' ]) collections = pkgdb2.lib.search_collection(SESSION, '*', 'Under Development') collections.extend(pkgdb2.lib.search_collection(SESSION, '*', 'Active')) branches_possible = [ collec.branchname for collec in collections if '%s %s' % (collec.name, collec.version) not in branches ] requester = False if is_authenticated(): for req in package.requests: if req.user == flask.g.fas_user.username: requester = True break return flask.render_template( 'package.html', package=package, commit_acls=commit_acls, watch_acls=watch_acls, pocs=pocs, admins=admins, statuses=statuses, pending_admins=pending_admins, branches=branches, branches_possible=branches_possible, committers=committers, form=pkgdb2.forms.ConfirmationForm(), requester=requester, )
def package_info(namespace, package): ''' Display the information about the specified package. ''' packagename = package package = None try: package_acl = pkgdblib.get_acl_package( SESSION, namespace, packagename) package = pkgdblib.search_package( SESSION, namespace, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') planned_acls = set( pkgdblib.get_status(SESSION, 'pkg_acl')['pkg_acl']) branches = set() commit_acls = {} watch_acls = {} admins = {} pending_admins = {} pocs = {} committers = [] for pkg in package_acl: if pkg.collection.status == 'EOL': # pragma: no cover continue collection_name = '%s %s' % ( pkg.collection.name, pkg.collection.version) branches.add(collection_name) if pkg.point_of_contact not in pocs: pocs[pkg.point_of_contact] = set() pocs[pkg.point_of_contact].add(collection_name) for acl in pkg.acls: if acl.acl == 'approveacls' and acl.status == 'Approved': if acl.fas_name not in admins: admins[acl.fas_name] = set() admins[acl.fas_name].add(collection_name) elif acl.acl == 'approveacls' and acl.status == 'Awaiting Review': if acl.fas_name not in pending_admins: pending_admins[acl.fas_name] = set() pending_admins[acl.fas_name].add(collection_name) if acl.acl == 'commit': dic = commit_acls if acl.status == 'Approved': committers.append(acl.fas_name) elif acl.acl.startswith('watch') and acl.status == 'Approved': dic = watch_acls else: # pragma: no cover -- pass isn't `covered` by coverage # We managed approveacls earlier continue if acl.fas_name not in dic: dic[acl.fas_name] = {} if collection_name not in dic[acl.fas_name]: dic[acl.fas_name][collection_name] = {} dic[acl.fas_name][collection_name][acl.acl] = \ acl.status for aclname in planned_acls: for user in commit_acls: if collection_name in commit_acls[user] and \ aclname not in commit_acls[user][collection_name]: commit_acls[user][collection_name][aclname] = None for aclname in planned_acls: for user in watch_acls: if collection_name in watch_acls[user] and \ aclname not in watch_acls[user][collection_name]: watch_acls[user][collection_name][aclname] = None statuses = set([ listing.status for listing in package.sorted_listings if listing.collection.status != 'EOL' ]) collections = pkgdb2.lib.search_collection( SESSION, '*', 'Under Development') collections.extend(pkgdb2.lib.search_collection(SESSION, '*', 'Active')) branches_possible = [ collec.branchname for collec in collections if '%s %s' % (collec.name, collec.version) not in branches] requester = False if is_authenticated(): for req in package.requests: if req.user == flask.g.fas_user.username: requester = True break return flask.render_template( 'package.html', package=package, commit_acls=commit_acls, watch_acls=watch_acls, pocs=pocs, admins=admins, statuses=statuses, pending_admins=pending_admins, branches=branches, branches_possible=branches_possible, committers=committers, form=pkgdb2.forms.ConfirmationForm(), requester=requester, )
def api_package_list(pattern=None): ''' List packages ------------- List packages based on a pattern. If no pattern is provided, return all the package. :: /api/packages/<pattern>/ /api/packages/?pattern=<pattern> Accepts GET queries only :arg pattern: Pattern to list packages from their name. :arg branches: List of string of the branches name in which these packages will be searched. :arg poc: String of the user name to to which restrict the search. :arg orphaned: Boolean to retrict the search to orphaned packages. :arg critpath: Boolean to retrict the search to critpath packages. Defaults to None which means results include both critpath and non-critpath packages. :arg status: Allows to filter packages based on their status: Approved, Orphaned, Retired, Removed. :arg acls: Boolean use to retrieve the acls in addition of the package information. Beware that this may reduce significantly the response time, it is advise to use it in combinaition with a specifir branch. Defaults to False. :kwarg eol: a boolean to specify whether to include results for EOL collections or not. Defaults to False. If True, it will return results for all collections (including EOL). If False, it will return results only for non-EOL collections. :kwarg limit: An integer to limit the number of results, defaults to 250, maximum is 500. :kwarg page: The page number to return (useful in combination to limit). :kwarg count: A boolean to return the number of packages instead of the list. Defaults to False. *Results are paginated* Sample response: :: /api/packages/guak* { "output": "ok", "packages": [ { "status": "Approved", "upstream_url": null, "description": "Guake is a drop-down terminal for Gnome " "Desktop Environment, so you just need to " "press a key to invoke him,and press again" " to hide." "summary": "Drop-down terminal for GNOME", "creation_date": 1384775354.0, "review_url": null, "name": "guake" } ], "page_total": 1, "page": 1 } /api/packages/cl*?status=Orphaned&branches=f20&acls=true { "output": "ok", "packages": [ { "status": "Approved", "upstream_url": null, "description": "clive is a video extraction tool for " "user-uploaded video hosts such as Youtube," "Google Video, Dailymotion, Guba, Metacafe " "and Sevenload.It can be chained with 3rd " "party tools for subsequent video re-encoding" " and and playing.", "summary": "Video extraction tool for user-uploaded video hosts", "acls": [ { "status": "Retired", "point_of_contact": "orphan", "status_change": 1385363055.0, "collection": { "status": "Active", "branchname": "f20", "version": "20", "name": "Fedora" }, "package": null } ], "creation_date": 1385361948.0, "review_url": null, "name": "clive" } ], "page_total": 1, "page": 1 } .. note:: the ``status_change`` and ``create_date`` fields are both timestamps expressed in `Unix TIME <https://en.wikipedia.org/wiki/Unix_time>`_ ''' httpcode = 200 output = {} pattern = flask.request.args.get('pattern', pattern) or '*' branches = flask.request.args.getlist('branches', None) poc = flask.request.args.get('poc', None) orphaned = flask.request.args.get('orphaned', None) if str(orphaned).lower() in ['0', 'false']: orphaned = False elif orphaned is not None: orphaned = bool(orphaned) critpath = flask.request.args.get('critpath', None) if critpath and str(critpath).lower() in ['0', 'false']: critpath = False elif critpath: critpath = True acls = bool(flask.request.args.get('acls', False)) statuses = flask.request.args.getlist('status', None) eol = flask.request.args.get('eol', False) page = flask.request.args.get('page', 1) limit = get_limit() count = flask.request.args.get('count', False) try: if not branches: branches = [None] if not statuses: statuses = [None] if count: packages = 0 for status, branch in itertools.product(statuses, branches): packages += pkgdblib.search_package( SESSION, pkg_name=pattern, pkg_branch=branch, pkg_poc=poc, orphaned=orphaned, critpath=critpath, status=status, eol=eol, page=page, limit=limit, count=count, ) output['output'] = 'ok' output['packages'] = packages output['page'] = 1 output['page_total'] = 1 else: packages = set() packages_count = 0 for status, branch in itertools.product(statuses, branches): packages.update( pkgdblib.search_package( SESSION, pkg_name=pattern, pkg_branch=branch, pkg_poc=poc, orphaned=orphaned, critpath=critpath, status=status, eol=eol, page=page, limit=limit, count=count, )) packages_count += pkgdblib.search_package( SESSION, pkg_name=pattern, pkg_branch=branch, pkg_poc=poc, orphaned=orphaned, critpath=critpath, status=status, eol=eol, page=page, limit=limit, count=True, ) if not packages: output['output'] = 'notok' output['packages'] = [] output['error'] = 'No packages found for these parameters' httpcode = 404 else: output['packages'] = [ pkg.to_json(acls=acls, collection=branches, package=False) for pkg in packages ] output['output'] = 'ok' output['page'] = int(page) output['page_total'] = int(ceil(packages_count / float(limit))) except pkgdblib.PkgdbException, err: SESSION.rollback() output['output'] = 'notok' output['error'] = str(err) httpcode = 500
def package_request_branch(namespace, package, full=True): ''' Gives the possibility to request a new branch for this package. ''' if not bool(full) or str(full) in ['0', 'False']: full = False try: package_acl = pkgdblib.get_acl_package(SESSION, namespace, package) package = pkgdblib.search_package(SESSION, namespace, package, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') branches = [ pkg.collection.branchname for pkg in package_acl if pkg.collection.status != 'EOL' ] collections = pkgdb2.lib.search_collection(SESSION, '*', 'Under Development') collections.extend(pkgdb2.lib.search_collection(SESSION, '*', 'Active')) # List the possible branches that this package does not already have. branches_possible = [ collec.branchname for collec in collections if collec.branchname not in branches ] # Further limit that list to only the branches allowed for this namespace. namespace_policy = APP.config.get('PKGDB2_NAMESPACE_POLICY') policy = namespace_policy.get(pkg.package.namespace) if policy: branches_possible = [b for b in branches_possible if b in policy] form = pkgdb2.forms.BranchForm(collections=branches_possible) if form.validate_on_submit(): for branch in form.branches.data: try: msg = pkgdblib.add_new_branch_request( session=SESSION, namespace=package.namespace, pkg_name=package.name, clt_to=branch, user=flask.g.fas_user) SESSION.commit() flask.flash(msg) except PkgdbException as err: # pragma: no cover flask.flash(str(err), 'error') SESSION.rollback() except SQLAlchemyError as err: # pragma: no cover APP.logger.exception(err) flask.flash( 'Could not save the request to the database for ' 'branch: %s' % branch, 'error') SESSION.rollback() return flask.redirect( flask.url_for('.package_info', namespace=package.namespace, package=package.name)) return flask.render_template( 'request_branch.html', full=full, package=package, form=form, action='request_branch', )
def api_package_list(pattern=None): ''' List packages ------------- List packages based on a pattern. If no pattern is provided, return all the package. :: /api/packages/<pattern>/ /api/packages/?pattern=<pattern> Accept GET queries only :arg pattern: Pattern to list packages from their name. :arg branches: List of string of the branches name in which these packages will be searched. :arg poc: String of the user name to to which restrict the search. :arg orphaned: Boolean to retrict the search to orphaned packages. :arg critpath: Boolean to retrict the search to critpath packages. Defaults to None which means results include both critpath and non-critpath packages. :arg status: Allows to filter packages based on their status: Approved, Orphaned, Retired, Removed. :arg acls: Boolean use to retrieve the acls in addition of the package information. Beware that this may reduce significantly the response time, it is advise to use it in combinaition with a specifir branch. Defaults to False. :kwarg eol: a boolean to specify whether to include results for EOL collections or not. Defaults to False. If True, it will return results for all collections (including EOL). If False, it will return results only for non-EOL collections. :kwarg limit: An integer to limit the number of results, defaults to 250, maximum is 500. :kwarg page: The page number to return (useful in combination to limit). :kwarg count: A boolean to return the number of packages instead of the list. Defaults to False. *Results are paginated* Sample response: :: /api/packages/guak* { "output": "ok", "packages": [ { "status": "Approved", "upstream_url": null, "description": "Guake is a drop-down terminal for Gnome " "Desktop Environment, so you just need to " "press a key to invoke him,and press again" " to hide." "summary": "Drop-down terminal for GNOME", "creation_date": 1384775354.0, "review_url": null, "name": "guake" } ], "page_total": 1, "page": 1 } /api/packages/cl*?status=Orphaned&branches=f20&acls=true { "output": "ok", "packages": [ { "status": "Approved", "upstream_url": null, "description": "clive is a video extraction tool for " "user-uploaded video hosts such as Youtube," "Google Video, Dailymotion, Guba, Metacafe " "and Sevenload.It can be chained with 3rd " "party tools for subsequent video re-encoding" " and and playing.", "summary": "Video extraction tool for user-uploaded video hosts", "acls": [ { "status": "Retired", "point_of_contact": "orphan", "status_change": 1385363055.0, "collection": { "status": "Active", "branchname": "f20", "version": "20", "name": "Fedora" }, "package": null } ], "creation_date": 1385361948.0, "review_url": null, "name": "clive" } ], "page_total": 1, "page": 1 } .. note:: the ``status_change`` and ``create_date`` fields are both timestamps expressed in `Unix TIME <https://en.wikipedia.org/wiki/Unix_time>`_ ''' httpcode = 200 output = {} pattern = flask.request.args.get('pattern', pattern) or '*' branches = flask.request.args.getlist('branches', None) poc = flask.request.args.get('poc', None) orphaned = flask.request.args.get('orphaned', None) if str(orphaned).lower() in ['0', 'false']: orphaned = False elif orphaned is not None: orphaned = bool(orphaned) critpath = flask.request.args.get('critpath', None) if critpath and str(critpath).lower() in ['0', 'false']: critpath = False elif critpath: critpath = True acls = bool(flask.request.args.get('acls', False)) statuses = flask.request.args.getlist('status', None) eol = flask.request.args.get('eol', False) page = flask.request.args.get('page', 1) limit = get_limit() count = flask.request.args.get('count', False) try: if not branches: branches = [None] if not statuses: statuses = [None] if count: packages = 0 for status, branch in itertools.product( statuses, branches): packages += pkgdblib.search_package( SESSION, pkg_name=pattern, pkg_branch=branch, pkg_poc=poc, orphaned=orphaned, critpath=critpath, status=status, eol=eol, page=page, limit=limit, count=count, ) output['output'] = 'ok' output['packages'] = packages output['page'] = 1 output['page_total'] = 1 else: packages = set() packages_count = 0 for status, branch in itertools.product( statuses, branches): packages.update( pkgdblib.search_package( SESSION, pkg_name=pattern, pkg_branch=branch, pkg_poc=poc, orphaned=orphaned, critpath=critpath, status=status, eol=eol, page=page, limit=limit, count=count, ) ) packages_count += pkgdblib.search_package( SESSION, pkg_name=pattern, pkg_branch=branch, pkg_poc=poc, orphaned=orphaned, critpath=critpath, status=status, eol=eol, page=page, limit=limit, count=True, ) if not packages: output['output'] = 'notok' output['packages'] = [] output['error'] = 'No packages found for these parameters' httpcode = 404 else: output['packages'] = [ pkg.to_json(acls=acls, collection=branches, package=False) for pkg in packages ] output['output'] = 'ok' output['page'] = int(page) output['page_total'] = int(ceil(packages_count / float(limit))) except pkgdblib.PkgdbException, err: SESSION.rollback() output['output'] = 'notok' output['error'] = str(err) httpcode = 500
def update_acl(namespace, package, update_acl): ''' Update the acls of a package. ''' packagename = package package = None try: package_acl = pkgdblib.get_acl_package( SESSION, namespace, packagename) package = pkgdblib.search_package( SESSION, namespace, packagename, limit=1)[0] except (NoResultFound, IndexError): SESSION.rollback() flask.flash('No package of this name found.', 'errors') return flask.render_template('msg.html') statues = pkgdblib.get_status(SESSION) planned_acls = set(statues['pkg_acl']) acl_status = list(set(statues['acl_status'])) acl_status.insert(0, '') if update_acl not in planned_acls: flask.flash('Invalid ACL to update.', 'errors') return flask.redirect(flask.url_for( '.package_info', namespace=package.namespace, package=package.name) ) branches = {} branches_inv = {} commit_acls = {} admins = {} committers = [] for pkg in package_acl: if pkg.collection.status == 'EOL': # pragma: no cover continue collection_name = '%s %s' % ( pkg.collection.name, pkg.collection.version) if collection_name not in branches: branches[collection_name] = pkg.collection.branchname if pkg.collection.branchname not in branches_inv: branches_inv[pkg.collection.branchname] = collection_name for acl in pkg.acls: if acl.acl == 'approveacls' and acl.status == 'Approved': if acl.fas_name not in admins: admins[acl.fas_name] = set() admins[acl.fas_name].add(collection_name) if acl.acl != update_acl: continue committers.append(acl.fas_name) if acl.fas_name not in commit_acls: commit_acls[acl.fas_name] = {} if collection_name not in commit_acls[acl.fas_name]: commit_acls[acl.fas_name][collection_name] = {} commit_acls[acl.fas_name][collection_name][acl.acl] = \ acl.status for aclname in planned_acls: for user in commit_acls: if collection_name in commit_acls[user] and \ aclname not in commit_acls[user][collection_name]: commit_acls[user][collection_name][aclname] = None # If the user is not an admin, he/she can only access his/her ACLs username = flask.g.fas_user.username if username not in admins and not is_pkgdb_admin(flask.g.fas_user): tmp = {username: []} if username in commit_acls: tmp = {username: commit_acls[username]} commit_acls = tmp form = pkgdb2.forms.ConfirmationForm() if form.validate_on_submit(): sub_acls = flask.request.values.getlist('acls') sub_users = flask.request.values.getlist('user') sub_branches = flask.request.values.getlist('branch') changed = False if sub_acls and len(sub_acls) == (len(sub_users) * len(sub_branches)): cnt = 0 for cnt_u in range(len(sub_users)): for cnt_b in range(len(sub_branches)): lcl_acl = sub_acls[cnt] lcl_user = sub_users[cnt_u] lcl_branch = sub_branches[cnt_b] if lcl_acl not in acl_status: flask.flash('Invalid ACL: %s' % lcl_acl, 'error') cnt += 1 continue if lcl_user not in commit_acls: flask.flash('Invalid user: %s' % lcl_user, 'error') cnt += 1 continue if lcl_branch not in branches_inv or ( branches_inv[lcl_branch] in commit_acls[lcl_user] and commit_acls[lcl_user][ branches_inv[lcl_branch]][ update_acl] == lcl_acl): cnt += 1 continue if not lcl_acl: if branches_inv[lcl_branch] \ not in commit_acls[lcl_user]: cnt += 1 continue elif branches_inv[lcl_branch] \ in commit_acls[lcl_user] \ and username != lcl_user: flask.flash( 'Only the user can remove his/her ACL', 'error') cnt += 1 continue try: pkgdblib.set_acl_package( SESSION, namespace=namespace, pkg_name=package.name, pkg_branch=lcl_branch, pkg_user=lcl_user, acl=update_acl, status=lcl_acl, user=flask.g.fas_user, ) SESSION.commit() flask.flash("%s's %s ACL updated on %s" % ( lcl_user, update_acl, lcl_branch)) changed = True except PkgdbException as err: SESSION.rollback() flask.flash(str(err), 'error') cnt += 1 SESSION.commit() if not changed: flask.flash('Nothing to update') return flask.redirect(flask.url_for( '.package_info', namespace=package.namespace, package=package.name) ) else: flask.flash('Invalid input submitted', 'error') return flask.render_template( 'acl_update.html', acl=update_acl, acl_status=acl_status, package=package, form=form, branches=branches, commit_acls=commit_acls, admins=admins, committers=committers, )