Example #1
0
    def traverse(self, name):
        """Traverse the paths of a feed.

        If a query string is provided it is normalized.  'bugs' paths and
        persons ('~') are special cased.
        """
        # Normalize the query string so caching is more effective.  This is
        # done by simply sorting the entries.

        # XXX bac 20071019, we would like to normalize with respect to case
        # too but cannot due to a problem with the bug search requiring status
        # values to be of a particular case.  See bug 154562.
        query_string = self.request.get('QUERY_STRING', '')
        fields = sorted(query_string.split('&'))
        normalized_query_string = '&'.join(fields)
        if query_string != normalized_query_string:
            # We must empty the traversal stack to prevent an error
            # when calling RedirectionView.publishTraverse().
            self.request.setTraversalStack([])
            target = "%s%s?%s" % (self.request.getApplicationURL(),
                                  self.request['PATH_INFO'],
                                  normalized_query_string)
            redirect = RedirectionView(target, self.request, 301)
            return redirect

        # Handle the two formats of urls:
        # http://feeds.launchpad.net/bugs/+bugs.atom?...
        # http://feeds.launchpad.net/bugs/1/bug.atom
        if name == 'bugs':
            stack = self.request.getTraversalStack()
            if len(stack) == 0:
                raise NotFound(self, '', self.request)
            bug_id = stack.pop()
            if bug_id.startswith('+'):
                if config.launchpad.is_bug_search_feed_active:
                    return getUtility(IBugTaskSet)
                else:
                    raise Unauthorized("Bug search feed deactivated")
            else:
                self.request.stepstogo.consume()
                return getUtility(IBugSet).getByNameOrID(bug_id)

        # Redirect to the canonical name before doing the lookup.
        if canonical_name(name) != name:
            return self.redirectSubTree(canonical_url(self.context) +
                                        canonical_name(name),
                                        status=301)

        try:
            if name.startswith('~'):
                # Handle persons and teams.
                # http://feeds.launchpad.net/~salgado/latest-bugs.html
                person = getUtility(IPersonSet).getByName(name[1:])
                return person
            else:
                # Otherwise, handle products, projects, and distros
                return getUtility(IPillarNameSet)[name]
        except NotFoundError:
            raise NotFound(self, name, self.request)
Example #2
0
    def traverse(self, name):
        """Traverse the paths of a feed.

        If a query string is provided it is normalized.  'bugs' paths and
        persons ('~') are special cased.
        """
        # Normalize the query string so caching is more effective.  This is
        # done by simply sorting the entries.

        # XXX bac 20071019, we would like to normalize with respect to case
        # too but cannot due to a problem with the bug search requiring status
        # values to be of a particular case.  See bug 154562.
        query_string = self.request.get('QUERY_STRING', '')
        fields = sorted(query_string.split('&'))
        normalized_query_string = '&'.join(fields)
        if query_string != normalized_query_string:
            # We must empty the traversal stack to prevent an error
            # when calling RedirectionView.publishTraverse().
            self.request.setTraversalStack([])
            target = "%s%s?%s" % (self.request.getApplicationURL(),
                                  self.request['PATH_INFO'],
                                  normalized_query_string)
            redirect = RedirectionView(target, self.request, 301)
            return redirect

        # Handle the two formats of urls:
        # http://feeds.launchpad.net/bugs/+bugs.atom?...
        # http://feeds.launchpad.net/bugs/1/bug.atom
        if name == 'bugs':
            stack = self.request.getTraversalStack()
            if len(stack) == 0:
                raise NotFound(self, '', self.request)
            bug_id = stack.pop()
            if bug_id.startswith('+'):
                if config.launchpad.is_bug_search_feed_active:
                    return getUtility(IBugTaskSet)
                else:
                    raise Unauthorized("Bug search feed deactivated")
            else:
                self.request.stepstogo.consume()
                return getUtility(IBugSet).getByNameOrID(bug_id)

        # Redirect to the canonical name before doing the lookup.
        if canonical_name(name) != name:
            return self.redirectSubTree(
                canonical_url(self.context) + canonical_name(name),
                status=301)

        try:
            if name.startswith('~'):
                # Handle persons and teams.
                # http://feeds.launchpad.net/~salgado/latest-bugs.html
                person = getUtility(IPersonSet).getByName(name[1:])
                return person
            else:
                # Otherwise, handle products, projects, and distros
                return getUtility(IPillarNameSet)[name]
        except NotFoundError:
            raise NotFound(self, name, self.request)
Example #3
0
    def traverse(self, name):
        if name in self.stepto_utilities:
            return getUtility(self.stepto_utilities[name])

        if name == '~':
            person = getUtility(ILaunchBag).user
            if person is None:
                raise Unauthorized()
            # Keep the context and the subtree so that
            # bugs.l.n/~/+assignedbugs goes to the person's canonical
            # assigned list.
            return self.redirectSubTree(
                canonical_url(self.context) + "~"
                + canonical_name(person.name),
                status=302)
        elif name.startswith('~'):  # Allow traversal to ~foo for People
            if canonical_name(name) != name:
                # (for instance, uppercase username?)
                if self.request.method == 'POST':
                    raise POSTToNonCanonicalURL
                return self.redirectSubTree(
                    canonical_url(self.context) + canonical_name(name),
                    status=301)
            else:
                person = getUtility(IPersonSet).getByName(name[1:])
                if person is None:
                    return person
                # Check to see if this is a team, and if so, whether the
                # logged in user is allowed to view the team, by virtue of
                # team membership or Launchpad administration.
                if (person.is_team and
                    not check_permission('launchpad.LimitedView', person)):
                    return None
                # Only admins are permitted to see suspended users.
                if person.account_status == AccountStatus.SUSPENDED:
                    if not check_permission('launchpad.Moderate', person):
                        raise GoneError(
                            'User is suspended: %s' % name)
                if person.account_status == AccountStatus.PLACEHOLDER:
                    if not check_permission('launchpad.Moderate', person):
                        return None
                return person

        # Dapper and Edgy shipped with https://launchpad.net/bazaar hard coded
        # into the Bazaar Launchpad plugin (part of Bazaar core). So in theory
        # we need to support this URL until 2011 (although I suspect the API
        # will break much sooner than that) or updates sent to
        # {dapper,edgy}-updates. Probably all irrelevant, as I suspect the
        # number of people using the plugin in edgy and dapper is 0.
        if name == 'bazaar' and IXMLRPCRequest.providedBy(self.request):
            return getUtility(IBazaarApplication)

        # account for common typing mistakes
        if canonical_name(name) != name:
            if self.request.method == 'POST':
                raise POSTToNonCanonicalURL
            return self.redirectSubTree(
                (canonical_url(self.context, request=self.request) +
                 canonical_name(name)),
                status=301)

        pillar = getUtility(IPillarNameSet).getByName(
            name, ignore_inactive=False)

        if pillar is None:
            return None

        if IProduct.providedBy(pillar):
            if not pillar.active:
                # Emergency brake for public but inactive products:
                # These products should not be shown to ordinary users.
                # The root problem is that many views iterate over products,
                # inactive products included, and access attributes like
                # name, displayname or call canonical_url(product) --
                # and finally throw the data away, if the product is
                # inactive. So we cannot make these attributes inaccessible
                # for inactive public products. On the other hand, we
                # require the permission launchpad.View to protect private
                # products.
                # This means that we cannot simply check if the current
                # user has the permission launchpad.View for an inactive
                # product.
                user = getUtility(ILaunchBag).user
                if user is None:
                    return None
                user = IPersonRoles(user)
                if (not user.in_commercial_admin and not user.in_admin and
                    not user.in_registry_experts):
                    return None
        if check_permission('launchpad.LimitedView', pillar):
            if pillar.name != name:
                # This pillar was accessed through one of its aliases, so we
                # must redirect to its canonical URL.
                return self.redirectSubTree(
                    canonical_url(pillar, self.request), status=301)
            return pillar
        return None
    def traverse(self, name):
        if name in self.stepto_utilities:
            return getUtility(self.stepto_utilities[name])

        if name == '~':
            person = getUtility(ILaunchBag).user
            if person is None:
                raise Unauthorized()
            # Keep the context and the subtree so that
            # bugs.l.n/~/+assignedbugs goes to the person's canonical
            # assigned list.
            return self.redirectSubTree(
                canonical_url(self.context) + "~"
                + canonical_name(person.name),
                status=302)
        elif name.startswith('~'):  # Allow traversal to ~foo for People
            if canonical_name(name) != name:
                # (for instance, uppercase username?)
                if self.request.method == 'POST':
                    raise POSTToNonCanonicalURL
                return self.redirectSubTree(
                    canonical_url(self.context) + canonical_name(name),
                    status=301)
            else:
                person = getUtility(IPersonSet).getByName(name[1:])
                if person is None:
                    return person
                # Check to see if this is a team, and if so, whether the
                # logged in user is allowed to view the team, by virtue of
                # team membership or Launchpad administration.
                if (person.is_team and
                    not check_permission('launchpad.LimitedView', person)):
                    raise NotFound(self.context, name)
                # Only admins are permitted to see suspended users.
                if person.account_status == AccountStatus.SUSPENDED:
                    if not check_permission('launchpad.Moderate', person):
                        raise GoneError(
                            'User is suspended: %s' % name)
                return person

        # Dapper and Edgy shipped with https://launchpad.net/bazaar hard coded
        # into the Bazaar Launchpad plugin (part of Bazaar core). So in theory
        # we need to support this URL until 2011 (although I suspect the API
        # will break much sooner than that) or updates sent to
        # {dapper,edgy}-updates. Probably all irrelevant, as I suspect the
        # number of people using the plugin in edgy and dapper is 0.
        if name == 'bazaar' and IXMLRPCRequest.providedBy(self.request):
            return getUtility(IBazaarApplication)

        # account for common typing mistakes
        if canonical_name(name) != name:
            if self.request.method == 'POST':
                raise POSTToNonCanonicalURL
            return self.redirectSubTree(
                (canonical_url(self.context, request=self.request) +
                 canonical_name(name)),
                status=301)

        pillar = getUtility(IPillarNameSet).getByName(
            name, ignore_inactive=False)

        if pillar is None:
            return None

        if IProduct.providedBy(pillar):
            if not pillar.active:
                # Emergency brake for public but inactive products:
                # These products should not be shown to ordinary users.
                # The root problem is that many views iterate over products,
                # inactive products included, and access attributes like
                # name, displayname or call canonical_url(product) --
                # and finally throw the data away, if the product is
                # inactive. So we cannot make these attributes inaccessible
                # for inactive public products. On the other hand, we
                # require the permission launchpad.View to protect private
                # products.
                # This means that we cannot simply check if the current
                # user has the permission launchpad.View for an inactive
                # product.
                user = getUtility(ILaunchBag).user
                if user is None:
                    return None
                user = IPersonRoles(user)
                if (not user.in_commercial_admin and not user.in_admin and
                    not user.in_registry_experts):
                    return None
        if check_permission('launchpad.LimitedView', pillar):
            if pillar.name != name:
                # This pillar was accessed through one of its aliases, so we
                # must redirect to its canonical URL.
                return self.redirectSubTree(
                    canonical_url(pillar, self.request), status=301)
            return pillar
        return None