Esempio n. 1
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
Esempio n. 2
0
def attach_http_request(report, context):
    """Add request metadata into the error report.

    This reads the exc_info and http_request keys from the context and will
    write to:
    * url
    * ignore
    * username
    * topic
    * req_vars
    """
    info = context.get('exc_info')
    request = context.get('http_request')
    if request is None:
        return
    # XXX jamesh 2005-11-22: Temporary fix, which Steve should
    #      undo. URL is just too HTTPRequest-specific.
    if safe_hasattr(request, 'URL'):
        # URL's are byte strings, but possibly str() will fail - safe_unicode
        # handles all those cases, and then we can safely encode it to utf8.
        # This is strictly double handling as a URL should never have unicode
        # characters in it anyway (though it may have them % encoded, which is
        # fine). Better safe than sorry, and the safe_unicode handling won't
        # cause double-encoding, so it is safe.
        url = oops.createhooks.safe_unicode(request.URL).encode('utf8')
        report['url'] = url

    if WebServiceLayer.providedBy(request) and info is not None:
        webservice_error = getattr(
            info[1], '__lazr_webservice_error__', 500)
        if webservice_error / 100 != 5:
            request.oopsid = None
            # Tell the oops machinery to ignore this error
            report['ignore'] = True

    missing = object()
    principal = getattr(request, 'principal', missing)
    if safe_hasattr(principal, 'getLogin'):
        login = principal.getLogin()
    elif principal is missing or principal is None:
        # Request has no principal (e.g. scriptrequest)
        login = None
    else:
        # Request has an UnauthenticatedPrincipal.
        login = '******'
        if _get_type(report) in (
            _ignored_exceptions_for_unauthenticated_users):
            report['ignore'] = True

    if principal is not None and principal is not missing:
        username = '******'.join([
                unicode(login),
                unicode(request.principal.id),
                unicode(request.principal.title),
                unicode(request.principal.description)])
        report['username'] = username

    if getattr(request, '_orig_env', None):
        report['topic'] = request._orig_env.get('launchpad.pageid', '')

    for key, value in request.items():
        if _is_sensitive(request, key):
            value = '<hidden>'
        if not isinstance(value, basestring):
            value = oops.createhooks.safe_unicode(value)
        # keys need to be unicode objects. The form items (a subset of
        # request.items) are generally just the url query_string url decoded,
        # which means the keys may be invalid in bson docs (bson requires that
        # they be unicode).
        key = oops.createhooks.safe_unicode(key)
        report['req_vars'][key] = value
    if IXMLRPCRequest.providedBy(request):
        args = request.getPositionalArguments()
        # Request variables are strings: this could move to its own key and be
        # raw.
        report['req_vars']['xmlrpc args'] = unicode(args)
Esempio n. 3
0
def attach_http_request(report, context):
    """Add request metadata into the error report.

    This reads the exc_info and http_request keys from the context and will
    write to:
    * url
    * ignore
    * username
    * topic
    * req_vars
    """
    info = context.get('exc_info')
    request = context.get('http_request')
    if request is None:
        return
    # XXX jamesh 2005-11-22: Temporary fix, which Steve should
    #      undo. URL is just too HTTPRequest-specific.
    if safe_hasattr(request, 'URL'):
        # URL's are byte strings, but possibly str() will fail - safe_unicode
        # handles all those cases, and then we can safely encode it to utf8.
        # This is strictly double handling as a URL should never have unicode
        # characters in it anyway (though it may have them % encoded, which is
        # fine). Better safe than sorry, and the safe_unicode handling won't
        # cause double-encoding, so it is safe.
        url = oops.createhooks.safe_unicode(request.URL).encode('utf8')
        report['url'] = url

    if WebServiceLayer.providedBy(request) and info is not None:
        webservice_error = getattr(
            info[1], '__lazr_webservice_error__', 500)
        if webservice_error / 100 != 5:
            request.oopsid = None
            # Tell the oops machinery to ignore this error
            report['ignore'] = True

    missing = object()
    principal = getattr(request, 'principal', missing)
    if safe_hasattr(principal, 'getLogin'):
        login = principal.getLogin()
    elif principal is missing or principal is None:
        # Request has no principal (e.g. scriptrequest)
        login = None
    else:
        # Request has an UnauthenticatedPrincipal.
        login = '******'
        if _get_type(report) in (
            _ignored_exceptions_for_unauthenticated_users):
            report['ignore'] = True

    if principal is not None and principal is not missing:
        username = '******'.join([
                unicode(login),
                unicode(request.principal.id),
                unicode(request.principal.title),
                unicode(request.principal.description)])
        report['username'] = username

    if getattr(request, '_orig_env', None):
        report['topic'] = request._orig_env.get('launchpad.pageid', '')

    for key, value in request.items():
        if _is_sensitive(request, key):
            value = '<hidden>'
        if not isinstance(value, basestring):
            value = oops.createhooks.safe_unicode(value)
        # keys need to be unicode objects. The form items (a subset of
        # request.items) are generally just the url query_string url decoded,
        # which means the keys may be invalid in bson docs (bson requires that
        # they be unicode).
        key = oops.createhooks.safe_unicode(key)
        report['req_vars'][key] = value
    if IXMLRPCRequest.providedBy(request):
        args = request.getPositionalArguments()
        # Request variables are strings: this could move to its own key and be
        # raw.
        report['req_vars']['xmlrpc args'] = unicode(args)
Esempio n. 4
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)):
                    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