Skip to content

Commit bc247ba

Browse files
authored
Redirect for / and /welcome URLs (#12163)
We will always redirect users hitting `readthedocs.org` and `readthedocs.com` to the `app.` version of it at `/welcome`. From there, we will redirect to the dashboard if logged in or to the website if not. If the user is logged in: readthedocs.org -> app.readthedocs.org/welcome -> app.readthedocs.org If the user is logged out: readthedocs.org -> app.readthedocs.org/welcome -> about.readthedocs.com On the other hand, people hitting the dashboard app, we will redirect to the login page or to the dashboard. Closes readthedocs/readthedocs-ops#1625
1 parent 9e3497a commit bc247ba

File tree

3 files changed

+74
-25
lines changed

3 files changed

+74
-25
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import django_dynamic_fixture as fixture
2+
from django.urls import reverse
3+
from django.contrib.auth.models import User
4+
from django.test import TestCase, override_settings
5+
6+
7+
class HomepageTest(TestCase):
8+
9+
def test_homepage_auth(self):
10+
user = fixture.get(
11+
User,
12+
username="user",
13+
)
14+
self.client.force_login(user)
15+
16+
# Hitting "app.readthedocs.org" at /
17+
response = self.client.get(
18+
reverse("homepage"),
19+
)
20+
assert response.headers.get("Location") == reverse("projects_dashboard")
21+
22+
def test_homepage_unauth(self):
23+
# Hitting "app.readthedocs.org" at /
24+
response = self.client.get(
25+
reverse("homepage"),
26+
)
27+
assert response.headers.get("Location") == reverse("account_login")
28+
29+
def test_welcome_auth(self):
30+
user = fixture.get(
31+
User,
32+
username="user",
33+
)
34+
self.client.force_login(user)
35+
36+
# Hitting "app.readthedocs.org" at /welcome
37+
response = self.client.get(
38+
reverse("welcome"),
39+
)
40+
assert response.headers.get("Location") == reverse("projects_dashboard")
41+
42+
@override_settings(PRODUCTION_DOMAIN="readthedocs.org")
43+
def test_welcome_unauth(self):
44+
# Hitting "app.readthedocs.org" at /welcome
45+
response = self.client.get(
46+
reverse("welcome"),
47+
)
48+
assert response.headers.get("Location") == "https://about.readthedocs.com/?ref=readthedocs.org"

readthedocs/core/views/__init__.py

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,25 @@ def get(self, request, *_, **__):
3636
return JsonResponse({"status": 200}, status=200)
3737

3838

39-
class HomepageView(TemplateView):
39+
class HomepageView(View):
40+
"""Conditionally redirect to dashboard or login page."""
41+
42+
def get(self, request, *args, **kwargs):
43+
# Redirect to user dashboard for logged in users
44+
if request.user.is_authenticated:
45+
return redirect(reverse("projects_dashboard"))
46+
47+
# Redirect to login page if unauthed
48+
return redirect(reverse("account_login"))
49+
50+
51+
class WelcomeView(View):
4052
"""
4153
Conditionally redirect to website home page or to dashboard.
4254
55+
User hitting readthedocs.org / readthedocs.com is redirected to this view (at /welcome).
56+
This view will redirect the user based on auth/unauthed:
4357
44-
User hitting readthedocs.org / readthedocs.com
4558
1. when user is logged in, redirect to dashboard
4659
2. when user is logged off, redirect to https://about.readthedocs.com/
4760
@@ -50,33 +63,19 @@ class HomepageView(TemplateView):
5063
2. when user is logged off, redirect to login page
5164
"""
5265

53-
template_name = "homepage.html"
54-
5566
def get(self, request, *args, **kwargs):
56-
# Request hitting the old domain (readthedocs.org / readthedocs.com)
57-
if request.get_host() == settings.PRODUCTION_DOMAIN.replace("app.", ""):
58-
# Redirect to user dashboard for logged in users
59-
if request.user.is_authenticated:
60-
return redirect("projects_dashboard")
61-
62-
# Redirect to ``about.`` in production
63-
if not settings.DEBUG:
64-
query_string = f"?ref={settings.PRODUCTION_DOMAIN}"
65-
if request.META["QUERY_STRING"]:
66-
# Small hack to not append `&` to URLs without a query_string
67-
query_string += "&" + request.META["QUERY_STRING"]
68-
69-
# Do a 302 here so that it varies on logged in status
70-
return redirect(f"https://about.readthedocs.com/{query_string}", permanent=False)
71-
72-
# Request hitting app.readthedocs.org / app.readthedocs.com
73-
#
7467
# Redirect to user dashboard for logged in users
7568
if request.user.is_authenticated:
76-
return redirect("projects_dashboard")
69+
return redirect(reverse("projects_dashboard"))
7770

78-
# Redirect to login page
79-
return redirect(reverse("account_login"))
71+
# Redirect to ``about.`` in production
72+
query_string = f"?ref={settings.PRODUCTION_DOMAIN}"
73+
if request.META["QUERY_STRING"]:
74+
# Small hack to not append `&` to URLs without a query_string
75+
query_string += "&" + request.META["QUERY_STRING"]
76+
77+
# Do a 302 here so that it varies on logged in status
78+
return redirect(f"https://about.readthedocs.com/{query_string}", permanent=False)
8079

8180

8281
class SupportView(PrivateViewMixin, TemplateView):

readthedocs/urls.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from readthedocs.core.views import ErrorView
1717
from readthedocs.core.views import HomepageView
1818
from readthedocs.core.views import SupportView
19+
from readthedocs.core.views import WelcomeView
1920
from readthedocs.core.views import do_not_track
2021
from readthedocs.search.views import GlobalSearchView
2122

@@ -33,6 +34,7 @@
3334

3435
basic_urls = [
3536
path("", HomepageView.as_view(), name="homepage"),
37+
path("welcome/", WelcomeView.as_view(), name="welcome"),
3638
path("security/", TemplateView.as_view(template_name="security.html")),
3739
re_path(
3840
r"^\.well-known/security.txt$",

0 commit comments

Comments
 (0)