Skip to content

Conversation

@redblom
Copy link

@redblom redblom commented Apr 8, 2025

This is a work in progress
This PR implements #4416

@hamza221 hamza221 added enhancement New feature or request 2. developing Work in progress labels Apr 8, 2025
@hamza221 hamza221 marked this pull request as draft April 8, 2025 09:14
@redblom
Copy link
Author

redblom commented Apr 8, 2025

General layout plan:

  • dedicated button to send an invite to a remote user - below 'New contact' button
  • dedicated button on cloud ID component for existing remote contacts that have no cloud ID set
  • new sent invites will be displayed in the left panel - with a revoke option

Status:

  • invite accept dialog route implemented

@hamza221 hamza221 added this to the v7.1.0 milestone Apr 10, 2025
@redblom redblom force-pushed the invite-for-cloudid-exchange branch from ea81812 to 7c0eaa0 Compare April 10, 2025 20:45
@github-actions
Copy link

Hello there,
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.

We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.

Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6

Thank you for contributing to Nextcloud and we hope to hear from you soon!

(If you believe you should not receive this message, you can add yourself to the blocklist.)

@codecov
Copy link

codecov bot commented Apr 24, 2025

Codecov Report

❌ Patch coverage is 1.10865% with 446 lines in your changes missing coverage. Please review.
✅ Project coverage is 1.84%. Comparing base (c98a2da) to head (5b7820f).

Files with missing lines Patch % Lines
src/views/Contacts.vue 0.00% 90 Missing ⚠️
src/components/Properties/PropertyCloudId.vue 0.00% 72 Missing ⚠️
src/components/Ocm/OcmInvitesList.vue 0.00% 53 Missing ⚠️
src/components/Ocm/Wayf.vue 0.00% 44 Missing ⚠️
src/store/ocminvites.js 10.41% 42 Missing and 1 partial ⚠️
src/components/Ocm/OcmInviteDetails.vue 0.00% 41 Missing ⚠️
src/components/AppContent/OcmInvitesContent.vue 0.00% 33 Missing ⚠️
src/components/Ocm/OcmInviteForm.vue 0.00% 18 Missing ⚠️
src/components/AppNavigation/RootNavigation.vue 0.00% 14 Missing ⚠️
src/components/Ocm/OcmInvitesListItem.vue 0.00% 13 Missing ⚠️
... and 5 more

❗ There is a different number of reports uploaded between BASE (c98a2da) and HEAD (5b7820f). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (c98a2da) HEAD (5b7820f)
2 1
Additional details and impacted files
@@             Coverage Diff             @@
##               main   #4417      +/-   ##
===========================================
- Coverage     10.76%   1.84%   -8.93%     
===========================================
  Files           128     113      -15     
  Lines          6512    6082     -430     
  Branches       1191    1270      +79     
===========================================
- Hits            701     112     -589     
- Misses         5690    5847     +157     
- Partials        121     123       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ChristophWurst
Copy link
Member

Thanks for the contribution, @redblom!

The features relies on an implementation of the Invitation Workflow (see https://github.com/sara-nl/nc-collaboration).

Is there any way this could work without introducing an app dependency?

@hamza221 hamza221 modified the milestones: v7.1.0, v7.2.0 Apr 28, 2025
@redblom
Copy link
Author

redblom commented Apr 29, 2025

Thanks for the contribution, @redblom!

The features relies on an implementation of the Invitation Workflow (see https://github.com/sara-nl/nc-collaboration).

Is there any way this could work without introducing an app dependency?

Short answer: No, that is to say, the actual cloud ID exchange is not a responsibility of the contacts app but the contacts app (the cloud ID field) is a logical place where to have this option (as per earlier discussion with the Design Team).
The feature actually depends on the implementation of OCM /invite-accepted. This is currently in the process of being implemented for nextcloud server core (nextcloud/server#51113) so cloud ID exchange can become an integral part of nextcloud. Up until then there should be an app present implementing this.
The idea is to make the option not visible to the user when the platform can not do the actual cloud ID exchange (by configuration).
(so the best answer is: yes, when cloud ID exchange has become an integral part of nextcloud :)

@redblom redblom force-pushed the invite-for-cloudid-exchange branch 2 times, most recently from 0112a78 to e7c2604 Compare April 30, 2025 14:32
@ChristophWurst
Copy link
Member

Thanks for the clarification

@ChristophWurst ChristophWurst requested review from ArtificialOwl and removed request for GVodyanov, SebastianKrupinski and hamza221 May 15, 2025 12:09
@redblom redblom force-pushed the invite-for-cloudid-exchange branch 5 times, most recently from 76d6df3 to ca42433 Compare June 18, 2025 14:33
@redblom redblom force-pushed the invite-for-cloudid-exchange branch from ca42433 to 62ce0c2 Compare June 26, 2025 08:21
@redblom
Copy link
Author

redblom commented Sep 19, 2025

Do we want to 'cc' the invitation email to the sender as well (by default or configurable) ? Eg. in case the receiver loses the invitation mail it would allow the sender to simply resend the invitation from the email client instead of having to create a new one (and revoke the old one) from the contacts app. * Another (possible future) option would be a resend button on the invitation details page.

I think a "resend button" makes sense, maybe along with a check box that is unchecked by default to send the invitation to the sender as well.

We do not persist the optional personal message with the invite. So that's lost for a resend. But in order to correlate to the previously sent invite, what we can do is to use a new message like:
"This is a copy of an invite send to you previously by $initiatorDisplayName on $sendDate"

Fwiw I prefer this to persisting the message.

@redblom redblom force-pushed the invite-for-cloudid-exchange branch 3 times, most recently from 9f0bca4 to 55647b8 Compare September 25, 2025 12:36
@mickenordin
Copy link

Adding some screenshots here to show you what it looks like, this is the dialog for adding a new invitation:
2025-09-25T16:01:24,021984991+02:00
This is what it looks like after it is sent:
2025-09-25T16:01:40,518818898+02:00
This is the default Where-Are-You-From page, when no federation has been configured
2025-09-25T16:05:10,821218256+02:00
This is what the WAYF-page looks like with a federation configured:
2025-09-25T16:06:40,570032364+02:00
It is also possible to add multiple federations:
2025-09-25T16:14:34,777039486+02:00
This is what the type-to-search feature looks like:
2025-09-25T16:14:50,748780755+02:00

@mickenordin
Copy link

Thanks for the contribution, @redblom!

The features relies on an implementation of the Invitation Workflow (see https://github.com/sara-nl/nc-collaboration).

Is there any way this could work without introducing an app dependency?

All the necessary plumbing is in Nextcloud 32.0.0.0rc4 so no external apps needed anymore.

@redblom redblom changed the title [WIP] exchange cloud ID feat: exchange cloud ID Sep 26, 2025
@redblom redblom marked this pull request as ready for review September 26, 2025 08:20
@redblom redblom force-pushed the invite-for-cloudid-exchange branch from 55647b8 to 20fc781 Compare September 26, 2025 08:52
@ChristophWurst ChristophWurst added 3. to review Waiting for reviews and removed 2. developing Work in progress labels Sep 26, 2025
@redblom redblom force-pushed the invite-for-cloudid-exchange branch 3 times, most recently from e51a605 to 153fdb1 Compare October 3, 2025 09:39
@redblom redblom force-pushed the invite-for-cloudid-exchange branch from 3fba972 to f9574de Compare October 13, 2025 16:16
@redblom redblom force-pushed the invite-for-cloudid-exchange branch from 26a76f8 to 2272c9f Compare October 29, 2025 15:05
@redblom
Copy link
Author

redblom commented Oct 29, 2025

@ArtificialOwl could you give it a go, the review.

Copy link
Member

@ArtificialOwl ArtificialOwl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

quick review, not fully complete, but already some elements to rework

* @return string the WAYF login page endpoint
*/
public function getWayfEndpoint(): string {
$wayfEndpoint = 'https://' . $this->federatedInvitesService->getProviderFQDN() . '/apps/' . Application::APP_ID . self::WAYF_ROUTE;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a possibility that contacts is installed in /custom_apps/, not sure this endpoint would 100% work


public function getMeshProvidersFromCache(): array {
$json = $this->appConfig->getValueString(Application::APP_ID, 'federations_cache');
$data = json_decode($json, true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use getValueArray() / setValueArray() and set the config value as lazy

* Interface IWayfProvider.
*
*/
interface IWayfProvider {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it does not feel like an interface is really needed

}

protected function execute(InputInterface $input, OutputInterface $output): int {
$isAlreadyDisabled = $this->appConfig->getValueBool('contacts', 'ocm_invites_enabled') === false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getValueBool is already a boolean, no need for comparaison

}

$this->appConfig->setValueBool('contacts', 'ocm_invites_enabled', false);
$this->appConfig->deleteKey('core', 'ocm_invite_accept_dialog');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be better to use OC\Core\AppInfo\ConfigLexicon::OCM_INVITE_ACCEPT_DIALOG despite being from private OC\


public function isOcmInvitesEnabled():bool {
$val = $this->appConfig->getValueBool(Application::APP_ID, 'ocm_invites_enabled', FederatedInvitesService::OCM_INVITES_ENABLED_BY_DEFAULT);
$boolval = (is_string($val) ? filter_var($val, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) : (bool)$val);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getValueBool() will always returns boolean

* @return JSONResponse
*/
#[NoAdminRequired]
#[NoCSRFRequired]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why no CSRF ? is the endpoint to be requested from a remote instance ?

#[NoAdminRequired]
#[NoCSRFRequired]
public function deleteInvite(string $token): JSONResponse {
if (!isset($token)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the feeling $token is always set

$data = $this->wayfProvider->getMeshProviders();
$data['expires'] = time() + $this->expire_time;
$json = json_encode($data);
$this->appConfig->setValueString(Application::APP_ID, 'federations_cache', $json);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as said somewhere else, use setValueArray() and set it as lazy

/**
* @template-extends QBMapper<FederatedInvite>
*/
class FederatedInviteMapper extends DbFederatedInviteMapper {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a huge fan of this,
if the DB is created and managed from cloud_federation_api, could this request be also integrated to the app, and calling an API from the cloud_federation_api to select/update/delete data from/to database ?

Copy link
Author

@redblom redblom Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I understand correctly that you propose to specify a db layer API/interface in cloud_federation_api and let the contacts app implement that? Meaning that cloud_federation_api can only access the db (and be functional) if there is an app implementing the API (the contacts app in this case)?

antoonp and others added 8 commits November 20, 2025 16:14
…ion 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: antoonp <[email protected]>
Co-authored-by: Micke Nordin <[email protected]>
IWayfProvider is redundant.
Use core config lexicon.
@redblom redblom force-pushed the invite-for-cloudid-exchange branch from 069d061 to 86027f9 Compare November 20, 2025 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review Waiting for reviews enhancement New feature or request feedback-requested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants