Skip to content

Commit 97109de

Browse files
committed
Merge branch 'master' into fix-search-sphinx-2.1
2 parents e7fd44b + 0c0e75e commit 97109de

File tree

2 files changed

+65
-26
lines changed

2 files changed

+65
-26
lines changed

readthedocs/proxito/tests/test_full.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Copied from .org
22

33
import os
4+
from unittest import mock
45

56
import django_dynamic_fixture as fixture
6-
from unittest import mock
77
from django.conf import settings
88
from django.http import HttpResponse
99
from django.test.utils import override_settings
@@ -232,6 +232,16 @@ def test_default_robots_txt(self, storage_mock):
232232
b'User-agent: *\nAllow: /\nSitemap: https://project.readthedocs.io/sitemap.xml\n'
233233
)
234234

235+
@mock.patch('readthedocs.proxito.views.serve.get_storage_class')
236+
def test_default_robots_txt_private_version(self, storage_mock):
237+
storage_mock()().exists.return_value = False
238+
self.project.versions.update(active=True, built=True, privacy_level=constants.PRIVATE)
239+
response = self.client.get(
240+
reverse('robots_txt'),
241+
HTTP_HOST='project.readthedocs.io',
242+
)
243+
self.assertEqual(response.status_code, 404)
244+
235245
def test_custom_robots_txt(self):
236246
self.project.versions.update(active=True, built=True)
237247
response = self.client.get(
@@ -242,6 +252,14 @@ def test_custom_robots_txt(self):
242252
response['x-accel-redirect'], '/proxito/media/html/project/latest/robots.txt',
243253
)
244254

255+
def test_custom_robots_txt_private_version(self):
256+
self.project.versions.update(active=True, built=True, privacy_level=constants.PRIVATE)
257+
response = self.client.get(
258+
reverse('robots_txt'),
259+
HTTP_HOST='project.readthedocs.io',
260+
)
261+
self.assertEqual(response.status_code, 404)
262+
245263
def test_directory_indexes(self):
246264
self.project.versions.update(active=True, built=True)
247265
# Confirm we've serving from storage for the `index-exists/index.html` file
@@ -303,6 +321,14 @@ def test_directory_indexes_get_args(self):
303321
@mock.patch('readthedocs.proxito.views.serve.get_storage_class')
304322
def test_404_storage_serves_404(self, storage_mock):
305323
self.project.versions.update(active=True, built=True)
324+
fancy_version = fixture.get(
325+
Version,
326+
slug='fancy-version',
327+
privacy_level=constants.PUBLIC,
328+
active=True,
329+
built=True,
330+
project=self.project,
331+
)
306332

307333
storage_mock()().exists.side_effect = [False, False, True]
308334
response = self.client.get(
@@ -323,6 +349,15 @@ def test_404_storage_serves_404(self, storage_mock):
323349
@mock.patch('readthedocs.proxito.views.serve.get_storage_class')
324350
def test_404_storage_paths_checked(self, storage_mock):
325351
self.project.versions.update(active=True, built=True)
352+
fancy_version = fixture.get(
353+
Version,
354+
slug='fancy-version',
355+
privacy_level=constants.PUBLIC,
356+
active=True,
357+
built=True,
358+
project=self.project,
359+
)
360+
326361
storage_mock()().exists.return_value = False
327362
self.client.get(
328363
reverse('proxito_404_handler', kwargs={'proxito_path': '/en/fancy-version/not-found'}),
@@ -466,3 +501,11 @@ def test_sitemap_xml(self):
466501
),)
467502
self.assertEqual(response.context['versions'][1]['priority'], 0.9)
468503
self.assertEqual(response.context['versions'][1]['changefreq'], 'daily')
504+
505+
def test_sitemap_all_private_versions(self):
506+
self.project.versions.update(active=True, built=True, privacy_level=constants.PRIVATE)
507+
response = self.client.get(
508+
reverse('sitemap_xml'),
509+
HTTP_HOST='project.readthedocs.io',
510+
)
511+
self.assertEqual(response.status_code, 404)

readthedocs/proxito/views/serve.py

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,17 @@
1414
from django.views import View
1515
from django.views.decorators.cache import cache_page
1616

17-
from readthedocs.builds.constants import LATEST, STABLE, EXTERNAL
17+
from readthedocs.builds.constants import EXTERNAL, LATEST, STABLE
1818
from readthedocs.builds.models import Version
1919
from readthedocs.core.utils.extend import SettingsOverrideObject
2020
from readthedocs.projects import constants
2121
from readthedocs.projects.templatetags.projects_tags import sort_version_aware
2222
from readthedocs.redirects.exceptions import InfiniteRedirectException
2323

24-
from .mixins import ServeDocsMixin, ServeRedirectMixin
25-
2624
from .decorators import map_project_slug
25+
from .mixins import ServeDocsMixin, ServeRedirectMixin
2726
from .utils import _get_project_data_from_request
2827

29-
3028
log = logging.getLogger(__name__) # noqa
3129

3230

@@ -266,14 +264,17 @@ def get(self, request, proxito_path, template_name='404.html'):
266264
if default_version_slug != version_slug:
267265
versions.append(default_version_slug)
268266
for version_slug_404 in versions:
267+
if not self.allowed_user(request, final_project, version_slug_404):
268+
continue
269+
270+
storage_root_path = final_project.get_storage_path(
271+
type_='html',
272+
version_slug=version_slug_404,
273+
include_file=False,
274+
version_type=self.version_type,
275+
)
269276
for tryfile in ('404.html', '404/index.html'):
270-
storage_root_path = final_project.get_storage_path(
271-
type_='html',
272-
version_slug=version_slug_404,
273-
include_file=False,
274-
version_type=self.version_type,
275-
)
276-
storage_filename_path = os.path.join(storage_root_path, tryfile)
277+
storage_filename_path = f'{storage_root_path}/{tryfile}'
277278
if storage.exists(storage_filename_path):
278279
log.info(
279280
'Serving custom 404.html page: [project: %s] [version: %s]',
@@ -307,9 +308,7 @@ def get(self, request, project):
307308
version = project.versions.get(slug=version_slug)
308309

309310
no_serve_robots_txt = any([
310-
# If project is private or,
311-
project.privacy_level == constants.PRIVATE,
312-
# default version is private or,
311+
# If the default version is private or,
313312
version.privacy_level == constants.PRIVATE,
314313
# default version is not active or,
315314
not version.active,
@@ -327,7 +326,7 @@ def get(self, request, project):
327326
include_file=False,
328327
version_type=self.version_type,
329328
)
330-
path = os.path.join(storage_path, 'robots.txt')
329+
path = f'{storage_path}/robots.txt'
331330

332331
storage = get_storage_class(settings.RTD_BUILD_MEDIA_STORAGE)()
333332
if storage.exists(path):
@@ -369,9 +368,7 @@ def get(self, request, project):
369368
frequency. Starting from 1 and decreasing by 0.1 for priorities and starting
370369
from daily, weekly to monthly for change frequency.
371370
372-
If the project is private, the view raises ``Http404``. On the other hand,
373-
if the project is public but a version is private, this one is not included
374-
in the sitemap.
371+
If the project doesn't have any public version, the view raises ``Http404``.
375372
376373
:param request: Django request object
377374
:param project: Project instance to generate the sitemap
@@ -417,15 +414,14 @@ def changefreqs_generator():
417414
changefreqs = ['weekly', 'daily']
418415
yield from itertools.chain(changefreqs, itertools.repeat('monthly'))
419416

420-
if project.privacy_level == constants.PRIVATE:
417+
public_versions = Version.internal.public(
418+
project=project,
419+
only_active=True,
420+
)
421+
if not public_versions.exists():
421422
raise Http404
422423

423-
sorted_versions = sort_version_aware(
424-
Version.internal.public(
425-
project=project,
426-
only_active=True,
427-
),
428-
)
424+
sorted_versions = sort_version_aware(public_versions)
429425

430426
# This is a hack to swap the latest version with
431427
# stable version to get the stable version first in the sitemap.

0 commit comments

Comments
 (0)