diff --git a/.gitignore b/.gitignore
index 389f31ad..18bf8f62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -183,3 +183,8 @@ config/extended_description_test.md
oclif.manifest.json
.direnv/
tsconfig.tsbuildinfo
+
+# Vitepress Docs
+
+*/.vitepress/dist
+*/.vitepress/cache
\ No newline at end of file
diff --git a/api/api/v1/emojis/index.ts b/api/api/v1/emojis/index.ts
index 6098b562..4ca850be 100644
--- a/api/api/v1/emojis/index.ts
+++ b/api/api/v1/emojis/index.ts
@@ -73,8 +73,8 @@ const route = createRoute({
},
},
responses: {
- 200: {
- description: "uploaded emoji",
+ 201: {
+ description: "Uploaded emoji",
content: {
"application/json": {
schema: Emoji.schema,
@@ -173,6 +173,6 @@ export default apiRoute((app) =>
alt,
});
- return context.json(emoji.toApi(), 200);
+ return context.json(emoji.toApi(), 201);
}),
);
diff --git a/benchmarks/timeline.ts b/benchmarks/timeline.ts
index 0639a3a9..a7d9647d 100644
--- a/benchmarks/timeline.ts
+++ b/benchmarks/timeline.ts
@@ -1,7 +1,7 @@
-import type { Status as ApiStatus } from "@versia/client/types";
-import { fakeRequest, getTestStatuses, getTestUsers } from "~/tests/utils";
-import { run, bench } from "mitata";
import { configureLoggers } from "@/loggers";
+import type { Status as ApiStatus } from "@versia/client/types";
+import { bench, run } from "mitata";
+import { fakeRequest, getTestStatuses, getTestUsers } from "~/tests/utils";
await configureLoggers(true);
diff --git a/biome.json b/biome.json
index b783d3c0..4ba5be90 100644
--- a/biome.json
+++ b/biome.json
@@ -91,6 +91,6 @@
"globals": ["Bun", "HTMLRewriter", "BufferEncoding"]
},
"files": {
- "ignore": ["node_modules", "dist"]
+ "ignore": ["node_modules", "dist", "cache"]
}
}
diff --git a/bun.lockb b/bun.lockb
index f4cc5ad0..4069286d 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/classes/database/emoji.ts b/classes/database/emoji.ts
index d37f97fd..55158f2e 100644
--- a/classes/database/emoji.ts
+++ b/classes/database/emoji.ts
@@ -23,6 +23,7 @@ type EmojiWithInstance = InferSelectModel :ms_rainbow_flag: :ms_bisexual_flagweb: :ms_nonbinary_flag: #awoo#admin#bi#nonbinary#games@dzuk
These are the terms of service for this instance.
", +} +``` + +## Get Instance Privacy Policy + +```http +GET /api/v1/instance/privacy_policy +``` + +Returns the instance's Privacy Policy, as configured in the instance settings. + +- **Returns**: [`ExtendedDescription`](https://docs.joinmastodon.org/entities/ExtendedDescription/) +- **Authentication**: Not required +- **Permissions**: None +- **Version History**: + - `0.7.0`: Added. + +### Request + +#### Example + +```http +GET /api/v1/instance/privacy_policy +``` + +### Response + +#### `200 OK` + +Instance's Privacy Policy. + +```json +{ + "updated_at": "2019-11-17T00:00:00.000Z", + "content": "This is the privacy policy for this instance.
", +} +``` ## `/api/v1/instance` -Three extra attributes have been added to the `/api/v1/instance` endpoint: +Extra attributes have been added to the `/api/v1/instance` endpoint. ```ts -{ - // ... +interface SSOProvider { + id: string; + name: string; + icon?: string; +} + +type ExtendedInstance = Instance & { banner: string | null; versia_version: string; sso: { forced: boolean; - providers: { - id: string; - name: string; - icon?: string; - }[]; - } + providers: SSOProvider[]; + }; } ``` ### `banner` -The URL of the instance's banner image. `null` if there is no banner set. +The URL of the instance's banner image. ### `versia_version` -The version of the Versia Server instance. +The version of Versia Server running on the instance. The normal `version` field is always set to `"4.3.0+glitch"` or similar, to not confuse clients that expect a Mastodon instance. @@ -44,29 +312,54 @@ Single Sign-On (SSO) settings for the instance. This object contains two fields: ## `/api/v2/instance` -Contains the same extensions as `/api/v1/instance`, except `banner` which uses the normal Mastodon API attribute. +Extra attributes have been added to the `/api/v2/instance` endpoint. These are identical to the `/api/v1/instance` endpoint, except that the `banner` attribute uses the normal Mastodon API attribute. + +```ts +type ExtendedInstanceV2 = Instance & { + versia_version: string; + sso: { + forced: boolean; + providers: SSOProvider[]; + }; +} +``` + +### `versia_version` + +The version of Versia Server running on the instance. + +The normal `version` field is always set to `"4.3.0+glitch"` or similar, to not confuse clients that expect a Mastodon instance. + +### `sso` + +Single Sign-On (SSO) settings for the instance. This object contains two fields: + +- `forced`: If this is enabled, normal identifier/password login is disabled and login must be done through SSO. +- `providers`: An array of external OpenID Connect providers that users can link their accounts to. Each provider object contains the following fields: + - `id`: The issuer ID of the OpenID Connect provider. + - `name`: The name of the provider. + - `icon`: The URL of the provider's icon. Optional. ## `Account` -(`/api/v1/accounts/:id`, `/api/v1/accounts/verify_credentials`, ...) +Two extra attributes have been added to all returned [`Account`](https://docs.joinmastodon.org/entities/Account/) objects. -Two extra attributes has been adding to all returned account objects: +This object is returned on routes such as `/api/v1/accounts/:id`, `/api/v1/accounts/verify_credentials`, etc. ```ts -{ - // ... - roles: VersiaRoles[]; +type ExtendedAccount = Account & { + roles: Role[]; uri: string; } ``` ### `roles` -An array of roles from [Versia Server Roles](./roles.md). +An array of [`Roles`](./roles.md#role) that the user has. ### `uri` -The URI of the account's Versia object (for federation). Similar to Mastodon's `uri` field on notes. +URI of the account's Versia entity (for federation). Similar to Mastodon's `uri` field on notes. ## `/api/v1/accounts/update_credentials` diff --git a/docs/api/moderation.md b/docs/api/moderation.md deleted file mode 100644 index e4603b5b..00000000 --- a/docs/api/moderation.md +++ /dev/null @@ -1,271 +0,0 @@ -# Moderation API - -> [!WARNING] -> **NOT IMPLEMENTED** - -The Versia Server project uses the Mastodon API to interact with clients. However, the moderation API is custom-made for Versia Server Server, as it allows for more fine-grained control over the server's behavior. - -## Flags, ModTags and ModNotes - -Flags are used by Versia Server Server to automatically attribute tags to a status or account based on rules. ModTags and ModNotes are used by moderators to manually tag and take notes on statuses and accounts. - -The difference between flags and modtags is that flags are automatically attributed by the server, while modtags are manually attributed by moderators. - -### Flag Types - -- `content_filter`: (Statuses only) The status contains content that was filtered by the server's content filter. -- `bio_filter`: (Accounts only) The account's bio contains content that was filtered by the server's content filter. -- `emoji_filter`: The status or account contains an emoji that was filtered by the server's content filter. -- `reported`: The status or account was previously reported by a user. -- `suspended`: The status or account was previously suspended by a moderator. -- `silenced`: The status or account was previously silenced by a moderator. - -### ModTag Types - -ModTag do not have set types and can be anything. Versia Server Server autosuggest previously used tags when a moderator is adding a new tag to avoid duplicates. - -### Data Format - -```ts -type Flag = { - id: string, - // One of the following two fields will be present - flaggedStatus?: Status, - flaggedUser?: User, - flagType: string, - createdAt: string, -} - -type ModTag = { - id: string, - // One of the following two fields will be present - taggedStatus?: Status, - taggedUser?: User, - mod: User, - tag: string, - createdAt: string, -} - -type ModNote = { - id: string, - // One of the following two fields will be present - notedStatus?: Status, - notedUser?: User, - mod: User, - note: string, - createdAt: string, -} -``` - -The `User` and `Status` types are the same as the ones in the Mastodon API. - -## Moderation API Routes - -### `GET /api/v1/moderation/accounts/:id` - -Returns full moderation data and flags for the account with the given ID. - -Output format: - -```ts -{ - id: string, // Same ID as in account field - flags: Flag[], - modtags: ModTag[], - modnotes: ModNote[], - account: User, -} -``` - -### `GET /api/v1/moderation/statuses/:id` - -Returns full moderation data and flags for the status with the given ID. - -Output format: - -```ts -{ - id: string, // Same ID as in status field - flags: Flag[], - modtags: ModTag[], - modnotes: ModNote[], - status: Status, -} -``` - -### `POST /api/v1/moderation/accounts/:id/modtags` - -Params: -- `tag`: string - -Adds a modtag to the account with the given ID - -### `POST /api/v1/moderation/statuses/:id/modtags` - -Params: -- `tag`: string - -Adds a modtag to the status with the given ID - -### `POST /api/v1/moderation/accounts/:id/modnotes` - -Params: -- `note`: string - -Adds a modnote to the account with the given ID - -### `POST /api/v1/moderation/statuses/:id/modnotes` - -Params: -- `note`: string - -Adds a modnote to the status with the given ID - -### `DELETE /api/v1/moderation/accounts/:id/modtags/:modtag_id` - -Deletes the modtag with the given ID from the account with the given ID - -### `DELETE /api/v1/moderation/statuses/:id/modtags/:modtag_id` - -Deletes the modtag with the given ID from the status with the given ID - -### `DELETE /api/v1/moderation/accounts/:id/modnotes/:modnote_id` - -Deletes the modnote with the given ID from the account with the given ID - -### `DELETE /api/v1/moderation/statuses/:id/modnotes/:modnote_id` - -Deletes the modnote with the given ID from the status with the given ID - -### `GET /api/v1/moderation/modtags` - -Returns a list of all modtags previously used by moderators - -Output format: - -```ts -{ - tags: string[], -} -``` - -### `GET /api/v1/moderation/accounts/flags/search` - -Allows moderators to search for accounts based on their flags, this can also include status flags - -Params: -- `limit`: Number -- `min_id`: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward. -- `max_id`: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results. -- `since_id`: String. All results returned will be greater than this ID. In effect, sets a lower bound on results. -- `flags`: String (optional). Comma-separated list of flag types to filter by. Can be left out to return accounts with at least one flag -- `flag_count`: Number (optional). Minimum number of flags to filter by -- `include_statuses`: Boolean (optional). If true, includes status flags in the search results -- `account_id`: Array of strings (optional). Filters accounts by account ID - -This method returns a `Link` header the same way Mastodon does, to allow for pagination. - -Output format: - -```ts -{ - accounts: { - account: User, - modnotes: ModNote[], - flags: Flag[], - statuses?: { - status: Status, - modnotes: ModNote[], - flags: Flag[], - }[], - }[], -} -``` - -### `GET /api/v1/moderation/statuses/flags/search` - -Allows moderators to search for statuses based on their flags - -Params: -- `limit`: Number -- `min_id`: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward. -- `max_id`: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results. -- `since_id`: String. All results returned will be greater than this ID. In effect, sets a lower bound on results. -- `flags`: String (optional). Comma-separated list of flag types to filter by. Can be left out to return statuses with at least one flag -- `flag_count`: Number (optional). Minimum number of flags to filter by -- `account_id`: Array of strings (optional). Filters statuses by account ID - -This method returns a `Link` header the same way Mastodon does, to allow for pagination. - -Output format: - -```ts -{ - statuses: { - status: Status, - modnotes: ModNote[], - flags: Flag[], - }[], -} -``` - -### `GET /api/v1/moderation/accounts/modtags/search` - -Allows moderators to search for accounts based on their modtags - -Params: -- `limit`: Number -- `min_id`: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward. -- `max_id`: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results. -- `since_id`: String. All results returned will be greater than this ID. In effect, sets a lower bound on results. -- `tags`: String (optional). Comma-separated list of tags to filter by. Can be left out to return accounts with at least one tag -- `tag_count`: Number (optional). Minimum number of tags to filter by -- `include_statuses`: Boolean (optional). If true, includes status tags in the search results -- `account_id`: Array of strings (optional). Filters accounts by account ID - -This method returns a `Link` header the same way Mastodon does, to allow for pagination. - -Output format: - -```ts -{ - accounts: { - account: User, - modnotes: ModNote[], - modtags: ModTag[], - statuses?: { - status: Status, - modnotes: ModNote[], - modtags: ModTag[], - }[], - }[], -} -``` - -### `GET /api/v1/moderation/statuses/modtags/search` - -Allows moderators to search for statuses based on their modtags - -Params: -- `limit`: Number -- `min_id`: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward. -- `max_id`: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results. -- `since_id`: String. All results returned will be greater than this ID. In effect, sets a lower bound on results. -- `tags`: String (optional). Comma-separated list of tags to filter by. Can be left out to return statuses with at least one tag -- `tag_count`: Number (optional). Minimum number of tags to filter by -- `account_id`: Array of strings (optional). Filters statuses by account ID -- `include_statuses`: Boolean (optional). If true, includes status tags in the search results - -This method returns a `Link` header the same way Mastodon does, to allow for pagination. - -Output format: - -```ts -{ - statuses: { - status: Status, - modnotes: ModNote[], - modtags: ModTag[], - }[], -} -``` diff --git a/docs/api/roles.md b/docs/api/roles.md index e7c3a5be..b908ea61 100644 --- a/docs/api/roles.md +++ b/docs/api/roles.md @@ -1,79 +1,82 @@ # Roles API -The Roles API lets users manage roles given to them by administrators. This API is available to all users. - > [!WARNING] -> The API for **administrators** is different (and unimplemented): this is the API for **users**. > -> Furthermore, users can only manage roles if they have the `roles` permission, and the role they wish to manage does not have a higher priority than their highest priority role. +> This API is due to be reworked in the future. The current implementation is not final. +> +> Missing features include the ability to create and delete roles, as well as the ability to assign roles to other users. + +This API allows users to create, read, update, and delete instance custom roles. Custom roles can be used to grant users specific permissions, such as managing the instance, uploading custom emojis, or moderating content. ## Priorities -Roles have a priority, which determines the order in which they are applied. Roles with higher priorities take precedence over roles with lower priorities. +Every role has a "priority" value, which determines the order in which roles are applied. Roles with higher priorities take precedence over roles with lower priorities. The default priority is `0`. -Additionally, users cannot remove or add roles with a higher priority than their highest priority role. +Additionally, users cannot edit roles with a higher priority than their highest priority role. ## Visibility -Roles can be visible or invisible. Invisible roles are not shown to users in the UI, but they can still be managed via the API. - -> [!WARNING] -> All roles assigned to a user are public information and can be retrieved via the API. The visibility of a role only affects whether it is shown in the UI, which clients can choose to respect or not. +Roles can be visible or invisible. Invisible roles are not shown to users in the UI, but they can still be managed via the API. This is useful for cosmetic roles that do not grant any permissions, e.g. `#1 Most Prominent Glizzy Eater`. ## Permissions -Default permissions for anonymous users, logged-in users and admins can be set in config. These are always applied in addition to the permissions granted by roles. You may set them to empty arrays to exclusively use roles for permissions (make sure your roles are set up correctly). +Default permissions for anonymous users, logged-in users, and administrators can be set in the configuration. These permissions are always applied in addition to the permissions granted by roles. You may set them to empty arrays to exclusively use roles for permissions (make sure your roles are set up correctly). + +### List of Permissions + +- `Manage` permissions grant the ability to create, read, update, and delete resources. +- `View` permissions grant the ability to read resources. +- `Owner` permissions grant the ability to manage resources that the user owns. ```ts -// Last updated: 2024-06-07 -// Search for "RolePermissions" in the source code (GitHub search bar) for the most up-to-date version -export enum RolePermissions { - MANAGE_NOTES = "notes", - MANAGE_OWN_NOTES = "owner:note", - VIEW_NOTES = "read:note", - VIEW_NOTE_LIKES = "read:note_likes", - VIEW_NOTE_BOOSTS = "read:note_boosts", - MANAGE_ACCOUNTS = "accounts", - MANAGE_OWN_ACCOUNT = "owner:account", - VIEW_ACCOUNT_FOLLOWS = "read:account_follows", - MANAGE_LIKES = "likes", - MANAGE_OWN_LIKES = "owner:like", - MANAGE_BOOSTS = "boosts", - MANAGE_OWN_BOOSTS = "owner:boost", - VIEW_ACCOUNTS = "read:account", - MANAGE_EMOJIS = "emojis", - VIEW_EMOJIS = "read:emoji", - MANAGE_OWN_EMOJIS = "owner:emoji", - MANAGE_MEDIA = "media", - MANAGE_OWN_MEDIA = "owner:media", - MANAGE_BLOCKS = "blocks", - MANAGE_OWN_BLOCKS = "owner:block", - MANAGE_FILTERS = "filters", - MANAGE_OWN_FILTERS = "owner:filter", - MANAGE_MUTES = "mutes", - MANAGE_OWN_MUTES = "owner:mute", - MANAGE_REPORTS = "reports", - MANAGE_OWN_REPORTS = "owner:report", - MANAGE_SETTINGS = "settings", - MANAGE_OWN_SETTINGS = "owner:settings", - MANAGE_ROLES = "roles", - MANAGE_NOTIFICATIONS = "notifications", - MANAGE_OWN_NOTIFICATIONS = "owner:notification", - MANAGE_FOLLOWS = "follows", - MANAGE_OWN_FOLLOWS = "owner:follow", - MANAGE_OWN_APPS = "owner:app", - SEARCH = "search", - VIEW_PUBLIC_TIMELINES = "public_timelines", - VIEW_PRIVATE_TIMELINES = "private_timelines", - IGNORE_RATE_LIMITS = "ignore_rate_limits", - IMPERSONATE = "impersonate", - MANAGE_INSTANCE = "instance", - MANAGE_INSTANCE_FEDERATION = "instance:federation", - MANAGE_INSTANCE_SETTINGS = "instance:settings", - OAUTH = "oauth", -} +ManageNotes: "notes", +ManageOwnNotes: "owner:note", +ViewNotes: "read:note", +ViewNoteLikes: "read:note_likes", +ViewNoteBoosts: "read:note_boosts", +ManageAccounts: "accounts", +ManageOwnAccount: "owner:account", +ViewAccountFollows: "read:account_follows", +ManageLikes: "likes", +ManageOwnLikes: "owner:like", +ManageBoosts: "boosts", +ManageOwnBoosts: "owner:boost", +ViewAccounts: "read:account", +ManageEmojis: "emojis", +ViewEmojis: "read:emoji", +ManageOwnEmojis: "owner:emoji", +ManageMedia: "media", +ManageOwnMedia: "owner:media", +ManageBlocks: "blocks", +ManageOwnBlocks: "owner:block", +ManageFilters: "filters", +ManageOwnFilters: "owner:filter", +ManageMutes: "mutes", +ManageOwnMutes: "owner:mute", +ManageReports: "reports", +ManageOwnReports: "owner:report", +ManageSettings: "settings", +ManageOwnSettings: "owner:settings", +ManageRoles: "roles", +ManageNotifications: "notifications", +ManageOwnNotifications: "owner:notification", +ManageFollows: "follows", +ManageOwnFollows: "owner:follow", +ManageOwnApps: "owner:app", +Search: "search", +ViewPublicTimelines: "public_timelines", +ViewPrimateTimelines: "private_timelines", +IgnoreRateLimits: "ignore_rate_limits", +Impersonate: "impersonate", +ManageInstance: "instance", +ManageInstanceFederation: "instance:federation", +ManageInstanceSettings: "instance:settings", +/** Users who do not have this permission will not be able to login! */ +OAuth: "oauth", ``` +An example usage of these permissions would be to not give the `ViewPublicTimelines` permission to anonymous users, but give it to logged-in users, in order to restrict access to public timelines. + ### Manage Roles The `roles` permission allows the user to manage roles, including adding and removing roles from themselves. This permission is required to use the Roles API. @@ -82,21 +85,29 @@ The `roles` permission allows the user to manage roles, including adding and rem The `impersonate` permission allows the user to impersonate other users (logging in with their credentials). This is a dangerous permission and should be used with caution. -### Manage Instance +Useful for administrators who need to troubleshoot user issues. -The `instance` permission allows the user to manage the instance, including viewing logs, restarting the instance, and more. +### OAuth -### Manage Instance Federation +The `oauth` permission is required for users to log in via OAuth. Users who do not have this permission will not be able to log in via OAuth. -The `instance:federation` permission allows the user to manage the instance's federation settings, including blocking and unblocking other instances. +## Role -### Manage Instance Settings +```ts +type UUID = string; +type URL = string; +type Permission = string; -The `instance:settings` permission allows the user to manage the instance's settings, including changing the instance's name, description, and more. - -### OAuth2 - -The `oauth` permission is required for users to log in to the instance. Users who do not have this permission will not be able to log in. +interface Role { + id: UUID; + name: string; + permissions: Permission[]; + priority: number; + description?: string | null; + visible: boolean; + icon?: URL | null; +} +``` ## Get Roles @@ -104,21 +115,117 @@ The `oauth` permission is required for users to log in to the instance. Users wh GET /api/v1/roles ``` -Retrieves a list of roles that the user has. +Get a list of all roles that the requesting user has. + +- **Returns**: Array of [`Role`](#role) +- **Authentication**: Required +- **Permissions**: None +- **Version History**: + - `0.7.0`: Added. + +### Example + +```http +GET /api/v1/roles +Authorization: Bearer ... +``` ### Response -```ts -// 200 OK -{ - id: string; - name: string; - permissions: RolePermissions[]; - priority: number; - description: string | null; - visible: boolean; - icon: string | null -}[]; +#### `200 OK` + +All roles owned by the user. + +```json +[ + { + "id": "default", + "name": "Default", + "permissions": [ + "owner:note", + "read:note", + "read:note_likes", + "read:note_boosts", + "owner:account", + "read:account_follows", + "owner:like", + "owner:boost", + "read:account", + "owner:emoji", + "read:emoji", + "owner:media", + "owner:block", + "owner:filter", + "owner:mute", + "owner:report", + "owner:settings", + "owner:notification", + "owner:follow", + "owner:app", + "search", + "public_timelines", + "private_timelines", + "oauth" + ], + "priority": 0, + "description": "Default role for all users", + "visible": false, + "icon": null + }, + { + "id": "admin", + "name": "Admin", + "permissions": [ + "owner:note", + "read:note", + "read:note_likes", + "read:note_boosts", + "owner:account", + "read:account_follows", + "owner:like", + "owner:boost", + "read:account", + "owner:emoji", + "read:emoji", + "owner:media", + "owner:block", + "owner:filter", + "owner:mute", + "owner:report", + "owner:settings", + "owner:notification", + "owner:follow", + "owner:app", + "search", + "public_timelines", + "private_timelines", + "oauth", + "notes", + "accounts", + "likes", + "boosts", + "emojis", + "media", + "blocks", + "filters", + "mutes", + "reports", + "settings", + "roles", + "notifications", + "follows", + "impersonate", + "ignore_rate_limits", + "instance", + "instance:federation", + "instance:settings" + ], + "priority": 2147483647, + "description": "Default role for all administrators", + "visible": false, + "icon": null + } +] ``` ## Get Role @@ -127,36 +234,94 @@ Retrieves a list of roles that the user has. GET /api/v1/roles/:id ``` -Retrieves information about a role. +Get a specific role's data. + +- **Returns**: [`Role`](#role) +- **Authentication**: Required +- **Permissions**: None +- **Version History**: + - `0.7.0`: Added. + +### Request + +#### Example + +```http +GET /api/v1/roles/default +Authorization: Bearer ... +``` ### Response -```ts -// 200 OK +#### `200 OK` + +Role data. + +```json { - id: string; - name: string; - permissions: RolePermissions[]; - priority: number; - description: string | null; - visible: boolean; - icon: string | null + "id": "default", + "name": "Default", + "permissions": [ + "owner:note", + "read:note", + "read:note_likes", + "read:note_boosts", + "owner:account", + "read:account_follows", + "owner:like", + "owner:boost", + "read:account", + "owner:emoji", + "read:emoji", + "owner:media", + "owner:block", + "owner:filter", + "owner:mute", + "owner:report", + "owner:settings", + "owner:notification", + "owner:follow", + "owner:app", + "search", + "public_timelines", + "private_timelines", + "oauth" + ], + "priority": 0, + "description": "Default role for all users", + "visible": false, + "icon": null } ``` -## Add Role +## Assign Role ```http POST /api/v1/roles/:id ``` -Adds the role with the given ID to the user making the request. +Assign a role to the user making the request. + +- **Returns**: `204 No Content` +- **Authentication**: Required +- **Permissions**: `roles` +- **Version History**: + - `0.7.0`: Added. + +### Request + +#### Example + +```http +POST /api/v1/roles/364fd13f-28b5-4e88-badd-ce3e533f0d02 +Authorization: Bearer ... +``` ### Response -```ts -// 204 No Content -``` +#### `204 No Content` + +Role successfully assigned. ## Remove Role @@ -164,10 +329,25 @@ Adds the role with the given ID to the user making the request. DELETE /api/v1/roles/:id ``` -Removes the role with the given ID from the user making the request. +Remove a role from the user making the request. + +- **Returns**: `204 No Content` +- **Authentication**: Required +- **Permissions**: `roles` +- **Version History**: + - `0.7.0`: Added. + +### Request + +#### Example + +```http +DELETE /api/v1/roles/364fd13f-28b5-4e88-badd-ce3e533f0d +Authorization: Bearer ... +``` ### Response -```ts -// 204 No Content -``` \ No newline at end of file +#### `204 No Content` + +Role successfully removed. \ No newline at end of file diff --git a/docs/api/sso.md b/docs/api/sso.md new file mode 100644 index 00000000..da234e83 --- /dev/null +++ b/docs/api/sso.md @@ -0,0 +1,164 @@ +# SSO API + +The SSO API is used to link, unlink, and list external OpenID Connect providers that the user has linked their account to. + +## SSO Provider + +```ts +interface SSOProvider { + id: string; + name: string; + icon: string; +} +``` + +## SSO Link + +```http +POST /api/v1/sso +``` + +Allows users to link their account to an external OpenID Connect provider. + +- **Returns**: Link to redirect the user to the external provider. +- **Authentication**: Required +- **Permissions**: `oauth` +- **Version History**: + - `0.6.0`: Added. + - `0.7.0`: Permissions added. + +### Request + +- `issuer` (string, required): The issuer ID of the OpenID Connect provider as set in config. + +#### Example + +```http +POST /api/v1/sso +Authorization: Bearer ... +Content-Type: application/json + +{ + "issuer": "google" +} +``` + +### Response + +#### `200 OK` + +Link to redirect the user to the external provider's page. + +```json +{ + "link": "https://accounts.google.com/o/oauth2/auth?client_id=..." +} +``` + +## SSO Unlink + +```http +DELETE /api/v1/sso/:issuer +``` + +Allows users to unlink their account from an external OpenID Connect provider. + +- **Returns**: `204 No Content` +- **Authentication**: Required +- **Permissions**: `oauth` +- **Version History**: + - `0.6.0`: Added. + - `0.7.0`: Permissions added. + +### Request + +#### Example + +```http +DELETE /api/v1/sso/google +Authorization: Bearer ... +``` + +### Response + +#### `204 No Content` + +Account successfully unlinked. + +## List Connected Providers + +```http +GET /api/v1/sso +``` + +Lists all external OpenID Connect providers that the user has linked their account to. + +- **Returns**: Array of [`SSOProvider`](#ssoprovider) objects. +- **Authentication**: Required +- **Permissions**: `oauth` +- **Version History**: + - `0.6.0`: Added. + - `0.7.0`: Permissions added. + +### Request + +#### Example + +```http +GET /api/v1/sso +Authorization: Bearer ... +``` + +### Response + +#### `200 OK` + +Array of [`SSOProvider`](#ssoprovider) objects. + +```json +[ + { + "id": "google", + "name": "Google", + "icon": "https://cdn.example.com/google.png" + } +] +``` + +## Get Linked Provider Data + +```http +GET /api/v1/sso/:issuer +``` + +Gets the data of an external OpenID Connect provider that the user has linked their account to. + +- **Returns**: [`SSOProvider`](#ssoprovider) object. +- **Authentication**: Required +- **Permissions**: `oauth` +- **Version History**: + - `0.6.0`: Added. + - `0.7.0`: Permissions added. + +### Request + +#### Example + +```http +GET /api/v1/sso/google +Authorization: Bearer ... +``` + +### Response + +#### `200 OK` + +[`SSOProvider`](#ssoprovider) object. + +```json +{ + "id": "google", + "name": "Google", + "icon": "https://cdn.example.com/google.png" +} +``` \ No newline at end of file diff --git a/docs/cli.md b/docs/cli/index.md similarity index 85% rename from docs/cli.md rename to docs/cli/index.md index 332ae782..d97e86a0 100644 --- a/docs/cli.md +++ b/docs/cli/index.md @@ -12,6 +12,7 @@ bun cli help # Source installs bun run dist/cli.js help # Docker +# Replace `versia` with the name of your container docker compose exec -it versia /bin/sh /app/entrypoint.sh cli help ``` @@ -19,6 +20,6 @@ You can use the `help` command to see a list of available commands. These includ ## Scripting with the CLI -Some CLI commands that return data as tables can be used in scripts. To convert them to JSON or CSV, some commands allow you to specify a `--format` flag that can be either `"json"` or `"csv"`. See `bun cli help` or `bun cli