diff --git a/docs/avatar.md b/docs/avatar.md index b63b8e145a9..7fc908c4414 100644 --- a/docs/avatar.md +++ b/docs/avatar.md @@ -70,6 +70,7 @@ ## Get conversations avatar (binary) * Required capability: `avatar` +* Federation capability: `federation-v1` * Method: `GET` * Endpoint: `/room/{token}/avatar` @@ -82,6 +83,7 @@ ## Get dark mode conversations avatar (binary) * Required capability: `avatar` +* Federation capability: `federation-v1` * Method: `GET` * Endpoint: `/room/{token}/avatar/dark` diff --git a/docs/capabilities.md b/docs/capabilities.md index c0d746cd78d..1f8987a1e49 100644 --- a/docs/capabilities.md +++ b/docs/capabilities.md @@ -144,3 +144,8 @@ * `edit-messages` - Whether messages can be edited (restricted to 24 hours after posting) * `silent-send-state` - Whether messages contain a flag that they were sent silently * `chat-read-last` - Whether chat can be marked read without giving a message ID (will fall back to the conversations last message ID) +* `federation-v1` - Whether basic chatting is possible with federation +* `config => federation => enabled` - Boolean, whether federation is enabled on instance +* `config => federation => incoming-enabled` - Boolean, whether users are allowed to be invited into federated conversations on other servers +* `config => federation => outgoing-enabled` - Boolean, whether users are allowed to invited federated users of other servers into conversations +* `config => federation => only-trusted-servers` - Boolean, whether federation invites are limited to trusted servers diff --git a/docs/chat.md b/docs/chat.md index 358e0b97605..4a02511cf47 100644 --- a/docs/chat.md +++ b/docs/chat.md @@ -10,6 +10,7 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`: since Nextcloud 13 It is therefor recommended to use `format=json` or send the `Accept: application/json` header, to receive a JSON response. +* Federation capability: `federation-v1` * Method: `GET` * Endpoint: `/chat/{token}` * Data: @@ -90,6 +91,7 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`: since Nextcloud 13 to receive a JSON response. * Required capability: `chat-get-context` +* Federation capability: `federation-v1` * Method: `GET` * Endpoint: `/chat/{token}/{messageId}/context` * Data: @@ -115,6 +117,7 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`: since Nextcloud 13 ## Sending a new chat message +* Federation capability: `federation-v1` * Method: `POST` * Endpoint: `/chat/{token}` * Data: @@ -284,6 +287,7 @@ See [OCP\RichObjectStrings\Definitions](https://github.com/nextcloud/server/blob ## Deleting a chat message * Required capability: `delete-messages` - `rich-object-delete` indicates if shared objects can be deleted from the chat +* Federation capability: `federation-v1` * Method: `DELETE` * Endpoint: `/chat/{token}/{messageId}` @@ -313,6 +317,7 @@ See [OCP\RichObjectStrings\Definitions](https://github.com/nextcloud/server/blob ## Editing a chat message * Required capability: `edit-messages` +* Federation capability: `federation-v1` * Method: `PUT` * Endpoint: `/chat/{token}/{messageId}` * Data: @@ -412,6 +417,7 @@ See [OCP\RichObjectStrings\Definitions](https://github.com/nextcloud/server/blob ## Mark chat as read * Required capability: `chat-read-marker` +* Federation capability: `federation-v1` * Method: `POST` * Endpoint: `/chat/{token}/read` * Data: @@ -439,6 +445,7 @@ See [OCP\RichObjectStrings\Definitions](https://github.com/nextcloud/server/blob ## Mark chat as unread * Required capability: `chat-unread` +* Federation capability: `federation-v1` * Method: `DELETE` * Endpoint: `/chat/{token}/read` @@ -460,6 +467,7 @@ See [OCP\RichObjectStrings\Definitions](https://github.com/nextcloud/server/blob ## Get mention autocomplete suggestions +* Federation capability: `federation-v1` * Method: `GET` * Endpoint: `/chat/{token}/mentions` * Data: diff --git a/docs/conversation.md b/docs/conversation.md index a043aa9d51f..bcb13ce2498 100644 --- a/docs/conversation.md +++ b/docs/conversation.md @@ -365,6 +365,7 @@ Get all (for moderators and in case of "free selection") or the assigned breakou ## Add conversation to favorites * Required capability: `favorites` +* Federation capability: `federation-v1` * Method: `POST` * Endpoint: `/room/{token}/favorite` @@ -377,6 +378,7 @@ Get all (for moderators and in case of "free selection") or the assigned breakou ## Remove conversation from favorites * Required capability: `favorites` +* Federation capability: `federation-v1` * Method: `DELETE` * Endpoint: `/room/{token}/favorite` @@ -389,6 +391,7 @@ Get all (for moderators and in case of "free selection") or the assigned breakou ## Set notification level * Required capability: `notification-levels` +* Federation capability: `federation-v1` * Method: `POST` * Endpoint: `/room/{token}/notify` * Data: @@ -478,3 +481,23 @@ Get all (for moderators and in case of "free selection") or the assigned breakou + `400 Bad Request` When the conversation is a breakout room + `403 Forbidden` When the current user is not a moderator/owner or the conversation is not a public conversation + `404 Not Found` When the conversation could not be found for the participant + +## Get conversation capabilities + +* Required capability: `federation-v1` +* Method: `GET` +* Endpoint: `/room/{token}/capabilities` + +* Response: + - Status code: + + `200 OK` Get capabilities + + `404 Not Found` When the conversation could not be found for the participant + + - Header: + +| field | type | Description | +|-------------------------------|--------|--------------------------------------------------------------------------------------------| +| `X-Nextcloud-Talk-Proxy-Hash` | string | Sha1 value over the capabilities in case the conversation is hosted **on another server**. | +| `X-Nextcloud-Talk-Hash` | string | Sha1 value over the capabilities in case the conversation is hosted **on this server**. | + + - Data: Server capabilities limited to the `spreed` sub-array or an empty array in case the app is disabled (for the user) diff --git a/docs/global.md b/docs/global.md index a1e728a7655..6ae8ff84a22 100644 --- a/docs/global.md +++ b/docs/global.md @@ -40,3 +40,19 @@ From time to time it is unavoidable to break compatibility. In such cases we try + `426 Upgrade Required` - Body: + `ocs.meta.message` contains the minimum required version of the used client + +## Federation - Not supported + +Endpoints without a "Federation capability: `federation-vX`" will return a `406 Not Acceptable` status code, when called with tokens that actually refer to a so-called proxy conversation on the local server. + +* Response: + - Status code: + + `406 Not Acceptable` + +## Federation - Remote error + +When a request is performed on a proxy conversation and the host can not be reached `422 Unprocessable Content` will be returned. The only exception will be leaving the room, where the request will still execute it's part locally so the user is no longer bothered. A background job will be queued to retry informing the remote server about the leave automatically. + +* Response: + - Status code: + + `422 Unprocessable Content` diff --git a/docs/participant.md b/docs/participant.md index d46380863c3..157f420fa27 100644 --- a/docs/participant.md +++ b/docs/participant.md @@ -7,6 +7,7 @@ ## Get list of participants in a conversation +* Federation capability: `federation-v1` * Method: `GET` * Endpoint: `/room/{token}/participants` * Data: @@ -108,6 +109,7 @@ ## Remove yourself from a conversation +* Federation capability: `federation-v1` * Method: `DELETE` * Endpoint: `/room/{token}/participants/self` @@ -119,6 +121,7 @@ ## Join a conversation (available for call and chat) +* Federation capability: `federation-v1` * Method: `POST` * Endpoint: `/room/{token}/participants/active` * Data: @@ -165,6 +168,7 @@ ## Set session state * Required capability: `session-state` +* Federation capability: `federation-v1` * Method: `PUT` * Endpoint: `/room/{token}/participants/state` @@ -176,6 +180,7 @@ ## Leave a conversation (not available for call and chat anymore) +* Federation capability: `federation-v1` * Method: `DELETE` * Endpoint: `/room/{token}/participants/active` diff --git a/docs/reaction.md b/docs/reaction.md index 0185886ffbc..1373c249fbc 100644 --- a/docs/reaction.md +++ b/docs/reaction.md @@ -5,6 +5,7 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`: since Nextcloud 24 ## React to a message * Required capability: `reactions` +* Federation capability: `federation-v1` * Method: `POST` * Endpoint: `/reaction/{token}/{messageId}` * Data: @@ -33,6 +34,7 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`: since Nextcloud 24 ## Delete a reaction * Required capability: `reactions` +* Federation capability: `federation-v1` * Method: `DELETE` * Endpoint: `/reaction/{token}/{messageId}` * Data: @@ -60,6 +62,7 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`: since Nextcloud 24 ## Retrieve reactions of a message by type * Required capability: `reactions` +* Federation capability: `federation-v1` * Method: `GET` * Endpoint: `/reaction/{token}/{messageId}` * Data: diff --git a/lib/Capabilities.php b/lib/Capabilities.php index f7648cacb2b..2f288ff8f9e 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -28,6 +28,7 @@ use OCA\Talk\Chat\ChatManager; use OCP\App\IAppManager; +use OCP\AppFramework\Services\IAppConfig; use OCP\Capabilities\IPublicCapability; use OCP\Comments\ICommentsManager; use OCP\ICache; @@ -47,6 +48,7 @@ class Capabilities implements IPublicCapability { public function __construct( protected IConfig $serverConfig, protected Config $talkConfig, + protected IAppConfig $appConfig, protected ICommentsManager $commentsManager, protected IUserSession $userSession, protected IAppManager $appManager, @@ -140,6 +142,7 @@ public function getCapabilities(): array { 'edit-messages', 'silent-send-state', 'chat-read-last', + 'federation-v1', ], 'config' => [ 'attachments' => [ @@ -163,6 +166,12 @@ public function getCapabilities(): array { 'conversations' => [ 'can-create' => $user instanceof IUser && !$this->talkConfig->isNotAllowedToCreateConversations($user) ], + 'federation' => [ + 'enabled' => false, + 'incoming-enabled' => false, + 'outgoing-enabled' => false, + 'only-trusted-servers' => true, + ], 'previews' => [ 'max-gif-size' => (int)$this->serverConfig->getAppValue('spreed', 'max-gif-size', '3145728'), ], @@ -173,6 +182,7 @@ public function getCapabilities(): array { 'version' => $this->appManager->getAppVersion('spreed'), ]; + if ($this->serverConfig->getAppValue('core', 'backgroundjobs_mode', 'ajax') === 'cron') { $capabilities['features'][] = 'message-expiration'; } @@ -182,6 +192,15 @@ public function getCapabilities(): array { } if ($user instanceof IUser) { + if ($this->talkConfig->isFederationEnabled() && $this->talkConfig->isFederationEnabledForUserId($user)) { + $capabilities['config']['federation'] = [ + 'enabled' => true, + 'incoming-enabled' => $this->appConfig->getAppValueBool('federation_incoming_enabled', true), + 'outgoing-enabled' => $this->appConfig->getAppValueBool('federation_outgoing_enabled', true), + 'only-trusted-servers' => $this->appConfig->getAppValueBool('federation_only_trusted_servers'), + ]; + } + $capabilities['config']['attachments']['folder'] = $this->talkConfig->getAttachmentFolder($user->getUID()); $capabilities['config']['chat']['read-privacy'] = $this->talkConfig->getUserReadPrivacy($user->getUID()); $capabilities['config']['chat']['typing-privacy'] = $this->talkConfig->getUserTypingPrivacy($user->getUID()); diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php index 1f257d8224b..52246635041 100644 --- a/lib/ResponseDefinitions.php +++ b/lib/ResponseDefinitions.php @@ -308,6 +308,12 @@ * conversations: array{ * can-create: bool, * }, + * federation: array{ + * enabled: bool, + * incoming-enabled: bool, + * outgoing-enabled: bool, + * only-trusted-servers: bool, + * }, * previews: array{ * max-gif-size: int, * }, diff --git a/lib/Settings/Admin/AdminSettings.php b/lib/Settings/Admin/AdminSettings.php index 2d3893a4d3a..ddffc99a95b 100644 --- a/lib/Settings/Admin/AdminSettings.php +++ b/lib/Settings/Admin/AdminSettings.php @@ -31,6 +31,7 @@ use OCA\Talk\Room; use OCA\Talk\Service\CommandService; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IAppConfig; use OCP\AppFramework\Services\IInitialState; use OCP\ICacheFactory; use OCP\IConfig; @@ -49,6 +50,7 @@ class AdminSettings implements ISettings { public function __construct( private Config $talkConfig, private IConfig $serverConfig, + private IAppConfig $appConfig, private CommandService $commandService, private IInitialState $initialState, private ICacheFactory $memcacheFactory, @@ -111,11 +113,11 @@ protected function initCommands(): void { } protected function initFederation(): void { - $this->initialState->provideInitialState('federation_enabled', $this->serverConfig->getAppValue('spreed', 'federation_enabled', 'no')); - $this->initialState->provideInitialState('federation_incoming_enabled', $this->serverConfig->getAppValue('spreed', 'federation_incoming_enabled', '1')); - $this->initialState->provideInitialState('federation_outgoing_enabled', $this->serverConfig->getAppValue('spreed', 'federation_outgoing_enabled', '1')); - $this->initialState->provideInitialState('federation_only_trusted_servers', $this->serverConfig->getAppValue('spreed', 'federation_only_trusted_servers', '0')); - $this->initialState->provideInitialState('federation_allowed_groups', $this->serverConfig->getAppValue('spreed', 'federation_allowed_groups', '[]')); + $this->initialState->provideInitialState('federation_enabled', $this->talkConfig->isFederationEnabled()); + $this->initialState->provideInitialState('federation_incoming_enabled', $this->appConfig->getAppValueBool('federation_incoming_enabled', true)); + $this->initialState->provideInitialState('federation_outgoing_enabled', $this->appConfig->getAppValueBool('federation_outgoing_enabled', true)); + $this->initialState->provideInitialState('federation_only_trusted_servers', $this->appConfig->getAppValueBool('federation_only_trusted_servers')); + $this->initialState->provideInitialState('federation_allowed_groups', $this->appConfig->getAppValueArray('federation_allowed_groups')); } protected function initMatterbridge(): void { diff --git a/openapi-administration.json b/openapi-administration.json index d7b0a3948c2..48d2bf496d9 100644 --- a/openapi-administration.json +++ b/openapi-administration.json @@ -108,6 +108,7 @@ "call", "chat", "conversations", + "federation", "previews", "signaling" ], @@ -217,6 +218,29 @@ } } }, + "federation": { + "type": "object", + "required": [ + "enabled", + "incoming-enabled", + "outgoing-enabled", + "only-trusted-servers" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "incoming-enabled": { + "type": "boolean" + }, + "outgoing-enabled": { + "type": "boolean" + }, + "only-trusted-servers": { + "type": "boolean" + } + } + }, "previews": { "type": "object", "required": [ diff --git a/openapi-backend-recording.json b/openapi-backend-recording.json index 67d229ba02c..a7d218e266e 100644 --- a/openapi-backend-recording.json +++ b/openapi-backend-recording.json @@ -41,6 +41,7 @@ "call", "chat", "conversations", + "federation", "previews", "signaling" ], @@ -150,6 +151,29 @@ } } }, + "federation": { + "type": "object", + "required": [ + "enabled", + "incoming-enabled", + "outgoing-enabled", + "only-trusted-servers" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "incoming-enabled": { + "type": "boolean" + }, + "outgoing-enabled": { + "type": "boolean" + }, + "only-trusted-servers": { + "type": "boolean" + } + } + }, "previews": { "type": "object", "required": [ diff --git a/openapi-backend-signaling.json b/openapi-backend-signaling.json index 0d8e8703bad..a0a2399801d 100644 --- a/openapi-backend-signaling.json +++ b/openapi-backend-signaling.json @@ -41,6 +41,7 @@ "call", "chat", "conversations", + "federation", "previews", "signaling" ], @@ -150,6 +151,29 @@ } } }, + "federation": { + "type": "object", + "required": [ + "enabled", + "incoming-enabled", + "outgoing-enabled", + "only-trusted-servers" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "incoming-enabled": { + "type": "boolean" + }, + "outgoing-enabled": { + "type": "boolean" + }, + "only-trusted-servers": { + "type": "boolean" + } + } + }, "previews": { "type": "object", "required": [ diff --git a/openapi-backend-sipbridge.json b/openapi-backend-sipbridge.json index 04f1ce51023..109f038f0be 100644 --- a/openapi-backend-sipbridge.json +++ b/openapi-backend-sipbridge.json @@ -41,6 +41,7 @@ "call", "chat", "conversations", + "federation", "previews", "signaling" ], @@ -150,6 +151,29 @@ } } }, + "federation": { + "type": "object", + "required": [ + "enabled", + "incoming-enabled", + "outgoing-enabled", + "only-trusted-servers" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "incoming-enabled": { + "type": "boolean" + }, + "outgoing-enabled": { + "type": "boolean" + }, + "only-trusted-servers": { + "type": "boolean" + } + } + }, "previews": { "type": "object", "required": [ diff --git a/openapi-bots.json b/openapi-bots.json index 67aa5a260bf..c7f0942f096 100644 --- a/openapi-bots.json +++ b/openapi-bots.json @@ -41,6 +41,7 @@ "call", "chat", "conversations", + "federation", "previews", "signaling" ], @@ -150,6 +151,29 @@ } } }, + "federation": { + "type": "object", + "required": [ + "enabled", + "incoming-enabled", + "outgoing-enabled", + "only-trusted-servers" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "incoming-enabled": { + "type": "boolean" + }, + "outgoing-enabled": { + "type": "boolean" + }, + "only-trusted-servers": { + "type": "boolean" + } + } + }, "previews": { "type": "object", "required": [ diff --git a/openapi-federation.json b/openapi-federation.json index ed3d8cf2802..6445bbfeb70 100644 --- a/openapi-federation.json +++ b/openapi-federation.json @@ -41,6 +41,7 @@ "call", "chat", "conversations", + "federation", "previews", "signaling" ], @@ -150,6 +151,29 @@ } } }, + "federation": { + "type": "object", + "required": [ + "enabled", + "incoming-enabled", + "outgoing-enabled", + "only-trusted-servers" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "incoming-enabled": { + "type": "boolean" + }, + "outgoing-enabled": { + "type": "boolean" + }, + "only-trusted-servers": { + "type": "boolean" + } + } + }, "previews": { "type": "object", "required": [ diff --git a/openapi-full.json b/openapi-full.json index 931ef296dce..ba5cef35da5 100644 --- a/openapi-full.json +++ b/openapi-full.json @@ -158,6 +158,7 @@ "call", "chat", "conversations", + "federation", "previews", "signaling" ], @@ -267,6 +268,29 @@ } } }, + "federation": { + "type": "object", + "required": [ + "enabled", + "incoming-enabled", + "outgoing-enabled", + "only-trusted-servers" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "incoming-enabled": { + "type": "boolean" + }, + "outgoing-enabled": { + "type": "boolean" + }, + "only-trusted-servers": { + "type": "boolean" + } + } + }, "previews": { "type": "object", "required": [ diff --git a/openapi.json b/openapi.json index 297c180914e..9f7862926f8 100644 --- a/openapi.json +++ b/openapi.json @@ -99,6 +99,7 @@ "call", "chat", "conversations", + "federation", "previews", "signaling" ], @@ -208,6 +209,29 @@ } } }, + "federation": { + "type": "object", + "required": [ + "enabled", + "incoming-enabled", + "outgoing-enabled", + "only-trusted-servers" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "incoming-enabled": { + "type": "boolean" + }, + "outgoing-enabled": { + "type": "boolean" + }, + "only-trusted-servers": { + "type": "boolean" + } + } + }, "previews": { "type": "object", "required": [ diff --git a/src/components/AdminSettings/Federation.vue b/src/components/AdminSettings/Federation.vue index fddd334552a..a986be3d7dd 100644 --- a/src/components/AdminSettings/Federation.vue +++ b/src/components/AdminSettings/Federation.vue @@ -107,11 +107,11 @@ import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js' import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js' -const FEDERATION_ENABLED = loadState('spreed', 'federation_enabled', 'no') === 'yes' -const FEDERATION_INCOMING_ENABLED = loadState('spreed', 'federation_incoming_enabled', '0') === '1' -const FEDERATION_OUTGOING_ENABLED = loadState('spreed', 'federation_outgoing_enabled', '0') === '1' -const FEDERATION_ONLY_TRUSTED_SERVERS = loadState('spreed', 'federation_only_trusted_servers', '0') === '1' -const FEDERATION_ALLOWED_GROUPS = JSON.parse(loadState('spreed', 'federation_allowed_groups', '[]')) +const FEDERATION_ENABLED = loadState('spreed', 'federation_enabled', false) +const FEDERATION_INCOMING_ENABLED = loadState('spreed', 'federation_incoming_enabled', true) +const FEDERATION_OUTGOING_ENABLED = loadState('spreed', 'federation_outgoing_enabled', true) +const FEDERATION_ONLY_TRUSTED_SERVERS = loadState('spreed', 'federation_only_trusted_servers', false) +const FEDERATION_ALLOWED_GROUPS = loadState('spreed', 'federation_allowed_groups', []) export default { name: 'Federation', diff --git a/src/types/openapi/openapi-administration.ts b/src/types/openapi/openapi-administration.ts index 6af90988f2c..7c593a1f24a 100644 --- a/src/types/openapi/openapi-administration.ts +++ b/src/types/openapi/openapi-administration.ts @@ -131,6 +131,12 @@ export type components = { conversations: { "can-create": boolean; }; + federation: { + enabled: boolean; + "incoming-enabled": boolean; + "outgoing-enabled": boolean; + "only-trusted-servers": boolean; + }; previews: { /** Format: int64 */ "max-gif-size": number; diff --git a/src/types/openapi/openapi-backend-recording.ts b/src/types/openapi/openapi-backend-recording.ts index 4b68802b265..9c62cae160f 100644 --- a/src/types/openapi/openapi-backend-recording.ts +++ b/src/types/openapi/openapi-backend-recording.ts @@ -56,6 +56,12 @@ export type components = { conversations: { "can-create": boolean; }; + federation: { + enabled: boolean; + "incoming-enabled": boolean; + "outgoing-enabled": boolean; + "only-trusted-servers": boolean; + }; previews: { /** Format: int64 */ "max-gif-size": number; diff --git a/src/types/openapi/openapi-backend-signaling.ts b/src/types/openapi/openapi-backend-signaling.ts index 10098dee7b8..8a431dafdf9 100644 --- a/src/types/openapi/openapi-backend-signaling.ts +++ b/src/types/openapi/openapi-backend-signaling.ts @@ -55,6 +55,12 @@ export type components = { conversations: { "can-create": boolean; }; + federation: { + enabled: boolean; + "incoming-enabled": boolean; + "outgoing-enabled": boolean; + "only-trusted-servers": boolean; + }; previews: { /** Format: int64 */ "max-gif-size": number; diff --git a/src/types/openapi/openapi-backend-sipbridge.ts b/src/types/openapi/openapi-backend-sipbridge.ts index bbdf239a724..ab8a5879f80 100644 --- a/src/types/openapi/openapi-backend-sipbridge.ts +++ b/src/types/openapi/openapi-backend-sipbridge.ts @@ -72,6 +72,12 @@ export type components = { conversations: { "can-create": boolean; }; + federation: { + enabled: boolean; + "incoming-enabled": boolean; + "outgoing-enabled": boolean; + "only-trusted-servers": boolean; + }; previews: { /** Format: int64 */ "max-gif-size": number; diff --git a/src/types/openapi/openapi-bots.ts b/src/types/openapi/openapi-bots.ts index 182cc90d7b1..c4f3ef46656 100644 --- a/src/types/openapi/openapi-bots.ts +++ b/src/types/openapi/openapi-bots.ts @@ -61,6 +61,12 @@ export type components = { conversations: { "can-create": boolean; }; + federation: { + enabled: boolean; + "incoming-enabled": boolean; + "outgoing-enabled": boolean; + "only-trusted-servers": boolean; + }; previews: { /** Format: int64 */ "max-gif-size": number; diff --git a/src/types/openapi/openapi-federation.ts b/src/types/openapi/openapi-federation.ts index 9ab19f8d777..9995752ed30 100644 --- a/src/types/openapi/openapi-federation.ts +++ b/src/types/openapi/openapi-federation.ts @@ -71,6 +71,12 @@ export type components = { conversations: { "can-create": boolean; }; + federation: { + enabled: boolean; + "incoming-enabled": boolean; + "outgoing-enabled": boolean; + "only-trusted-servers": boolean; + }; previews: { /** Format: int64 */ "max-gif-size": number; diff --git a/src/types/openapi/openapi-full.ts b/src/types/openapi/openapi-full.ts index 6e379f3d35c..ca65decb1bb 100644 --- a/src/types/openapi/openapi-full.ts +++ b/src/types/openapi/openapi-full.ts @@ -576,6 +576,12 @@ export type components = { conversations: { "can-create": boolean; }; + federation: { + enabled: boolean; + "incoming-enabled": boolean; + "outgoing-enabled": boolean; + "only-trusted-servers": boolean; + }; previews: { /** Format: int64 */ "max-gif-size": number; diff --git a/src/types/openapi/openapi.ts b/src/types/openapi/openapi.ts index ec40b172cff..b58d20e7cf0 100644 --- a/src/types/openapi/openapi.ts +++ b/src/types/openapi/openapi.ts @@ -431,6 +431,12 @@ export type components = { conversations: { "can-create": boolean; }; + federation: { + enabled: boolean; + "incoming-enabled": boolean; + "outgoing-enabled": boolean; + "only-trusted-servers": boolean; + }; previews: { /** Format: int64 */ "max-gif-size": number; diff --git a/tests/php/CapabilitiesTest.php b/tests/php/CapabilitiesTest.php index 1c1862a3215..d62e84353a3 100644 --- a/tests/php/CapabilitiesTest.php +++ b/tests/php/CapabilitiesTest.php @@ -31,6 +31,7 @@ use OCA\Talk\Participant; use OCA\Talk\Room; use OCP\App\IAppManager; +use OCP\AppFramework\Services\IAppConfig; use OCP\Capabilities\IPublicCapability; use OCP\ICache; use OCP\ICacheFactory; @@ -44,6 +45,7 @@ class CapabilitiesTest extends TestCase { protected IConfig|MockObject $serverConfig; protected Config|MockObject $talkConfig; + protected IAppConfig|MockObject $appConfig; protected CommentsManager|MockObject $commentsManager; protected IUserSession|MockObject $userSession; protected IAppManager|MockObject $appManager; @@ -56,6 +58,7 @@ public function setUp(): void { parent::setUp(); $this->serverConfig = $this->createMock(IConfig::class); $this->talkConfig = $this->createMock(Config::class); + $this->appConfig = $this->createMock(IAppConfig::class); $this->commentsManager = $this->createMock(CommentsManager::class); $this->userSession = $this->createMock(IUserSession::class); $this->appManager = $this->createMock(IAppManager::class); @@ -148,6 +151,7 @@ public function setUp(): void { 'edit-messages', 'silent-send-state', 'chat-read-last', + 'federation-v1', 'message-expiration', 'reactions', ]; @@ -157,6 +161,7 @@ public function testGetCapabilitiesGuest(): void { $capabilities = new Capabilities( $this->serverConfig, $this->talkConfig, + $this->appConfig, $this->commentsManager, $this->userSession, $this->appManager, @@ -223,6 +228,12 @@ public function testGetCapabilitiesGuest(): void { 'conversations' => [ 'can-create' => false, ], + 'federation' => [ + 'enabled' => false, + 'incoming-enabled' => false, + 'outgoing-enabled' => false, + 'only-trusted-servers' => true, + ], 'previews' => [ 'max-gif-size' => 200000, ], @@ -255,6 +266,7 @@ public function testGetCapabilitiesUserAllowed(bool $isNotAllowed, bool $canCrea $capabilities = new Capabilities( $this->serverConfig, $this->talkConfig, + $this->appConfig, $this->commentsManager, $this->userSession, $this->appManager, @@ -351,6 +363,12 @@ public function testGetCapabilitiesUserAllowed(bool $isNotAllowed, bool $canCrea 'conversations' => [ 'can-create' => $canCreate, ], + 'federation' => [ + 'enabled' => false, + 'incoming-enabled' => false, + 'outgoing-enabled' => false, + 'only-trusted-servers' => true, + ], 'previews' => [ 'max-gif-size' => 200000, ], @@ -382,6 +400,7 @@ public function testGetCapabilitiesUserDisallowed(): void { $capabilities = new Capabilities( $this->serverConfig, $this->talkConfig, + $this->appConfig, $this->commentsManager, $this->userSession, $this->appManager, @@ -407,6 +426,7 @@ public function testCapabilitiesHelloV2Key(): void { $capabilities = new Capabilities( $this->serverConfig, $this->talkConfig, + $this->appConfig, $this->commentsManager, $this->userSession, $this->appManager, @@ -429,6 +449,7 @@ public function testConfigRecording(bool $enabled): void { $capabilities = new Capabilities( $this->serverConfig, $this->talkConfig, + $this->appConfig, $this->commentsManager, $this->userSession, $this->appManager, @@ -455,6 +476,7 @@ public function testCapabilitiesTranslations(): void { $capabilities = new Capabilities( $this->serverConfig, $this->talkConfig, + $this->appConfig, $this->commentsManager, $this->userSession, $this->appManager, diff --git a/tests/php/Settings/Admin/AdminSettingsTest.php b/tests/php/Settings/Admin/AdminSettingsTest.php index c5c13a02d88..023ea331d45 100644 --- a/tests/php/Settings/Admin/AdminSettingsTest.php +++ b/tests/php/Settings/Admin/AdminSettingsTest.php @@ -27,6 +27,7 @@ use OCA\Talk\MatterbridgeManager; use OCA\Talk\Service\CommandService; use OCA\Talk\Settings\Admin\AdminSettings; +use OCP\AppFramework\Services\IAppConfig; use OCP\AppFramework\Services\IInitialState; use OCP\ICacheFactory; use OCP\IConfig; @@ -43,6 +44,7 @@ class AdminSettingsTest extends TestCase { protected $talkConfig; /** @var IConfig|MockObject */ protected $serverConfig; + protected IAppConfig|MockObject $appConfig; /** @var CommandService|MockObject */ protected $commandService; /** @var IInitialState|MockObject */ @@ -66,6 +68,7 @@ public function setUp(): void { $this->talkConfig = $this->createMock(Config::class); $this->serverConfig = $this->createMock(IConfig::class); + $this->appConfig = $this->createMock(IAppConfig::class); $this->commandService = $this->createMock(CommandService::class); $this->initialState = $this->createMock(IInitialState::class); $this->cacheFactory = $this->createMock(ICacheFactory::class); @@ -87,6 +90,7 @@ protected function getAdminSettings(array $methods = []): AdminSettings { return new AdminSettings( $this->talkConfig, $this->serverConfig, + $this->appConfig, $this->commandService, $this->initialState, $this->cacheFactory, @@ -102,6 +106,7 @@ protected function getAdminSettings(array $methods = []): AdminSettings { ->setConstructorArgs([ $this->talkConfig, $this->serverConfig, + $this->appConfig, $this->commandService, $this->initialState, $this->cacheFactory,