Skip to content

Commit 55dafdf

Browse files
redblommickenordin
andcommitted
feat(OCM-Invites): Implement exchanging cloud IDs through OCM invitation workflow
see https://github.com/cs3org/OCM-API/blob/v1.2.1/IETF-RFC.md Features: - Button to invite remote users to exchange cloudIDs. - Button to manually accept invite to exchange cloudIDs. - WAYF page allowing the receiver of the invite to open and accept the invitation. - Listing of open invitations. - Option to resend, revoke open invitations. Signed-off-by: Antoon P. <antoon.prins@surf.nl> Co-authored-by: Micke Nordin <kano@sunet.se>
1 parent f941d0b commit 55dafdf

42 files changed

Lines changed: 3085 additions & 29 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

appinfo/info.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949

5050
<background-jobs>
5151
<job>OCA\Contacts\Cron\SocialUpdateRegistration</job>
52+
<job>OCA\Contacts\Cron\UpdateOcmProviders</job>
5253
</background-jobs>
5354

5455
<settings>
@@ -67,4 +68,10 @@
6768
<contactsmenu>
6869
<provider>OCA\Contacts\ContactsMenu\Providers\DetailsProvider</provider>
6970
</contactsmenu>
71+
72+
<commands>
73+
<command>OCA\Contacts\Command\EnableOcmInvites</command>
74+
<command>OCA\Contacts\Command\DisableOcmInvites</command>
75+
<command>OCA\Contacts\Command\SetMeshProvidersService</command>
76+
</commands>
7077
</info>

appinfo/routes.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,22 @@
55
* SPDX-License-Identifier: AGPL-3.0-or-later
66
*/
77

8+
use OCA\Contacts\Service\FederatedInvitesService;
9+
810
return [
911
'routes' => [
1012
['name' => 'contacts#direct', 'url' => '/direct/contact/{contact}', 'verb' => 'GET'],
1113
['name' => 'contacts#directcircle', 'url' => '/direct/circle/{singleId}', 'verb' => 'GET'],
14+
15+
['name' => 'federated_invites#get_invites', 'url' => '/ocm/invitations', 'verb' => 'GET'],
16+
['name' => 'federated_invites#delete_invite', 'url' => '/ocm/invitations/{token}', 'verb' => 'DELETE'],
17+
['name' => 'federated_invites#create_invite', 'url' => '/ocm/invitations', 'verb' => 'POST'],
18+
['name' => 'federated_invites#accept_invite', 'url' => '/ocm/invitations/{token}/accept', 'verb' => 'PATCH'],
19+
['name' => 'federated_invites#resend_invite', 'url' => '/ocm/invitations/{token}/resend', 'verb' => 'PATCH'],
20+
['name' => 'federated_invites#invite_accept_dialog', 'url' => FederatedInvitesService::OCM_INVITE_ACCEPT_DIALOG_ROUTE, 'verb' => 'GET'],
21+
['name' => 'federated_invites#wayf', 'url' => '/wayf', 'verb' => 'GET'],
22+
['name' => 'federated_invites#discover', 'url' => '/discover', 'verb' => 'GET'],
23+
1224
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
1325
['name' => 'page#index', 'url' => '/{group}', 'verb' => 'GET', 'postfix' => 'group'],
1426
['name' => 'page#index', 'url' => '/{group}/{contact}', 'verb' => 'GET', 'postfix' => 'group.contact'],

lib/AppInfo/Application.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,19 @@
99
use OCA\Contacts\Capabilities;
1010
use OCA\Contacts\Dav\PatchPlugin;
1111
use OCA\Contacts\Event\LoadContactsOcaApiEvent;
12+
use OCA\Contacts\Listener\FederatedInviteAcceptedListener;
1213
use OCA\Contacts\Listener\LoadContactsFilesActions;
1314
use OCA\Contacts\Listener\LoadContactsOcaApi;
15+
use OCA\Contacts\Listener\OcmDiscoveryListener;
1416
use OCA\DAV\Events\SabrePluginAddEvent;
1517
use OCA\Files\Event\LoadAdditionalScriptsEvent;
1618
use OCP\AppFramework\App;
1719
use OCP\AppFramework\Bootstrap\IBootContext;
1820
use OCP\AppFramework\Bootstrap\IBootstrap;
1921
use OCP\AppFramework\Bootstrap\IRegistrationContext;
2022
use OCP\EventDispatcher\IEventDispatcher;
23+
use OCP\OCM\Events\LocalOCMDiscoveryEvent;
24+
use OCP\OCM\Events\OCMEndpointRequestEvent;
2125

2226
class Application extends App implements IBootstrap {
2327
public const APP_ID = 'contacts';
@@ -33,8 +37,11 @@ public function __construct() {
3337
#[\Override]
3438
public function register(IRegistrationContext $context): void {
3539
$context->registerCapability(Capabilities::class);
40+
3641
$context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadContactsFilesActions::class);
3742
$context->registerEventListener(LoadContactsOcaApiEvent::class, LoadContactsOcaApi::class);
43+
$context->registerEventListener(OCMEndpointRequestEvent::class, FederatedInviteAcceptedListener::class);
44+
$context->registerEventListener(LocalOCMDiscoveryEvent::class, OcmDiscoveryListener::class);
3845
}
3946

4047
#[\Override]

lib/Command/DisableOcmInvites.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
/**
4+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-License-Identifier: AGPL-3.0-only
6+
*/
7+
8+
namespace OCA\Contacts\Command;
9+
10+
use OC\Core\AppInfo\ConfigLexicon;
11+
use OCP\IAppConfig;
12+
use Symfony\Component\Console\Command\Command;
13+
use Symfony\Component\Console\Input\InputInterface;
14+
use Symfony\Component\Console\Output\OutputInterface;
15+
16+
class DisableOcmInvites extends Command {
17+
public function __construct(
18+
protected IAppConfig $appConfig,
19+
) {
20+
parent::__construct();
21+
}
22+
23+
protected function configure(): void {
24+
$this
25+
->setName('contacts:disable-ocm-invites')
26+
->setDescription('Disable OCM Invites.');
27+
}
28+
29+
protected function execute(InputInterface $input, OutputInterface $output): int {
30+
$isEnabled = $this->appConfig->getValueBool('contacts', 'ocm_invites_enabled');
31+
if (!$isEnabled) {
32+
$output->writeln('OCM Invites already disabled.');
33+
return self::SUCCESS;
34+
}
35+
36+
$this->appConfig->setValueBool('contacts', 'ocm_invites_enabled', false);
37+
$this->appConfig->deleteKey('core', ConfigLexicon::OCM_INVITE_ACCEPT_DIALOG);
38+
$output->writeln('OCM Invites successfully disabled.');
39+
return self::SUCCESS;
40+
}
41+
}

lib/Command/EnableOcmInvites.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/**
4+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-License-Identifier: AGPL-3.0-only
6+
*/
7+
8+
namespace OCA\Contacts\Command;
9+
10+
use OCP\IAppConfig;
11+
use Symfony\Component\Console\Command\Command;
12+
use Symfony\Component\Console\Input\InputInterface;
13+
use Symfony\Component\Console\Output\OutputInterface;
14+
15+
class EnableOcmInvites extends Command {
16+
public function __construct(
17+
protected IAppConfig $appConfig,
18+
) {
19+
parent::__construct();
20+
}
21+
22+
protected function configure(): void {
23+
$this
24+
->setName('contacts:enable-ocm-invites')
25+
->setDescription('Enable OCM Invites.');
26+
}
27+
28+
protected function execute(InputInterface $input, OutputInterface $output): int {
29+
$isAlreadyEnabled = $this->appConfig->getValueBool('contacts', 'ocm_invites_enabled');
30+
31+
if ($isAlreadyEnabled) {
32+
$output->writeln('OCM Invites already enabled.');
33+
return self::SUCCESS;
34+
}
35+
36+
$this->appConfig->setValueBool('contacts', 'ocm_invites_enabled', true);
37+
$this->appConfig->setValueString('core', 'ocm_invite_accept_dialog', 'contacts.federated_invites.invite_accept_dialog');
38+
39+
$output->writeln('OCM Invites successfully enabled.');
40+
return self::SUCCESS;
41+
}
42+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-only
8+
*/
9+
10+
namespace OCA\Contacts\Command;
11+
12+
use OCP\IConfig;
13+
use Symfony\Component\Console\Command\Command;
14+
use Symfony\Component\Console\Input\InputArgument;
15+
use Symfony\Component\Console\Input\InputInterface;
16+
use Symfony\Component\Console\Output\OutputInterface;
17+
18+
class SetMeshProvidersService extends Command {
19+
20+
public function __construct(
21+
protected IConfig $config,
22+
) {
23+
parent::__construct();
24+
}
25+
26+
protected function configure(): void {
27+
$this->setName('contacts:set-mesh-providers-service');
28+
$this->addArgument(
29+
'mesh-providers-service',
30+
InputArgument::REQUIRED,
31+
'The URL to the OCM Discovery Service'
32+
);
33+
}
34+
35+
public function execute(InputInterface $input, OutputInterface $output): int {
36+
$disco = $input->getArgument('mesh-providers-service');
37+
$this->config->setAppValue('contacts', 'mesh_providers_service', $disco);
38+
$output->writeln('OCM Discovery Service successfully configured.');
39+
return self::SUCCESS;
40+
}
41+
}

0 commit comments

Comments
 (0)