docs: rearrange paths, update links and redirects

Part-of: <https://dev.funkwhale.audio/funkwhale/funkwhale/-/merge_requests/2353>
This commit is contained in:
Ciarán Ainsworth 2023-02-01 13:41:44 +01:00
commit 65316d43c1
169 changed files with 254 additions and 255 deletions

View file

@ -0,0 +1,137 @@
# API authentication
Funkwhale uses the OAuth [authorization grant flow](https://tools.ietf.org/html/rfc6749#section-4.1) for external apps. This flow is a secure way to authenticate apps that requires a user's explicit consent to perform actions.
```{mermaid}
%%{init: { 'sequence': {'mirrorActors': false} } }%%
sequenceDiagram
accTitle: "Funkwhale OAuth token flow"
accDescr: "A sequence diagram showing how apps authenticate with Funkwhale"
autonumber
actor User
participant A as Application
participant F as Funkwhale web interface
participant T as Token endpoint
User ->> A: Log in to Funkwhale
A ->> F: Direct to login screen
F -->> User: Authenticate this app?
User ->> F: Confirm
F -->> A: Authorization code
A ->> T: Authorization code and redirect URI
T -->> A: Access token and refresh token
loop Refresh
A ->> T: Refresh token
T -->> A: Access token
end
```
```{contents} Steps
:local:
```
## 1. Create an application
To connect to the Funkwhale API using OAuth, you need to create an **application**. This represents the entity credentials are related to.
When creating an application you need to define the [**scopes**](https://www.rfc-editor.org/rfc/rfc6749#section-3.3) the application has access to. Scopes define what information your application can access. Each scope can be granted with the following rights:
- `read:<scope>`: grants read-only access to the resource
- `write:<scope>`: grants write-only access to the resource
`read` rights are required to fetch information using a `GET` request. All other actions (`POST`, `PATCH`, `PUT`, and `DELETE`) require `write` privileges. You may give an application **both** `read` and `write` access to any scope.
```{list-table}
:header-rows: 1
* - Scope
- Description
* - `read`
- Read-only access to all data
* - `write`
- Read-only access to all data
* - `<read/write>:profile`
- Access to profile data (email address, username, etc.)
* - `<read/write>:libraries`
- Access to library data (uploads, libraries, tracks, albums, artists, etc.)
* - `<read/write>:favorites`
- Access to favorites
* - `<read/write>:listenings`
- Access to history
* - `<read/write>:follows`
- Access to followers
* - `<read/write>:playlists`
- Access to playlists
* - `<read/write>:radios`
- Access to radios
* - `<read/write>:filters`
- Access to content filters
* - `<read/write>:notifications`
- Access to notifications
* - `<read/write>:edits`
- Access to metadata edits
```
Next, you need to define a [**Redirect URI**](https://www.rfc-editor.org/rfc/rfc6749#section-3.1.2). This is the location the user is redirected to once they authenticate your app. This can be any URI you want.
```{note}
Funkwhale supports the `urn:ietf:wg:oauth:2.0:oob` redirect URI for non-web applications. If you use this URI, the user is shown a token to copy and paste.
```
Once you've decided on your scopes and your redirect URI, you can create your app using one of the following methods:
1. Visit `/settings/applications/new` on your Funkwhale pod while logged in
2. Send a `POST` request to `/api/v1/oauth/apps`. See our [API documentation](https://docs.funkwhale.audio/swagger/) for more information
Both methods return a [**client ID**](https://www.rfc-editor.org/rfc/rfc6749#section-2.2) and a [**secret**](https://www.rfc-editor.org/rfc/rfc6749#section-2.3.1).
## 2. Get an authorization code
```{important}
Authorization codes are only valid for 5 minutes after the user approves the request.
```
You need an [**authorization code**](https://www.rfc-editor.org/rfc/rfc6749#section-1.3.1) to request an access token for your user. This code confirms to the server that a user has authorized access to their account.
To fetch an authorization code, you need to send the user to their Funkwhale pod to authenticate. This sends an [authorization request](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2) to the server.
To do this, call the `/authorize` endpoint with the following URL encoded query parameters:
- `client_id`\* - Your application's client ID
- `response_type`\* - Must be set to `code`.
- `redirect_uri` - Your redirect URI
- `scope` - A list of scopes
- `state` - Used to maintain state between the request and the callback to prevent cross-site request forgery. Typically corresponds with a location in the app (e.g. `/library`)
Here is an example URL: `https://demo.funkwhale.audio/authorize?response_type=code&scope=read%20write&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fauth%2Fcallback&state=/library&client_id=jDOUfhqLlrbuOkToDCanZmBKEiyorMb9ZUgD2tFQ`.
When the user authorizes your app, the server responds with an authorization code. See [the OAuth spec](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2) for more information about this response.
## 3. Get an access token
Once you receive your authorization code, you need to [request an access token](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3). To request an access token, call the `/api/v1/oauth/token` endpoint with the following information:
- `grant_type`\* - Must be set to `authorization_code`
- `code`\* - Your application's authorization code
- `redirect_uri`\* - Your redirect URI
- `client_id`\* Your application's client ID
The server responds with an [`access_token`](https://www.rfc-editor.org/rfc/rfc6749#section-1.4) and a [`refresh_token`](https://www.rfc-editor.org/rfc/rfc6749#section-1.5). See [the OAuth spec](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.4) for more information about this response.
You can use this token to authenticate calls from your application to the Funkwhale API by passing it as a request header with the following format: `Authorization: Bearer <token>`.
## 4. Refresh your access token
```{important}
When you refresh your token the endpoint returns a new `refresh_token`. You must update your refresh token each time you request a new access token.
```
By default, Funkwhale access tokens are valid for **10 hours**. Pod admins can configure this by setting the `ACCESS_TOKEN_EXPIRE_SECONDS` variable in their `.env` file.
After the access token expires, you must request a new access token by calling the `/api/v1/oauth/token` endpoint with the following information:
- `grant_type`\* - Must be set to `refresh_token`
- `refresh_token`\* - Your current refresh token
- `scope` - A list of scopes
See [the OAuth spec](https://www.rfc-editor.org/rfc/rfc6749#section-6) for more information about this response.

View file

@ -0,0 +1,18 @@
# Funkwhale API
The Funkwhale API is a [REST API](https://developer.mozilla.org/en-US/docs/Glossary/REST) written in [Python](https://www.python.org/) using the [Django REST framework](https://www.django-rest-framework.org/). It is the central component of the project and houses the application's logic.
The current API (v1) is **stable**, meaning we are committed to not introducing breaking changes and to maintaining compatibility. We are currently working on Funkwhale API v2, but this is a work in progress and not yet ready for production use.
```{toctree}
---
caption: Resources
maxdepth: 1
---
API explorer<https://docs.funkwhale.audio/swagger/>
authentication
rate_limit
subsonic
```

View file

@ -0,0 +1,51 @@
# Rate limiting
Funkwhale supports rate-limiting as of version 0.2.0. Pod admins can choose to rate limit specific endpoints to prevent abuse and improve the stability of the service. If the server drops a request due to rate-limiting, it returns a `429` status code.
By default, rate limits follow these rules:
1. Anonymous (unauthenticated) requests are subject to lower limits than authenticated requests
2. `PUT`, `DELETE`, `PUT`, `POST`, and `PATCH` requests are subject to lower limits than `GET` requests
You can return a full list of scope with their corresponding rate-limits by making a `GET` request to `/api/v1/rate-limit`.
## HTTP headers
Each API call returns HTTP headers to pass the following information:
- What was the scope of the request
- What is the rate-limit associated with the request scope
- How many more requests in the scope can be made within the rate-limit timeframe
- How much time does the client need to wait to send another request
Here is a full list of supported headers
```{list-table}
:header-rows: 1
* - Header
- Example value
- Description
* - `X-RateLimit-Limit`
- 50
- The number of requests allowed within a given period
* - `X-RateLimit-Duration`
- 3600
- The time window, in seconds, during which the number of requests are measured
* - `X-RateLimit-Scope`
- `login`
- The name of the scope computed for the request
* - `X-RateLimit-Remaining`
- 42
- How many requests can be sent with the same scope before the rate-limit applies
* - `Retry-After`
- 3543
- How many seconds the client must wait before it can retry. Only applies if `X-RateLimit-Remaining` is `0`
* - `X-RateLimit-Reset`
- 1568126089
- A timestamp indicating when the `X-RateLimit-Remaining` value will reset
* - `X-RateLimit-ResetSeconds`
- 3599
- The number of seconds until the `X-RateLimit-Remaining` value resets
```

View file

@ -0,0 +1,71 @@
# Subsonic API
Funkwhale supports a subset of the [Subsonic API's](http://www.subsonic.org/pages/api.jsp) endpoints. This enables users to listen to music stored on their Funkwhale pod through a Subsonic-compatible app.
We aim to support as many endpoints as we can to give Subsonic users the best possible experience. However, some endpoints require a folder-based endpoint. This doesn't match Funkwhale's internal structure, which means emulating them is difficult.
## Supported endpoints
```{note}
We aim to keep this list up-to-date. If you think something is missing, you can see all supported endpoints in the [API views](https://dev.funkwhale.audio/funkwhale/funkwhale/blob/develop/api/funkwhale_api/subsonic/views.py).
```
Funkwhale supports both XML and JSON formats for the following Subsonic endpoints:
- [`createPlaylist`](http://www.subsonic.org/pages/api.jsp#createPlaylist)
- [`deletePlaylist`](http://www.subsonic.org/pages/api.jsp#deletePlaylist)
- [`getAlbum`](http://www.subsonic.org/pages/api.jsp#getAlbum)
- [`getAlbumList2`](http://www.subsonic.org/pages/api.jsp#getAlbumList2)
- [`getArtist`](http://www.subsonic.org/pages/api.jsp#getArtist)
- [`getArtistInfo2`](http://www.subsonic.org/pages/api.jsp#getArtistInfo2)
- [`getArtists`](http://www.subsonic.org/pages/api.jsp#getArtists)
- [`getAvatar`](http://www.subsonic.org/pages/api.jsp#getAvatar)
- [`getCoverArt`](http://www.subsonic.org/pages/api.jsp#getCoverArt)
- [`getIndexes`](http://www.subsonic.org/pages/api.jsp#getIndexes)
- [`getLicense`](http://www.subsonic.org/pages/api.jsp#getLicense)
- [`getMusicFolders`](http://www.subsonic.org/pages/api.jsp#getMusicFolders)
- [`getPlaylist`](http://www.subsonic.org/pages/api.jsp#getPlaylist)
- [`getPlaylists`](http://www.subsonic.org/pages/api.jsp#getPlaylists)
- [`getRandomSongs`](http://www.subsonic.org/pages/api.jsp#getRandomSongs)
- [`getSong`](http://www.subsonic.org/pages/api.jsp#getSong)
- [`getStarred`](http://www.subsonic.org/pages/api.jsp#getStarred)
- [`getStarred2`](http://www.subsonic.org/pages/api.jsp#getStarred2)
- [`getUser`](http://www.subsonic.org/pages/api.jsp#getUser)
- [`ping`](http://www.subsonic.org/pages/api.jsp#ping)
- [`scrobble`](http://www.subsonic.org/pages/api.jsp#scrobble)
- [`search3`](http://www.subsonic.org/pages/api.jsp#search3)
- [`star`](http://www.subsonic.org/pages/api.jsp#star)
- [`stream`](http://www.subsonic.org/pages/api.jsp#stream)
- [`unstar`](http://www.subsonic.org/pages/api.jsp#unstar)
- [`updatePlaylist`](http://www.subsonic.org/pages/api.jsp#updatePlaylist)
### Additional properties
Funkwhale returns some additional properties to Subsonic payloads. You can use these properties to adapt your client behavior if needed:
```{list-table}
* - Property
- Data type
- Description
* - `type`
- String
- The name of the app (`funkwhale`)
* - `funkwhaleVersion`
- String
- The Funkwhale version the pod is running
```
```{code-block} json
{
"subsonic-response": {
"type": "funkwhale",
"funkwhaleVersion": "1.3.0"
}
}
```
## Test a Subsonic app
We host a demo server at <https://demo.funkwhale.audio> which you can use to test your Subsonic app.
You can test the Subsonic API by logging in with a Subsonic client or by directly by calling an endpoint. For example, call this URL to test the `ping` endpoint: <https://demo.funkwhale.audio/rest/ping.view?f=json>