mirror of
https://github.com/zhigang1992/hasura-backend-plus.git
synced 2026-04-30 13:02:00 +08:00
Merge pull request #235 from nhost/docs-api-updates
Updated API docs and password-change routes for concistency
This commit is contained in:
11
CHANGELOG.md
Normal file
11
CHANGELOG.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Hasura Backend Plus
|
||||
|
||||
## Next release
|
||||
|
||||
### Bug fixes and improvements
|
||||
|
||||
(Add entries here in the order of: server, docs, others)
|
||||
|
||||
- server: Updated change password routes for concistency with change email (#235)
|
||||
- docs: Added API documentation (#235)
|
||||
- other: Added CHANGELOG.md file (#235)
|
||||
454
docs/api.md
454
docs/api.md
@@ -1,40 +1,47 @@
|
||||
# API
|
||||
|
||||
| Category | Path | Description |
|
||||
| --------------------------------- | --------------------------------------------------------- | -------------------- |
|
||||
| [Authentication](#authentication) | [POST /auth/register](#registration) | Account registration |
|
||||
| ^^ | [POST /auth/login](#login) | Login |
|
||||
| ^^ | [GET /auth/jwks](#jwks) | JWK Set |
|
||||
| ^^ | [POST /auth/activate](#activation) | Activate account |
|
||||
| ^^ | [POST /auth/delete](#delete-account) | Delete account |
|
||||
| ^^ | [POST /auth/change-password/request](#forgotten-password) | Forgotten password |
|
||||
| ^^ | [POST /auth/change-password/change](#reset-password) | Reset password |
|
||||
| ^^ | [POST /auth/change-email/request](#) | |
|
||||
| ^^ | [POST /auth/change-email/change](#) | |
|
||||
| ^^ | [POST /auth/token/refresh](#refresh-token) | Refresh token |
|
||||
| ^^ | [POST /auth/token/revoke](#revoke-token) | Revoke token |
|
||||
| ^^ | [POST /auth/mfa/generate](#generate-mfa-qr-code) | Generate MFA QR code |
|
||||
| ^^ | [POST /auth/mfa/enable](#enable-mfa) | Enable MFA |
|
||||
| ^^ | [POST /auth/mfa/disable](#disable-mfa) | Disable MFA |
|
||||
| ^^ | [POST /auth/mfa/totp](#totp) | TOTP |
|
||||
| [Storage](storage) | [GET /storage/<custom-rule>](#) | |
|
||||
| ^^ | [POST /storage/<custom-rule>](#) | |
|
||||
| ^^ | [DELETE /storage/<custom-rule>](#) | |
|
||||
| ^^ | [GET /storage/meta/<custom-rule>](#) | |
|
||||
| ^^ | [POST /storage/meta/<custom-rule>](#) | |
|
||||
| ^^ | [DELETE /storage/meta/<custom-rule>](#) | |
|
||||
| [Other](#other) | [GET /healthz](#health-check) | Health Check |
|
||||
| Category | Endpoint | Description |
|
||||
| --------------------------------- | -------------------------------------------------------------- | ----------------------------------------- |
|
||||
| [Authentication](#authentication) | [POST /auth/register](#registration) | Account registration |
|
||||
| ^^ | [POST /auth/login](#login) | Login |
|
||||
| ^^ | [POST /auth/logout](#logout) | Logout |
|
||||
| ^^ | [GET /auth/jwks](#jwks) | JWK Set |
|
||||
| ^^ | [POST /auth/activate](#activate-account) | Activate account |
|
||||
| ^^ | [POST /auth/delete](#delete-account) | Delete account |
|
||||
| ^^ | [POST /auth/change-password/](#change-password) | Change password |
|
||||
| ^^ | [POST /auth/change-password/request](#change-password-request) | Request to change password password |
|
||||
| ^^ | [POST /auth/change-password/change](#change-password-change) | Change password |
|
||||
| ^^ | [POST /auth/change-email/](#) | Change email (without email verification) |
|
||||
| ^^ | [POST /auth/change-email/request](#) | Request email change |
|
||||
| ^^ | [POST /auth/change-email/change](#) | Change email |
|
||||
| ^^ | [POST /auth/token/refresh](#refresh-token) | Get new refresh token |
|
||||
| ^^ | [POST /auth/token/revoke](#revoke-refresh-token) | Revoke tokens |
|
||||
| ^^ | [POST /auth/mfa/generate](#generate-mfa-qr-code) | Generate MFA QR code |
|
||||
| ^^ | [POST /auth/mfa/enable](#enable-mfa) | Enable MFA |
|
||||
| ^^ | [POST /auth/mfa/disable](#disable-mfa) | Disable MFA |
|
||||
| ^^ | [POST /auth/mfa/totp](#totp) | TOTP |
|
||||
| [Storage](storage) | [GET /storage/o/\<rule-path\>](#file) | Get file |
|
||||
| ^^ | [GET /storage/m/\<rule-path\>](#file-metadata) | Get metadata of file |
|
||||
| ^^ | [GET /storage/o/\<rule-path\>/](#file-directory) | Get zip of all files in directory |
|
||||
| ^^ | [GET /storage/m/\<rule-path\>/](#file-directory-metadata) | Get metadata of all files in direcotry |
|
||||
| ^^ | [POST /storage/o/\<rule-path\>](#upload-file) | Upload a file |
|
||||
| ^^ | [DELETE /storage/o/\<rule-path\>](#delete-file) | Delete a file |
|
||||
| [Other](#other) | [GET /healthz](#health-check) | Health Check |
|
||||
|
||||
## Authentication
|
||||
|
||||
### Registration
|
||||
|
||||
Register a new account.
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/register`
|
||||
|
||||
```json
|
||||
{
|
||||
"email": "hello@example.com",
|
||||
"password": "between 6-128 characters"
|
||||
"password": "between MIN_PASSWORD_LENGTH-128 characters"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -44,14 +51,20 @@
|
||||
204 No Content
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Login
|
||||
|
||||
###### Request
|
||||
Login an account.
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/login`
|
||||
|
||||
```json
|
||||
{
|
||||
"email": "hello@example.com",
|
||||
"password": "between 6-128 characters"
|
||||
"password": "secretpassword"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -59,22 +72,80 @@
|
||||
|
||||
```
|
||||
Set-Cookie: refresh_token=...
|
||||
Set-Cookie: permission_variables=...
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"mfa": false,
|
||||
"jwt_token": "...",
|
||||
"jwt_expires_in": 900000
|
||||
}
|
||||
```
|
||||
|
||||
> If MFA is enabled for the account, a `ticket` is returned in the JSON response.<br />
|
||||
> Proceed authentication by requesting the `/auth/mfa/totp` endpoint (see below).
|
||||
If Multi Factor Authentication (MFA) is enabled for the account the following response body is returned:
|
||||
|
||||
### Activation
|
||||
```json
|
||||
{
|
||||
"mfa": true,
|
||||
"ticket": "..."
|
||||
}
|
||||
```
|
||||
|
||||
For login with MFA, proceed authentication by requesting the [TOTP](#totp) `/auth/mfa/totp` endpoint.
|
||||
|
||||
---
|
||||
|
||||
### Logout
|
||||
|
||||
Logout an account.
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/logout`
|
||||
|
||||
```
|
||||
<empty>
|
||||
```
|
||||
|
||||
#### Response
|
||||
|
||||
```
|
||||
204 No Content
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### JWK
|
||||
|
||||
JWK. This endpoint is active if env var `JWT_ALGORITHM` is one of `['RS256', 'RS384', 'RS512']`.
|
||||
|
||||
#### Request
|
||||
|
||||
`GET /auth/jwks`
|
||||
|
||||
```
|
||||
<empty>
|
||||
```
|
||||
|
||||
#### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"keys": [...]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Activate account
|
||||
|
||||
Activate account. This endpoint is active if env var `AUTO_ACTIVATE_NEW_USERS=false` (default `true`).
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/activate`
|
||||
|
||||
```json
|
||||
{
|
||||
"ticket": "0175b2e2-b6b5-4d3f-a5db-5b2d4bfc2ce7"
|
||||
@@ -87,18 +158,18 @@ Set-Cookie: refresh_token=...
|
||||
204 No Content
|
||||
```
|
||||
|
||||
### JWKS
|
||||
---
|
||||
|
||||
### Delete Account
|
||||
|
||||
Delete account. This endpoint is active if env var `ALLOW_USER_SELF_DELETE=true` (default `false`).
|
||||
|
||||
#### Request
|
||||
|
||||
#### Response
|
||||
|
||||
### Delete account
|
||||
|
||||
#### Request
|
||||
`POST /auth/delete`
|
||||
|
||||
```
|
||||
Authorization: Bearer ...
|
||||
<empty>
|
||||
```
|
||||
|
||||
#### Response
|
||||
@@ -107,14 +178,20 @@ Authorization: Bearer ...
|
||||
204 No Content
|
||||
```
|
||||
|
||||
### Forgotten password
|
||||
---
|
||||
|
||||
### Change password
|
||||
|
||||
Change password of an account. The account must be logged in for this endpoint to work.
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/change-password/`
|
||||
|
||||
```json
|
||||
{
|
||||
"ticket": "6a135423-85c8-4c99-b9ca-3a0108202255",
|
||||
"new_password": "between 6-128 characters"
|
||||
"old_password": "secretpassword",
|
||||
"new_password": "newsecretpassword"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -124,14 +201,106 @@ Authorization: Bearer ...
|
||||
204 No Content
|
||||
```
|
||||
|
||||
### Reset password
|
||||
---
|
||||
|
||||
### Change Password Request
|
||||
|
||||
Request to change password. This endpoint is active if env var `LOST_PASSWORD_ENABLE=true`.
|
||||
|
||||
::: warning
|
||||
This endpoint will always return HTTP status code 204 in order to not leak information about the database.
|
||||
:::
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/change-password/request`
|
||||
|
||||
```json
|
||||
{
|
||||
"ticket": "6a135423-85c8-4c99-b9ca-3a0108202255",
|
||||
"new_password": "between 6-128 characters"
|
||||
"email": "hello@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
#### Response
|
||||
|
||||
```
|
||||
204 No Content
|
||||
```
|
||||
|
||||
### Change Password Change
|
||||
|
||||
Change password based on a ticket. This endpoint is active if env var `LOST_PASSWORD_ENABLE=true`.
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/change-password/change`
|
||||
|
||||
```json
|
||||
{
|
||||
"ticket": "uuid",
|
||||
"new_password": "newsecretpassword"
|
||||
}
|
||||
```
|
||||
|
||||
#### Response
|
||||
|
||||
```
|
||||
204 No Content
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Change Email
|
||||
|
||||
Change email without email verification as a logged in account. This endpoint is only active if env var `VARIFY_EMAILS=false` (default ``).
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/change-email/`
|
||||
|
||||
```json
|
||||
{
|
||||
"new_email": "new-hello@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
#### Response
|
||||
|
||||
```
|
||||
204 No Content
|
||||
```
|
||||
|
||||
### Change Email Request
|
||||
|
||||
Send request for the new email that the account wants to change to. This endpoint is only active if `VERIFY_EMAILS=true`.
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/change-email/request`
|
||||
|
||||
```json
|
||||
{
|
||||
"new_email": "new-hello@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
#### Response
|
||||
|
||||
```
|
||||
204 No Content
|
||||
```
|
||||
|
||||
### Change Email Change
|
||||
|
||||
Change email to the new email that you specified in [Change Email Request](#change-email-request). This endpoint is only active if `VERIFY_EMAILS=true`.
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/change-email/change`
|
||||
|
||||
```json
|
||||
{
|
||||
"ticket": "uuid-ticket"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -143,8 +312,12 @@ Authorization: Bearer ...
|
||||
|
||||
### Refresh token
|
||||
|
||||
Get new refresh token. The browser will send the cookie automatically.
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/token/refresh`
|
||||
|
||||
```
|
||||
Cookie: refresh_token=...
|
||||
```
|
||||
@@ -157,17 +330,23 @@ Set-Cookie: refresh_token=...
|
||||
|
||||
```json
|
||||
{
|
||||
"jwt_token": "...",
|
||||
"jwt_token": "token",
|
||||
"jwt_expires_in": 900000
|
||||
}
|
||||
```
|
||||
|
||||
### Revoke token
|
||||
---
|
||||
|
||||
### Revoke Refresh Token
|
||||
|
||||
Revoke a refresh token.
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/token/revoke/`
|
||||
|
||||
```
|
||||
Authorization: Bearer ...
|
||||
Cookie: refresh_token=...
|
||||
```
|
||||
|
||||
#### Response
|
||||
@@ -176,30 +355,34 @@ Authorization: Bearer ...
|
||||
204 No Content
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Generate MFA QR code
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/mfa/generate`
|
||||
|
||||
```
|
||||
Authorization: Bearer ...
|
||||
<empty>
|
||||
```
|
||||
|
||||
#### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"image_url": "...",
|
||||
"image_url": "base64_data_image_of_qe_code",
|
||||
"otp_secret": "..."
|
||||
}
|
||||
```
|
||||
|
||||
### Enable MFA
|
||||
|
||||
Enable Multi Factor Authentication.
|
||||
|
||||
#### Request
|
||||
|
||||
```
|
||||
Authorization: Bearer ...
|
||||
```
|
||||
`POST /auth/mfa/enable`
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -215,15 +398,15 @@ Authorization: Bearer ...
|
||||
|
||||
### Disable MFA
|
||||
|
||||
Disable Multi Facetor Authentication.
|
||||
|
||||
#### Request
|
||||
|
||||
```
|
||||
Authorization: Bearer ...
|
||||
```
|
||||
`POST /auth/mfa/disable`
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "109509"
|
||||
"code": "code-from-mfa-client"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -235,12 +418,16 @@ Authorization: Bearer ...
|
||||
|
||||
### TOTP
|
||||
|
||||
Time-based One-time Password. Use the `ticket` from [Login](#login) that is returned if the account has activated MFA.
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /auth/mfa/totp`
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "364124",
|
||||
"ticket": "259878d6-87be-4729-a3cc-53548f7ff72c"
|
||||
"code": "code-from-mfa-client",
|
||||
"ticket": "uuid-ticket"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -252,21 +439,168 @@ Set-Cookie: refresh_token=...
|
||||
|
||||
```json
|
||||
{
|
||||
"jwt_token": "...",
|
||||
"jwt_token": "jwt-token",
|
||||
"jwt_expires_in": 900000
|
||||
}
|
||||
```
|
||||
|
||||
## Storage
|
||||
|
||||
## Other
|
||||
### File
|
||||
|
||||
Get file
|
||||
|
||||
#### Request
|
||||
|
||||
`GET /storage/o/<path-to-file>`
|
||||
|
||||
#### Response
|
||||
|
||||
```
|
||||
<file>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### File metadata
|
||||
|
||||
Get file metadata.
|
||||
|
||||
#### Request
|
||||
|
||||
`GET /storage/m/<path-to-file>`
|
||||
|
||||
#### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "<path-to-file>",
|
||||
"AcceptRanges": "bytes",
|
||||
"LastModified": "2020-01-01T01:02:03.000Z",
|
||||
"ContentLength": 12345,
|
||||
"ETag": "Etag",
|
||||
"ContentType": "<content-type>",
|
||||
"Metadata": {
|
||||
"filename": "<original-file-name>",
|
||||
"token": "<auto-generated-access-token-uuid>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### File directory
|
||||
|
||||
Get zip of all files in directory.
|
||||
|
||||
#### Request
|
||||
|
||||
`GET /storage/o/<path-to-folder>/`
|
||||
|
||||
#### Response
|
||||
|
||||
```
|
||||
Downloadable list.zip file
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
### File directory metadata
|
||||
|
||||
Get zip of all files in directory.
|
||||
|
||||
#### Request
|
||||
|
||||
`GET /storage/m/<path-to-folder>/`
|
||||
|
||||
#### Response
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"key": "<path-to-file>",
|
||||
"AcceptRanges": "bytes",
|
||||
"LastModified": "2020-01-01T01:02:03.000Z",
|
||||
"ContentLength": 12345,
|
||||
"ETag": "Etag",
|
||||
"ContentType": "<content-type>",
|
||||
"Metadata": {
|
||||
"filename": "<original-file-name>",
|
||||
"token": "<auto-generated-access-token-uuid>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "<other-path-to-file>",
|
||||
"AcceptRanges": "bytes",
|
||||
"LastModified": "2020-05-04T03:02:01.000Z",
|
||||
"ContentLength": 54321,
|
||||
"ETag": "Etag",
|
||||
"ContentType": "<content-type>",
|
||||
"Metadata": {
|
||||
"filename": "<other-original-file-name>",
|
||||
"token": "<auto-generated-access-token-uuid>"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Upload file
|
||||
|
||||
Upload, or overwrite, a file.
|
||||
|
||||
#### Request
|
||||
|
||||
`POST /storage/o/<path-to-file>/`
|
||||
|
||||
#### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "<path-to-file>",
|
||||
"AcceptRanges": "bytes",
|
||||
"LastModified": "2020-01-01T01:02:03.000Z",
|
||||
"ContentLength": 12345,
|
||||
"ETag": "Etag",
|
||||
"ContentType": "<content-type>",
|
||||
"Metadata": {
|
||||
"filename": "<original-file-name>",
|
||||
"token": "<auto-generated-access-token-uuid>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Delete file
|
||||
|
||||
Delete a file.
|
||||
|
||||
#### Request
|
||||
|
||||
`DELETE /storage/o/<path-to-file>/`
|
||||
|
||||
#### Response
|
||||
|
||||
```json
|
||||
204 No Content
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Health Check
|
||||
|
||||
Simple health check.
|
||||
|
||||
#### Request
|
||||
|
||||
`GET /healthz`
|
||||
|
||||
#### Response
|
||||
|
||||
```
|
||||
OK
|
||||
200 OK
|
||||
```
|
||||
|
||||
@@ -8,6 +8,6 @@ import reset from './reset'
|
||||
|
||||
const router = Router().post('/', change)
|
||||
|
||||
if (LOST_PASSWORD_ENABLE) router.post('/lost', lost).post('/reset', reset)
|
||||
if (LOST_PASSWORD_ENABLE) router.post('/request', lost).post('/change', reset)
|
||||
|
||||
export default router
|
||||
|
||||
@@ -10,7 +10,7 @@ describeIfSecurePasswordChange('Reset lost password', () => {
|
||||
|
||||
it('should request a reset ticket to be sent by email', async () => {
|
||||
const { status } = await request
|
||||
.post('/auth/change-password/lost')
|
||||
.post('/auth/change-password/request')
|
||||
.send({ email: account.email })
|
||||
expect(status).toBe(204)
|
||||
})
|
||||
@@ -25,7 +25,7 @@ describeIfSecurePasswordChange('Reset lost password', () => {
|
||||
})
|
||||
|
||||
it('should change the password from a ticket', async () => {
|
||||
const { status } = await request.post('/auth/change-password/reset').send({
|
||||
const { status } = await request.post('/auth/change-password/change').send({
|
||||
ticket,
|
||||
new_password: account.password
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user