Skip to content

Commit 900a6e8

Browse files
redblommickenordinMahdiBaghbani
committed
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 select provider and accept the invitation. - Listing of open invitations. - Option to resend, revoke open invitations. - Administer invitation settings Signed-off-by: Antoon P. <antoon.prins@surf.nl> Co-authored-by: Micke Nordin <kano@sunet.se> Co-authored-by: Mahdi Baghbani <mahdi-baghbani@azadehafzar.io>
1 parent 8e27e79 commit 900a6e8

54 files changed

Lines changed: 7683 additions & 65 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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949

5050
<background-jobs>
5151
<job>OCA\Contacts\Cron\SocialUpdateRegistration</job>
52+
<job>OCA\Contacts\Cron\UpdateOcmProviders</job>
53+
<job>OCA\Contacts\Cron\UpdateDeltaOcmProviders</job>
5254
</background-jobs>
5355

5456
<settings>

lib/AppInfo/Application.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,23 @@
77
namespace OCA\Contacts\AppInfo;
88

99
use OCA\Contacts\Capabilities;
10+
use OCA\Contacts\ConfigLexicon;
1011
use OCA\Contacts\Dav\PatchPlugin;
1112
use OCA\Contacts\Event\LoadContactsOcaApiEvent;
13+
use OCA\Contacts\Listener\FederatedInviteAcceptedListener;
1214
use OCA\Contacts\Listener\LoadContactsFilesActions;
1315
use OCA\Contacts\Listener\LoadContactsOcaApi;
16+
use OCA\Contacts\Listener\OcmDiscoveryListener;
1417
use OCA\DAV\Events\SabrePluginAddEvent;
1518
use OCA\Files\Event\LoadAdditionalScriptsEvent;
1619
use OCP\AppFramework\App;
1720
use OCP\AppFramework\Bootstrap\IBootContext;
1821
use OCP\AppFramework\Bootstrap\IBootstrap;
1922
use OCP\AppFramework\Bootstrap\IRegistrationContext;
2023
use OCP\EventDispatcher\IEventDispatcher;
24+
use OCP\OCM\Events\LocalOCMDiscoveryEvent;
25+
use OCP\OCM\Events\OCMEndpointRequestEvent;
26+
use OCP\OCM\Events\ResourceTypeRegisterEvent;
2127

2228
class Application extends App implements IBootstrap {
2329
public const APP_ID = 'contacts';
@@ -37,8 +43,15 @@ public function __construct() {
3743
#[\Override]
3844
public function register(IRegistrationContext $context): void {
3945
$context->registerCapability(Capabilities::class);
46+
$context->registerConfigLexicon(ConfigLexicon::class);
47+
4048
$context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadContactsFilesActions::class);
4149
$context->registerEventListener(LoadContactsOcaApiEvent::class, LoadContactsOcaApi::class);
50+
$context->registerEventListener(OCMEndpointRequestEvent::class, FederatedInviteAcceptedListener::class);
51+
$ocmDiscoveryEvent = class_exists(LocalOCMDiscoveryEvent::class)
52+
? LocalOCMDiscoveryEvent::class
53+
: ResourceTypeRegisterEvent::class;
54+
$context->registerEventListener($ocmDiscoveryEvent, OcmDiscoveryListener::class);
4255
}
4356

4457
#[\Override]

lib/ConfigLexicon.php

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
namespace OCA\Contacts;
11+
12+
use OCP\Config\Lexicon\Entry;
13+
use OCP\Config\Lexicon\ILexicon;
14+
use OCP\Config\Lexicon\Strictness;
15+
use OCP\Config\ValueType;
16+
use OCP\IAppConfig;
17+
18+
/**
19+
* Config Lexicon for contacts.
20+
*
21+
* Please add and manage your config keys in this file and keep the
22+
* Lexicon up to date.
23+
*
24+
* {@see ILexicon}
25+
*/
26+
class ConfigLexicon implements ILexicon {
27+
public const OCM_INVITES_ENABLED = 'ocm_invites_enabled';
28+
public const OCM_INVITES_OPTIONAL_MAIL = 'ocm_invites_optional_mail';
29+
public const OCM_INVITES_ENCODED_COPY_BUTTON = 'ocm_invites_encoded_copy_button';
30+
public const OCM_INVITES_DISABLE_SSRF_GUARD = 'ocm_invites_disable_ssrf_guard';
31+
public const MESH_PROVIDERS_SERVICE = 'mesh_providers_service';
32+
public const WAYF_ENDPOINT = 'wayf_endpoint';
33+
public const FEDERATIONS_CACHE = 'federations_cache';
34+
public const FEDERATIONS_CACHE_EXPIRES = 'expires';
35+
public const FEDERATIONS_CACHE_DELTA_EXPIRES = 'delta_expires';
36+
37+
#[\Override]
38+
public function getStrictness(): Strictness {
39+
return Strictness::NOTICE;
40+
}
41+
42+
#[\Override]
43+
public function getAppConfigs(): array {
44+
return [
45+
new Entry(
46+
self::OCM_INVITES_ENABLED,
47+
ValueType::BOOL,
48+
defaultRaw: false,
49+
definition: 'Whether OCM invites for contacts are enabled.',
50+
lazy: true,
51+
),
52+
new Entry(
53+
self::OCM_INVITES_OPTIONAL_MAIL,
54+
ValueType::BOOL,
55+
defaultRaw: false,
56+
definition: 'Whether the recipient email field is optional when creating an OCM invite.',
57+
lazy: true,
58+
),
59+
new Entry(
60+
self::OCM_INVITES_ENCODED_COPY_BUTTON,
61+
ValueType::BOOL,
62+
defaultRaw: false,
63+
definition: 'Whether the invite email "Open invite" button uses the encoded WAYF URL instead of the raw token.',
64+
lazy: true,
65+
),
66+
new Entry(
67+
self::OCM_INVITES_DISABLE_SSRF_GUARD,
68+
ValueType::BOOL,
69+
defaultRaw: false,
70+
definition: 'Unsafe development override that disables private-host and localhost checks for OCM invite discovery.',
71+
lazy: true,
72+
),
73+
new Entry(
74+
self::MESH_PROVIDERS_SERVICE,
75+
ValueType::STRING,
76+
defaultRaw: '',
77+
definition: 'Space-separated list of mesh provider service URLs used for WAYF discovery.',
78+
lazy: true,
79+
),
80+
new Entry(
81+
self::WAYF_ENDPOINT,
82+
ValueType::STRING,
83+
defaultRaw: '',
84+
definition: 'Optional override for the base WAYF endpoint used in invite links.',
85+
note: 'If empty, the app route is used at runtime.',
86+
lazy: true,
87+
),
88+
new Entry(
89+
self::FEDERATIONS_CACHE,
90+
ValueType::ARRAY,
91+
defaultRaw: [],
92+
definition: 'Internal cron-maintained cache for discovered federations and expiry metadata.',
93+
flags: IAppConfig::FLAG_SENSITIVE,
94+
lazy: true,
95+
),
96+
new Entry(
97+
self::FEDERATIONS_CACHE_EXPIRES,
98+
ValueType::INT,
99+
defaultRaw: 0,
100+
definition: 'Federations cache refresh expiration time.',
101+
lazy: true,
102+
),
103+
new Entry(
104+
self::FEDERATIONS_CACHE_DELTA_EXPIRES,
105+
ValueType::INT,
106+
defaultRaw: 0,
107+
definition: 'Federations cache update (delta) expiration time.',
108+
lazy: true,
109+
),
110+
];
111+
}
112+
113+
#[\Override]
114+
public function getUserConfigs(): array {
115+
return [];
116+
}
117+
}

0 commit comments

Comments
 (0)