mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
feat(setup): add a setup token for first-run setup (#3437)
This commit is contained in:
1 parent
8e39380ee6
commit
78272521bb
135 files changed
+3045
-771
No files matched your search
@@ -572,6 +572,7 @@ Registration verifies a [CAPTCHA](/topics/captcha/). It permits 3 attempts per h
|
||||
| invite_code? | ?string | The invite accepted immediately after registration (0-256 characters) |
|
||||
| registration_url_code?<sup>6</sup> | ?string | The administrator-issued registration URL code (1-256 characters) |
|
||||
| theme? | string | The initial theme preference, one of `dark`, `dark_legacy`, `coal`, `light`, or `system` |
|
||||
| setup_token?<sup>7</sup> | ?string | The setup token of a new self-hosted instance (1-256 characters) |
|
||||
|
||||
<sup>1</sup> Omitting the email address creates an unclaimed account, which has no recovery path until it is claimed. An address whose domain has no usable DNS records, or whose top-level domain the instance blocks, returns the field code `INVALID_EMAIL_ADDRESS`, and an address already in use returns `EMAIL_ALREADY_IN_USE`. A `username` instance accepts any string of 1-320 characters here, because older apps send one, and discards it. It stores no address and sends no email. It does not check the address against DNS or the blocklists, or whether another account uses it
|
||||
|
||||
@@ -585,10 +586,14 @@ Registration verifies a [CAPTCHA](/topics/captcha/). It permits 3 attempts per h
|
||||
|
||||
<sup>6</sup> A code supplied on an instance with administrator registration URLs disabled, and a code that does not resolve, both return 400 `REGISTRATION_URL_INVALID`. A valid code overrides the closed registration mode and replaces the instance approval mode with its own approval setting
|
||||
|
||||
<sup>7</sup> Required while a self-hosted instance is unconfigured and has no admin account, where an absent or blank value returns the field code `SETUP_TOKEN_REQUIRED`. Accepted until the first admin account exists, and a wrong value returns the field code `SETUP_TOKEN_INVALID`. Ignored afterwards, on a hosted instance, and on a self-hosted instance that does not [enforce the token](/operator/configuration/#setup-token). Surrounding whitespace is trimmed
|
||||
|
||||
Fluxer resolves the region from the client IP address, and an age below the minimum for that region returns the field code `MUST_BE_MINIMUM_AGE`. That minimum is 13 years unless the region sets a different minimum, and the applied minimum appears only in the localised message.
|
||||
|
||||
Registration returns 403 `REGISTRATION_CLOSED` when the instance is closed and no valid registration URL was supplied. A username whose discriminator space is exhausted returns the field code `TOO_MANY_USERS_WITH_THIS_USERNAME`. A username or display name containing a blocked substring returns 403 `CONTENT_BLOCKED`.
|
||||
|
||||
After the route rate limit, the CAPTCHA and schema validation, the setup token is checked before every other registration rule. A registration that presents the correct token is admitted whatever the registration mode is, is exempt from the registration allowances above, and receives the wildcard [Admin ACL](/admin-api/#acl-registry) when it creates a claimed account, which needs `email` on an `email` instance and `password` on a `username` instance. A client IP address is permitted 10 wrong tokens per 30 minutes, and further requests that present a token from that address return 429 until the window passes, the correct token included. A request with no token does not count.
|
||||
|
||||
:::caution[Registration reports an address already in use]
|
||||
[Log in with a password](#log-in-with-a-password) and [request password recovery](#request-password-recovery) are enumeration-safe and registration is not. An address that already holds an account returns the field code `EMAIL_ALREADY_IN_USE`, so an unauthenticated caller learns from the response whether that address is registered.
|
||||
:::
|
||||
@@ -602,10 +607,10 @@ There is no retry key. A repeated request with the same values creates a second
|
||||
| Status | Body | Condition |
|
||||
| --- | --- | --- |
|
||||
| 200 | [authentication token response](#authentication-token-response) \| [registration pending approval response](#registration-pending-approval-response-object) | Registration completed or entered the approval state |
|
||||
| 400 | [error response](/http-api/#error-response) | The body, CAPTCHA, account fields, or registration URL code is invalid |
|
||||
| 400 | [error response](/http-api/#error-response) | The body, CAPTCHA, account fields, registration URL code, or setup token is invalid |
|
||||
| 403 | [error response](/http-api/#error-response) | SSO enforcement, registration policy, or content moderation rejects the registration |
|
||||
| 423 | [error response](/http-api/#error-response) | `GENERAL_ERROR`, because a self-hosted instance with no account yet is still settling its [sign-in method](/http-api/instance/#set-the-setup-sign-in-method) after 15 seconds |
|
||||
| 429 | [rate limit response](/topics/rate-limits/#rate-limit-response-object) | A route, global, email, IP, or subnet bucket denies the request |
|
||||
| 429 | [rate limit response](/topics/rate-limits/#rate-limit-response-object) | A route, global, email, IP, or subnet bucket denies the request, or the address has used its wrong setup token allowance |
|
||||
| 500 | [error response](/http-api/#error-response) | Unexpected internal failure occurs |
|
||||
| 503 | [error response](/http-api/#error-response) | The instance is at its in-flight request ceiling |
|
||||
|
||||
|
||||
@@ -2003,6 +2003,14 @@ Referenced attachment "{filename}" wasn't found in message attachments
|
||||
|
||||
Session timed out
|
||||
|
||||
### `SETUP_TOKEN_INVALID`
|
||||
|
||||
That setup token is not correct. Check the token and try again.
|
||||
|
||||
### `SETUP_TOKEN_REQUIRED`
|
||||
|
||||
This instance is not set up yet. Finish setup in a web browser with the setup token before creating accounts.
|
||||
|
||||
### `SNOWFLAKE_OUT_OF_RANGE`
|
||||
|
||||
Invalid snowflake
|
||||
|
||||
@@ -6,7 +6,7 @@ description: Guild member objects, profiles, voice moderation, ownership, remova
|
||||
|
||||
import RouteHeader from '@/components/RouteHeader.astro';
|
||||
|
||||
A guild member is an account that has joined a guild. The membership has a nickname, avatar, role set, and moderation state that apply in that guild alone. Indexed member queries live on [Guild member search](/http-api/guild-member-search/), and bans on [Guild moderation](/http-api/guild-moderation/).
|
||||
A guild member is an account that has joined a guild. The membership has a nickname, avatar, role set, and moderation state that apply in that guild alone. Indexed member queries are on [Guild member search](/http-api/guild-member-search/), and bans on [Guild moderation](/http-api/guild-moderation/).
|
||||
|
||||
An unknown guild returns 404 `UNKNOWN_GUILD`, a non-member receives 403 `MISSING_PERMISSIONS`, and a guild marked unavailable returns 403 `MISSING_ACCESS`. [Transfer guild ownership](#transfer-guild-ownership) also returns 403 `ACCESS_DENIED` when the guild exists in storage but the Gateway reports it as not found.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ description: Guild objects, creation templates, configuration registries, and li
|
||||
|
||||
import RouteHeader from '@/components/RouteHeader.astro';
|
||||
|
||||
A guild is a community with its own channels, roles, members, and configuration. Membership and ownership transfer live on [Guild members](/http-api/guild-members/), and channels on [Guild channels](/http-api/guild-channels/).
|
||||
A guild is a community with its own channels, roles, members, and configuration. Membership and ownership transfer are on [Guild members](/http-api/guild-members/), and channels on [Guild channels](/http-api/guild-channels/).
|
||||
|
||||
[List current user guilds](#list-current-user-guilds) and [Get guild](#get-guild) declare the `guilds` [OAuth2 scope](/http-api/oauth2/#oauth2-scopes), and a bearer credential without that scope receives 403 `MISSING_OAUTH_SCOPE`. Every other route rejects a bearer credential with 403 `ACCESS_DENIED`.
|
||||
|
||||
|
||||
@@ -444,11 +444,14 @@ Whether the deployment has finished its initial configuration, and where an oper
|
||||
| configured | boolean | Whether initial deployment configuration is complete |
|
||||
| admin_url<sup>1</sup> | ?string | The admin application URL used to continue setup, or null |
|
||||
| account_identity_locked? | boolean | Whether the sign-in method can no longer change, sent only while a self-hosted deployment is not configured |
|
||||
| setup_token_required? | boolean | Whether registration needs the setup token, sent only while a self-hosted deployment is not configured |
|
||||
|
||||
<sup>1</sup> The value is the deployment's configured admin endpoint, and it is null when no admin endpoint is configured
|
||||
|
||||
`account_identity_locked` is true once the first account exists, and on a deployment stored as already in use. [Set the setup sign-in method](#set-the-setup-sign-in-method) returns 409 there.
|
||||
|
||||
`setup_token_required` is true while [Register an account](/http-api/authentication/#register-an-account) refuses a body without `setup_token`. It is false once the first admin account exists, and on a deployment that does not enforce the token.
|
||||
|
||||
## Public legal configuration object
|
||||
|
||||
The public document URLs a client links from its registration form and its report flows.
|
||||
@@ -615,8 +618,8 @@ Chooses how members sign in on a new self-hosted deployment, and on an `email` d
|
||||
|
||||
The setup wizard calls this before the owner account exists. The choice stays open on a self-hosted deployment until setup is complete or the first account exists. After that, on a deployment that was already in use before username sign-in existed, and on every hosted deployment, the route returns 409 `ACCOUNT_IDENTITY_LOCKED`. The choice and the first registration take turns, so a choice never lands after the first account exists. A repeated call while the choice is open replaces the earlier one.
|
||||
|
||||
:::caution[Anyone can call this before the first account exists]
|
||||
The route needs no credential, the same as the rule that makes the first registration the instance admin. An operator finishes setup in the same sitting that brings the deployment up.
|
||||
:::caution[The setup token stands in for a credential]
|
||||
The route needs no credential. While `setup_token_required` is true in the [public setup state](#public-setup-state-object), a call without the correct `setup_token` is refused.
|
||||
:::
|
||||
|
||||
### JSON body
|
||||
@@ -625,18 +628,21 @@ The route needs no credential, the same as the rule that makes the first registr
|
||||
| --- | --- | --- |
|
||||
| mode | string | The [account identity mode](#account-identity-modes) to use |
|
||||
| tag_style?<sup>1</sup> | string | How usernames are tagged, one of the [tag styles](#tag-styles). Defaults to `none` |
|
||||
| setup_token?<sup>2</sup> | ?string | The setup token of the deployment (1-256 characters) |
|
||||
|
||||
<sup>1</sup> A `username` instance always uses `none`. Sending `random` with `username` returns the field code `TAG_STYLE_REQUIRES_EMAIL_SIGN_IN` on `tag_style`
|
||||
|
||||
<sup>2</sup> Checked the way [Register an account](/http-api/authentication/#register-an-account) checks it, with the same field codes and the same allowance for wrong tokens
|
||||
|
||||
### Response
|
||||
|
||||
| Status | Body | Condition |
|
||||
| --- | --- | --- |
|
||||
| 200 | [account identity](#account-identity-object) object | The mode was stored |
|
||||
| 400 | [error response](/http-api/#error-response) | The body is invalid, or `random` tags were requested with `username` |
|
||||
| 400 | [error response](/http-api/#error-response) | The body is invalid, `random` tags were requested with `username`, or the setup token is missing or wrong |
|
||||
| 409 | [error response](/http-api/#error-response) | `ACCOUNT_IDENTITY_LOCKED`, because the sign-in method can no longer change |
|
||||
| 423 | [error response](/http-api/#error-response) | `GENERAL_ERROR`, because a registration or another choice held the turn for more than 15 seconds |
|
||||
| 429 | [rate limit response](/topics/rate-limits/#rate-limit-response-object) | Route or global bucket denies the request |
|
||||
| 429 | [rate limit response](/topics/rate-limits/#rate-limit-response-object) | Route or global bucket denies the request, or the address has used its wrong setup token allowance |
|
||||
|
||||
### Side effects
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ description: User objects, public profiles, account tags, and the settings recor
|
||||
|
||||
import RouteHeader from '@/components/RouteHeader.astro';
|
||||
|
||||
A user is a Fluxer account. Another account sees the [partial user object](#partial-user-object), and the owner sees the [user object](#user-object). Account mutation lives on [Current user](/http-api/users/current-user/).
|
||||
A user is a Fluxer account. Another account sees the [partial user object](#partial-user-object), and the owner sees the [user object](#user-object). Account mutation is on [Current user](/http-api/users/current-user/).
|
||||
|
||||
Every route on this page takes a user session token or a bot token. An OAuth2 bearer credential is rejected with 403 `ACCESS_DENIED`.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ description: Recent mentions, saved messages, and deletion of the caller's own m
|
||||
|
||||
import RouteHeader from '@/components/RouteHeader.astro';
|
||||
|
||||
Recent mentions and saved messages are private lists that only the account owning them can read. Further routes delete the messages the caller authored, one filtered and immediate, the other unfiltered and delayed by a day. Data harvests live on [Data harvests](/http-api/users/data-harvest/).
|
||||
Recent mentions and saved messages are private lists that only the account owning them can read. Further routes delete the messages the caller authored, one filtered and immediate, the other unfiltered and delayed by a day. Data harvests are on [Data harvests](/http-api/users/data-harvest/).
|
||||
|
||||
These routes are user-only. Fluxer rejects a bot or OAuth2 bearer credential with 403 `ACCESS_DENIED`.
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ An over-length string draws two entries for the one path.
|
||||
| double_tap_action | int32 | [Double tap action](#double-tap-actions) on a message |
|
||||
| swipe_right_to_left_action | int32 | [Swipe right to left action](#swipe-right-to-left-actions) in a channel |
|
||||
|
||||
<sup>1</sup> The entries live inside the snapshot, and the account [memes](/http-api/memes/) collection holds none of them
|
||||
<sup>1</sup> The entries are inside the snapshot, and the account [memes](/http-api/memes/) collection holds none of them
|
||||
|
||||
<sup>2</sup> The only bare scalar on the root message, so it has no presence and reads as false until a client stores true. It applies to the content a client is about to send, and the first-party client leaves the URLs inside inline code and code blocks unchanged
|
||||
|
||||
|
||||
Reference in new issue
Block a user