summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/avatar.md2
-rw-r--r--docs/capabilities.md5
-rw-r--r--docs/chat.md8
-rw-r--r--docs/conversation.md23
-rw-r--r--docs/global.md16
-rw-r--r--docs/participant.md5
-rw-r--r--docs/reaction.md3
-rw-r--r--lib/Capabilities.php19
-rw-r--r--lib/ResponseDefinitions.php6
-rw-r--r--lib/Settings/Admin/AdminSettings.php12
-rw-r--r--openapi-administration.json24
-rw-r--r--openapi-backend-recording.json24
-rw-r--r--openapi-backend-signaling.json24
-rw-r--r--openapi-backend-sipbridge.json24
-rw-r--r--openapi-bots.json24
-rw-r--r--openapi-federation.json24
-rw-r--r--openapi-full.json24
-rw-r--r--openapi.json24
-rw-r--r--src/components/AdminSettings/Federation.vue10
-rw-r--r--src/types/openapi/openapi-administration.ts6
-rw-r--r--src/types/openapi/openapi-backend-recording.ts6
-rw-r--r--src/types/openapi/openapi-backend-signaling.ts6
-rw-r--r--src/types/openapi/openapi-backend-sipbridge.ts6
-rw-r--r--src/types/openapi/openapi-bots.ts6
-rw-r--r--src/types/openapi/openapi-federation.ts6
-rw-r--r--src/types/openapi/openapi-full.ts6
-rw-r--r--src/types/openapi/openapi.ts6
-rw-r--r--tests/php/CapabilitiesTest.php22
-rw-r--r--tests/php/Settings/Admin/AdminSettingsTest.php5
29 files changed, 366 insertions, 10 deletions
diff --git a/docs/avatar.md b/docs/avatar.md
index b63b8e145..7fc908c44 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 c0d746cd7..1f8987a1e 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 358e0b976..4a02511cf 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 a043aa9d5..bcb13ce24 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 a1e728a76..6ae8ff84a 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 d46380863..157f420fa 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 0185886ff..1373c249f 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 f7648cacb..2f288ff8f 100644
--- a/lib/Capabilities.php
+++ b/lib/Capabilities.php
@@ -28,6 +28,7 @@ namespace OCA\Talk;
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 @@ class Capabilities implements IPublicCapability {
'edit-messages',
'silent-send-state',
'chat-read-last',
+ 'federation-v1',
],
'config' => [
'attachments' => [
@@ -163,6 +166,12 @@ class Capabilities implements IPublicCapability {
'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 @@ class Capabilities implements IPublicCapability {
'version' => $this->appManager->getAppVersion('spreed'),
];
+
if ($this->serverConfig->getAppValue('core', 'backgroundjobs_mode', 'ajax') === 'cron') {
$capabilities['features'][] = 'message-expiration';
}
@@ -182,6 +192,15 @@ class Capabilities implements IPublicCapability {
}
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 1f257d822..522466350 100644
--- a/lib/ResponseDefinitions.php
+++ b/lib/ResponseDefinitions.php
@@ -308,6 +308,12 @@ namespace OCA\Talk;
* 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 2d3893a4d..ddffc99a9 100644
--- a/lib/Settings/Admin/AdminSettings.php
+++ b/lib/Settings/Admin/AdminSettings.php
@@ -31,6 +31,7 @@ use OCA\Talk\Participant;
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 $