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, '')
def unresolved_url(self): url = self.request.GET.get('url') if not url: return None return unresolve(url)
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)
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