diff --git a/markdown/dev/reference/backend/api/users/confirm/en.md b/markdown/dev/reference/backend/api/account/confirm/en.md similarity index 95% rename from markdown/dev/reference/backend/api/users/confirm/en.md rename to markdown/dev/reference/backend/api/account/confirm/en.md index 067995f5f34..cd29e0fbdc1 100644 --- a/markdown/dev/reference/backend/api/users/confirm/en.md +++ b/markdown/dev/reference/backend/api/account/confirm/en.md @@ -1,13 +1,13 @@ --- -title: Confirm a User +title: Confirm an account --- -Confirms a newly created User. +Confirms a newly created User account. If confirmation is successful this will also result in a (passwordless) login. ## Endpoints -Confirming a new User is possible via this endpoint: +Confirming a new User account is possible via this endpoint: | Method | Path | Authentication | | --------: | :--- | :------------- | @@ -18,7 +18,7 @@ Confirming a new User is possible via this endpoint: ## Request url The url should contain the confirmation ID that was E-mailed to the E-mail -address used for the signup. It replaces the `:id` placeholder in the +address used for the signup. It replaces the `:id` placeholder in the [endpoint listed above](#endpoints). ## Request body diff --git a/markdown/dev/reference/backend/api/users/create/en.md b/markdown/dev/reference/backend/api/account/create/en.md similarity index 87% rename from markdown/dev/reference/backend/api/users/create/en.md rename to markdown/dev/reference/backend/api/account/create/en.md index 3ef6291a6f6..6016aeaeb2f 100644 --- a/markdown/dev/reference/backend/api/users/create/en.md +++ b/markdown/dev/reference/backend/api/account/create/en.md @@ -1,13 +1,13 @@ --- -title: Create a User +title: Create an account --- -Creates a new User. The User account will remain inactive -until [it is confirmed](/reference/backend/api/users/confirm). +Creates a new User account. The User account will remain inactive +until [it is confirmed](/reference/backend/api/account/confirm). ## Endpoints -Creating a new User is possible via this endpoint: +Creating a new User account is possible via this endpoint: | Method | Path | Authentication | | --------: | :--- | :------------- | diff --git a/markdown/dev/reference/backend/api/users/en.md b/markdown/dev/reference/backend/api/account/en.md similarity index 92% rename from markdown/dev/reference/backend/api/users/en.md rename to markdown/dev/reference/backend/api/account/en.md index 2c1d523d394..40ff4728e60 100644 --- a/markdown/dev/reference/backend/api/users/en.md +++ b/markdown/dev/reference/backend/api/account/en.md @@ -1,8 +1,12 @@ --- -title: Users +title: Account --- -A User holds the account data for a FreeSewing user. +From an end-user's point of view, their account holds all of their data. From +an API point of view, these endpoints deal with data in the User table. + +As the endpoints typically use `/account` we tend to use _account_ more often +than _user_. ## Endpoints diff --git a/markdown/dev/reference/backend/api/account/login/en.md b/markdown/dev/reference/backend/api/account/login/en.md new file mode 100644 index 00000000000..a5324fb61c9 --- /dev/null +++ b/markdown/dev/reference/backend/api/account/login/en.md @@ -0,0 +1,113 @@ +--- +title: Login +--- + +Login as a User with username and password, and optional MFA token. + +## Endpoints + +Password-based login is possible via this endpoint: + +| Method | Path | Authentication | +| --------: | :--- | :------------- | +| | `/login` | None | + +This endpoint requires no authentication + +## Request body + +| Property | Type | Description | +| ----------: | :------- | :---------- | +| `username` | `string` | The E-mail address of the User | +| `password` | `boolean`| The language code for the User | +| `token` | `boolean`| The MFA token | + +An MFA token is required (only) when the User enabled MFA + +## Response status codes + +Possible status codes for these endpoints are: + +| Status code | Description | +| ----------: | :---------- | +| | success | +| | the request was malformed | +| | authentication failed | +| | MFA token missing | +| | server error | + + +If the status code is not the `error` property +in the response body should indicate the nature of the problem. + + +## 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. | +| `token` | String | A JSON web token (JWT) token to authenticate with | +| `account.id` | Number | The ID of the User | +| `account.bio` | String | The bio of the User | +| `account.consent` | Number | The consent given by the User | +| `account.control` | Number | The control desired by the User | +| `account.createdAt` | String | Date string indicating the moment the User was created | +| `account.email` | String | The E-mail address currently tied to the User | +| `account.github` | String | The Github username of the User | +| `account.img` | String | The URL to the image stored with this User | +| `account.imperial` | Boolean| Whether or not the User prefers imperial units | +| `account.initial` | String | The E-mail address that the User was created with | +| `account.language` | String | The language preferred by the user | +| `account.lastLogin` | String | Date string indicating them moment the User last logged in | +| `account.mfaEnabled`| Boolean| Whether or not the User has MFA enabled | +| `account.newsletter`| Boolean| Whether or not the User is subscribed to the FreeSewing newsletter | +| `account.patron` | Number | The level of patronage the user provides to FreeSewing | +| `account.role` | String | The role of the User | +| `account.status` | Number | The status of the user | +| `account.updatedAt` | String | Date string indicating the last time the User was updated | +| `account.username` | String | The username of the User | +| `account.lusername` | String | A lowercased version of the username of the User | + +## Example request + +```js +const signup = await axios.post( + 'https://backend.freesewing.org/signup', + { + username: "jimmy", + language: "I like big bewbs and I just can't lie", + token: 231586 + } +) +``` + +## Example response +```200.json +{ + "result": "success", + "token": "eyJhbGciOiJIUzI1NiIsInR5c...truncated", + "account": { + "id": 14, + "bio": "", + "consent": 1, + "control": 1, + "createdAt": "2022-11-19T18:15:22.642Z", + "email": "test_54c6856275aaa8a1@freesewing.dev", + "github": "", + "img": "https://freesewing.org/avatar.svg", + "imperial": false, + "initial": "test_54c6856275aaa8a1@freesewing.dev", + "language": "en", + "lastLogin": "2022-11-19T18:15:22.668Z", + "mfaEnabled": false, + "newsletter": false, + "patron": 0, + "role": "user", + "status": 1, + "updatedAt": "2022-11-19T18:15:22.668Z", + "username": "jimmy", + "lusername": "jimmy" + } +} +``` diff --git a/markdown/dev/reference/backend/api/account/mfa/en.md b/markdown/dev/reference/backend/api/account/mfa/en.md new file mode 100644 index 00000000000..a1245131625 --- /dev/null +++ b/markdown/dev/reference/backend/api/account/mfa/en.md @@ -0,0 +1,214 @@ +--- +title: MFA +--- + +Enable of disable Multi-Factor Authentication (MFA) on the User account. + +- [Setup MFA](#setup-mfa) +- [Confirm MFA](#confirm-mfa) +- [Disable MFA](#disable-mfa) + +## Endpoints + +Enabling, confirming, and disabling MFA is all possible via this endpoint: + +| Method | Path | Authentication | +| --------: | :--- | :------------- | +| | `/account/mfa/jwt` | [JSON Web Token](/reference/backend/api/authentication#jwt-authentication) | +| | `/account/mfa/key` | [API Key & Secret](/reference/backend/api/authentication#key-authentication) | + +## Setup MFA + +### Request body + +| Property | Type | Description | +| ----------: | :------- | :---------- | +| `mfa` | `boolean`| Set to `true` to enable MFA | + +### Response status codes + +Possible status codes for this endpoints are: + +| Status code | Description | +| ----------: | :---------- | +| | success | +| | the request was malformed | +| | authentication failed | +| | access denied | +| | server error | + + +If the status code is not the `error` property +in the response body should indicate the nature of the problem. + + +### 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. | +| `mfa.secret` | String | The shared secret for generating one-time password (OTP) tokens | +| `mfa.otpauth` | String | The OTP Auth uri that is encoded in the QR code | +| `mfa.qrcode` | String | SVG to display a QR code with the otpauth uri encoded | + + +##### Styling the SVG +The SVG returned by the backend uses `currentColor` for the QR code, so you can +style it with CSS if you embed it in the page. + + +### Example request + +```js +const mfa = await axios.post( + 'https://backend.freesewing.org/account/mfa/jwt', + { mfa: true }, + { + headers: { + Authorization: `Bearer ${token}` + } + } +) +``` + +### Example response +```200.json +{ + "result": "success", + "mfa": { + "secret": "KBTSKUKRDJPEGCZK", + "otpauth": "otpauth://totp/FreeSewing:user-294?secret=KBTSKUKRDJPEGCZK&period=30&digits=6&algorithm=SHA1&issuer=FreeSewing", + "qrcode": "\n" + } +} +``` + +## Confirm MFA + +To confirm the MFA, we need to provide an MFA token to ensure the user can +generate them. + +### Request body + +| Property | Type | Description | +| ----------: | :------- | :---------- | +| `mfa` | `boolean`| Must be set to `true` to confirm MFA | +| `secret` | `boolean`| The secret returned when setting up MFA | +| `token` | `boolean`| Must be set to `true` to confirm MFA | + +### Response status codes + +Possible status codes for this endpoints are: + +| Status code | Description | +| ----------: | :---------- | +| | success | +| | the request was malformed | +| | authentication failed | +| | access denied | +| | server error | + + +If the status code is not the `error` property +in the response body should indicate the nature of the problem. + + +### 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. | + +### Example request + +```js +import { authenticator } from '@otplib/preset-default' + +const confirm = await axios.post( + 'https://backend.freesewing.org/account/mfa/jwt', + { + mfa: true, + secret: mfa.secret, + token: authenticator.generate(mfa.secret) + }, + { + headers: { + Authorization: `Bearer ${token}` + } + } +) +``` + +### Example response + +```200.json +{ + "result": "success", +} +``` +## Disable MFA + +To disable MFA, you need to provide both the account password and a valid token. + +### Request body + +| Property | Type | Description | +| ----------: | :------- | :---------- | +| `mfa` | `boolean`| Must be set to `false` to disable MFA | +| `password` | `boolean`| The User's password | +| `token` | `boolean`| Must be set to `true` to confirm MFA | + +### Response status codes + +Possible status codes for this endpoints are: + +| Status code | Description | +| ----------: | :---------- | +| | success | +| | the request was malformed | +| | authentication failed | +| | access denied | +| | server error | + + +If the status code is not the `error` property +in the response body should indicate the nature of the problem. + + +### 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. | + +### Example request + +```js +import { authenticator } from '@otplib/preset-default' + +const confirm = await axios.post( + 'https://backend.freesewing.org/account/mfa/jwt', + { + mfa: false, + password: "I like big bewbs and I just can't lie", + token: authenticator.generate(mfa.secret) + }, + { + headers: { + Authorization: `Bearer ${token}` + } + } +) +``` + +### Example response + +```200.json +{ + "result": "success", +} +``` + diff --git a/markdown/dev/reference/backend/api/account/update/en.md b/markdown/dev/reference/backend/api/account/update/en.md new file mode 100644 index 00000000000..de5afd79151 --- /dev/null +++ b/markdown/dev/reference/backend/api/account/update/en.md @@ -0,0 +1,126 @@ +--- +title: Update account +--- + +Updates an existing User account. + +## Access control + +- [Permission level](/reference/backend/api/rbac) `4` or higher is required to update your own User account +- [Permission level](/reference/backend/api/rbac) `8` is required to update **another user's** account + +## Endpoints + +Updating an existing User account is possible via these endpoints: + +| Method | Path | Authentication | +| --------: | :--- | :------------- | +| | `/account/jwt` | [JSON Web Token](/reference/backend/api/authentication#jwt-authentication) | +| | `/account/key` | [API Key & Secret](/reference/backend/api/authentication#key-authentication) | + +## Request body + +| Property | Type | Description | +| ----------: | :------- | :---------- | +| `bio` | `string` | The User's bio | +| `consent` | `string` | A number that indicates [the consent given by the user](/reference/backend/api/account#the-consent-field-is-about-data-protection) | +| `control` | `string` | A number that indicates [the level of control the user prefers](/reference/backend/api/account#the-control-field-is-about-keeping-it-simple) | +| `github` | `string` | The User's username on Github | +| `imperial` | `boolean`| Whether or not the User prefers imperial units | +| `newsletter`| `boolean`| Whether this Person prefers imperial measurements (`true`) or not (`false`) | +| `img` | `string` | An image [data-uri][duri] to store with this Person | +| `password` | `string` | The (new) password for the User | +| `username` | `string` | The (new) username for the User | + +## Response status codes + +Possible status codes for these endpoints are: + +| Status code | Description | +| ----------: | :---------- | +| | success | +| | the request was malformed | +| | the request lacks authentication | +| | authentication failed | +| | server error | + + +If the status code is not the `error` property +in the response body should indicate the nature of the problem. + + +## 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. | +| `account.id` | Number | The ID of the User | +| `account.bio` | String | The bio of the User | +| `account.consent` | Number | The consent given by the User | +| `account.control` | Number | The control desired by the User | +| `account.createdAt` | String | Date string indicating the moment the User was created | +| `account.email` | String | The E-mail address currently tied to the User | +| `account.github` | String | The Github username of the User | +| `account.img` | String | The URL to the image stored with this User | +| `account.imperial` | Boolean| Whether or not the User prefers imperial units | +| `account.initial` | String | The E-mail address that the User was created with | +| `account.language` | String | The language preferred by the user | +| `account.lastLogin` | String | Date string indicating them moment the User last logged in | +| `account.mfaEnabled`| Boolean| Whether or not the User has MFA enabled | +| `account.newsletter`| Boolean| Whether or not the User is subscribed to the FreeSewing newsletter | +| `account.patron` | Number | The level of patronage the user provides to FreeSewing | +| `account.role` | String | The role of the User | +| `account.status` | Number | The status of the user | +| `account.updatedAt` | String | Date string indicating the last time the User was updated | +| `account.username` | String | The username of the User | +| `account.lusername` | String | A lowercased version of the username of the User | + +## Example request + +```js +const udpate = await axios.put( + 'https://backend.freesewing.org/account/jwt', + { + bio: "I like imperial now", + imperial: true, + username: "ImperialLover" + }, + { + headers: { + Authorization: `Bearer ${token}` + } + } +) +``` + +## Example response +```200.json +{ + "result": "success", + "account": { + "id": 14, + "bio": "I like imperial now", + "consent": 1, + "control": 1, + "createdAt": "2022-11-19T18:15:22.642Z", + "email": "test_54c6856275aaa8a1@freesewing.dev", + "github": "", + "img": "https://freesewing.org/avatar.svg", + "imperial": true, + "initial": "test_54c6856275aaa8a1@freesewing.dev", + "language": "en", + "lastLogin": "2022-11-19T18:15:22.668Z", + "mfaEnabled": false, + "newsletter": false, + "patron": 0, + "role": "user", + "status": 1, + "updatedAt": "2022-11-19T18:15:22.668Z", + "username": "ImperialLover", + "lusername": "imperiallover" + } +} +``` + +[duri]: https://en.wikipedia.org/wiki/Data_URI_scheme diff --git a/markdown/dev/reference/backend/api/users/login/en.md b/markdown/dev/reference/backend/api/users/login/en.md deleted file mode 100644 index c3db833cd46..00000000000 --- a/markdown/dev/reference/backend/api/users/login/en.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: User login ---- - -Create docs diff --git a/markdown/dev/reference/backend/api/users/mfa/en.md b/markdown/dev/reference/backend/api/users/mfa/en.md deleted file mode 100644 index 97f32ce9c4b..00000000000 --- a/markdown/dev/reference/backend/api/users/mfa/en.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: MFA ---- - -Create docs diff --git a/markdown/dev/reference/backend/api/users/update/en.md b/markdown/dev/reference/backend/api/users/update/en.md deleted file mode 100644 index d19feb64745..00000000000 --- a/markdown/dev/reference/backend/api/users/update/en.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update a User ---- - -Create docs