Skip to content

Initial structure for APIv3 #5356

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 96 commits into from
May 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
d90abf2
Initial structure for APIv3
humitos Feb 26, 2019
4e33c1a
Improve expandable fields using drf-flex-fields
humitos Feb 28, 2019
2494cc9
Basic throttle rates setting
humitos Feb 28, 2019
6930782
Use a class filter to allow expansion
humitos Feb 28, 2019
d0919d0
Use methods from models instead of custom from serializer
humitos Feb 28, 2019
7150fb2
Improve serializers
humitos Feb 28, 2019
b1f3d81
Push filters file
humitos Mar 3, 2019
73f49df
Nested (under /projects/) versions endpoint
humitos Mar 5, 2019
2c3eecd
Build endpoints
humitos Mar 5, 2019
4577fe5
Build filters
humitos Mar 5, 2019
a043589
Endpoints for related projects
humitos Mar 5, 2019
1936654
Add "links" field for Project, Version and Build
humitos Mar 5, 2019
7968af2
Style
humitos Mar 5, 2019
cedb137
Allow . (dots) on version_slug endpoint URLs
humitos Mar 6, 2019
577f4ae
Make the API really browsable
humitos Mar 7, 2019
f5502ea
Make build.state render as code/name
humitos Mar 7, 2019
47888dd
Generate valid links for current logged in user in documentation
humitos Mar 7, 2019
9da9ede
Omit form rendering on POST for builds endpoint
humitos Mar 7, 2019
6930902
Default router with nesting support
humitos Mar 7, 2019
a528102
Use custom AlphabeticalSortedJSONRenderer
humitos Mar 7, 2019
e827cad
Use JWT as default Token authentication
humitos Mar 7, 2019
36cf2d2
Register `users` endpoint
humitos Mar 7, 2019
bbeb9b7
Add documentation to the root view of BrowsableAPI
humitos Mar 7, 2019
d5aed8a
Follow the pattern for URLs
humitos Mar 7, 2019
b7055c5
Return proper serializers (Version, Build) depending on the action
humitos Mar 7, 2019
0f2a7fc
Comment about why BrowsableAPI does not work on no GET/POST methods
humitos Mar 7, 2019
6a620c8
Make PATCH/PUT for version return properly 204 and No Content
humitos Mar 7, 2019
e970e96
Make superproject endpoint to return a single project if exists
humitos Mar 10, 2019
dfa5b2e
Browsable API branding
humitos Mar 10, 2019
f4475a1
Proper query for dynamic description
humitos Mar 10, 2019
cf905c5
Fix superproject serializer field
humitos Mar 10, 2019
c363eeb
Go back to simple Token authorization
humitos Mar 10, 2019
547ead4
Use internal documentation framework
humitos Mar 10, 2019
b1b38b3
Update Project filters and docs
humitos Mar 12, 2019
745558b
Update docs for triggering a build
humitos Mar 12, 2019
31cc708
Linting
humitos Mar 21, 2019
254def3
Organize API v1, v2 and v3 structure
humitos Apr 22, 2019
0b9ab9e
Revert api auth URL to keep compatibility
humitos Apr 22, 2019
7fdec50
Remove autogenerated URL docs
humitos Apr 22, 2019
e014d86
Cleanup
humitos Apr 22, 2019
86c63b3
Typo fixed
humitos Apr 22, 2019
1e9355c
Do not expose names on API results
humitos Apr 22, 2019
39ff39c
Extend docs a little
humitos Apr 22, 2019
b4b8bab
Use our own querysets/managers permission backend
humitos Apr 22, 2019
b676988
Rename field
humitos Apr 22, 2019
1029b2d
Typo
humitos Apr 22, 2019
db51c32
Handle detail/list permissions in a Mixin
humitos Apr 23, 2019
2249f6e
Allow authenticated users and authenticate them only via Token
humitos Apr 23, 2019
289d927
Use proper queryset for ProjectViewSet.subprojects
humitos Apr 24, 2019
eb3d358
Use pagination_class on APIv3 settings
humitos Apr 24, 2019
bbe4113
Different approach to centralize authentication on APIAuthMixin
humitos Apr 24, 2019
512b5df
Tests showing small problems on some endpoints
humitos Apr 24, 2019
995fd09
Define /projects/pip/subprojects/ as a nested listing view
humitos Apr 24, 2019
b3736cb
Refactor and exception for /api/v3/projects/ listing
humitos Apr 29, 2019
894ba15
Make /projects/pip/translations/ a proper listing view (nested)
humitos Apr 29, 2019
13e4d66
Better query/modeling for subprojects
humitos Apr 29, 2019
9c0dda6
Fix subprojects query
humitos Apr 29, 2019
6abd053
Render subproject/superproject in detail
humitos Apr 29, 2019
e57843e
Remove unused import
humitos Apr 29, 2019
b473ddc
Properly generation of vcs_url for Version object
humitos Apr 29, 2019
df82ddd
Prefetch relations on Project queryset
humitos Apr 29, 2019
f519787
Serializer docstrings
humitos Apr 29, 2019
854530f
Rely on a custom permission class
humitos Apr 29, 2019
4406687
Some docstrings
humitos Apr 29, 2019
e6585e2
Cleanup after rebase
humitos Apr 29, 2019
ebbe613
Response (list/detail) test cases
humitos Apr 29, 2019
443f277
More tests and superproject endpoint fixed
humitos Apr 29, 2019
d09c09f
Remove old examples
humitos Apr 29, 2019
41ef2d3
Requirements updated
humitos Apr 29, 2019
55cbf46
Avoid throttling on tests
humitos Apr 29, 2019
4e74205
Variable name
humitos May 1, 2019
86f89f0
Explicit return
humitos May 1, 2019
2035ea1
Rename file
humitos May 1, 2019
8d11b9d
Remove unused import
humitos May 1, 2019
99c7954
Lint fixes
humitos May 1, 2019
276a979
pre-commit auto style
humitos May 1, 2019
5dfc7bb
Improve/Fix build triggering
humitos May 1, 2019
c034972
Fix BrowsableAPIRenderer /projects/
humitos May 1, 2019
fa0dc1f
Fix serializer on Build
humitos May 1, 2019
e0b716a
More docstrings
humitos May 1, 2019
c4da1b7
Valid success field on Build object
humitos May 1, 2019
e3a58e2
Use `created` instead of `date_joined` on User response
humitos May 1, 2019
86d8865
Update the APIv3 docs to the current state of the implementation
humitos May 1, 2019
2e40de9
Increase logged in throttling to 60/minute
humitos May 6, 2019
9ae1814
Typo
humitos May 6, 2019
fa5c823
Always expand users in Project details
humitos May 6, 2019
b634daa
Move specific list action on projects view to the specific view
humitos May 6, 2019
4f1f587
Remove /projects/pip//users/ endpoint
humitos May 6, 2019
741e017
Docstring URL typo
humitos May 6, 2019
ade5392
User endpoint does not exist anymore
humitos May 6, 2019
71a6539
Remove some fields from responses
humitos May 6, 2019
6d3eee5
Use more generic viewset from DRF
humitos May 6, 2019
85b393c
Rename mixin to match what it does (QuerySet)
humitos May 6, 2019
b4d7942
Rename "links" field to "_links" since it's an internal generated field
humitos May 6, 2019
8ebfb1c
Lint fixes
humitos May 6, 2019
e4ac327
Inherit order matters
humitos May 8, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 30 additions & 148 deletions docs/api/v3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,7 @@ Authentication and authorization
--------------------------------

Requests to the Read the Docs public API are for public and private information.
Some listing endpoints and some detailed ones are allowed to access without being authenticated.
Although, all endpoints that perform non-readonly operations, require authentication.


No authentication
~~~~~~~~~~~~~~~~~

Some endpoints on read-only requests won't require any kind of authentication.
Most of them are detailed information of specific listings for a particular object.
All endpoints require authentication.


Token
Expand All @@ -35,6 +27,10 @@ and have the same permissions that the user itself.
Session
~~~~~~~

.. warning::

Authentication via session is not enabled yet.

Session authentication is allowed on very specific endpoints,
to allow hitting the API when reading documentation.

Expand Down Expand Up @@ -77,13 +73,16 @@ Projects list
:>json string previous: URI for previous set of projects.
:>json array results: array of ``project`` objects.

:query string privacy_level: one of ``public``, ``private``, ``protected``.
:query string name: name of the project.
:query string name__contains: part of the name of the project.
:query string slug: slug of the project.
:query string slug__contains: part of the slug of the project.
:query string language: language code as ``en``, ``es``, ``ru``, etc.
:query string privacy_level: one of ``public``, ``private``, ``protected``.
:query string programming_language: programming language code as ``py``, ``js``, etc.
:query string repository_url: URL of the repository.
:query string repository_type: one of ``git``, ``hg``, ``bzr``, ``svn``.

:requestheader Authorization: required token to authenticate.
:requestheader Authorization: token to authenticate.


Project details
Expand All @@ -97,7 +96,7 @@ Project details

.. sourcecode:: bash

$ curl https://readthedocs.org/api/v3/projects/pip/
$ curl -H "Authorization: Token <token>" https://readthedocs.org/api/v3/projects/pip/

**Example response**:

Expand Down Expand Up @@ -168,9 +167,7 @@ Project details

.. TODO: complete the returned data docs once agreed on this.

:query boolean inactive_versions: whether or not include inactive versions.

:requestheader Authorization: optional token to authenticate.
:requestheader Authorization: token to authenticate.

:statuscode 200: Success
:statuscode 404: There is no ``Project`` with this slug
Expand Down Expand Up @@ -199,7 +196,7 @@ Versions listing

.. sourcecode:: bash

$ curl https://readthedocs.org/api/v3/projects/pip/versions/
$ curl -H "Authorization: Token <token>" https://readthedocs.org/api/v3/projects/pip/versions/

**Example response**:

Expand All @@ -225,7 +222,7 @@ Versions listing
:query boolean active: whether return active versions only
:query boolean built: whether return only built version

:requestheader Authorization: optional token to authenticate.
:requestheader Authorization: token to authenticate.


Version detail
Expand All @@ -239,7 +236,7 @@ Version detail

.. sourcecode:: bash

$ curl https://readthedocs.org/api/v3/projects/pip/versions/stable/
$ curl -H "Authorization: Token <token>" https://readthedocs.org/api/v3/projects/pip/versions/stable/

**Example response**:

Expand Down Expand Up @@ -287,7 +284,7 @@ Version detail
:>json string last_build: Build object representing the last build of this version
:>json array downloads: URLs to downloads of this version's documentation

:requestheader Authorization: optional token to authenticate.
:requestheader Authorization: token to authenticate.

:statuscode 200: Success
:statuscode 404: There is no ``Version`` with this slug for this project
Expand All @@ -309,11 +306,7 @@ Version edit
"privacy_level": "public"
}

**Example response**:

`See Version details <#version-detail>`_

:requestheader Authorization: required token to authenticate.
:requestheader Authorization: token to authenticate.

:statuscode 204: Edited sucessfully
:statuscode 400: Some field is invalid
Expand Down Expand Up @@ -344,7 +337,7 @@ Build details

.. sourcecode:: bash

$ curl https://readthedocs.org/api/v3/projects/pip/builds/8592686/?include_config=true
$ curl -H "Authorization: Token <token>" https://readthedocs.org/api/v3/projects/pip/builds/8592686/?expand=config

**Example response**:

Expand Down Expand Up @@ -422,29 +415,12 @@ Build details

:query boolean include_config: whether or not include the configs used for this build. Default is ``false``

:requestheader Authorization: optional token to authenticate.
:requestheader Authorization: token to authenticate.

:statuscode 200: Success
:statuscode 404: There is no ``Build`` with this ID


.. http:get:: /api/v3/projects/(str:project_slug)/builds/latest/

Retrieve details for latest build on this project.

**Example request**:

.. sourcecode:: bash

$ curl https://readthedocs.org/api/v3/projects/pip/builds/latest/

**Example response**:

`See Build details <#build-details>`_

:requestheader Authorization: optional token to authenticate.


Builds listing
++++++++++++++

Expand Down Expand Up @@ -472,102 +448,28 @@ Builds listing
:query string commit: commit hash to filter the builds returned by commit
:query boolean running: whether or not to filter the builds returned by currently building

:requestheader Authorization: optional token to authenticate.
:requestheader Authorization: token to authenticate.


Build triggering
++++++++++++++++


.. http:post:: /api/v3/projects/(string:project_slug)/builds/

Trigger a new build for this project.

**Example request**:

.. sourcecode:: json
.. http:post:: /api/v3/projects/(string:project_slug)/versions/(string:version_slug)/builds/

{
"version": "latest",
}
Trigger a new build for the ``version_slug`` version of this project.

**Example response**:

`See Build details <#build-details>`_

:requestheader Authorization: required token to authenticate.
:requestheader Authorization: token to authenticate.

:statuscode 201: Created sucessfully
:statuscode 202: Accepted
:statuscode 400: Some field is invalid
:statuscode 401: Not valid permissions


Build commands listing
++++++++++++++++++++++

.. http:get:: /api/v3/projects/(str:project_slug)/builds/(int:build_id)/commands/

Retrieve build command list of a single build.

**Example request**:

.. sourcecode:: bash

$ curl https://readthedocs.org/api/v3/projects/pip/builds/719263915/commands/

**Example response**:

.. sourcecode:: json

{
"count": 15,
"next": "/api/v3/projects/pip/builds/719263915/commands/?limit=10&offset=10",
"previous": null,
"results": ["BUILDCOMMAND"]
}

:requestheader Authorization: optional token to authenticate.


Build command details
+++++++++++++++++++++

.. http:get:: /api/v3/projects/(str:project_slug)/builds/(int:build_id)/commands/(int:buildcommand_id)

Retrieve build command detail.

**Example request**:

.. sourcecode:: bash

$ curl https://readthedocs.org/api/v3/projects/pip/builds/719263915/commands/9182639172/

**Example response**:

.. sourcecode:: json

{
"id": 9182639172,
"build": 719263915,
"project": "pip",
"version": "stable",
"created": "2018-06-19T15:15:59+00:00",
"finished": "2018-06-19T15:16:58+00:00",
"duration": 59,
"command": "cat docs/config.py",
"output": "...",
"exit_code": 0,
"links": {
"self": "/api/v3/projects/pip/builds/719263915/commands/9182639172/",
"build": "/api/v3/projects/pip/builds/719263915/",
"version": "/api/v3/projects/pip/versions/stable/",
"project": "/api/v3/projects/pip/"
}
}

:requestheader Authorization: optional token to authenticate.


Users
~~~~~

Expand All @@ -590,36 +492,16 @@ User detail
.. sourcecode:: json

{
"id": 25,
"username": "humitos",
"created": "2008-10-23T18:12:31+00:00",
"last_login": "2010-10-23T18:12:31+00:00",
"first_name": "Manuel",
"last_name": "Kaufmann",
"email": "[email protected]",
"links": {
"self": "/api/v3/users/humitos/",
"projects": "/api/v3/projects/?user=humitos"
}
"last_login": "2010-10-23T18:12:31+00:00"
}

.. TODO: considering that ``/api/v3/projects/`` will return only
the projects for the authenticated user, the ``projects`` link
here won't work.

On the other hand, ``/api/v3/projects/all/?user=humitos`` can't
be used because we will be mixing ``all`` as project slug with
our endpoint URL.

:>json integer id: ID for the user on the database.
:>json string username: username for the user.
:>json string created: date and time when the user was created.
:>json string last_login: date and time for last time this user was logged in.
:>json string first_name: first name of the user.
:>json string last_name: last name of the user.
:>json string email: email of the user.

:requestheader Authorization: required token to authenticate.
:requestheader Authorization: token to authenticate.


User listing
Expand Down Expand Up @@ -652,7 +534,7 @@ User listing
:>json string previous: URI for previous set of users.
:>json array results: array of ``user`` objects.

:requestheader Authorization: optional token to authenticate.
:requestheader Authorization: token to authenticate.


Subprojects
Expand Down Expand Up @@ -688,7 +570,7 @@ Subprojects listing
:>json string previous: URI for previous set of projects.
:>json array results: array of ``project`` objects.

:requestheader Authorization: required token to authenticate.
:requestheader Authorization: token to authenticate.


Translations
Expand Down Expand Up @@ -724,4 +606,4 @@ Translations listing
:>json string previous: URI for previous set of projects.
:>json array results: array of ``project`` objects.

:requestheader Authorization: required token to authenticate.
:requestheader Authorization: token to authenticate.
3 changes: 3 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ filterwarnings =
ignore:Pagination may yield inconsistent results with an unordered object_list.*:django.core.paginator.UnorderedObjectListWarning
# docutils
ignore:'U' mode is deprecated:DeprecationWarning

# rest_framework_extensions.routers raises these
ignore::rest_framework.RemovedInDRF311Warning
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-

"""Simple client to access our API with Slumber credentials."""

import logging
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-

"""Defines access permissions for the API."""

from rest_framework import permissions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-

"""Defines serializers for each of our models."""

from allauth.socialaccount.models import SocialAccount
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-

"""We define custom Django signals to trigger when a footer is rendered."""

import django.dispatch
Expand Down
8 changes: 3 additions & 5 deletions readthedocs/restapi/urls.py → readthedocs/api/v2/urls.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
# -*- coding: utf-8 -*-

"""Define routes between URL paths and views/endpoints."""

from django.conf import settings
from django.conf.urls import include, url
from rest_framework import routers

from readthedocs.constants import pattern_opts
from readthedocs.restapi.views import (
from readthedocs.api.v2.views import (
core_views,
footer_views,
integrations,
task_views,
)
from readthedocs.constants import pattern_opts
from readthedocs.sphinx_domains.api import SphinxDomainAPIView

from .views.model_views import (
BuildCommandViewSet,
Expand All @@ -25,7 +24,6 @@
SocialAccountViewSet,
VersionViewSet,
)
from readthedocs.sphinx_domains.api import SphinxDomainAPIView


router = routers.DefaultRouter()
Expand Down
2 changes: 0 additions & 2 deletions readthedocs/restapi/utils.py → readthedocs/api/v2/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-

"""Utility functions that are used by both views and celery tasks."""

import logging
Expand Down
Loading