Skip to content

Addons: load_when_embedded config #11765

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
Nov 18, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 4.2.16 on 2024-11-13 12:00

from django.db import migrations, models
from django_safemigrate import Safe


class Migration(migrations.Migration):
safe = Safe.before_deploy

dependencies = [
('projects', '0132_addons_linkpreviews_fields'),
]

operations = [
migrations.AddField(
model_name='addonsconfig',
name='options_load_when_embedded',
field=models.BooleanField(default=False, null=True),
),
migrations.AddField(
model_name='historicaladdonsconfig',
name='options_load_when_embedded',
field=models.BooleanField(default=False, null=True),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 4.2.16 on 2024-11-13 12:01

from django.db import migrations, models
from django_safemigrate import Safe


class Migration(migrations.Migration):
safe = Safe.after_deploy

dependencies = [
('projects', '0133_addons_options_load_when_embedded'),
]

operations = [
migrations.AlterField(
model_name='addonsconfig',
name='options_load_when_embedded',
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name='historicaladdonsconfig',
name='options_load_when_embedded',
field=models.BooleanField(default=False),
),
]
35 changes: 35 additions & 0 deletions readthedocs/projects/migrations/0135_addons_customscript.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Generated by Django 4.2.16 on 2024-11-13 13:34

from django.db import migrations, models
from django_safemigrate import Safe


class Migration(migrations.Migration):
safe = Safe.before_deploy

dependencies = [
('projects', '0134_addons_load_when_embedded_notnull'),
]

operations = [
migrations.AddField(
model_name='addonsconfig',
name='customscript_enabled',
field=models.BooleanField(default=False, null=True),
),
migrations.AddField(
model_name='addonsconfig',
name='customscript_src',
field=models.CharField(blank=True, help_text='URL to a JavaScript file to inject at serve time', max_length=512, null=True),
),
migrations.AddField(
model_name='historicaladdonsconfig',
name='customscript_enabled',
field=models.BooleanField(default=False, null=True),
),
migrations.AddField(
model_name='historicaladdonsconfig',
name='customscript_src',
field=models.CharField(blank=True, help_text='URL to a JavaScript file to inject at serve time', max_length=512, null=True),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 4.2.16 on 2024-11-13 13:36

from django.db import migrations, models
from django_safemigrate import Safe


class Migration(migrations.Migration):
safe = Safe.after_deploy

dependencies = [
('projects', '0135_addons_customscript'),
]

operations = [
migrations.AlterField(
model_name='addonsconfig',
name='customscript_enabled',
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name='historicaladdonsconfig',
name='customscript_enabled',
field=models.BooleanField(default=False),
),
]
16 changes: 16 additions & 0 deletions readthedocs/projects/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ class AddonsConfig(TimeStampedModel):
help_text="Enable/Disable all the addons on this project",
)

# Whether or not load addons library when the requested page is embedded (e.g. inside an iframe)
# https://github.com/readthedocs/addons/pull/415
options_load_when_embedded = models.BooleanField(default=False)

# Analytics

# NOTE: we keep analytics disabled by default to save resources.
Expand Down Expand Up @@ -218,6 +222,18 @@ class AddonsConfig(TimeStampedModel):
search_enabled = models.BooleanField(default=True)
search_default_filter = models.CharField(null=True, blank=True, max_length=128)

# User JavaScript File
customscript_enabled = models.BooleanField(default=False)

# This is a user-defined file that will be injected at serve time by our
# Cloudflare Worker if defined
customscript_src = models.CharField(
max_length=512,
null=True,
blank=True,
help_text="URL to a JavaScript file to inject at serve time",
)

# Notifications
notifications_enabled = models.BooleanField(default=True)
notifications_show_on_latest = models.BooleanField(default=True)
Expand Down
9 changes: 4 additions & 5 deletions readthedocs/proxito/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
unresolver,
)
from readthedocs.core.utils import get_cache_tag
from readthedocs.projects.models import Project
from readthedocs.projects.models import AddonsConfig
from readthedocs.proxito.cache import add_cache_tags, cache_response, private_response
from readthedocs.proxito.redirects import redirect_to_https

Expand Down Expand Up @@ -283,12 +283,11 @@ def add_hosting_integrations_headers(self, request, response):
project_slug = getattr(request, "path_project_slug", "")

if project_slug:
addons = Project.objects.filter(
slug=project_slug, addons__enabled=True
).exists()
addons = AddonsConfig.objects.filter(project__slug=project_slug).first()

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

def add_cors_headers(self, request, response):
"""
Expand Down
7 changes: 7 additions & 0 deletions readthedocs/proxito/tests/responses/v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@
}
},
"addons": {
"configs": {
"load_when_embedded": false
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.com tests will probably need to be updated

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrm, I don't think we have this file in .com. At least, I didn't find it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have two files in tests/responses/addons/

"analytics": {
"enabled": false,
"code": null
Expand Down Expand Up @@ -161,6 +164,10 @@
"default_filter": "project:project/latest",
"filters": []
},
"customscript": {
"enabled": false,
"src": null
},
"linkpreviews": {
"enabled": false,
"root_selector": "[role=main] a.internal",
Expand Down
7 changes: 7 additions & 0 deletions readthedocs/proxito/views/hosting.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,9 @@ def _v1(self, project, version, build, filename, url, request):
# Mainly, all the fields including a Project, Version or Build will use the exact same
# serializer than the keys ``project``, ``version`` and ``build`` from the top level.
"addons": {
"options": {
"load_when_embedded": project.addons.load_when_embedded,
},
"analytics": {
"enabled": project.addons.analytics_enabled,
# TODO: consider adding this field into the ProjectSerializer itself.
Expand Down Expand Up @@ -487,6 +490,10 @@ def _v1(self, project, version, build, filename, url, request):
# "filepath": "/docs/index.rst",
# },
},
"customscript": {
"enabled": project.addons.customscript_enabled,
"src": project.addons.customscript_src,
},
"search": {
"enabled": project.addons.search_enabled,
# TODO: figure it out where this data comes from.
Expand Down