예제 #1
0
    def login(self, forward_url=None, *args, **kwargs):
        '''Page to become authenticated to the Account System.

        This shows a small login box to type in your username and password
        from the Fedora Account System.

        :kwarg forward_url: The url to send to once authentication succeeds
        '''
        login_dict = f_ctrlers.login(forward_url=forward_url, *args, **kwargs)

        if not identity.current.anonymous and identity.was_login_attempted() \
                and not identity.get_identity_errors():
            # Success that needs to be passed back via json
            return login_dict

        if identity.was_login_attempted() and request.fas_provided_username:
            if request.fas_identity_failure_reason == 'status_inactive':
                turbogears.flash(_('Your old password has expired.  Please'
                    ' reset your password below.'))
                if request_format() != 'json':
                    redirect('/user/resetpass')
            if request.fas_identity_failure_reason == 'status_account_disabled':
                turbogears.flash(_('Your account is currently disabled.  For'
                        ' more information, please contact %(admin_email)s' %
                        {'admin_email': config.get('accounts_email')}))
                if request_format() != 'json':
                    redirect('/login')

        return login_dict
예제 #2
0
파일: util.py 프로젝트: tyll/bodhi
def json_redirect(f, *args, **kw):
    try:
        return f(*args, **kw)
    except InvalidUpdateException, e:
        if request_format() == 'json':
            return dict()
        else:
            raise redirect('/new', **e.args[0])
예제 #3
0
파일: controllers.py 프로젝트: 0-T-0/fas
 def index(self):
     if turbogears.identity.not_anonymous():
         if request_format() == 'json':
             # redirects don't work with JSON calls.  This is a bit of a
             # hack until we can figure out something better.
             return dict()
         turbogears.redirect('/home')
     return dict(now=time.ctime())
예제 #4
0
 def index(self):
     if turbogears.identity.not_anonymous():
         if request_format() == 'json':
             # redirects don't work with JSON calls.  This is a bit of a
             # hack until we can figure out something better.
             return dict()
         turbogears.redirect('/home')
     return dict(now=time.ctime())
예제 #5
0
파일: util.py 프로젝트: kmcdowell85/bodhi
def json_redirect(f, *args, **kw):
    try:
        return f(*args, **kw)
    except InvalidUpdateException, e:
        if request_format() == 'json':
            return dict()
        else:
            raise redirect('/new', **e.args[0])
예제 #6
0
파일: configs.py 프로젝트: chepioq/fas
    def error(self, tg_errors=None):
        '''Show a friendly error message'''
        # Only tg controller methods are served via the web so we have to have
        # methods even if they could be functions. (R0201)
        # pylint: disable-msg=R0201

        ### FIXME: This can be made simpler once we have a new python-fedora
        # with jsonify_validation_errors()
        if tg_errors:
            if request_format() == 'json':
                message = '\n'.join([u'%s: %s' % (param, msg) for param, msg in
                    tg_errors.items()])
                return dict(exc='Invalid', tg_flash=message, tg_template='json')
        if not tg_errors:
            # We should only reach this if the user hit the url manually.
            if request_format() == 'json':
                return dict()
            else:
                redirect('/')
        return dict(tg_errors=tg_errors)
예제 #7
0
    def error(self, tg_errors=None):
        '''Show a friendly error message'''
        # Only tg controller methods are served via the web so we have to have
        # methods even if they could be functions. (R0201)
        # pylint: disable-msg=R0201

        ### FIXME: This can be made simpler once we have a new python-fedora
        # with jsonify_validation_errors()
        if tg_errors:
            if request_format() == 'json':
                message = '\n'.join([u'%s: %s' % (param, msg) for param, msg in
                    tg_errors.items()])
                return dict(exc='Invalid', tg_flash=message, tg_template='json')
        if not tg_errors:
            # We should only reach this if the user hit the url manually.
            if request_format() == 'json':
                return dict()
            else:
                redirect('/')
        return dict(tg_errors=tg_errors)
예제 #8
0
    def name(self, collctn):
        '''Return a page with information on a particular Collection

        :arg collctn: Collection shortname
        '''
        ### FIXME: Want to return additional info:
        # date it was created (join log table: creation date)
        # The initial import doesn't have this information, though.
        try:
            #pylint:disable-msg=E1101
            collection = Collection.by_simple_name(collctn)
        except InvalidRequestError:
            # Either the name doesn't exist or somehow it references more than
            # one value
            flash(
                _('The collection name you were linked to, %(collctn)s,'
                  ' does not exist.  If you received this error from'
                  ' a link on the fedoraproject.org website, please'
                  ' report it.') % {'collctn': collctn})
            if request_format() == 'json':
                error = dict(exc='InvalidCollection')
            else:
                error = dict(title=_('%(app)s -- Invalid Collection Name') %
                             {'app': self.app_title},
                             tg_template='pkgdb.templates.errors')
            return error

        # Why do we reformat the data returned from the database?
        # 1) We don't need all the information in the collection object
        # 2) We need statusname which is not in the specific table.
        collection_entry = {
            'name': collection.name,
            'version': collection.version,
            'owner': collection.owner,
            'summary': collection.summary,
            'description': collection.description,
            'statusname': collection.status.locale['C'].statusname
        }

        # Retrieve the package list for this collection
        # pylint:disable-msg=E1101
        packages = select((PackageTable, ),
                          and_(Package.id == PackageListing.packageid,
                               PackageListing.collectionid == collection.id,
                               Package.statuscode != STATUS['Removed']),
                          order_by=(Package.name, )).execute()
        # pylint:enable-msg=E1101

        return dict(title='%s -- %s %s' %
                    (self.app_title, collection.name, collection.version),
                    collection=collection_entry,
                    packages=packages)
예제 #9
0
def login(forward_url=None, *args, **kwargs):
    '''Page to become authenticated to the Account System.

    This shows a small login box to type in your username and password
    from the Fedora Account System.

    To use this, replace your current login controller method with::

        from fedora.controllers import login as fc_login

        @expose(template='yourapp.yourlogintemplate', allow_json=True)
        def login(self, forward_url=None, *args, **kwargs):
            login_dict = fc_login(forward_url, args, kwargs)
            # Add anything to the return dict that you need for your app
            return login_dict

    :kwarg: forward_url: The url to send to once authentication succeeds
    '''
    if forward_url:
        if isinstance(forward_url, list):
            forward_url = forward_url.pop(0)
        else:
            del request.params['forward_url']

    if not identity.current.anonymous and identity.was_login_attempted() \
            and not identity.get_identity_errors():
        # User is logged in
        flash(_('Welcome, %s') % identity.current.user_name)
        if request_format() == 'json':
            # When called as a json method, doesn't make any sense to redirect
            # to a page.  Returning the logged in identity is better.
            return dict(user=identity.current.user,
                        _csrf_token=identity.current.csrf_token)
        redirect(forward_url or '/')

    if identity.was_login_attempted():
        msg = _('The credentials you supplied were not correct or '
                'did not grant access to this resource.')
    elif identity.get_identity_errors():
        msg = _('You must provide your credentials before accessing '
                'this resource.')
    else:
        msg = _('Please log in.')
        if not forward_url:
            forward_url = request.headers.get('Referer', '/')

    response.status = 403
    return dict(logging_in=True,
                message=msg,
                forward_url=forward_url,
                previous_url=request.path_info,
                original_parameters=request.params)
예제 #10
0
def login(forward_url=None, *args, **kwargs):
    '''Page to become authenticated to the Account System.

    This shows a small login box to type in your username and password
    from the Fedora Account System.

    To use this, replace your current login controller method with::

        from fedora.controllers import login as fc_login

        @expose(template='yourapp.yourlogintemplate', allow_json=True)
        def login(self, forward_url=None, *args, **kwargs):
            login_dict = fc_login(forward_url, args, kwargs)
            # Add anything to the return dict that you need for your app
            return login_dict

    :kwarg: forward_url: The url to send to once authentication succeeds
    '''
    if forward_url:
        if isinstance(forward_url, list):
            forward_url = forward_url.pop(0)
        else:
            del request.params['forward_url']

    if not identity.current.anonymous and identity.was_login_attempted() \
            and not identity.get_identity_errors():
        # User is logged in
        flash(f_('Welcome, %s') % identity.current.user_name)
        if request_format() == 'json':
            # When called as a json method, doesn't make any sense to redirect
            # to a page.  Returning the logged in identity is better.
            return dict(user=identity.current.user,
                        _csrf_token=identity.current.csrf_token)
        redirect(forward_url or '/')

    if identity.was_login_attempted():
        msg = f_('The credentials you supplied were not correct or '
                 'did not grant access to this resource.')
    elif identity.get_identity_errors():
        msg = f_('You must provide your credentials before accessing '
                 'this resource.')
    else:
        msg = f_('Please log in.')
        if not forward_url:
            forward_url = request.headers.get('Referer', '/')

    response.status = 403
    return dict(
        logging_in=True, message=msg,
        forward_url=forward_url, previous_url=request.path_info,
        original_parameters=request.params
    )
예제 #11
0
    def default(self, buildName=None, repo='F-11-i386'):
        '''Retrieve PackageBuild by their name.

        This method returns general packagebuild/rpm information about a
        package like: version, release, size, last changelog message,
        committime etc. This information comes from yum and is stored in
        the pkgdb.

        :arg buildName: Name of the packagebuild/rpm to lookup
        :arg repo: shortname of the repository to look in
        '''
        if buildName == None:
            raise redirect('/packages/list/')

        #pylint:disable-msg=E1101
        #builds_query = PackageBuild.query.filter_by(name=buildName)
        #pylint:enable-msg=E1101

        # look for The One packagebuild
        try:
            #pylint:disable-msg=E1101
            build = builds_query.join(
                PackageBuild.repos).filter(Repo.shortname == repo).one()
        except:
            error = dict(
                status=False,
                title=_('%(app)s -- Invalid PackageBuild Name') %
                {'app': self.app_title},
                message=_('The package build you were linked to'
                          ' (%(pkg)s) does not appear in the Package '
                          ' Database. If you received this error from a link'
                          ' on the fedoraproject.org website, please report'
                          ' it.') % {'pkg': buildName})
            if request_format() != 'json':
                error['tg_template'] = 'pkgdb.templates.errors'
                return error
        other_repos = []
        arches = set()
        for b in builds_query.all():
            other_repos.append(b.repo)
            arches.add(b.architecture)
        other_repos.remove(build.repo)

        return dict(title=_('%(title)s -- %(pkg)s') % {
            'title': self.app_title,
            'pkg': buildName
        },
                    repo=repo,
                    build=build,
                    other_repos=other_repos,
                    arches=arches)
예제 #12
0
    def name(self, collctn):
        '''Return a page with information on a particular Collection

        :arg collctn: Collection shortname
        '''
        ### FIXME: Want to return additional info:
        # date it was created (join log table: creation date)
        # The initial import doesn't have this information, though.
        try:
            #pylint:disable-msg=E1101
            collection = Collection.by_simple_name(collctn)
        except InvalidRequestError:
            # Either the name doesn't exist or somehow it references more than
            # one value
            flash(_('The collection name you were linked to, %(collctn)s,'
                    ' does not exist.  If you received this error from'
                    ' a link on the fedoraproject.org website, please'
                    ' report it.') % {'collctn': collctn})
            if request_format() == 'json':
                error = dict(exc='InvalidCollection')
            else:
                error = dict(title=_('%(app)s -- Invalid Collection Name') % {
                            'app': self.app_title},
                        tg_template='pkgdb.templates.errors')
            return error

        # Why do we reformat the data returned from the database?
        # 1) We don't need all the information in the collection object
        # 2) We need statusname which is not in the specific table.
        collection_entry = {'name': collection.name,
                'version': collection.version,
                'owner': collection.owner,
                'summary': collection.summary,
                'description': collection.description,
                'statusname': collection.status.locale['C'].statusname
                }

        # Retrieve the package list for this collection
        # pylint:disable-msg=E1101
        packages = select((PackageTable,), and_(Package.id==PackageListing.packageid,
                PackageListing.collectionid==collection.id,
                Package.statuscode!=STATUS['Removed']),
                order_by=(Package.name,)).execute()
        # pylint:enable-msg=E1101

        return dict(title='%s -- %s %s' % (self.app_title, collection.name,
            collection.version), collection=collection_entry,
            packages=packages)
예제 #13
0
    def default(self, buildName=None, repo='F-11-i386'):
        '''Retrieve PackageBuild by their name.

        This method returns general packagebuild/rpm information about a
        package like: version, release, size, last changelog message,
        committime etc. This information comes from yum and is stored in
        the pkgdb.

        :arg buildName: Name of the packagebuild/rpm to lookup
        :arg repo: shortname of the repository to look in
        '''
        if buildName == None:
            raise redirect('/packages/list/')

        #pylint:disable-msg=E1101
        #builds_query = PackageBuild.query.filter_by(name=buildName)
        #pylint:enable-msg=E1101

        # look for The One packagebuild
        try:
            #pylint:disable-msg=E1101
            build = builds_query.join(PackageBuild.repos).filter(
                Repo.shortname==repo).one()
        except:
            error = dict(status=False,
                         title=_('%(app)s -- Invalid PackageBuild Name') % {
                             'app': self.app_title},
                             message=_('The package build you were linked to'
                             ' (%(pkg)s) does not appear in the Package '
                             ' Database. If you received this error from a link'
                             ' on the fedoraproject.org website, please report'
                             ' it.') % {'pkg': buildName})
            if request_format() != 'json':
                error['tg_template'] = 'pkgdb.templates.errors'
                return error
        other_repos = []
        arches = set()
        for b in builds_query.all():
            other_repos.append(b.repo)
            arches.add(b.architecture)
        other_repos.remove(build.repo)
        


        return dict(title=_('%(title)s -- %(pkg)s') % {
            'title': self.app_title, 'pkg': buildName},
                    repo=repo, build=build, other_repos=other_repos,
                    arches=arches)
예제 #14
0
파일: configs.py 프로젝트: echevemaster/fas
    def set(self, username, application, attribute, value=None):
        '''Retrieve configs for a user and application.

        Arguments:
        :username: owner of the configs we're searching for
        :application: program that the configs are for
        :attribute: name of the option we're setting
        :value: value to set in the db.  If ths is None, we won't set anything
        '''
        # Only tg controller methods are served via the web so we have to have
        # methods even if they could be functions. (R0201)
        # pylint: disable-msg=R0201

        # Verify user is allowed to set this config
        target = People.by_username(username)
        if not can_edit_user(identity.current.user, target):
            flash(_('You cannot edit configs for %s') % username)
            if request_format() == 'json':
                return dict(exc='AuthorizationError')
            else:
                redirect('/')

        # Retrieve the data and reformat it as a dict keyed on attribute
        try:
            # pylint: disable-msg=E1101
            config = Configs.query.filter_by(
                application=application, attribute=attribute).filter(
                    Configs.person_id == target.id).one()
            config.value = value
        except InvalidRequestError:
            # There was no Config, create a new one
            config = Configs(application=application,
                             attribute=attribute,
                             value=value)
            # pylint: disable-msg=E1101
            config.person = People.query.filter_by(username=username).one()

        try:
            # ScopedSession really does have a flush() method
            # pylint: disable-msg=E1101
            session.flush()
        except DBAPIError, error:
            flash(_('Error saving the config to the database: %s' % (error)))
            return dict(exc='DBAPIError')
예제 #15
0
파일: configs.py 프로젝트: chepioq/fas
    def set(self, username, application, attribute, value=None):
        '''Retrieve configs for a user and application.

        Arguments:
        :username: owner of the configs we're searching for
        :application: program that the configs are for
        :attribute: name of the option we're setting
        :value: value to set in the db.  If ths is None, we won't set anything
        '''
        # Only tg controller methods are served via the web so we have to have
        # methods even if they could be functions. (R0201)
        # pylint: disable-msg=R0201

        # Verify user is allowed to set this config
        target = People.by_username(username)
        if not can_edit_user(identity.current.user, target):
            flash(_('You cannot edit configs for %s') % username)
            if request_format() == 'json':
                return dict(exc='AuthorizationError')
            else:
                redirect('/')

        # Retrieve the data and reformat it as a dict keyed on attribute
        try:
            # pylint: disable-msg=E1101
            config = Configs.query.filter_by(application=application,
                    attribute=attribute).filter(Configs.person_id==target.id).one()
            config.value = value
        except InvalidRequestError:
            # There was no Config, create a new one
            config = Configs(application=application, attribute=attribute,
                    value=value)
            # pylint: disable-msg=E1101
            config.person = People.query.filter_by(username=username).one()

        try:
            # ScopedSession really does have a flush() method
            # pylint: disable-msg=E1101
            session.flush()
        except DBAPIError, error:
            flash(_('Error saving the config to the database: %s' % (error)))
            return dict(exc='DBAPIError')
예제 #16
0
파일: configs.py 프로젝트: echevemaster/fas
    def list(self, username, application, pattern=u'*'):
        '''Retrieve configs for a user and application.

        Arguments:
        :username: owner of the configs we're searching for
        :application: program that the configs are for
        :pattern: Limit the configs to ones which match this pattern. '*' is a
            wildcard character

        Returns: dict that maps the name of the config attribute to the config
            value.
        '''
        # Only tg controller methods are served via the web so we have to have
        # methods even if they could be functions. (R0201)
        # pylint: disable-msg=R0201

        # Verify user is allowed to view this config
        target = People.by_username(username)
        if not can_edit_user(identity.current.user, target):
            flash(_('You cannot look at configs for %s') % username)
            if request_format() == 'json':
                return dict(exc='AuthorizationError')
            else:
                redirect('/')

        # This only works if pattern is unicode.  But it should be unicode
        # because of the validator.
        pattern = pattern.translate({ord(u'*'): ur'%'}).lower()

        # Retrieve the data and reformat it as a dict keyed on attribute
        # pylint: disable-msg=E1101
        cfgs = Configs.query.filter_by(application=application).filter(
            and_(Configs.attribute.like(pattern),
                 Configs.person_id == target.id))
        # pylint: enable-msg=E1101
        results = dict((cfg.attribute, cfg.value) for cfg in cfgs.all())

        return dict(username=username,
                    application=application,
                    pattern=pattern,
                    configs=results)
예제 #17
0
def logout(url=None):
    '''Logout from the server.

    To use this, replace your current login controller method with::

        from fedora.controllers import logout as fc_logout

        @expose(allow_json=True)
        def logout(self):
            return fc_logout()

    :kwarg url: If provided, when the user logs out, they will always be taken
        to this url.  This defaults to taking the user to the URL they were
        at when they clicked logout.
    '''
    identity.current.logout()
    flash(_('You have successfully logged out.'))
    if request_format() == 'json':
        return dict()
    if not url:
        url = request.headers.get('Referer','/')
    redirect(url)
예제 #18
0
파일: configs.py 프로젝트: chepioq/fas
    def list(self, username, application, pattern=u'*'):
        '''Retrieve configs for a user and application.

        Arguments:
        :username: owner of the configs we're searching for
        :application: program that the configs are for
        :pattern: Limit the configs to ones which match this pattern. '*' is a
            wildcard character

        Returns: dict that maps the name of the config attribute to the config
            value.
        '''
        # Only tg controller methods are served via the web so we have to have
        # methods even if they could be functions. (R0201)
        # pylint: disable-msg=R0201

        # Verify user is allowed to view this config
        target = People.by_username(username)
        if not can_edit_user(identity.current.user, target):
            flash(_('You cannot look at configs for %s') % username)
            if request_format() == 'json':
                return dict(exc='AuthorizationError')
            else:
                redirect('/')

        # This only works if pattern is unicode.  But it should be unicode
        # because of the validator.
        pattern = pattern.translate({ord(u'*'): ur'%'}).lower()

        # Retrieve the data and reformat it as a dict keyed on attribute
        # pylint: disable-msg=E1101
        cfgs = Configs.query.filter_by(application=application).filter(
                and_(Configs.attribute.like(pattern),
                    Configs.person_id==target.id))
        # pylint: enable-msg=E1101
        results = dict((cfg.attribute, cfg.value) for cfg in cfgs.all())

        return dict(username=username, application=application,
                pattern=pattern, configs=results)
예제 #19
0
def logout(url=None):
    '''Logout from the server.

    To use this, replace your current login controller method with::

        from fedora.controllers import logout as fc_logout

        @expose(allow_json=True)
        def logout(self):
            return fc_logout()

    :kwarg url: If provided, when the user logs out, they will always be taken
        to this url.  This defaults to taking the user to the URL they were
        at when they clicked logout.
    '''
    identity.current.logout()
    flash(_('You have successfully logged out.'))
    if request_format() == 'json':
        return dict()
    if not url:
        url = request.headers.get('Referer', '/')
    redirect(url)
예제 #20
0
    def name(self, packageName, collectionName=None, collectionVersion=None, eol=False):
        '''Retrieve Packages by their name.

        This method returns ownership and acl information about a package.
        When given optional arguments the information can be limited by what
        collections they are present in.

        :arg packageName: Name of the package to lookup
        :kwarg collectionName: If given, limit information to branches for
            this distribution.
        :kwarg collectionVersion: If given, limit information to this
            particular version of a distribution.  Has no effect if
            collectionName is not also specified.
        :kwarg eol: end-of-life flag.  If True, do not limit information.
            If False, limit information to non-eol collections.
        '''
        
        #pylint:disable-msg=E1101
        # Return the information about a package.
        package = Package.query.filter(
                Package.statuscode!=STATUS['Removed']
                ).filter_by(name=packageName).first()
        #pylint:enable-msg=E1101
        if not package:
            error = dict(status=False,
                    title=_('%(app)s -- Invalid Package Name') % {
                        'app': self.app_title},
                        message=_('The packagename you were linked to'
                        ' (%(pkg)s) does not appear in the Package Database.'
                        ' If you received this error from a link on the'
                        ' fedoraproject.org website, please report it.') % {
                            'pkg': packageName})
            if request_format() != 'json':
                error['tg_template'] = 'pkgdb.templates.errors'
            return error

        collection = None
        if collectionName:
            #pylint:disable-msg=E1101
            collection = Collection.query.filter_by(name=collectionName)
            #pylint:enable-msg=E1101
            if collectionVersion:
                collection = collection.filter_by(version=collectionVersion)
            if (not eol):
                collection = collection.filter(Collection.statuscode!=STATUS['EOL'])
            if not collection.count():
                error = dict(status=False,
                        title=_('%(app)s -- Not a Collection') % {
                            'app': self.app_title},
                        message=_('%(name)s %(ver)s is not a Collection.') % {
                            'name': collectionName,
                            'ver': collectionVersion or ''})
                if request_format() != 'json':
                    error['tg_template'] = 'pkgdb.templates.errors'
                return error

        # Possible ACLs
        acl_names = ('watchbugzilla', 'watchcommits', 'commit', 'approveacls')
        # Possible statuses for acls:
        acl_status = PackageAclStatus.query.options( #pylint:disable-msg=E1101
                eagerload('locale')).all()
        acl_status_translations = ['']
        for status in acl_status:
            ### FIXME: At some point, we have to pull other translations out,
            # not just C
            if acl_status_translations != 'Obsolete':
                acl_status_translations.append(
                        status.locale['C'].statusname)

        #pylint:disable-msg=E1101
        # Fetch information about all the packageListings for this package
        # The order is a bit complex.  We want:
        # 1) EOL collections last
        # 2) Within those groups, same named collections together
        # 3) Within collections, version devel first,
        # 4) All other collections sorted as numbers in descending order
        pkg_listings = PackageListing.query.options(
                eagerload('people2.acls2.status.locale'),
                eagerload('groups2.acls2.status.locale'),
                eagerload('status.locale'),
                eagerload('collection.status.locale'),)\
                        .filter(PackageListingTable.c.packageid==package.id)\
                        .join(Collection)\
                        .order_by(case(value=Collection.statuscode,
                                whens={STATUS['EOL']: 999999},
                                else_=0),
                            Collection.name,
                            case(value=Collection.version,
                                whens={'devel':999999},
                                else_=cast(Collection.version, Integer))\
                            .desc()
                        )
        #pylint:enable-msg=E1101
        if collection:
            # User asked to limit it to specific collections
            pkg_listings = pkg_listings.filter(
                    PackageListingTable.c.collectionid.in_(
                    [c.id for c in collection]))
            if not pkg_listings.count():
                error = dict(status=False,
                        title=_('%(app)s -- Not in Collection') % {
                            'app': self.app_title},
                        message=_('The package %(pkg)s is not in Collection'
                            ' %(collctn_name)s %(collctn_ver)s.') % {
                                'pkg': packageName,
                                'collctn_name': collectionName,
                                'collctn_ver': collectionVersion or ''})
                if request_format() != 'json':
                    error['tg_template'] = 'pkgdb.templates.errors'
                return error

        # Map of statuscode to statusnames used in this package
        status_map = {}

        if (not eol):
            pkg_listings = pkg_listings.filter(Collection.statuscode!=STATUS['EOL'])

        pkg_listings = pkg_listings.order_by().all()

        for pkg in pkg_listings:
            pkg.json_props = {'PackageListing': ('package', 'collection',
                    'people', 'groups', 'qacontact', 'owner'),
                'PersonPackageListing': ('aclOrder', ),
                'GroupPackageListing': ('aclOrder', ),
                }

            status_map[pkg.statuscode] = pkg.status.locale['C'].statusname
            status_map[pkg.collection.statuscode] = \
                    pkg.collection.status.locale['C'].statusname

            for person in pkg.people:
                # Setup acls to be accessible via aclName
                person.aclOrder = {}
                for acl in acl_names:
                    person.aclOrder[acl] = None
                for acl in person.acls:
                    statusname = acl.status.locale['C'].statusname
                    status_map[acl.statuscode] = statusname
                    if statusname != 'Obsolete':
                        person.aclOrder[acl.acl] = acl

            for group in pkg.groups:
                # Setup acls to be accessible via aclName
                group.aclOrder = {}
                for acl in acl_names:
                    group.aclOrder[acl] = None
                for acl in group.acls:
                    status_map[acl.statuscode] = \
                            acl.status.locale['C'].statusname
                    group.aclOrder[acl.acl] = acl

        status_map[pkg_listings[0].package.statuscode] = \
                pkg_listings[0].package.status.locale['C'].statusname

        return dict(title=_('%(title)s -- %(pkg)s') % {
            'title': self.app_title, 'pkg': package.name},
            packageListings=pkg_listings, statusMap = status_map,
            aclNames=acl_names, aclStatus=acl_status_translations)
예제 #21
0
    def name(self,
             packageName,
             collectionName=None,
             collectionVersion=None,
             eol=False):
        '''Retrieve Packages by their name.

        This method returns ownership and acl information about a package.
        When given optional arguments the information can be limited by what
        collections they are present in.

        :arg packageName: Name of the package to lookup
        :kwarg collectionName: If given, limit information to branches for
            this distribution.
        :kwarg collectionVersion: If given, limit information to this
            particular version of a distribution.  Has no effect if
            collectionName is not also specified.
        :kwarg eol: end-of-life flag.  If True, do not limit information.
            If False, limit information to non-eol collections.
        '''

        #pylint:disable-msg=E1101
        # Return the information about a package.
        package = Package.query.filter(
            Package.statuscode != STATUS['Removed']).filter_by(
                name=packageName).first()
        #pylint:enable-msg=E1101
        if not package:
            error = dict(
                status=False,
                title=_('%(app)s -- Invalid Package Name') %
                {'app': self.app_title},
                message=_('The packagename you were linked to'
                          ' (%(pkg)s) does not appear in the Package Database.'
                          ' If you received this error from a link on the'
                          ' fedoraproject.org website, please report it.') %
                {'pkg': packageName})
            if request_format() != 'json':
                error['tg_template'] = 'pkgdb.templates.errors'
            return error

        collection = None
        if collectionName:
            #pylint:disable-msg=E1101
            collection = Collection.query.filter_by(name=collectionName)
            #pylint:enable-msg=E1101
            if collectionVersion:
                collection = collection.filter_by(version=collectionVersion)
            if (not eol):
                collection = collection.filter(
                    Collection.statuscode != STATUS['EOL'])
            if not collection.count():
                error = dict(
                    status=False,
                    title=_('%(app)s -- Not a Collection') %
                    {'app': self.app_title},
                    message=_('%(name)s %(ver)s is not a Collection.') % {
                        'name': collectionName,
                        'ver': collectionVersion or ''
                    })
                if request_format() != 'json':
                    error['tg_template'] = 'pkgdb.templates.errors'
                return error

        # Possible ACLs
        acl_names = ('watchbugzilla', 'watchcommits', 'commit', 'approveacls')
        # Possible statuses for acls:
        acl_status = PackageAclStatus.query.options(  #pylint:disable-msg=E1101
            eagerload('locale')).all()
        acl_status_translations = ['']
        for status in acl_status:
            ### FIXME: At some point, we have to pull other translations out,
            # not just C
            if acl_status_translations != 'Obsolete':
                acl_status_translations.append(status.locale['C'].statusname)

        #pylint:disable-msg=E1101
        # Fetch information about all the packageListings for this package
        # The order is a bit complex.  We want:
        # 1) EOL collections last
        # 2) Within those groups, same named collections together
        # 3) Within collections, version devel first,
        # 4) All other collections sorted as numbers in descending order
        pkg_listings = PackageListing.query.options(
                eagerload('people2.acls2.status.locale'),
                eagerload('groups2.acls2.status.locale'),
                eagerload('status.locale'),
                eagerload('collection.status.locale'),)\
                        .filter(PackageListingTable.c.packageid==package.id)\
                        .join(Collection)\
                        .order_by(case(value=Collection.statuscode,
                                whens={STATUS['EOL']: 999999},
                                else_=0),
                            Collection.name,
                            case(value=Collection.version,
                                whens={'devel':999999},
                                else_=cast(Collection.version, Integer))\
                            .desc()
                        )
        #pylint:enable-msg=E1101
        if collection:
            # User asked to limit it to specific collections
            pkg_listings = pkg_listings.filter(
                PackageListingTable.c.collectionid.in_(
                    [c.id for c in collection]))
            if not pkg_listings.count():
                error = dict(
                    status=False,
                    title=_('%(app)s -- Not in Collection') %
                    {'app': self.app_title},
                    message=_('The package %(pkg)s is not in Collection'
                              ' %(collctn_name)s %(collctn_ver)s.') % {
                                  'pkg': packageName,
                                  'collctn_name': collectionName,
                                  'collctn_ver': collectionVersion or ''
                              })
                if request_format() != 'json':
                    error['tg_template'] = 'pkgdb.templates.errors'
                return error

        # Map of statuscode to statusnames used in this package
        status_map = {}

        if (not eol):
            pkg_listings = pkg_listings.filter(
                Collection.statuscode != STATUS['EOL'])

        pkg_listings = pkg_listings.order_by().all()

        for pkg in pkg_listings:
            pkg.json_props = {
                'PackageListing': ('package', 'collection', 'people', 'groups',
                                   'qacontact', 'owner'),
                'PersonPackageListing': ('aclOrder', ),
                'GroupPackageListing': ('aclOrder', ),
            }

            status_map[pkg.statuscode] = pkg.status.locale['C'].statusname
            status_map[pkg.collection.statuscode] = \
                    pkg.collection.status.locale['C'].statusname

            for person in pkg.people:
                # Setup acls to be accessible via aclName
                person.aclOrder = {}
                for acl in acl_names:
                    person.aclOrder[acl] = None
                for acl in person.acls:
                    statusname = acl.status.locale['C'].statusname
                    status_map[acl.statuscode] = statusname
                    if statusname != 'Obsolete':
                        person.aclOrder[acl.acl] = acl

            for group in pkg.groups:
                # Setup acls to be accessible via aclName
                group.aclOrder = {}
                for acl in acl_names:
                    group.aclOrder[acl] = None
                for acl in group.acls:
                    status_map[acl.statuscode] = \
                            acl.status.locale['C'].statusname
                    group.aclOrder[acl.acl] = acl

        status_map[pkg_listings[0].package.statuscode] = \
                pkg_listings[0].package.status.locale['C'].statusname

        return dict(title=_('%(title)s -- %(pkg)s') % {
            'title': self.app_title,
            'pkg': package.name
        },
                    packageListings=pkg_listings,
                    statusMap=status_map,
                    aclNames=acl_names,
                    aclStatus=acl_status_translations)
예제 #22
0
    def packages(self, fasname=None, acls=None, eol=None):
        '''List packages that the user is interested in.

        This method returns a list of packages owned by the user in current,
        non-EOL distributions.  The user has the ability to filter this to
        provide more or less information by adding query params for acls and
        EOL.

        :kwarg fasname: The name of the user to get the package list for.
                  Default: The logged in user.
        :kwarg acls: List of acls to select.
               Note: for backwards compatibility, this can also be a comma
               separated string of acls.
               Default: all acls.
        :kwarg eol: If set, list packages that are in EOL distros.
        :returns: A list of packages.
        '''
        # Set EOL to false for a few obvious values
        if not eol or eol.lower() in ('false', 'f', '0'):
            eol = False
        else:
            eol = bool(eol)

        # For backward compat, redirect the orphan user to the orphan page
        if fasname == 'orphan':
            params = {}
            if eol:
                params['eol'] = True
            if request_format() == 'json':
                params['tg_format'] = 'json'
            url = '/acls/orphans'
            if params:
                url = url + '?' + urllib.urlencode(params, True)

            raise redirect(url)

        if not acls:
            # Default to all acls
            acls = [k[0] for k in self.allAcls]
        elif isinstance(acls, basestring):
            # For backwards compatibility, make acls into a list if it's a
            # comma separated string of values
            acls = acls.split(',')

        # Create a list where store acl name, whether the acl is currently
        # being filtered for, and the label to use to display the acl.
        acl_list = [(a[0], a[0] in acls, a[1]) for a in self.allAcls]

        # Have to either get fasname from the URL or current user
        if fasname == None:
            if identity.current.anonymous:
                raise identity.IdentityFailure(
                        _('You must be logged in to view your information'))
            else:
                fasname = identity.current.user_name

        page_title = _('%(app)s -- %(name)s -- Packages') % {
                'app': self.app_title, 'name': fasname}

        # pylint: disable-msg=E1101
        query = Package.query.join('listings2').distinct().options(
                lazyload('listings2.groups2'), 
                lazyload('listings2.groups2.acls2'),
                lazyload('listings2.people2'), 
                lazyload('listings2.people2.acls2'), lazyload('listings2'))

        if not eol:
            # We don't want EOL releases, filter those out of each clause
            query = query.join(['listings2', 'collection']).filter(
                        Collection.statuscode != STATUS['EOL'])

        queries = []
        if 'owner' in acls:
            # Return any package for which the user is the owner
            queries.append(query.filter(sqlalchemy.and_(
                        Package.statuscode.in_((
                            STATUS['Approved'],
                            STATUS['Awaiting Review'],
                            STATUS['Under Review'])),
                        PackageListing.owner==fasname,
                        PackageListing.statuscode.in_((
                            STATUS['Approved'],
                            STATUS['Awaiting Branch'],
                            STATUS['Awaiting Review']))
                        )))
            del acls[acls.index('owner')]

        if acls:
            # Return any package on which the user has an Approved acl.
            queries.append(query.join(['listings2', 'people2']).join(
                    ['listings2', 'people2', 'acls2']).filter(sqlalchemy.and_(
                    Package.statuscode.in_((STATUS['Approved'],
                        STATUS['Awaiting Review'], STATUS['Under Review'])),
                    PersonPackageListing.username == fasname,
                    PersonPackageListingAcl.statuscode == STATUS['Approved'],
                    PackageListing.statuscode.in_((STATUS['Approved'],
                        STATUS['Awaiting Branch'], STATUS['Awaiting Review']))
                    )))
            # Return only those acls which the user wants listed
            queries[-1] = queries[-1].filter(
                    PersonPackageListingAcl.acl.in_(acls))

        if len(queries) == 2:
            my_pkgs = Package.query.select_from(
                            sqlalchemy.union(
                                    queries[0].statement,
                                    queries[1].statement
                                    ))
        else:
            my_pkgs = queries[0]

        my_pkgs = my_pkgs.options(lazyload('listings2.people2'), 
                                  lazyload('listings2.people2.acls2'), 
                                  lazyload('listings2.groups2'), 
                                  lazyload('listings2.groups2.acls2'), 
                                  lazyload('listings2')
                                  ).order_by(Package.name)
        # pylint: enable-msg=E1101
        pkg_list = []
        statuses = set()
        collectn_map = {}
        for pkg in my_pkgs:
            pkg.json_props = {'Package': ('listings',)}
            pkg_list.append(pkg)
            for pkglisting in pkg.listings:
                statuses.add(pkglisting.statuscode)
                if pkglisting.collection.collectionid not in collectn_map \
                    and pkglisting.collection.statuscode!=STATUS['EOL']:
                    collectn_map[pkglisting.collection.collectionid] = pkglisting.collection.branchname

        statusMap = dict([(statuscode, STATUS[statuscode]) for statuscode in
            statuses])

        return dict(title=page_title, pkgCount=len(pkg_list),
                pkgs=pkg_list, acls=acl_list, fasname=fasname, eol=eol,
                statusMap=statusMap, collectn_map=collectn_map)
예제 #23
0
    def default(self, package_name, *args, **kwargs):
        '''Display a list of Fedora bugs against a given package.'''
        # Nasty, nasty hack.  The packagedb, via bugz.fp.o is getting sent
        # requests to download files.  These refused to go away even when
        # we fixed up the apache redirects.  Send them to download.fp.o
        # manually.
        if args or kwargs:
            if args:
                url = 'http://download.fedoraproject.org/' \
                        + quote(package_name) \
                        + '/' + '/'.join([quote(a) for a in args])
            elif kwargs:
                url = 'http://mirrors.fedoraproject.org/' \
                        + quote(package_name) \
                        + '?' + '&'.join([quote(q) + '=' + quote(v) for (q, v)
                            in kwargs.items()])
                LOG.warning(
                    _('Invalid URL: redirecting: %(url)s') % {'url': url})
            raise redirect(url)

        query = {
            'product': ('Fedora', 'Fedora EPEL'),
            'component':
            package_name,
            'bug_status': ('ASSIGNED', 'NEW', 'MODIFIED', 'ON_DEV', 'ON_QA',
                           'VERIFIED', 'FAILS_QA', 'RELEASE_PENDING', 'POST')
        }
        # :E1101: python-bugzilla monkey patches this in
        try:
            bugzilla = get_bz()
        except xmlrpclib.ProtocolError:
            error = dict(
                status=False,
                title=_('%(app)s -- Unable to contact bugzilla') %
                {'app': self.app_title},
                message=_('Bugzilla is unavailable.  Unable to determine'
                          ' bugs for %(pkg)s') % {'pkg': package_name})
            if request_format() != 'json':
                error['tg_template'] = 'pkgdb.templates.errors'
            return error

        raw_bugs = bugzilla.query(query)  # pylint: disable-msg=E1101
        bugs = BugList(self.bzQueryUrl, self.bzUrl)
        for bug in raw_bugs:
            bugs.append(bug)

        if not bugs:
            # Check that the package exists
            try:
                # pylint: disable-msg=E1101
                Package.query.filter_by(name=package_name).one()
            except InvalidRequestError:
                error = dict(status=False,
                             title=_('%(app)s -- Not a Valid Package Name') %
                             {'app': self.app_title},
                             message=_('No such package %(pkg)s') %
                             {'pkg': package_name})
                if request_format() != 'json':
                    error['tg_template'] = 'pkgdb.templates.errors'
                return error

        return dict(title=_('%(app)s -- Open Bugs for %(pkg)s') % {
            'app': self.app_title,
            'pkg': package_name
        },
                    package=package_name,
                    bugs=bugs)
예제 #24
0
class FPCA(controllers.Controller):
    ''' Processes FPCA workflow '''
    # Group name for people having signed the FPCA
    CLAGROUPNAME = config.get('cla_standard_group')
    # Meta group for everyone who has satisfied the requirements of the FPCA
    # (By signing or having a corporate signatue or, etc)
    CLAMETAGROUPNAME = config.get('cla_done_group')

    # Values legal in phone numbers
    PHONEDIGITS = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '+',
            '-', ')' ,'(', ' ')

    def __init__(self):
        '''Create a FPCA Controller.'''

    @identity.require(turbogears.identity.not_anonymous())
    @expose(template="fas.templates.fpca.index")
    def index(self):
        '''Display the FPCAs (and accept/do not accept buttons)'''
        show = {}
        show['show_postal_address'] = config.get('show_postal_address')

        username = turbogears.identity.current.user_name
        person = People.by_username(username)
        try:
            code_len = len(person.country_code)
        except TypeError:
            code_len = 0
        if show['show_postal_address']:
            contactInfo = person.telephone or person.postal_address
            if person.country_code == 'O1' and not person.telephone:
                turbogears.flash(_('A telephone number is required to ' + \
                    'complete the FPCA.  Please fill out below.'))
            elif not person.country_code or not person.human_name \
                or not contactInfo:
                turbogears.flash(_('A valid country and telephone number ' + \
                    'or postal address is required to complete the FPCA.  ' + \
                    'Please fill them out below.'))
        else:
            if not person.telephone or code_len != 2 or \
                person.country_code == '  ':
                turbogears.flash(_('A valid country and telephone number are' +
                        ' required to complete the FPCA.  Please fill them ' +
                        'out below.'))
        (cla, undeprecated_cla) = undeprecated_cla_done(person)
        person = person.filter_private()
        return dict(cla=undeprecated_cla, person=person, date=datetime.utcnow().ctime(),
                    show=show)

    def _cla_dependent(self, group):
        '''
        Check whether a group has the cla in its prerequisite chain.

        Arguments:
        :group: group to check

        Returns: True if the group requires the cla_group_name otherwise
        '''
        if group.name in (self.CLAGROUPNAME, self.CLAMETAGROUPNAME):
            return True
        if group.prerequisite_id:
            return self._cla_dependent(group.prerequisite)
        return False

    def json_request(self):
        ''' Helps define if json is being used for this request

        :returns: 1 or 0 depending on if request is json or not
        '''

        return 'tg_format' in cherrypy.request.params and \
                cherrypy.request.params['tg_format'] == 'json'

    @expose(template="fas.templates.error")
    def error(self, tg_errors=None):
        '''Show a friendly error message'''
        if not tg_errors:
            turbogears.redirect('/')
        return dict(tg_errors=tg_errors)

    @identity.require(turbogears.identity.not_anonymous())
    @expose(template = "genshi-text:fas.templates.fpca.fpca", format = "text",
            content_type = 'text/plain; charset=utf-8')
    def text(self):
        '''View FPCA as text'''
        username = turbogears.identity.current.user_name
        person = People.by_username(username)
        person = person.filter_private()
        return dict(person=person, date=datetime.utcnow().ctime())

    @identity.require(turbogears.identity.not_anonymous())
    @expose(template = "genshi-text:fas.templates.fpca.fpca", format = "text",
            content_type = 'text/plain; charset=utf-8')
    def download(self):
        '''Download FPCA'''
        username = turbogears.identity.current.user_name
        person = People.by_username(username)
        person = person.filter_private()
        return dict(person=person, date=datetime.utcnow().ctime())

    @identity.require(turbogears.identity.not_anonymous())
    @expose(template="fas.templates.user.view", allow_json=True)
    def reject(self, person_name):
        '''Reject a user's FPCA.

        This method will remove a user from the FPCA group and any other groups
        that they are in that require the FPCA.  It is used when a person has
        to fulfill some more legal requirements before having a valid FPCA.

        Arguments
        :person_name: Name of the person to reject.
        '''
        show = {}
        show['show_postal_address'] = config.get('show_postal_address')
        exc = None
        user = People.by_username(turbogears.identity.current.user_name)
        if not is_admin(user):
            # Only admins can use this
            turbogears.flash(_('You are not allowed to reject FPCAs.'))
            exc = 'NotAuthorized'
        else:
            # Unapprove the cla and all dependent groups
            person = People.by_username(person_name)
            for role in person.roles:
                if self._cla_dependent(role.group):
                    role.role_status = 'unapproved'
            try:
                session.flush()
            except DBAPIError, error:
                turbogears.flash(_('Error removing cla and dependent groups' \
                        ' for %(person)s\n Error was: %(error)s') %
                        {'person': person_name, 'error': str(error)})
                exc = 'DBAPIError'

        if not exc:
            # Send a message that the ICLA has been revoked
            date_time = datetime.utcnow()
            Log(author_id=user.id, description='Revoked %s FPCA' %
                person.username, changetime=date_time)
            revoke_subject = _('Fedora ICLA Revoked', person.locale)
            i18n_revoke_text = _('''
Hello %(human_name)s,

We're sorry to bother you but we had to reject your FPCA for now because
information you provided has been deemed incorrect.  The most common cause
of this is people abbreviating their name like "B L Couper" instead of
providing their actual full name "Bill Lay Couper".  Other causes of this
include are using a country, or phone number that isn't accurate [1]_.
If you could edit your account [2]_ to fix any of these problems and resubmit
the FPCA we would appreciate it.

.. [1]: Why does it matter that we have your real name and phone
        number?   It's because the FPCA is a legal document and should we ever
        need to contact you about one of your contributions (as an example,
        because someone contacts *us* claiming that it was really they who
        own the copyright to the contribution) we might need to contact you
        for more information about what's going on.

.. [2]: Edit your account by logging in at this URL:
        https://admin.fedoraproject.org/accounts/user/edit/%(username)s

If you have questions about what specifically might be the problem with your
account, please contact us at [email protected].

Thanks!

    ''' % {'username': person.username, 'human_name': person.human_name}, person.locale)
            #TODO: Look at a better way to handle one text for mutiple usage.
            #      while dealing with pot files.
            std_revoke_text = '''

English version:
Hello %(human_name)s,

We're sorry to bother you but we had to reject your FPCA for now because
information you provided has been deemed incorrect.  The most common cause
of this is people abbreviating their name like "B L Couper" instead of
providing their actual full name "Bill Lay Couper".  Other causes of this
include are using a country, or phone number that isn't accurate [1]_.
If you could edit your account [2]_ to fix any of these problems and resubmit
the FPCA we would appreciate it.

.. [1]: Why does it matter that we have your real name and phone
        number?   It's because the FPCA is a legal document and should we ever
        need to contact you about one of your contributions (as an example,
        because someone contacts *us* claiming that it was really they who
        own the copyright to the contribution) we might need to contact you
        for more information about what's going on.

.. [2]: Edit your account by logging in at this URL:
        https://admin.fedoraproject.org/accounts/user/edit/%(username)s

If you have questions about what specifically might be the problem with your
account, please contact us at [email protected].

Thanks!
    ''' % {'username': person.username, 'human_name': person.human_name}

            revoke_text = i18n_revoke_text + std_revoke_text
            send_mail(person.email, revoke_subject, revoke_text)

            # Yay, sweet success!
            turbogears.flash(_('FPCA Successfully Removed.'))
        # and now we're done
        if request_format() == 'json':
            return_val = {}
            if exc:
                return_val['exc'] = exc
            return return_val
        else:
            turbogears.redirect('/user/view/%s' % person_name)
예제 #25
0
class Root(plugin.RootController):

    user = User()
    group = Group()
    fpca = FPCA()
    json = JsonRequest()
    config = Config()
    help = Help()

    def __init__(self):
        # TODO: Find a better place for this.
        os.environ['GNUPGHOME'] = config.get('gpghome')
        plugin.RootController.__init__(self)

    def getpluginident(self):
        return 'fas'

    @expose(template="fas.templates.welcome", allow_json=True)
    def index(self):
        if turbogears.identity.not_anonymous():
            if request_format() == 'json':
                # redirects don't work with JSON calls.  This is a bit of a
                # hack until we can figure out something better.
                return dict()
            turbogears.redirect('/home')
        return dict(now=time.ctime())

    @identity.require(identity.not_anonymous())
    @expose(template="fas.templates.home", allow_json=True)
    def home(self):
        user_name = turbogears.identity.current.user_name
        person = People.by_username(user_name)
        (cla_done, undeprecated_cla) = undeprecated_cla_done(person)

        person = person.filter_private()
        return dict(person=person,
                    memberships=person['memberships'],
                    cla=undeprecated_cla)

    @expose(template="fas.templates.about")
    def about(self):
        return dict()

    @expose(template="fas.templates.login", allow_json=True)
    def login(self, forward_url=None, *args, **kwargs):
        '''Page to become authenticated to the Account System.

        This shows a small login box to type in your username and password
        from the Fedora Account System.

        :kwarg forward_url: The url to send to once authentication succeeds
        '''
        actual_login_dict = f_ctrlers.login(forward_url=forward_url,
                                            *args,
                                            **kwargs)

        try:
            login_dict = Bunch()
            login_dict['user'] = Bunch()
            for field in People.allow_fields['complete']:
                login_dict['user'][field] = None
            for field in People.allow_fields['self']:
                login_dict['user'][field] = getattr(actual_login_dict['user'],
                                                    field)
            # Strip out things that the user shouldn't see about their own
            # login
            login_dict['user']['internal_comments'] = None
            login_dict['user']['emailtoken'] = None
            login_dict['user']['security_answer'] = None
            login_dict['user']['alias_enabled'] = None
            login_dict['user']['passwordtoken'] = None

            # Add things that are needed by some other apps
            login_dict['user'].approved_memberships = list(
                actual_login_dict['user'].approved_memberships)
            login_dict['user'].memberships = list(
                actual_login_dict['user'].memberships)
            login_dict['user'].unapproved_memberships = list(
                actual_login_dict['user'].unapproved_memberships)
            login_dict['user'].group_roles = list(
                actual_login_dict['user'].group_roles)
            login_dict['user'].roles = list(actual_login_dict['user'].roles)
            login_dict['user'].groups = [
                g.name for g in actual_login_dict['user'].approved_memberships
            ]
            return login_dict
        except KeyError, e:
            # No problem, this usually means that we failed to login and
            # therefore we don't have a user field.
            login_dict = actual_login_dict

        if not identity.current.anonymous and identity.was_login_attempted() \
                and not identity.get_identity_errors():
            # Success that needs to be passed back via json
            return login_dict

        if identity.was_login_attempted() and request.fas_provided_username:
            if request.fas_identity_failure_reason == 'status_inactive':
                turbogears.flash(
                    _('Your old password has expired.  Please'
                      ' reset your password below.'))
                if request_format() != 'json':
                    redirect('/user/resetpass')
            if request.fas_identity_failure_reason == 'status_account_disabled':
                turbogears.flash(
                    _('Your account is currently disabled.  For'
                      ' more information, please contact %(admin_email)s' %
                      {'admin_email': config.get('accounts_email')}))
                if request_format() != 'json':
                    redirect('/login')

        return login_dict
예제 #26
0
    def default(self, package_name, *args, **kwargs):
        """Display a list of Fedora bugs against a given package."""
        # Nasty, nasty hack.  The packagedb, via bugz.fp.o is getting sent
        # requests to download files.  These refused to go away even when
        # we fixed up the apache redirects.  Send them to download.fp.o
        # manually.
        if args or kwargs:
            if args:
                url = (
                    "http://download.fedoraproject.org/"
                    + quote(package_name)
                    + "/"
                    + "/".join([quote(a) for a in args])
                )
            elif kwargs:
                url = (
                    "http://mirrors.fedoraproject.org/"
                    + quote(package_name)
                    + "?"
                    + "&".join([quote(q) + "=" + quote(v) for (q, v) in kwargs.items()])
                )
                LOG.warning(_("Invalid URL: redirecting: %(url)s") % {"url": url})
            raise redirect(url)

        query = {
            "product": ("Fedora", "Fedora EPEL"),
            "component": package_name,
            "bug_status": (
                "ASSIGNED",
                "NEW",
                "MODIFIED",
                "ON_DEV",
                "ON_QA",
                "VERIFIED",
                "FAILS_QA",
                "RELEASE_PENDING",
                "POST",
            ),
        }
        # :E1101: python-bugzilla monkey patches this in
        try:
            bugzilla = get_bz()
        except xmlrpclib.ProtocolError:
            error = dict(
                status=False,
                title=_("%(app)s -- Unable to contact bugzilla") % {"app": self.app_title},
                message=_("Bugzilla is unavailable.  Unable to determine" " bugs for %(pkg)s") % {"pkg": package_name},
            )
            if request_format() != "json":
                error["tg_template"] = "pkgdb.templates.errors"
            return error

        raw_bugs = bugzilla.query(query)  # pylint: disable-msg=E1101
        bugs = BugList(self.bzQueryUrl, self.bzUrl)
        for bug in raw_bugs:
            bugs.append(bug)

        if not bugs:
            # Check that the package exists
            try:
                # pylint: disable-msg=E1101
                Package.query.filter_by(name=package_name).one()
            except InvalidRequestError:
                error = dict(
                    status=False,
                    title=_("%(app)s -- Not a Valid Package Name") % {"app": self.app_title},
                    message=_("No such package %(pkg)s") % {"pkg": package_name},
                )
                if request_format() != "json":
                    error["tg_template"] = "pkgdb.templates.errors"
                return error

        return dict(
            title=_("%(app)s -- Open Bugs for %(pkg)s") % {"app": self.app_title, "pkg": package_name},
            package=package_name,
            bugs=bugs,
        )
예제 #27
0
    def packages(self, fasname=None, acls=None, eol=None):
        '''List packages that the user is interested in.

        This method returns a list of packages owned by the user in current,
        non-EOL distributions.  The user has the ability to filter this to
        provide more or less information by adding query params for acls and
        EOL.

        :kwarg fasname: The name of the user to get the package list for.
                  Default: The logged in user.
        :kwarg acls: List of acls to select.
               Note: for backwards compatibility, this can also be a comma
               separated string of acls.
               Default: all acls.
        :kwarg eol: If set, list packages that are in EOL distros.
        :returns: A list of packages.
        '''
        # Set EOL to false for a few obvious values
        if not eol or eol.lower() in ('false', 'f', '0'):
            eol = False
        else:
            eol = bool(eol)

        # For backward compat, redirect the orphan user to the orphan page
        if fasname == 'orphan':
            params = {}
            if eol:
                params['eol'] = True
            if request_format() == 'json':
                params['tg_format'] = 'json'
            url = '/acls/orphans'
            if params:
                url = url + '?' + urllib.urlencode(params, True)

            raise redirect(url)

        if not acls:
            # Default to all acls
            acls = [k[0] for k in self.allAcls]
        elif isinstance(acls, basestring):
            # For backwards compatibility, make acls into a list if it's a
            # comma separated string of values
            acls = acls.split(',')

        # Create a list where store acl name, whether the acl is currently
        # being filtered for, and the label to use to display the acl.
        acl_list = [(a[0], a[0] in acls, a[1]) for a in self.allAcls]

        # Have to either get fasname from the URL or current user
        if fasname == None:
            if identity.current.anonymous:
                raise identity.IdentityFailure(
                    _('You must be logged in to view your information'))
            else:
                fasname = identity.current.user_name

        page_title = _('%(app)s -- %(name)s -- Packages') % {
            'app': self.app_title,
            'name': fasname
        }

        # pylint: disable-msg=E1101
        query = Package.query.join('listings2').distinct().options(
            lazyload('listings2.groups2'), lazyload('listings2.groups2.acls2'),
            lazyload('listings2.people2'), lazyload('listings2.people2.acls2'),
            lazyload('listings2'))

        if not eol:
            # We don't want EOL releases, filter those out of each clause
            query = query.join(
                ['listings2',
                 'collection']).filter(Collection.statuscode != STATUS['EOL'])

        queries = []
        if 'owner' in acls:
            # Return any package for which the user is the owner
            queries.append(
                query.filter(
                    sqlalchemy.and_(
                        Package.statuscode.in_(
                            (STATUS['Approved'], STATUS['Awaiting Review'],
                             STATUS['Under Review'])),
                        PackageListing.owner == fasname,
                        PackageListing.statuscode.in_(
                            (STATUS['Approved'], STATUS['Awaiting Branch'],
                             STATUS['Awaiting Review'])))))
            del acls[acls.index('owner')]

        if acls:
            # Return any package on which the user has an Approved acl.
            queries.append(
                query.join(['listings2', 'people2']).join(
                    ['listings2', 'people2', 'acls2']).filter(
                        sqlalchemy.and_(
                            Package.statuscode.in_(
                                (STATUS['Approved'], STATUS['Awaiting Review'],
                                 STATUS['Under Review'])),
                            PersonPackageListing.username == fasname,
                            PersonPackageListingAcl.statuscode ==
                            STATUS['Approved'],
                            PackageListing.statuscode.in_(
                                (STATUS['Approved'], STATUS['Awaiting Branch'],
                                 STATUS['Awaiting Review'])))))
            # Return only those acls which the user wants listed
            queries[-1] = queries[-1].filter(
                PersonPackageListingAcl.acl.in_(acls))

        if len(queries) == 2:
            my_pkgs = Package.query.select_from(
                sqlalchemy.union(queries[0].statement, queries[1].statement))
        else:
            my_pkgs = queries[0]

        my_pkgs = my_pkgs.options(lazyload('listings2.people2'),
                                  lazyload('listings2.people2.acls2'),
                                  lazyload('listings2.groups2'),
                                  lazyload('listings2.groups2.acls2'),
                                  lazyload('listings2')).order_by(Package.name)
        # pylint: enable-msg=E1101
        pkg_list = []
        statuses = set()
        collectn_map = {}
        for pkg in my_pkgs:
            pkg.json_props = {'Package': ('listings', )}
            pkg_list.append(pkg)
            for pkglisting in pkg.listings:
                statuses.add(pkglisting.statuscode)
                if pkglisting.collection.collectionid not in collectn_map \
                    and pkglisting.collection.statuscode!=STATUS['EOL']:
                    collectn_map[
                        pkglisting.collection.
                        collectionid] = pkglisting.collection.branchname

        statusMap = dict([(statuscode, STATUS[statuscode])
                          for statuscode in statuses])

        return dict(title=page_title,
                    pkgCount=len(pkg_list),
                    pkgs=pkg_list,
                    acls=acl_list,
                    fasname=fasname,
                    eol=eol,
                    statusMap=statusMap,
                    collectn_map=collectn_map)