def test_unresolver_single_version(self):
     self.pip.single_version = True
     parts = unresolve('http://pip.readthedocs.io/')
     self.assertEqual(parts.project.slug, 'pip')
     self.assertEqual(parts.language_slug, None)
     self.assertEqual(parts.version_slug, None)
     self.assertEqual(parts.filename, '')
 def test_unresolver_subproject(self):
     parts = unresolve(
         'http://pip.readthedocs.io/projects/sub/ja/latest/foo.html')
     self.assertEqual(parts.project.slug, 'sub')
     self.assertEqual(parts.language_slug, 'ja')
     self.assertEqual(parts.version_slug, 'latest')
     self.assertEqual(parts.filename, 'foo.html')
 def test_unresolver(self):
     parts = unresolve(
         'http://pip.readthedocs.io/en/latest/foo.html#fragment')
     self.assertEqual(parts.project.slug, 'pip')
     self.assertEqual(parts.language_slug, 'en')
     self.assertEqual(parts.version_slug, 'latest')
     self.assertEqual(parts.filename, 'foo.html')
     self.assertEqual(parts.fragment, 'fragment')
def decide_if_cors(sender, request, **kwargs):  # pylint: disable=unused-argument
    """
    Decide whether a request should be given CORS access.

    Allow the request if:

    * It's a safe HTTP method
    * The origin is in ALLOWED_URLS
    * The URL is owned by the project that they are requesting data from
    * The version is public

    .. note::

       Requests from the sustainability API are always allowed
       if the donate app is installed.

    :returns: `True` when a request should be given CORS access.
    """
    if 'HTTP_ORIGIN' not in request.META or request.method not in SAFE_METHODS:
        return False

    # Always allow the sustainability API,
    # it's used only on .org to check for ad-free users.
    if _has_donate_app() and request.path_info.startswith(
            '/api/v2/sustainability'):
        return True

    valid_url = None
    for url in ALLOWED_URLS:
        if request.path_info.startswith(url):
            valid_url = url
            break

    if valid_url:
        url = request.GET.get('url')
        if url:
            unresolved = unresolve(url)
            project = unresolved.project
            version_slug = unresolved.version_slug
        else:
            project_slug = request.GET.get('project', None)
            version_slug = request.GET.get('version', None)
            project = Project.objects.filter(slug=project_slug).first()

        if project and version_slug:
            # This is from IsAuthorizedToViewVersion,
            # we should abstract is a bit perhaps?
            is_public = (Version.objects.public(
                project=project,
                only_active=False,
            ).filter(slug=version_slug).exists())
            # Allowing CORS on public versions,
            # since they are already public.
            if is_public:
                return True

    return False
 def test_unresolver_external_version(self):
     ver = self.pip.versions.first()
     ver.type = 'external'
     ver.slug = '10'
     parts = unresolve('http://pip--10.dev.readthedocs.build/en/10/')
     self.assertEqual(parts.project.slug, 'pip')
     self.assertEqual(parts.language_slug, 'en')
     self.assertEqual(parts.version_slug, '10')
     self.assertEqual(parts.filename, '')
 def test_unresolver_subproject_alias(self):
     relation = self.pip.subprojects.first()
     relation.alias = 'sub_alias'
     relation.save()
     parts = unresolve(
         'http://pip.readthedocs.io/projects/sub_alias/ja/latest/')
     self.assertEqual(parts.project.slug, 'sub')
     self.assertEqual(parts.language_slug, 'ja')
     self.assertEqual(parts.version_slug, 'latest')
     self.assertEqual(parts.filename, '')
 def test_unresolver_domain(self):
     self.domain = fixture.get(
         Domain,
         domain='docs.foobar.com',
         project=self.pip,
         canonical=True,
     )
     parts = unresolve('http://docs.foobar.com/en/latest/')
     self.assertEqual(parts.project.slug, 'pip')
     self.assertEqual(parts.language_slug, 'en')
     self.assertEqual(parts.version_slug, 'latest')
     self.assertEqual(parts.filename, '')
Exemple #8
0
 def unresolved_url(self):
     url = self.request.GET.get('url')
     if not url:
         return None
     return unresolve(url)
Exemple #9
0
def decide_if_cors(sender, request, **kwargs):  # pylint: disable=unused-argument
    """
    Decide whether a request should be given CORS access.

    Allow the request if:

    * It's a safe HTTP method
    * The origin is in ALLOWED_URLS
    * The URL is owned by the project that they are requesting data from
    * The version is public or the domain is linked to the project
      (except for the embed API).

    .. note::

       Requests from the sustainability API are always allowed
       if the donate app is installed.

    :returns: `True` when a request should be given CORS access.
    """
    if 'HTTP_ORIGIN' not in request.META or request.method not in SAFE_METHODS:
        return False

    host = urlparse(request.META['HTTP_ORIGIN']).netloc.split(':')[0]

    # Always allow the sustainability API,
    # it's used only on .org to check for ad-free users.
    if _has_donate_app() and request.path_info.startswith(
            '/api/v2/sustainability'):
        return True

    valid_url = None
    for url in ALLOWED_URLS:
        if request.path_info.startswith(url):
            valid_url = url
            break

    if valid_url:
        url = request.GET.get('url')
        if url:
            unresolved = unresolve(url)
            project = unresolved.project
            version_slug = unresolved.version_slug
        else:
            project_slug = request.GET.get('project', None)
            version_slug = request.GET.get('version', None)
            project = Project.objects.filter(slug=project_slug).first()

        if project and version_slug:
            # This is from IsAuthorizedToViewVersion,
            # we should abstract is a bit perhaps?
            is_public = (Version.objects.public(
                project=project,
                only_active=False,
            ).filter(slug=version_slug).exists())
            # Allowing CORS on public versions,
            # since they are already public.
            if is_public:
                return True

            # Don't check for known domains for the embed api.
            # It gives a lot of information,
            # we should use a list of trusted domains from the user.
            if valid_url == '/api/v2/embed':
                return False

            # Or allow if they have a registered domain
            # linked to that project.
            domain = Domain.objects.filter(
                Q(domain__iexact=host),
                Q(project=project) | Q(project__subprojects__child=project),
            )
            if domain.exists():
                return True
    return False
 def test_unresolver_unknown_host(self):
     parts = unresolve('http://random.stuff.com/en/latest/')
     self.assertEqual(parts, None)
Exemple #11
0
def decide_if_cors(sender, request, **kwargs):  # pylint: disable=unused-argument
    """
    Decide whether a request should be given CORS access.

    This checks that:
    * The URL is whitelisted against our CORS-allowed domains
    * The Domain exists in our database, and belongs to the project being queried.

    Returns True when a request should be given CORS access.
    """
    if 'HTTP_ORIGIN' not in request.META:
        return False
    host = urlparse(request.META['HTTP_ORIGIN']).netloc.split(':')[0]

    # Don't do domain checking for this API for now
    if request.path_info.startswith('/api/v2/sustainability'):
        return True

    # Don't do domain checking for APIv2 when the Domain is known
    if request.path_info.startswith(
            '/api/v2/') and request.method in SAFE_METHODS:
        domain = Domain.objects.filter(domain__icontains=host)
        if domain.exists():
            return True

    # Check for Embed API, allowing CORS on public projects
    # since they are already public
    if request.path_info.startswith('/api/v2/embed'):
        url = request.GET.get('url')
        if url:
            unresolved = unresolve(url)
            project = unresolved.project
            version_slug = unresolved.version_slug
        else:
            project_slug = request.GET.get('project', None)
            version_slug = request.GET.get('version', None)
            project = Project.objects.filter(slug=project_slug).first()

        if project and version_slug:
            # This is from IsAuthorizedToViewVersion,
            # we should abstract is a bit perhaps?
            has_access = (Version.objects.public(
                project=project,
                only_active=False,
            ).filter(slug=version_slug).exists())
            if has_access:
                return True

        return False

    valid_url = False
    for url in ALLOWED_URLS:
        if request.path_info.startswith(url):
            valid_url = True
            break

    if valid_url:
        project_slug = request.GET.get('project', None)
        try:
            project = Project.objects.get(slug=project_slug)
        except Project.DoesNotExist:
            log.warning(
                'Invalid project passed to domain. [%s:%s]',
                project_slug,
                host,
            )
            return False

        domain = Domain.objects.filter(
            Q(domain__icontains=host),
            Q(project=project) | Q(project__subprojects__child=project),
        )
        if domain.exists():
            return True

    return False