feat(markdown): Work on backend docs
This commit is contained in:
parent
6c2cb71f51
commit
4edfe29726
17 changed files with 1196 additions and 347 deletions
|
@ -1,314 +0,0 @@
|
|||
---
|
||||
title: API Keys
|
||||
---
|
||||
|
||||
Documentation for the REST API endpoints to create, read, or remove API keys.
|
||||
|
||||
<Tip>
|
||||
The FreeSewing backend REST API supports authentication both with JSON Web
|
||||
Tokens (JWT) as with API keys (KEY). This describes the endpoints that deal
|
||||
with creating, reading, and removing API keys. For authentication details,
|
||||
refer to [the section on authenticating to the
|
||||
API](/reference/backend/api#authentication).
|
||||
</Tip>
|
||||
|
||||
## Create a new API key
|
||||
|
||||
Create a new API key. The API key will belong to the user who is authenticated
|
||||
when making the call. Supported for both JWT and KEY authentication.
|
||||
|
||||
<Note compact>
|
||||
The response to this API call is the only time the secret will be
|
||||
revealed.
|
||||
</Note>
|
||||
|
||||
### Endpoints
|
||||
|
||||
| Method | Path | Description | Auth |
|
||||
| ------ | ---- | ----------- | ---- |
|
||||
| <Method post /> | `/apikey/jwt` | Create a new API key | _jwt_ |
|
||||
| <Method post /> | `/apikey/key` | Create a new API key | _key_ |
|
||||
|
||||
### Parameters
|
||||
<Tabs tabs="Request, Response">
|
||||
<Tab>
|
||||
| Where | Variable | Type | Description |
|
||||
| ----- | ------------- | -------- | ----------- |
|
||||
| _body_ | `name` | `string` | Create a new API key. Endpoint for JWT authentication |
|
||||
| _body_ | `level` | `number` | A privilege level from 0 to 8. |
|
||||
| _body_ | `expiresIn` | `number` | body | The number of seconds until this key expires. |
|
||||
</Tab>
|
||||
<Tab>
|
||||
Returns HTTP status code <StatusCode status="201"/> on success, <StatusCode status="400"/> if
|
||||
the request is malformed, and <StatusCode status="500"/> on server error.
|
||||
|
||||
| Value | Type | Description |
|
||||
| ------------------- | -------- | ----------- |
|
||||
| `result` | `string` | `created` on success, and `error` on error |
|
||||
| `apikey.key` | `string` | The API key |
|
||||
| `apikey.secret` | `string` | The API secret |
|
||||
| `apikey.level` | `number` | The privilege level of the API key |
|
||||
| `apikey.expiresAt` | `string` | A string representation of the moment the API key expires |
|
||||
| `apikey.name` | `string` | The name of the API key |
|
||||
| `apikey.userId` | `number` | The ID of the user who created the API key |
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
### Example
|
||||
<Tabs tabs="Request, Response">
|
||||
<Tab>
|
||||
```js
|
||||
const apiKey = axios.post(
|
||||
'https://backend.freesewing.org/apikey/jwt',
|
||||
{
|
||||
name: 'My first API key',
|
||||
level: 2, // Read only
|
||||
expiresIn: 3600, // One hour
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab>
|
||||
|
||||
```json
|
||||
{
|
||||
result: 'success',
|
||||
apikey: {
|
||||
key: '7ea12968-7758-40b6-8c73-75cc99be762b',
|
||||
secret: '503d7adbdb3ec18ab27adfcd895d8b47a8d6bc8307d548500fbf9c05a5a8820e',
|
||||
level: 3,
|
||||
expiresAt: '2022-11-06T15:57:30.190Z',
|
||||
name: 'My first API key',
|
||||
userId: 61
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Read an API key
|
||||
|
||||
Reads an existing API key. Note that the API secret can only be retrieved at
|
||||
the moment the API key is created.
|
||||
|
||||
<Note compact>
|
||||
You need the `admin` role to read API keys of other users
|
||||
</Note>
|
||||
### Endpoints
|
||||
|
||||
| Method | Path | Description | Auth |
|
||||
| ------ | ---- | ----------- | ---- |
|
||||
| <Method get /> | `/apikey/:id/jwt` | Reads an API key | _jwt_ |
|
||||
| <Method get /> | `/apikey/:id/key` | Reads an API key | _key_ |
|
||||
|
||||
### Parameters
|
||||
<Tabs tabs="Request, Response">
|
||||
<Tab>
|
||||
| Where | Variable | Type | Description |
|
||||
| ----- | ----------- | -------- | ----------- |
|
||||
| _url_ | `:id` | `string` | The `key` field of the API key |
|
||||
</Tab>
|
||||
<Tab>
|
||||
Returns HTTP status code <StatusCode status="200"/> on success, <StatusCode status="400"/> if
|
||||
the request is malformed, <StatusCode status="404"/> if the key is not found,
|
||||
and <StatusCode status="500"/> on server error.
|
||||
|
||||
| Value | Type | Description |
|
||||
| ------------------- | -------- | ----------- |
|
||||
| `result` | `string` | `success` on success, and `error` on error |
|
||||
| `apikey.key` | `string` | The API key |
|
||||
| `apikey.level` | `number` | The privilege level of the API key |
|
||||
| `apikey.expiresAt` | `string` | A string representation of the moment the API key expires |
|
||||
| `apikey.name` | `string` | The name of the API key |
|
||||
| `apikey.userId` | `number` | The ID of the user who created the API key |
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
### Example
|
||||
<Tabs tabs="Request, Response">
|
||||
<Tab>
|
||||
```js
|
||||
const keyInfo = axios.get(
|
||||
'https://backend.freesewing.org/apikey/7ea12968-7758-40b6-8c73-75cc99be762b/jwt',
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab>
|
||||
|
||||
```json
|
||||
{
|
||||
result: 'success',
|
||||
apikey: {
|
||||
key: '7ea12968-7758-40b6-8c73-75cc99be762b',
|
||||
level: 3,
|
||||
expiresAt: '2022-11-06T15:57:30.190Z',
|
||||
name: 'My first API key',
|
||||
userId: 61
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Read the current API key
|
||||
|
||||
Reads the API key with which the current request was authenticated.
|
||||
|
||||
### Endpoints
|
||||
|
||||
| Method | Path | Description | Auth |
|
||||
| ------ | ---- | ----------- | ---- |
|
||||
| <Method get /> | `/whoami/key` | Reads the current API key | _key_ |
|
||||
|
||||
### Parameters
|
||||
<Tabs tabs="Request, Response">
|
||||
<Tab>
|
||||
<Note compact>This endpoint takes no parameters</Note>
|
||||
</Tab>
|
||||
<Tab>
|
||||
Returns status code `200` on success, `400` on if the request is malformed,
|
||||
`404` if the key is not found, and `500` on server error.
|
||||
|
||||
| Value | Type | Description |
|
||||
| ------------------- | -------- | ----------- |
|
||||
| `result` | `string` | `success` on success, and `error` on error |
|
||||
| `apikey.key` | `string` | The API key |
|
||||
| `apikey.level` | `number` | The privilege level of the API key |
|
||||
| `apikey.expiresAt` | `string` | A string representation of the moment the API key expires |
|
||||
| `apikey.name` | `string` | The name of the API key |
|
||||
| `apikey.userId` | `number` | The ID of the user who created the API key |
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
### Example
|
||||
<Tabs tabs="Request, Response">
|
||||
<Tab>
|
||||
```js
|
||||
const keyInfo = axios.get(
|
||||
'https://backend.freesewing.org/whoami/key',
|
||||
{
|
||||
auth: {
|
||||
username: apikey.key,
|
||||
password: apikey.secret,
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab>
|
||||
|
||||
```json
|
||||
{
|
||||
result: 'success',
|
||||
apikey: {
|
||||
key: '7ea12968-7758-40b6-8c73-75cc99be762b',
|
||||
level: 3,
|
||||
expiresAt: '2022-11-06T15:57:30.190Z',
|
||||
name: 'My first API key',
|
||||
userId: 61
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
|
||||
## Remove an API key
|
||||
|
||||
Removes an existing API key.
|
||||
|
||||
<Note compact>
|
||||
You need the `admin` role to remove API keys of other users
|
||||
</Note>
|
||||
|
||||
### Endpoints
|
||||
|
||||
| Method | Path | Description | Auth |
|
||||
| ------ | ---- | ----------- | ---- |
|
||||
| <Method delete /> | `/apikey/:id/jwt` | Removes an API key | _jwt_ |
|
||||
| <Method delete /> | `/apikey/:id/key` | Removes an API key | _key_ |
|
||||
|
||||
### Parameters
|
||||
<Tabs tabs="Request, Response">
|
||||
<Tab>
|
||||
| Where | Variable | Type | Description |
|
||||
| ----- | ----------- | -------- | ----------- |
|
||||
| _url_ | `:id` | `string` | The `key` field of the API key |
|
||||
</Tab>
|
||||
<Tab>
|
||||
Returns HTTP status code <StatusCode status="204"/> on success, <StatusCode status="400"/> if
|
||||
the request is malformed, <StatusCode status="404"/> if the key is not found,
|
||||
and <StatusCode status="500"/> on server error.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
### Example
|
||||
<Tabs tabs="Request, Response">
|
||||
<Tab>
|
||||
```js
|
||||
const keyInfo = axios.get(
|
||||
'https://backend.freesewing.org/apikey/7ea12968-7758-40b6-8c73-75cc99be762b/jwt',
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab>
|
||||
<Note compact>Status code <StatusCode status="204"/> (no content) does not come with a body</Note>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Notes
|
||||
|
||||
The following is good to keep in mind when working with API keys:
|
||||
|
||||
### This is not the authentication documentation
|
||||
|
||||
The FreeSewing backend REST API supports authentication both with JSON Web
|
||||
Tokens (JWT) as with API keys (KEY).
|
||||
|
||||
This describes the endpoints that deal with creating, reading, and removing API
|
||||
keys. For authentication details, refer to [the section on authenticating to
|
||||
the API](/reference/backend/api#authentication).
|
||||
|
||||
### API keys are immutable
|
||||
|
||||
Once created, API keys cannot be updated.
|
||||
You should remove them and re-create a new one if you want to make change.
|
||||
|
||||
### API keys have an expiry
|
||||
|
||||
API keys have an expiry date. The maximum validity for an API key is 1 year.
|
||||
|
||||
### API keys have a permission level
|
||||
|
||||
API keys have a permission level. You can never create an API key with a higher
|
||||
permission level than your own permission level.
|
||||
|
||||
### Circumstances that will trigger your API keys to be revoked
|
||||
|
||||
As a precaution, all your API keys will be revoked when:
|
||||
|
||||
- Your role is downgraded to a role with fewer privileges
|
||||
- Your account is (b)locked
|
||||
- You revoke your consent for FreeSewing to process your data
|
||||
|
||||
<Note>
|
||||
This is not an exhaustive list. For example, if we find your use of our API to
|
||||
be excessive, we might also revoke your API keys to shield us from the
|
||||
financial impact of your use of our API.
|
||||
</Note>
|
||||
|
||||
|
97
markdown/dev/reference/backend/api/apikeys/create/en.md
Normal file
97
markdown/dev/reference/backend/api/apikeys/create/en.md
Normal file
|
@ -0,0 +1,97 @@
|
|||
---
|
||||
title: Create an API key
|
||||
---
|
||||
|
||||
Creates a new API key. An API key can be used to authenticate against the
|
||||
backend API.
|
||||
|
||||
## Access control
|
||||
|
||||
- [Permission level](/reference/backend/api/rbac) `4` or higher is required to create an API key
|
||||
|
||||
## Endpoints
|
||||
|
||||
Creating a new API key is possible via these endpoints:
|
||||
|
||||
| Method | Path | Authentication |
|
||||
| --------: | :--- | :------------- |
|
||||
| <Method post /> | `/apikeys/jwt` | [JSON Web Token](/reference/backend/api/authentication#jwt-authentication) |
|
||||
| <Method post /> | `/apikeys/key` | [API Key & Secret](/reference/backend/api/authentication#key-authentication) |
|
||||
|
||||
## Request body
|
||||
|
||||
| Property | Type | Description |
|
||||
| ----------: | :------- | :---------- |
|
||||
| `name` | `string` | A name for the API key |
|
||||
| `level` | `number` | A privilege level from 0 to 8. |
|
||||
| `expiresIn` | `number` | The number of seconds until the API key expires |
|
||||
|
||||
## Response status codes
|
||||
|
||||
Possible status codes for these endpoints are:
|
||||
|
||||
| Status code | Description |
|
||||
| ----------: | :---------- |
|
||||
| <StatusCode status="200"/> | success |
|
||||
| <StatusCode status="400"/> | the request was malformed |
|
||||
| <StatusCode status="401"/> | the request lacks authentication |
|
||||
| <StatusCode status="403"/> | authentication failed |
|
||||
| <StatusCode status="500"/> | server error |
|
||||
|
||||
<Note>
|
||||
If the status code is not <StatusCode status="200" /> the `error` property
|
||||
in the response body should indicate the nature of the problem.
|
||||
</Note>
|
||||
|
||||
## Response body
|
||||
|
||||
<Warning>
|
||||
##### Make sure to save the secret
|
||||
The response body is the only time the API key's secret will be revealed.
|
||||
</Warning>
|
||||
|
||||
| Value | Type | Description |
|
||||
| ------------------- | -------- | ----------- |
|
||||
| `result` | `string` | Either `success` or `error` |
|
||||
| `error` | `string` | Will give info on the nature of the error. Only set if an error occured. |
|
||||
| `apikey.key` | `string` | The API key |
|
||||
| `apikey.secret` | `string` | The API secret |
|
||||
| `apikey.level` | `number` | The privilege level of the API key |
|
||||
| `apikey.expiresAt` | `string` | A string representation of the moment the API key expires |
|
||||
| `apikey.name` | `string` | The name of the API key |
|
||||
| `apikey.userId` | `number` | The ID of the user who created the API key |
|
||||
|
||||
|
||||
|
||||
## Example request
|
||||
|
||||
```js
|
||||
const apiKey = axios.post(
|
||||
'https://backend.freesewing.org/apikeys/jwt',
|
||||
{
|
||||
name: 'My first API key',
|
||||
level: 2, // Read only
|
||||
expiresIn: 3600, // One hour
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Example response
|
||||
```200.json
|
||||
{
|
||||
"result": "success",
|
||||
"apikey": {
|
||||
"key": "7ea12968-7758-40b6-8c73-75cc99be762b",
|
||||
"secret": "503d7adbdb3ec18ab27adfcd895d8b47a8d6bc8307d548500fbf9c05a5a8820e",
|
||||
"level": 3,
|
||||
"expiresAt": "2022-11-06T15:57:30.190Z",
|
||||
"name": "My first API key",
|
||||
"userId": 61
|
||||
}
|
||||
}
|
||||
```
|
58
markdown/dev/reference/backend/api/apikeys/delete/en.md
Normal file
58
markdown/dev/reference/backend/api/apikeys/delete/en.md
Normal file
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
title: Delete an API key
|
||||
---
|
||||
|
||||
Deletes an existing API key.
|
||||
|
||||
## Access control
|
||||
|
||||
- [Permission level](/reference/backend/api/rbac) `4` or higher is required to delete an API key
|
||||
|
||||
## Endpoints
|
||||
|
||||
Deleting an API key is possible via these endpoints:
|
||||
|
||||
| Method | Path | Authentication |
|
||||
| --------: | :--- | :------------- |
|
||||
| <Method delete /> | `/apikeys/:id/jwt` | [JSON Web Token](/reference/backend/api/authentication#jwt-authentication) |
|
||||
| <Method delete /> | `/apikeys/:id/key` | [API Key & Secret](/reference/backend/api/authentication#key-authentication) |
|
||||
|
||||
## Request url
|
||||
|
||||
The url should contain the ID of the API key you wish to remove.
|
||||
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
|
||||
|
||||
## Response status codes
|
||||
|
||||
Possible status codes for these endpoints are:
|
||||
|
||||
| Status code | Description |
|
||||
| ----------: | :---------- |
|
||||
| <StatusCode status="204"/> | success |
|
||||
| <StatusCode status="400"/> | the request was malformed |
|
||||
| <StatusCode status="401"/> | the request lacks authentication |
|
||||
| <StatusCode status="403"/> | authentication failed |
|
||||
| <StatusCode status="500"/> | server error |
|
||||
|
||||
## Example request
|
||||
|
||||
```js
|
||||
await axios.delete(
|
||||
'https://backend.freesewing.org/apikeys/7ea12968-7758-40b6-8c73-75cc99be762b/jwt',
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Example response
|
||||
|
||||
```204.json
|
||||
```
|
||||
<Note>
|
||||
These endpoints return status code <StatusCode status="204"/> (no content) on
|
||||
success, with no response body.
|
||||
</Note>
|
||||
|
53
markdown/dev/reference/backend/api/apikeys/en.md
Normal file
53
markdown/dev/reference/backend/api/apikeys/en.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
title: API Keys
|
||||
---
|
||||
|
||||
API keys are a way to authenticate to the API with basic authentication.
|
||||
They are intended to be used when interacting with the API in an automated
|
||||
way such as from a script or a CI/CD pipeline.
|
||||
|
||||
They are an alternative to JSON Web Tokens (JWT) which is typically used
|
||||
to authenticate users in a browser session.
|
||||
|
||||
The FreeSewing backend REST API supports authentication both with JSON Web
|
||||
Tokens (JWT) as with API keys (KEY). This describes the endpoints that deal
|
||||
with creating, reading, and removing API keys. For authentication details,
|
||||
refer to [the section on
|
||||
authenticating](/reference/backend/api#authentication).
|
||||
|
||||
## Endpoints
|
||||
|
||||
<ReadMore />
|
||||
|
||||
## Notes
|
||||
|
||||
The following is good to keep in mind when working with API keys:
|
||||
|
||||
### API keys are immutable
|
||||
|
||||
Once created, API keys cannot be updated.
|
||||
You should remove them and re-create a new one if you want to make a change.
|
||||
|
||||
### API keys have an expiry
|
||||
|
||||
API keys have an expiry date. The maximum validity for an API key is 1 year.
|
||||
|
||||
### API keys have a permission level
|
||||
|
||||
API keys have a permission level. You can never create an API key with a higher
|
||||
permission level than your own permission level.
|
||||
|
||||
### Circumstances that will trigger your API keys to be revoked
|
||||
|
||||
As a precaution, all your API keys will be revoked when:
|
||||
|
||||
- Your role is downgraded to a role with fewer privileges
|
||||
- Your account is (b)locked
|
||||
- You revoke your consent for FreeSewing to process your data
|
||||
|
||||
<Note>
|
||||
This is not an exhaustive list. For example, if we find your use of our API to
|
||||
be excessive, we might also revoke your API keys to shield us from the
|
||||
financial impact of your use of our API.
|
||||
</Note>
|
||||
|
81
markdown/dev/reference/backend/api/apikeys/read/en.md
Normal file
81
markdown/dev/reference/backend/api/apikeys/read/en.md
Normal file
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
title: Read an API key
|
||||
---
|
||||
|
||||
Reads an existing API key. Note that the API secret can only be retrieved at
|
||||
the moment the API key is created.
|
||||
|
||||
## Access control
|
||||
|
||||
- [Permission level](/reference/backend/api/rbac) `4` or higher is required to read an API key
|
||||
|
||||
## Endpoints
|
||||
|
||||
Reading an API key is possible via these endpoints:
|
||||
|
||||
| Method | Path | Authentication |
|
||||
| --------: | :--- | :------------- |
|
||||
| <Method get /> | `/apikeys/:id/jwt` | [JSON Web Token](/reference/backend/api/authentication#jwt-authentication) |
|
||||
| <Method get /> | `/apikeys/:id/key` | [API Key & Secret](/reference/backend/api/authentication#key-authentication) |
|
||||
|
||||
## Request url
|
||||
|
||||
The url should contain the ID of the API key you wish to remove.
|
||||
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
|
||||
|
||||
## Response status codes
|
||||
|
||||
Possible status codes for these endpoints are:
|
||||
|
||||
| Status code | Description |
|
||||
| ----------: | :---------- |
|
||||
| <StatusCode status="200"/> | success |
|
||||
| <StatusCode status="400"/> | the request was malformed |
|
||||
| <StatusCode status="401"/> | the request lacks authentication |
|
||||
| <StatusCode status="403"/> | authentication failed |
|
||||
| <StatusCode status="404"/> | API key not found |
|
||||
| <StatusCode status="500"/> | server error |
|
||||
|
||||
<Note>
|
||||
If the status code is not <StatusCode status="200" /> the `error` property
|
||||
in the response body should indicate the nature of the problem.
|
||||
</Note>
|
||||
|
||||
## Response body
|
||||
|
||||
| Value | Type | Description |
|
||||
| ------------------- | -------- | ----------- |
|
||||
| `result` | `string` | `success` on success, and `error` on error |
|
||||
| `error` | `string` | Will give info on the nature of the error. Only set if an error occured. |
|
||||
| `apikey.key` | `string` | The API key |
|
||||
| `apikey.level` | `number` | The privilege level of the API key |
|
||||
| `apikey.expiresAt` | `string` | A string representation of the moment the API key expires |
|
||||
| `apikey.name` | `string` | The name of the API key |
|
||||
| `apikey.userId` | `number` | The ID of the user who created the API key |
|
||||
|
||||
## Example request
|
||||
|
||||
```js
|
||||
const keyInfo = await axios.get(
|
||||
'https://backend.freesewing.org/apikeys/7ea12968-7758-40b6-8c73-75cc99be762b/jwt',
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Example response
|
||||
```200.json
|
||||
{
|
||||
"result": "success",
|
||||
"apikey": {
|
||||
"key": "7ea12968-7758-40b6-8c73-75cc99be762b",
|
||||
"level": 3,
|
||||
"expiresAt": "2022-11-06T15:57:30.190Z",
|
||||
"name": "My first API key",
|
||||
"userId": 61
|
||||
}
|
||||
}
|
||||
```
|
73
markdown/dev/reference/backend/api/apikeys/whoami/en.md
Normal file
73
markdown/dev/reference/backend/api/apikeys/whoami/en.md
Normal file
|
@ -0,0 +1,73 @@
|
|||
---
|
||||
title: Read the current API key
|
||||
---
|
||||
|
||||
Reads the current API key used to authenticate the request.
|
||||
For obvious reasons, this endpoint is only available with API key authentication.
|
||||
However, there's an equivalent endpoint for JWT authentication.
|
||||
|
||||
## Access control
|
||||
|
||||
- [Permission level](/reference/backend/api/rbac) `0` or higher is required to read the current API key
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Authentication |
|
||||
| --------: | :--- | :------------- |
|
||||
| <Method get /> | `/whoami/key` | [API Key & Secret](/reference/backend/api/authentication#key-authentication) |
|
||||
|
||||
## Response status codes
|
||||
|
||||
Possible status codes for these endpoints are:
|
||||
|
||||
| Status code | Description |
|
||||
| ----------: | :---------- |
|
||||
| <StatusCode status="200"/> | success |
|
||||
| <StatusCode status="400"/> | the request was malformed |
|
||||
| <StatusCode status="401"/> | the request lacks authentication |
|
||||
| <StatusCode status="403"/> | authentication failed |
|
||||
| <StatusCode status="500"/> | server error |
|
||||
|
||||
<Note>
|
||||
If the status code is not <StatusCode status="200" /> the `error` property
|
||||
in the response body should indicate the nature of the problem.
|
||||
</Note>
|
||||
|
||||
## Response body
|
||||
|
||||
| Value | Type | Description |
|
||||
| ------------------- | -------- | ----------- |
|
||||
| `result` | `string` | `success` on success, and `error` on error |
|
||||
| `error` | `string` | Will give info on the nature of the error. Only set if an error occured. |
|
||||
| `apikey.key` | `string` | The API key |
|
||||
| `apikey.level` | `number` | The privilege level of the API key |
|
||||
| `apikey.expiresAt` | `string` | A string representation of the moment the API key expires |
|
||||
| `apikey.name` | `string` | The name of the API key |
|
||||
| `apikey.userId` | `number` | The ID of the user who created the API key |
|
||||
|
||||
## Example request
|
||||
|
||||
```js
|
||||
const keyInfo = await axios.get(
|
||||
'https://backend.freesewing.org/whoami/key',
|
||||
{
|
||||
auth: {
|
||||
username: apikey.key,
|
||||
password: apikey.secret,
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Example response
|
||||
```200.json
|
||||
{
|
||||
"result": "success",
|
||||
"apikey": {
|
||||
"key": "7ea12968-7758-40b6-8c73-75cc99be762b",
|
||||
"level": 3,
|
||||
"expiresAt": "2022-11-06T15:57:30.190Z",
|
||||
"name": "My first API key",
|
||||
"userId": 61
|
||||
}
|
||||
}
|
64
markdown/dev/reference/backend/api/authentication/en.md
Normal file
64
markdown/dev/reference/backend/api/authentication/en.md
Normal file
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
title: Authentication
|
||||
---
|
||||
|
||||
The FreeSewing backend API requires authentication for all but a handfull of
|
||||
endpoints.
|
||||
|
||||
The API supports two different types of authentication:
|
||||
|
||||
| Type | Name | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| [JSON Web Tokens](#jwt-authentication) | `jwt` | This is typically used to authenticate humans in a browser session. |
|
||||
| [API Keys](#key-authentication) | `key` | This is typically used to interact with the API in an automated way. Like in a script, a CI/CD context, a serverless runner, and so on. |
|
||||
|
||||
While the API supports both, they are not supported on the same endpoint.
|
||||
Instead, add the authentication type you want to use as the final part of
|
||||
endpoint:
|
||||
|
||||
- `/some/endpoint/jwt` : Authenticate with a JSON Web Token
|
||||
- `/some/endpoint/key` : Authenticate with an API key and secret
|
||||
|
||||
## `jwt` authentication
|
||||
|
||||
The use of JSON Web Tokens ([jwt](https://jwt.io)) is typically used in a
|
||||
browser context where we want to establish a *session*.
|
||||
|
||||
To get a token, you must first authenticate at the [`/login`](/reference/backend/api/user/login) endpoint.
|
||||
You will receive a JSON Web Token (jwt) as part of the response.
|
||||
|
||||
In subsequent API calls, you must then include this token in the
|
||||
`Authorization` header prefixed by `Bearer `. Like his:
|
||||
|
||||
```js
|
||||
const account = await axios.get(
|
||||
`https://backend.freesewing.org/account/jwt`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## `key` authentication
|
||||
|
||||
The combination of API key & secret serves as a username & password for [HTTP
|
||||
basic authentication](https://en.wikipedia.org/wiki/Basic_access_authentication).
|
||||
|
||||
<Note>
|
||||
In basic authentication, the password is sent
|
||||
unencrypted. To guard against this, this API should only be served over a
|
||||
connection that is encrypted with TLS. (a url starting with `https://`).
|
||||
</Note>
|
||||
|
||||
Sending a username and password with a request like this is supported
|
||||
pretty much everywhere. In addition, there is no need to establish a session
|
||||
first, so this make the entire transation stateless.
|
||||
|
||||
Below is an example using curl:
|
||||
|
||||
```sh
|
||||
curl -u api-key-here:api-secret-here \
|
||||
https://backend.freesewing.org/account/key
|
||||
```
|
|
@ -1,6 +1,5 @@
|
|||
---
|
||||
title: Backend REST API
|
||||
linktitle: REST API
|
||||
title: REST API
|
||||
---
|
||||
|
||||
This is the reference documentation for the FreeSewing backend REST API.
|
||||
|
|
110
markdown/dev/reference/backend/api/patterns/clone/en.md
Normal file
110
markdown/dev/reference/backend/api/patterns/clone/en.md
Normal file
|
@ -0,0 +1,110 @@
|
|||
---
|
||||
title: Clone a Pattern
|
||||
---
|
||||
|
||||
Create a new Pattern by cloning an existing one.
|
||||
|
||||
## Access control
|
||||
|
||||
The [Permission level](/reference/backend/api/rbac) required to clone a
|
||||
Pattern depends on:
|
||||
|
||||
- Whether the Pattern is `public`
|
||||
- Who created the Pattern
|
||||
|
||||
The details are outlined in the table below:
|
||||
|
||||
| | Public Patterns | Non-Public Patterns |
|
||||
| ---------------: | :-------------: | :-----------------: |
|
||||
| **Your own** | `0` or higher | `4` or higher |
|
||||
| **Other user's** | `0` or higher | `5` or higher |
|
||||
|
||||
## Endpoints
|
||||
|
||||
Creating a new API key is possible via these endpoints:
|
||||
|
||||
| Method | Path | Authentication |
|
||||
| --------: | :--- | :------------- |
|
||||
| <Method post /> | `/patterns/:id/clone/jwt` | [JSON Web Token](/reference/backend/api/authentication#jwt-authentication) |
|
||||
| <Method post /> | `/patterns/:id/clone/key` | [API Key & Secret](/reference/backend/api/authentication#key-authentication) |
|
||||
|
||||
## Request url
|
||||
|
||||
The url should contain the ID of the Pattern you wish to remove.
|
||||
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
|
||||
|
||||
## Response status codes
|
||||
|
||||
Possible status codes for these endpoints are:
|
||||
|
||||
| Status code | Description |
|
||||
| ----------: | :---------- |
|
||||
| <StatusCode status="200"/> | success |
|
||||
| <StatusCode status="400"/> | the request was malformed |
|
||||
| <StatusCode status="401"/> | the request lacks authentication |
|
||||
| <StatusCode status="403"/> | authentication failed |
|
||||
| <StatusCode status="500"/> | server error |
|
||||
|
||||
<Note>
|
||||
If the status code is not <StatusCode status="200" /> the `error` property
|
||||
in the response body should indicate the nature of the problem.
|
||||
</Note>
|
||||
|
||||
## Response body
|
||||
|
||||
| Value | Type | Description |
|
||||
| ------------------- | -------- | ----------- |
|
||||
| `result` | String | Either `success` or `error` |
|
||||
| `error` | String | Will give info on the nature of the error. Only set if an error occured. |
|
||||
| `pattern.id` | Number | The ID of the Pattern |
|
||||
| `pattern.createdAt` | String | Date string indicating the moment the pattern was created |
|
||||
| `pattern.data` | Object | Any additional data that was stored with Pattern data |
|
||||
| `pattern.design` | String | The name of the design of which this Pattern is an instance |
|
||||
| `pattern.img` | String | The URL to the image stored with this Pattern |
|
||||
| `pattern.name` | String | The name of the Pattern |
|
||||
| `pattern.notes` | String | The notes stored with the Pattern |
|
||||
| `pattern.personId` | Number | The ID of the Person for whom the Pattern was created |
|
||||
| `pattern.public` | Boolean| Indicates whether the Pattern is publicly accessible or not |
|
||||
| `pattern.settings` | Object | The settings used to (re-)create the Pattern |
|
||||
| `pattern.userId` | Number | The ID of the user who created the Pattern |
|
||||
| `pattern.updatedAt` | String | Date string indicating the last time the pattern was updated |
|
||||
|
||||
## Example request
|
||||
|
||||
```js
|
||||
const apiKey = axios.post(
|
||||
'https://backend.freesewing.org/patterns/10/clone/jwt',
|
||||
null,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Example response
|
||||
```200.json
|
||||
{
|
||||
"result": "success",
|
||||
"pattern": {
|
||||
"id": 19,
|
||||
"createdAt": "2022-11-19T16:29:33.346Z",
|
||||
"data": {
|
||||
"some": "value"
|
||||
},
|
||||
"design": "aaron",
|
||||
"img": "https://cdn.sanity.io/images/hl5bw8cj/production/a1565c8c6c70cfe7ea0fdf5c65501cd885adbe78-200x187.png",
|
||||
"name": "Just a test",
|
||||
"notes": "These are my notes",
|
||||
"personId": 17,
|
||||
"public": true,
|
||||
"settings": {
|
||||
"sa": 5
|
||||
},
|
||||
"userId": 10,
|
||||
"updatedAt": "2022-11-19T16:29:33.346Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
121
markdown/dev/reference/backend/api/patterns/create/en.md
Normal file
121
markdown/dev/reference/backend/api/patterns/create/en.md
Normal file
|
@ -0,0 +1,121 @@
|
|||
---
|
||||
title: Create a Pattern
|
||||
---
|
||||
|
||||
Creates a new Pattern. This is typically used when users choose to save a pattern.
|
||||
|
||||
## Access control
|
||||
|
||||
- [Permission level](/reference/backend/api/rbac) `4` or higher is required to create a Pattern
|
||||
|
||||
## Endpoints
|
||||
|
||||
Creating a new Pattern is possible via these endpoints:
|
||||
|
||||
| Method | Path | Authentication |
|
||||
| --------: | :--- | :------------- |
|
||||
| <Method post /> | `/patterns/jwt` | [JSON Web Token](/reference/backend/api/authentication#jwt-authentication) |
|
||||
| <Method post /> | `/patterns/key` | [API Key & Secret](/reference/backend/api/authentication#key-authentication) |
|
||||
|
||||
## Request body
|
||||
The request body is a JSON object with the following properties:
|
||||
|
||||
| Property | Type | Description |
|
||||
| ----------: | :------- | :---------- |
|
||||
| `data` | `object` | Any additional data to store with the pattern |
|
||||
| `design` | `string` | The name of the design this Pattern is an instance of |
|
||||
| `img` | `object` | An image [data-uri][duri] to store with this Pattern |
|
||||
| `name` | `string` | A name for the Pattern |
|
||||
| `notes` | `string` | User notes for the pattern |
|
||||
| `person` | `object` | The ID of the person to associate with this pattern |
|
||||
| `settings` | `object` | The settings object to (re-)create the Pattern |
|
||||
|
||||
## Response status codes
|
||||
|
||||
Possible status codes for these endpoints are:
|
||||
|
||||
| Status code | Description |
|
||||
| ----------: | :---------- |
|
||||
| <StatusCode status="200"/> | success |
|
||||
| <StatusCode status="400"/> | the request was malformed |
|
||||
| <StatusCode status="401"/> | the request lacks authentication |
|
||||
| <StatusCode status="403"/> | authentication failed |
|
||||
| <StatusCode status="500"/> | server error |
|
||||
|
||||
<Note>
|
||||
If the status code is not <StatusCode status="200" /> the `error` property
|
||||
in the response body should indicate the nature of the problem.
|
||||
</Note>
|
||||
|
||||
## Response body
|
||||
|
||||
| Value | Type | Description |
|
||||
| ------------------- | -------- | ----------- |
|
||||
| `result` | String | Either `success` or `error` |
|
||||
| `error` | String | Will give info on the nature of the error. Only set if an error occured. |
|
||||
| `pattern.id` | Number | The ID of the Pattern |
|
||||
| `pattern.createdAt` | String | Date string indicating the moment the pattern was created |
|
||||
| `pattern.data` | Object | Any additional data that was stored with Pattern data |
|
||||
| `pattern.design` | String | The name of the design of which this Pattern is an instance |
|
||||
| `pattern.img` | String | The URL to the image stored with this Pattern |
|
||||
| `pattern.name` | String | The name of the Pattern |
|
||||
| `pattern.notes` | String | The notes stored with the Pattern |
|
||||
| `pattern.personId` | Number | The ID of the Person for whom the Pattern was created |
|
||||
| `pattern.public` | Boolean| Indicates whether the Pattern is publicly accessible or not |
|
||||
| `pattern.settings` | Object | The settings used to (re-)create the Pattern |
|
||||
| `pattern.userId` | Number | The ID of the user who created the Pattern |
|
||||
| `pattern.updatedAt` | String | Date string indicating the last time the pattern was updated |
|
||||
|
||||
## Example request
|
||||
|
||||
```js
|
||||
const pattern = await axios.post(
|
||||
'https://backend.freesewing.org/patterns/jwt',
|
||||
{
|
||||
data: {
|
||||
some: 'value',
|
||||
}
|
||||
design: "aaron",
|
||||
img: "data:image/png;base64,iVBORw0KGgoAAAANSUhEU...truncated",
|
||||
name: "Just a test",
|
||||
notes: "These are my notes",
|
||||
person: 17,
|
||||
public: true,
|
||||
settings: {
|
||||
sa: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Example response
|
||||
```200.json
|
||||
{
|
||||
"result": "success",
|
||||
"pattern": {
|
||||
"id": 10,
|
||||
"createdAt": "2022-11-19T16:29:33.346Z",
|
||||
"data": {
|
||||
"some": "value"
|
||||
},
|
||||
"design": "aaron",
|
||||
"img": "https://cdn.sanity.io/images/hl5bw8cj/production/a1565c8c6c70cfe7ea0fdf5c65501cd885adbe78-200x187.png",
|
||||
"name": "Just a test",
|
||||
"notes": "These are my notes",
|
||||
"personId": 17,
|
||||
"public": true,
|
||||
"settings": {
|
||||
"sa": 5
|
||||
},
|
||||
"userId": 10,
|
||||
"updatedAt": "2022-11-19T16:29:35.023Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[duri]: https://en.wikipedia.org/wiki/Data_URI_scheme
|
59
markdown/dev/reference/backend/api/patterns/delete/en.md
Normal file
59
markdown/dev/reference/backend/api/patterns/delete/en.md
Normal file
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
title: Delete a Pattern
|
||||
---
|
||||
|
||||
Deletes an existing Pattern.
|
||||
|
||||
## Access control
|
||||
|
||||
- [Permission level](/reference/backend/api/rbac) `4` or higher is required to delete a Pattern
|
||||
- [Permission level](/reference/backend/api/rbac) `8` is required to delete **another user's** Pattern
|
||||
|
||||
## Endpoints
|
||||
|
||||
Deleting a Pattern is possible via these endpoints:
|
||||
|
||||
| Method | Path | Authentication |
|
||||
| --------: | :--- | :------------- |
|
||||
| <Method delete /> | `/patterns/:id/jwt` | [JSON Web Token](/reference/backend/api/authentication#jwt-authentication) |
|
||||
| <Method delete /> | `/patterns/:id/key` | [API Key & Secret](/reference/backend/api/authentication#key-authentication) |
|
||||
|
||||
## Request url
|
||||
|
||||
The url should contain the ID of the Pattern you wish to remove.
|
||||
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
|
||||
|
||||
## Response status codes
|
||||
|
||||
Possible status codes for these endpoints are:
|
||||
|
||||
| Status code | Description |
|
||||
| ----------: | :---------- |
|
||||
| <StatusCode status="204"/> | success |
|
||||
| <StatusCode status="400"/> | the request was malformed |
|
||||
| <StatusCode status="401"/> | the request lacks authentication |
|
||||
| <StatusCode status="403"/> | authentication failed |
|
||||
| <StatusCode status="500"/> | server error |
|
||||
|
||||
## Example request
|
||||
|
||||
```js
|
||||
await axios.delete(
|
||||
'https://backend.freesewing.org/patterns/10/jwt',
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Example response
|
||||
|
||||
```204.json
|
||||
```
|
||||
<Note>
|
||||
These endpoints return status code <StatusCode status="204"/> (no content) on
|
||||
success, with no response body.
|
||||
</Note>
|
||||
|
34
markdown/dev/reference/backend/api/patterns/en.md
Normal file
34
markdown/dev/reference/backend/api/patterns/en.md
Normal file
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
title: Patterns
|
||||
---
|
||||
|
||||
Patterns hold information on and settings for a user's patterns.
|
||||
|
||||
## Endpoints
|
||||
|
||||
<ReadMore />
|
||||
|
||||
## Notes
|
||||
|
||||
### The `design` property should hold the design
|
||||
|
||||
The `design` property should hold the name of the FreeSewing design.
|
||||
For example, `aaron`.
|
||||
|
||||
### The `notes` vs `data` properties
|
||||
|
||||
Both the `data` and `notes` properties can hold additional information about
|
||||
the pattern.
|
||||
|
||||
Keep in mind that:
|
||||
- The `notes` property is intended to be used by the user to add notes about
|
||||
their pattern. It will only accept data of type `string`.
|
||||
- The `data` property is intended to allow frontend developers to store
|
||||
additional data about the pattern. It wil only accept data of type `object`.
|
||||
|
||||
### The `settings` property should hold the pattern settings
|
||||
|
||||
The `settings` property should hold [a settings object](/reference/settings)
|
||||
that can be passed to [the Pattern
|
||||
constructor](/reference/api/pattern#creating-a-pattern).
|
||||
|
109
markdown/dev/reference/backend/api/patterns/read/en.md
Normal file
109
markdown/dev/reference/backend/api/patterns/read/en.md
Normal file
|
@ -0,0 +1,109 @@
|
|||
---
|
||||
title: Read a Pattern
|
||||
---
|
||||
|
||||
Reads an existing Pattern.
|
||||
|
||||
## Access control
|
||||
|
||||
The [Permission level](/reference/backend/api/rbac) required to read a
|
||||
Pattern depends on:
|
||||
|
||||
- Whether the Pattern is `public`
|
||||
- Who created the Pattern
|
||||
|
||||
The details are outlined in the table below:
|
||||
|
||||
| | Public Patterns | Non-Public Patterns |
|
||||
| ---------------: | :-------------: | :-----------------: |
|
||||
| **Your own** | `0` or higher | `4` or higher |
|
||||
| **Other user's** | `0` or higher | `5` or higher |
|
||||
|
||||
## Endpoints
|
||||
|
||||
Reading a Pattern is possible via these endpoints:
|
||||
|
||||
| Method | Path | Authentication |
|
||||
| --------: | :--- | :------------- |
|
||||
| <Method get /> | `/patterns/:id/jwt` | [JSON Web Token](/reference/backend/api/authentication#jwt-authentication) |
|
||||
| <Method get /> | `/patterns/:id/key` | [API Key & Secret](/reference/backend/api/authentication#key-authentication) |
|
||||
|
||||
## Request url
|
||||
|
||||
The url should contain the ID of the Pattern you wish to read.
|
||||
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
|
||||
|
||||
## Response status codes
|
||||
|
||||
Possible status codes for these endpoints are:
|
||||
|
||||
| Status code | Description |
|
||||
| ----------: | :---------- |
|
||||
| <StatusCode status="200"/> | success |
|
||||
| <StatusCode status="400"/> | the request was malformed |
|
||||
| <StatusCode status="401"/> | the request lacks authentication |
|
||||
| <StatusCode status="403"/> | authentication failed |
|
||||
| <StatusCode status="404"/> | API key not found |
|
||||
| <StatusCode status="500"/> | server error |
|
||||
|
||||
<Note>
|
||||
If the status code is not <StatusCode status="200" /> the `error` property
|
||||
in the response body should indicate the nature of the problem.
|
||||
</Note>
|
||||
|
||||
## Response body
|
||||
|
||||
| Value | Type | Description |
|
||||
| ------------------- | -------- | ----------- |
|
||||
| `result` | String | Either `success` or `error` |
|
||||
| `error` | String | Will give info on the nature of the error. Only set if an error occured. |
|
||||
| `pattern.id` | Number | The ID of the Pattern |
|
||||
| `pattern.createdAt` | String | Date string indicating the moment the pattern was created |
|
||||
| `pattern.data` | Object | Any additional data that was stored with Pattern data |
|
||||
| `pattern.design` | String | The name of the design of which this Pattern is an instance |
|
||||
| `pattern.img` | String | The URL to the image stored with this Pattern |
|
||||
| `pattern.name` | String | The name of the Pattern |
|
||||
| `pattern.notes` | String | The notes stored with the Pattern |
|
||||
| `pattern.personId` | Number | The ID of the Person for whom the Pattern was created |
|
||||
| `pattern.public` | Boolean| Indicates whether the Pattern is publicly accessible or not |
|
||||
| `pattern.settings` | Object | The settings used to (re-)create the Pattern |
|
||||
| `pattern.userId` | Number | The ID of the user who created the Pattern |
|
||||
| `pattern.updatedAt` | String | Date string indicating the last time the pattern was updated |
|
||||
|
||||
## Example request
|
||||
|
||||
```js
|
||||
const pattern = await axios.get(
|
||||
'https://backend.freesewing.org/patterns/10/jwt',
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Example response
|
||||
```200.json
|
||||
{
|
||||
"result": "success",
|
||||
"pattern": {
|
||||
"id": 10,
|
||||
"createdAt": "2022-11-19T16:29:33.346Z",
|
||||
"data": {
|
||||
"some": "value"
|
||||
},
|
||||
"design": "aaron",
|
||||
"img": "https://cdn.sanity.io/images/hl5bw8cj/production/a1565c8c6c70cfe7ea0fdf5c65501cd885adbe78-200x187.png",
|
||||
"name": "Just a test",
|
||||
"notes": "These are my notes",
|
||||
"personId": 17,
|
||||
"public": true,
|
||||
"settings": {
|
||||
"sa": 5
|
||||
},
|
||||
"userId": 10,
|
||||
"updatedAt": "2022-11-19T16:29:35.023Z"
|
||||
}
|
||||
}
|
||||
```
|
119
markdown/dev/reference/backend/api/patterns/update/en.md
Normal file
119
markdown/dev/reference/backend/api/patterns/update/en.md
Normal file
|
@ -0,0 +1,119 @@
|
|||
---
|
||||
title: Update a Pattern
|
||||
---
|
||||
|
||||
Updates an existing Pattern.
|
||||
This is typically used when users choose to save/overwrite a pattern.
|
||||
|
||||
## Access control
|
||||
|
||||
- [Permission level](/reference/backend/api/rbac) `4` or higher is required to update a Pattern
|
||||
- [Permission level](/reference/backend/api/rbac) `8` is required to update **another user's** Pattern
|
||||
|
||||
## Endpoints
|
||||
|
||||
Updating an existing Pattern is possible via these endpoints:
|
||||
|
||||
| Method | Path | Authentication |
|
||||
| --------: | :--- | :------------- |
|
||||
| <Method put /> | `/patterns/:id/jwt` | [JSON Web Token](/reference/backend/api/authentication#jwt-authentication) |
|
||||
| <Method put /> | `/patterns/:id/key` | [API Key & Secret](/reference/backend/api/authentication#key-authentication) |
|
||||
|
||||
## Request url
|
||||
|
||||
The url should contain the ID of the Pattern you wish to remove.
|
||||
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
|
||||
|
||||
## Request body
|
||||
|
||||
| Property | Type | Description |
|
||||
| ----------: | :------- | :---------- |
|
||||
| `data` | `object` | Any additional data to store with the pattern |
|
||||
| `design` | `string` | The name of the design this Pattern is an instance of |
|
||||
| `img` | `object` | An image [data-uri][duri] to store with this Pattern |
|
||||
| `name` | `string` | A name for the Pattern |
|
||||
| `notes` | `string` | User notes for the pattern |
|
||||
| `person` | `object` | The ID of the person to associate with this pattern |
|
||||
| `settings` | `object` | The settings object to (re-)create the Pattern |
|
||||
|
||||
## Response status codes
|
||||
|
||||
Possible status codes for these endpoints are:
|
||||
|
||||
| Status code | Description |
|
||||
| ----------: | :---------- |
|
||||
| <StatusCode status="200"/> | success |
|
||||
| <StatusCode status="400"/> | the request was malformed |
|
||||
| <StatusCode status="401"/> | the request lacks authentication |
|
||||
| <StatusCode status="403"/> | authentication failed |
|
||||
| <StatusCode status="500"/> | server error |
|
||||
|
||||
<Note>
|
||||
If the status code is not <StatusCode status="200" /> the `error` property
|
||||
in the response body should indicate the nature of the problem.
|
||||
</Note>
|
||||
|
||||
## Response body
|
||||
|
||||
| Value | Type | Description |
|
||||
| ------------------- | -------- | ----------- |
|
||||
| `result` | String | Either `success` or `error` |
|
||||
| `error` | String | Will give info on the nature of the error. Only set if an error occured. |
|
||||
| `pattern.id` | Number | The ID of the Pattern |
|
||||
| `pattern.createdAt` | String | Date string indicating the moment the pattern was created |
|
||||
| `pattern.data` | Object | Any additional data that was stored with Pattern data |
|
||||
| `pattern.design` | String | The name of the design of which this Pattern is an instance |
|
||||
| `pattern.img` | String | The URL to the image stored with this Pattern |
|
||||
| `pattern.name` | String | The name of the Pattern |
|
||||
| `pattern.notes` | String | The notes stored with the Pattern |
|
||||
| `pattern.personId` | Number | The ID of the Person for whom the Pattern was created |
|
||||
| `pattern.public` | Boolean| Indicates whether the Pattern is publicly accessible or not |
|
||||
| `pattern.settings` | Object | The settings used to (re-)create the Pattern |
|
||||
| `pattern.userId` | Number | The ID of the user who created the Pattern |
|
||||
| `pattern.updatedAt` | String | Date string indicating the last time the pattern was updated |
|
||||
|
||||
## Example request
|
||||
|
||||
```js
|
||||
const udpate = await axios.put(
|
||||
'https://backend.freesewing.org/patterns/10/jwt',
|
||||
{
|
||||
data: {
|
||||
some: 'new value',
|
||||
}
|
||||
public: false,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Example response
|
||||
```200.json
|
||||
{
|
||||
"result": "success",
|
||||
"pattern": {
|
||||
"id": 10,
|
||||
"createdAt": "2022-11-19T16:29:33.346Z",
|
||||
"data": {
|
||||
"some": "new value"
|
||||
},
|
||||
"design": "aaron",
|
||||
"img": "https://cdn.sanity.io/images/hl5bw8cj/production/a1565c8c6c70cfe7ea0fdf5c65501cd885adbe78-200x187.png",
|
||||
"name": "Just a test",
|
||||
"notes": "These are my notes",
|
||||
"personId": 17,
|
||||
"public": false,
|
||||
"settings": {
|
||||
"sa": 5
|
||||
},
|
||||
"userId": 10,
|
||||
"updatedAt": "2022-11-19T16:43:39.223Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[duri]: https://en.wikipedia.org/wiki/Data_URI_scheme
|
42
markdown/dev/reference/backend/api/rbac/en.md
Normal file
42
markdown/dev/reference/backend/api/rbac/en.md
Normal file
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
title: Access control
|
||||
---
|
||||
|
||||
The backend API implements role-based access control (RBAC). Each
|
||||
user has a role and that role determines what they can and cannot do.
|
||||
|
||||
## Roles vs levels
|
||||
|
||||
In practice, the different user roles map to a permission level between
|
||||
`0` and `8`.
|
||||
The available roles and their privilege levels are:
|
||||
|
||||
- **user**: `4`
|
||||
- **bughunter**: `5`
|
||||
- **support**: `6`
|
||||
- **admin**: `8`
|
||||
|
||||
We offer more fine-grained control over the permission level when
|
||||
authenticating with API keys. When you create an API key, you can choose any
|
||||
permissing level that is equal or lower than your own role's permission level.
|
||||
|
||||
This allows you to -- for example -- generate an API key that only have read
|
||||
access to your data.
|
||||
|
||||
## Permission levels
|
||||
|
||||
The table below lists the priviledge of all levels as well as their
|
||||
corresponding <small><small><b>`role`</b></small></small>
|
||||
|
||||
| Level | Abilities | <small><small>`user`</small></small> | <small><small>`bughunter`</small></small> | <small><small>`support`</small></small> | <small><small>`admin`</small></small> |
|
||||
| --: | -- | :--: | :--: | :--: | :--: |
|
||||
| `0` | authenticate | ✅ | ✅ | ✅ | ✅ |
|
||||
| `1` | **read** measurements and patterns | ✅ | ✅ | ✅ | ✅ |
|
||||
| `2` | **read all** account data | ✅ | ✅ | ✅ | ✅ |
|
||||
| `3` | **write** measurements or patterns | ✅ | ✅ | ✅ | ✅ |
|
||||
| `4` | **write all** account data | ✅ | ✅ | ✅ | ✅ |
|
||||
| `5` | **read** measurements or patterns of **other users** | ❌ | ✅ | ✅ | ✅ |
|
||||
| `6` | **read all** account data of **other users** | ❌ | ❌ | ✅ | ✅ |
|
||||
| `7` | **write** account data of **other users** through **specific support methods** | ❌ | ❌ | ✅ | ✅ |
|
||||
| `8` | impersonate other users, **full write access** | ❌ | ❌ | ❌ | ✅ |
|
||||
|
167
markdown/dev/reference/backend/db/en.md
Normal file
167
markdown/dev/reference/backend/db/en.md
Normal file
|
@ -0,0 +1,167 @@
|
|||
---
|
||||
title: Database schema
|
||||
---
|
||||
|
||||
The database schema for the backend is available in the [prisma.schema][prisma]
|
||||
file in our monorepo. For your convenience, we're replicated the info below.
|
||||
|
||||
<Note>
|
||||
In the tables below, the following symbols are used:
|
||||
|
||||
- 🔑 : Field holds the primary key
|
||||
- 🗝️ : Field holds a foreign key
|
||||
- ❄️ : Field must be unique
|
||||
- ⚡ : Field is indexed
|
||||
- 🔐 : Field is encrypted
|
||||
- 🧂 : Field is salted & hashed
|
||||
|
||||
</Note>
|
||||
|
||||
## Table Apikey
|
||||
|
||||
| | Field | Type | Default |
|
||||
| -: | :---------- | :------- | :------ |
|
||||
| | `createdAt` | DateTime | `now()` |
|
||||
| | `expiresAt` | DateTime | |
|
||||
| 🔑 | `id` | String (UUID) | `uuid()` |
|
||||
| | `level` | Int | `0` |
|
||||
| | `name` | String | |
|
||||
| 🧂 | `secret` | String(ified JSON) | |
|
||||
| 🗝️ | `userId` | Int | |
|
||||
|
||||
```json
|
||||
{
|
||||
"createdAt": 1668448465659,
|
||||
"expiresAt": 1668448525632,
|
||||
"id": "5122738c-2e44-4165-a9db-2f0b6ba4fbaf",
|
||||
"level": 4,
|
||||
"name": "Test API key",
|
||||
"secret": "{\"type\":\"v3\",\"hash\":\"a88747549512991836332813ccc82abba652bf5835dfa0a5a8177e2ddacf1f2d0f6340a6c36c0e816cf7a9976847bb14010c658703d4fa1bc4a0f3bdf3f187c2\",\"salt\":\"9eba4d132010a534a54d76fa9a6083eb\"}",
|
||||
"userId": 10
|
||||
}
|
||||
```
|
||||
|
||||
## Table Confirmation
|
||||
|
||||
| | Field | Type | Default |
|
||||
| -: | :---------- | :------- | :------ |
|
||||
| | `createdAt` | DateTime | `now()` |
|
||||
| 🔐 | `data` | String(ified JSON) | |
|
||||
| 🔑 | `id` | String (UUID) | `uuid()` |
|
||||
| | `type` | String | |
|
||||
| 🗝️ | `userId` | Int | |
|
||||
|
||||
```json
|
||||
{
|
||||
"createdAt": 1668447926731,
|
||||
"data": "{\"iv\":\"01a57e75817327cc99b08c5fabdf4c89\",\"ct\":\"03b89a100a67dd85898a313fd832c720700f4b3a800aa715a6bbbe66a4f2ab01f02215e995b0983b609ef8606912546fb27b63ea5436c5bbacd73cb9363024e8339d5f25899c3a7172b66991aed3e9a6c8dda850bea0d40c84f630f0f9f76b80052810639ee6f62a97ac9e45cab3c05abd768ff6ca22b8b4255993dc76023c948f80ee208e6455c28097402f63fe26afeab8d082e12bef760320ce3a5d2ea123\"}",
|
||||
"id": "2319e09e-ffe0-4781-9add-46d73a57bb34",
|
||||
"type": "signup",
|
||||
"userId": 9
|
||||
}
|
||||
```
|
||||
|
||||
## Table Subscriber
|
||||
|
||||
| | Field | Type | Default |
|
||||
| -: | :---------- | :------- | :------ |
|
||||
| | `createdAt` | DateTime | `now()` |
|
||||
| 🔐 | `data` | String(ified JSON) | |
|
||||
| ❄️ | `ehash` | String | |
|
||||
| 🔐 | `email` | String(ified JSON) | |
|
||||
| 🔑 | `id` | String (UUID) | `uuid()` |
|
||||
| | `updatedAt` | DateTime | |
|
||||
|
||||
<Fixme>Include example</Fixme>
|
||||
|
||||
## Table User
|
||||
|
||||
| | Field | Type | Default |
|
||||
| -: | :---------- | :------- | :------ |
|
||||
| 🔐 | `bio` | String(ified JSON) | |
|
||||
| | `consent` | Int | |
|
||||
| | `control` | Int | |
|
||||
| | `createdAt` | DateTime | `now()` |
|
||||
| ❄️ | `ehash` | String | |
|
||||
| 🔐 | `email` | String(ified JSON) | |
|
||||
| 🔐 | `github` | String(ified JSON) | |
|
||||
| 🔑 | `id` | Int | |
|
||||
| ⚡ | `ihash` | String | |
|
||||
| 🔐 | `img` | String(ified JSON) | |
|
||||
| | `imperial` | Boolean | `false` |
|
||||
| 🔐 | `initial` | String(ified JSON) | |
|
||||
| | `language` | String | `en` |
|
||||
| | `lastLogin` | DateTime | |
|
||||
| ❄️ | `lusername` | String | |
|
||||
| | `newsletter`| Boolean | `false` |
|
||||
| 🧂 | `password` | String(ified JSON) | |
|
||||
| | `patron` | Int | `0` |
|
||||
| | `role` | String | `user` |
|
||||
| | `status` | Int | `0` |
|
||||
| | `updatedAt` | DateTime | |
|
||||
| | `username` | String | |
|
||||
|
||||
```json
|
||||
{
|
||||
"bio": "{\"iv\":\"92bc05493831ccd92c522a7c1395058d\",\"ct\":\"5a520bf84a1e194c87e294f1e28c6100\"}",
|
||||
"consent": 1,
|
||||
"control": 1,
|
||||
"createdAt": 1668447881259,
|
||||
"ehash": "57c20ec1135355d378145a994bc26ce1f1720e382474116cafbd5f4c3fb676c3",
|
||||
"email": "{\"iv\":\"b48d8e4769e359cec69f53629c5ad4ce\",\"ct\":\"57211cdeb0c1d5641aae953b10058e8ad94604df8183a3f5c99517620858674696e1e988ccf8e527f132095c2f303a12\"}",
|
||||
"github": "{\"iv\":\"42ab19245da9a4d35d5b5ea66c5897a9\",\"ct\":\"7b3b39bf1811e46e887d81222e99251d\"}",
|
||||
"id": 7,
|
||||
"ihash": "57c20ec1135355d378145a994bc26ce1f1720e382474116cafbd5f4c3fb676c3",
|
||||
"img": "{\"iv\":\"2757b3674a4adb71a535d5d37e923469\",\"ct\":\"e80750ff6bfa7f8c1694558a73673c8714948d67425c5cf01848be8decd612ef8d3129b34c4140f665a5ad7919f32616\"}",
|
||||
"imperial": 0,
|
||||
"initial": "{\"iv\":\"b48d8e4769e359cec69f53629c5ad4ce\",\"ct\":\"57211cdeb0c1d5641aae953b10058e8ad94604df8183a3f5c99517620858674696e1e988ccf8e527f132095c2f303a12\"}",
|
||||
"language": "en",
|
||||
"lastLogin": 1668447881273,
|
||||
"lusername": "user-7",
|
||||
"newsletter": 0,
|
||||
"password": "{\"type\":\"v3\",\"hash\":\"bc5b64b1932a5d4a053777011a61a244e07edfe78eaa52beb56d08bf0ec3f8d8946e8749c872db5a03d5720e53b8da1d6df3ee12d96443d107c01dd2392e2848\",\"salt\":\"648d1218a93ded40ad42cc5bed603bcf\"}",
|
||||
"patron": 0,
|
||||
"role": "user",
|
||||
"status": 1,
|
||||
"updatedAt": 1668447881274,
|
||||
"username": "user-7"
|
||||
}
|
||||
```
|
||||
|
||||
## Table Pattern
|
||||
|
||||
| | Field | Type | Default |
|
||||
| -: | :---------- | :------- | :------ |
|
||||
| 🔑 | `id` | Int | |
|
||||
| | `createdAt` | DateTime | `now()` |
|
||||
| 🔐 | `data` | String(ified JSON) | |
|
||||
| | `design` | String | |
|
||||
| 🔐 | `img` | String(ified JSON) | |
|
||||
| 🔐 | `name` | String(ified JSON) | |
|
||||
| 🔐 | `notes` | String(ified JSON) | |
|
||||
| 🗝️ | `personId` | Int | |
|
||||
| | `public` | Boolean | `false` |
|
||||
| 🔐 | `settings` | String(ified JSON) | |
|
||||
| 🗝️ | `userId` | Int | |
|
||||
| | `updatedAt` | DateTime | |
|
||||
|
||||
<Fixme>Include example</Fixme>
|
||||
|
||||
## Table Person
|
||||
|
||||
| | Field | Type | Default |
|
||||
| -: | :---------- | :------- | :------ |
|
||||
| 🔑 | `id` | Int | |
|
||||
| | `createdAt` | DateTime | `now()` |
|
||||
| 🔐 | `img` | String(ified JSON) | |
|
||||
| | `imperial` | Boolean | `false` |
|
||||
| 🔐 | `measies` | String(ified JSON) | |
|
||||
| 🔐 | `name` | String(ified JSON) | |
|
||||
| 🔐 | `notes` | String(ified JSON) | |
|
||||
| 🗝️ | `userId` | Int | |
|
||||
| | `public` | Boolean | `false` |
|
||||
| | `updatedAt` | DateTime | |
|
||||
|
||||
<Fixme>Include example</Fixme>
|
||||
|
||||
[prisma]: https://github.com/freesewing/freesewing/blob/develop/sites/backend/prisma/schema.prisma
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: FreeSewing backend
|
||||
title: FreeSewing Backend
|
||||
---
|
||||
|
||||
The FreeSewing backend handles all user data. Prior to version 3 of FreeSewing,
|
||||
|
@ -14,37 +14,14 @@ environments and so on.
|
|||
In other words, we no longer merely provide our own frontend, you can now also
|
||||
use our backend as a service to build your own projects.
|
||||
|
||||
## Changes for developers
|
||||
## Under the hood
|
||||
|
||||
We've made a number of changes to make it easier for external developers and
|
||||
contributors to work with our backend.
|
||||
|
||||
### Authentication with JWT and API keys
|
||||
|
||||
Before version 3, the backend only supported authentication via JSON Web
|
||||
Tokens. That's fine for a browser session, but not very handy if you want to
|
||||
talk to the API directly.
|
||||
|
||||
Since version 3, we support authentication with API keys. Furthermore, we
|
||||
allow any FreeSewing user to generate their own API keys.
|
||||
|
||||
In other words, if you want to connect to our backend API, you don't need to
|
||||
ask us. You can generate your own API key and start right away.
|
||||
|
||||
### Sqlite instead of MongoDB
|
||||
|
||||
Our backend used to use MongoDB for storage. Since version 3, we've moved to
|
||||
Sqlite which is a file-based database making local development a breeze since
|
||||
you don't need to run a local database server.
|
||||
|
||||
### Sanity instead of local storage
|
||||
|
||||
We now use Sanity and the Sanity API to stored images for users (avatars for
|
||||
user accounts and people). Furthermore, we also generate PDFs in the browser
|
||||
now so we also don't need storage for that.
|
||||
|
||||
As a result, our backend does not need any storage, only access to the Sqlite
|
||||
file. This also makes it easier to work with the backend as a developer.
|
||||
The FreeSewing backend is written in [NodeJS](https://nodejs.org/en/) on top of
|
||||
[Express](https://expressjs.com/). It uses [Prisma](https://www.prisma.io/) to
|
||||
interface with a [Sqlite database](https://www.sqlite.org/) database,
|
||||
[Sanity](https://www.sanity.io/) to store images, [AWS SES](
|
||||
https://aws.amazon.com/ses/) to send out emails, and
|
||||
[pino](https://github.com/pinojs/pino) for logging.
|
||||
|
||||
## Use, don't abuse
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue