-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
APIv3: proxy these URLs to be served from El Proxito /_/api/v3/
#11831
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
base: main
Are you sure you want to change the base?
Changes from 5 commits
b60813e
fac75b3
3306c4d
cd5b0e6
3c582ba
ba741e2
3be7a0c
fefe902
76e4fc4
2e0f9f9
c73ff65
5584ca3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,9 +10,12 @@ | |
from readthedocs.api.v3.proxied_views import ProxiedEmbedAPI | ||
from readthedocs.search.api.v3.views import ProxiedSearchAPI | ||
|
||
from .urls import router | ||
|
||
api_proxied_urls = [ | ||
path("embed/", ProxiedEmbedAPI.as_view(), name="embed_api_v3"), | ||
path("search/", ProxiedSearchAPI.as_view(), name="search_api_v3"), | ||
] | ||
|
||
urlpatterns = api_proxied_urls | ||
urlpatterns += router.urls | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are proxying the whole API here instead of what addons needs, this has several implications:
I'd suggest we explicitly bring what we need and adapt it to work under proxito (as we have done with search and embed APIs) instead of trying to bring the whole API v3 at once. For example, we don't need to list all projects from docs pages, or redirects. |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -19,16 +19,17 @@ | |||||||||
from rest_framework.permissions import IsAuthenticated | ||||||||||
from rest_framework.renderers import BrowsableAPIRenderer | ||||||||||
from rest_framework.response import Response | ||||||||||
from rest_framework.throttling import AnonRateThrottle, UserRateThrottle | ||||||||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet, ReadOnlyModelViewSet | ||||||||||
from rest_framework_extensions.mixins import NestedViewSetMixin | ||||||||||
|
||||||||||
from readthedocs.api.v2.permissions import ReadOnlyPermission | ||||||||||
from readthedocs.builds.constants import EXTERNAL | ||||||||||
from readthedocs.builds.models import Build, Version | ||||||||||
from readthedocs.core.resolver import Resolver | ||||||||||
from readthedocs.core.utils import trigger_build | ||||||||||
from readthedocs.core.utils.extend import SettingsOverrideObject | ||||||||||
from readthedocs.core.views.hooks import trigger_sync_versions | ||||||||||
from readthedocs.filetreediff import get_diff | ||||||||||
from readthedocs.notifications.models import Notification | ||||||||||
from readthedocs.oauth.models import ( | ||||||||||
RemoteOrganization, | ||||||||||
|
@@ -110,7 +111,7 @@ class APIv3Settings: | |||||||||
LimitOffsetPagination.default_limit = 10 | ||||||||||
|
||||||||||
renderer_classes = (AlphabeticalSortedJSONRenderer, BrowsableAPIRenderer) | ||||||||||
throttle_classes = (UserRateThrottle, AnonRateThrottle) | ||||||||||
# throttle_classes = (UserRateThrottle, AnonRateThrottle) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did we remove this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I temporary commented this because I was blocked immediately since we have the throttle very low in our settings. readthedocs.org/readthedocs/settings/base.py Lines 902 to 905 in e70cf31
We should increase these values to be able to use APIv3 in the way we want with addons. |
||||||||||
filter_backends = (filters.DjangoFilterBackend,) | ||||||||||
metadata_class = SimpleMetadata | ||||||||||
|
||||||||||
|
@@ -382,6 +383,126 @@ def get_queryset(self): | |||||||||
return super().get_queryset().exclude(type=EXTERNAL) | ||||||||||
|
||||||||||
|
||||||||||
class FileTreeDiffViewSet( | ||||||||||
APIv3Settings, | ||||||||||
NestedViewSetMixin, | ||||||||||
ProjectQuerySetMixin, | ||||||||||
FlexFieldsMixin, | ||||||||||
ReadOnlyModelViewSet, | ||||||||||
): | ||||||||||
model = Version | ||||||||||
lookup_field = "slug" | ||||||||||
lookup_url_kwarg = "version_slug" | ||||||||||
|
||||||||||
# Allow ``.`` (dots) on version slug | ||||||||||
lookup_value_regex = r"[^/]+" | ||||||||||
|
||||||||||
permission_classes = [ReadOnlyPermission | (IsAuthenticated & IsProjectAdmin)] | ||||||||||
|
||||||||||
def _get_filetreediff_response(self, *, request, project, version, resolver): | ||||||||||
""" | ||||||||||
Get the file tree diff response for the given version. | ||||||||||
|
||||||||||
This response is only enabled for external versions, | ||||||||||
we do the comparison between the current version and the latest version. | ||||||||||
""" | ||||||||||
if not version.is_external: | ||||||||||
return None | ||||||||||
|
||||||||||
if not project.addons.filetreediff_enabled: | ||||||||||
return None | ||||||||||
|
||||||||||
base_version = ( | ||||||||||
project.addons.options_base_version or project.get_latest_version() | ||||||||||
) | ||||||||||
# TODO: check if `self._has_permission` is important after the migration here. | ||||||||||
# if not base_version or not self._has_permission( | ||||||||||
# request=request, version=base_version | ||||||||||
# ): | ||||||||||
if not base_version: | ||||||||||
return None | ||||||||||
|
||||||||||
diff = get_diff(version_a=version, version_b=base_version) | ||||||||||
if not diff: | ||||||||||
return None | ||||||||||
|
||||||||||
return { | ||||||||||
"outdated": diff.outdated, | ||||||||||
"diff": { | ||||||||||
"added": [ | ||||||||||
{ | ||||||||||
"filename": filename, | ||||||||||
"urls": { | ||||||||||
"current": resolver.resolve_version( | ||||||||||
project=project, | ||||||||||
filename=filename, | ||||||||||
version=version, | ||||||||||
), | ||||||||||
"base": resolver.resolve_version( | ||||||||||
project=project, | ||||||||||
filename=filename, | ||||||||||
version=base_version, | ||||||||||
), | ||||||||||
}, | ||||||||||
} | ||||||||||
for filename in diff.added | ||||||||||
], | ||||||||||
"deleted": [ | ||||||||||
{ | ||||||||||
"filename": filename, | ||||||||||
"urls": { | ||||||||||
"current": resolver.resolve_version( | ||||||||||
project=project, | ||||||||||
filename=filename, | ||||||||||
version=version, | ||||||||||
), | ||||||||||
"base": resolver.resolve_version( | ||||||||||
project=project, | ||||||||||
filename=filename, | ||||||||||
version=base_version, | ||||||||||
), | ||||||||||
}, | ||||||||||
} | ||||||||||
for filename in diff.deleted | ||||||||||
], | ||||||||||
"modified": [ | ||||||||||
{ | ||||||||||
"filename": filename, | ||||||||||
"urls": { | ||||||||||
"current": resolver.resolve_version( | ||||||||||
project=project, | ||||||||||
filename=filename, | ||||||||||
version=version, | ||||||||||
), | ||||||||||
"base": resolver.resolve_version( | ||||||||||
project=project, | ||||||||||
filename=filename, | ||||||||||
version=base_version, | ||||||||||
), | ||||||||||
}, | ||||||||||
} | ||||||||||
for filename in diff.modified | ||||||||||
], | ||||||||||
}, | ||||||||||
} | ||||||||||
|
||||||||||
def list(self, request, **kwargs): | ||||||||||
project = self._get_parent_project() | ||||||||||
version = self._get_parent_version() | ||||||||||
resolver = Resolver() | ||||||||||
|
||||||||||
data = ( | ||||||||||
self._get_filetreediff_response( | ||||||||||
request=request, | ||||||||||
project=project, | ||||||||||
version=version, | ||||||||||
resolver=resolver, | ||||||||||
) | ||||||||||
or {} | ||||||||||
) | ||||||||||
return Response(data=data) | ||||||||||
|
||||||||||
|
||||||||||
class BuildsViewSet( | ||||||||||
APIv3Settings, | ||||||||||
NestedViewSetMixin, | ||||||||||
|
Uh oh!
There was an error while loading. Please reload this page.