Merge pull request #235 from nhost/docs-api-updates

Updated API docs and password-change routes for concistency
This commit is contained in:
Johan Eliasson
2020-05-15 08:41:32 +02:00
committed by GitHub
4 changed files with 408 additions and 63 deletions

11
CHANGELOG.md Normal file
View 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)

View File

@@ -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
```

View File

@@ -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

View File

@@ -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
})