Skip to content

Addons: prepare Proxito and dashboard to enable them by default #11513

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Sep 23, 2024
15 changes: 14 additions & 1 deletion readthedocs/projects/forms.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
"""Project forms."""

import datetime
import json
from random import choice
from re import fullmatch
from urllib.parse import urlparse

import pytz
from allauth.socialaccount.models import SocialAccount
from django import forms
from django.conf import settings
from django.contrib.auth.models import User
from django.db.models import Q
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from readthedocs.builds.constants import INTERNAL
Expand Down Expand Up @@ -677,14 +680,24 @@ class Meta:

def __init__(self, *args, **kwargs):
self.project = kwargs.pop("project", None)

tzinfo = pytz.timezone("America/Los_Angeles")
addons_enabled_by_default = timezone.now() > datetime.datetime(
2024, 10, 7, 0, 0, 0, tzinfo=tzinfo
)

addons, created = AddonsConfig.objects.get_or_create(project=self.project)
if created:
addons.enabled = False
addons.enabled = addons_enabled_by_default
addons.save()

kwargs["instance"] = addons
super().__init__(*args, **kwargs)

# Keep the ability to disable addons completely on Read the Docs for Business
if not settings.RTD_ALLOW_ORGANIZATIONS and addons_enabled_by_default:
self.fields.pop("enabled")

def clean(self):
if (
self.cleaned_data["flyout_sorting"] == ADDONS_FLYOUT_SORTING_CUSTOM_PATTERN
Expand Down
4 changes: 4 additions & 0 deletions readthedocs/projects/views/private.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
WebHookForm,
)
from readthedocs.projects.models import (
AddonsConfig,
Domain,
EmailHook,
EnvironmentVariable,
Expand Down Expand Up @@ -423,6 +424,9 @@ def done(self, form_list, **kwargs):
# attributes directly from other forms
project = basics_form.save()

# Create an AddonsConfig object for this project.
AddonsConfig.objects.get_or_create(project=project)

self.finish_import_project(self.request, project)

return HttpResponseRedirect(
Expand Down
63 changes: 47 additions & 16 deletions readthedocs/proxito/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

Additional processing is done to get the project from the URL in the ``views.py`` as well.
"""
import datetime
import re
from urllib.parse import urlparse

import pytz
import structlog
from corsheaders.middleware import (
ACCESS_CONTROL_ALLOW_METHODS,
Expand All @@ -17,6 +19,7 @@
from django.core.exceptions import SuspiciousOperation
from django.shortcuts import redirect
from django.urls import reverse
from django.utils import timezone
from django.utils.deprecation import MiddlewareMixin
from django.utils.encoding import iri_to_uri
from django.utils.html import escape
Expand All @@ -31,7 +34,7 @@
unresolver,
)
from readthedocs.core.utils import get_cache_tag
from readthedocs.projects.models import Project
from readthedocs.projects.models import Feature, Project
from readthedocs.proxito.cache import add_cache_tags, cache_response, private_response
from readthedocs.proxito.redirects import redirect_to_https

Expand Down Expand Up @@ -289,23 +292,51 @@ def add_hosting_integrations_headers(self, request, response):
version_slug = getattr(request, "path_version_slug", "")

if project_slug:
force_addons = Project.objects.filter(
slug=project_slug,
addons__enabled=True,
).exists()
if force_addons:
response["X-RTD-Force-Addons"] = "true"
return

if version_slug:
addons = Version.objects.filter(
project__slug=project_slug,
slug=version_slug,
addons=True,
tzinfo = pytz.timezone("America/Los_Angeles")
addons_enabled_by_default = timezone.now() > datetime.datetime(
2024,
10,
7,
0,
0,
0,
tzinfo=tzinfo,
)
if addons_enabled_by_default:
addons = Project.objects.filter(
slug=project_slug, addons__enabled=True
).exists()

if addons:
response["X-RTD-Force-Addons"] = "true"
return

else:
# TODO: remove "else" code once DISABLE_SPHINX_MANIPULATION and addons becomes the default
# https://about.readthedocs.com/blog/2024/07/addons-by-default/
disable_sphinx_manipulation_enabled = Feature.objects.filter(
feature_id=Feature.DISABLE_SPHINX_MANIPULATION,
projects__slug=Project.objects.filter(slug=project_slug).first(),
).exists()

if addons:
response["X-RTD-Hosting-Integrations"] = "true"
force_addons = Project.objects.filter(
slug=project_slug,
addons__enabled=True,
).exists()

if force_addons or disable_sphinx_manipulation_enabled:
response["X-RTD-Force-Addons"] = "true"
return

if version_slug:
addons = Version.objects.filter(
project__slug=project_slug,
slug=version_slug,
addons=True,
).exists()

if addons:
response["X-RTD-Hosting-Integrations"] = "true"

def add_cors_headers(self, request, response):
"""
Expand Down