Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(contactsMenu): Attach user cloud to each contact entry #44954

Draft
wants to merge 1 commit into
base: stable29
Choose a base branch
from

Conversation

nfebe
Copy link
Contributor

@nfebe nfebe commented Apr 22, 2024

The contact entry should carry cloud information, this can help to fix various issues including:

  • Displaying correct avatar links for federated users

This can also lead to UI improvements in the frontend where, it's federated contacts are shown with a marker or indicator on the UI.

Summary

TODO

  • ...

Checklist

@nfebe nfebe force-pushed the 44319-fix-fed-share-user-avatars branch 2 times, most recently from 70f529c to fe83f91 Compare April 22, 2024 09:08
lib/private/Contacts/ContactsMenu/Entry.php Fixed Show fixed Hide fixed
lib/private/Contacts/ContactsMenu/Entry.php Fixed Show fixed Hide fixed
$this->cloud = $cloudId;
}

public function getCloud(): CloudId {

Check failure

Code scanning / Psalm

InvalidNullableReturnType Error

The declared return type 'OC\Federation\CloudId' for OC\Contacts\ContactsMenu\Entry::getCloud is not nullable, but 'OC\Federation\CloudId|null' contains null
}

public function getCloud(): CloudId {
return $this->cloud;

Check failure

Code scanning / Psalm

NullableReturnStatement Error

The declared return type 'OC\Federation\CloudId' for OC\Contacts\ContactsMenu\Entry::getCloud is not nullable, but the function returns 'OC\Federation\CloudId|null'
@nfebe nfebe force-pushed the 44319-fix-fed-share-user-avatars branch from fe83f91 to 8640581 Compare April 22, 2024 15:34
Copy link
Contributor Author

@nfebe nfebe left a comment

Choose a reason for hiding this comment

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

To solve this issue we could simple use the isUser property of the contact along side isNouser boolean of NcAvatar to show the text generated icons.

However, here:

  • I instead try to link to the actual avatars on the remote server, since the links public
  • I am adding the cloud data to be passed to the frontend

Problems:

  • This code is able to load the avatars from a federated server but would like to "Content Security Policy" errors if the remote server is unsecured.

There are other places in the code base such as here where the current approach is used but we could swap if this attempt to directly load the avatars from the federated server is successful/useful.

@nickvergessen since you are familiar with section of the code, does this approach make sense?

@nfebe nfebe force-pushed the 44319-fix-fed-share-user-avatars branch from 8640581 to 2b1c1ab Compare April 22, 2024 15:43
The contact entry should carry cloud information, this can help to fix various issues including:

- Displaying correct avatar links for federated users

This can also lead to UI improvements in the frontend where, it's federated contacts are shown with
a marker or indicator on the UI.

Signed-off-by: fenn-cs <[email protected]>
@nfebe nfebe force-pushed the 44319-fix-fed-share-user-avatars branch from 2b1c1ab to 990d244 Compare April 22, 2024 15:46
} elseif (!empty($contact['FN'])) {
$avatar = $this->urlGenerator->linkToRouteAbsolute('core.GuestAvatar.getAvatar', ['guestName' => str_replace('/', ' ', $contact['FN']), 'size' => 64]);
} elseif ($username != '') {
$avatar = $this->urlGenerator->linkToRemoteRouteAbsolute($remoteServer, 'core.avatar.getAvatar', ['userId' => str_replace('/', ' ', $username), 'size' => 64]);

Check failure

Code scanning / Psalm

UndefinedInterfaceMethod Error

Method OCP\IURLGenerator::linkToRemoteRouteAbsolute does not exist
} else {
$avatar = $this->urlGenerator->linkToRouteAbsolute('core.GuestAvatar.getAvatar', ['guestName' => str_replace('/', ' ', $uid), 'size' => 64]);
$avatar = $this->urlGenerator->linkToRemoteRouteAbsolute($remoteServer, 'core.avatar.getAvatar', ['userId' => str_replace('/', ' ', $uid), 'size' => 64]);

Check failure

Code scanning / Psalm

UndefinedInterfaceMethod Error

Method OCP\IURLGenerator::linkToRemoteRouteAbsolute does not exist

public function setId(string $id): void {
$this->id = $id;
}

public function getId(): string {

Check failure

Code scanning / Psalm

InvalidNullableReturnType Error

The declared return type 'string' for OC\Contacts\ContactsMenu\Entry::getId is not nullable, but 'null|string' contains null

public function setId(string $id): void {
$this->id = $id;
}

public function getId(): string {
return $this->id;

Check failure

Code scanning / Psalm

NullableReturnStatement Error

The declared return type 'string' for OC\Contacts\ContactsMenu\Entry::getId is not nullable, but the function returns 'null|string'
@@ -115,6 +115,19 @@
return $this->getAbsoluteURL($this->linkToRoute($routeName, $arguments));
}


public function linkToRemoteRouteAbsolute(string $remote, $routeName, array $arguments = []): string {

Check failure

Code scanning / Psalm

InvalidNullableReturnType Error

The declared return type 'string' for OC\URLGenerator::linkToRemoteRouteAbsolute is not nullable, but 'null|string' contains null
@@ -115,6 +115,19 @@
return $this->getAbsoluteURL($this->linkToRoute($routeName, $arguments));
}


public function linkToRemoteRouteAbsolute(string $remote, $routeName, array $arguments = []): string {
return $this->formatAsUrl($remote, $this->linkToRoute($routeName, $arguments));

Check failure

Code scanning / Psalm

NullableReturnStatement Error

The declared return type 'string' for OC\URLGenerator::linkToRemoteRouteAbsolute is not nullable, but the function returns 'null|string'
$remoteServer = '';

if (isset($contact['CLOUD']) && is_array($contact['CLOUD']) && isset($contact['CLOUD'][0])) {
preg_match('/^(.*?)@(https?:\/\/.*?)$/', $contact['CLOUD'][0], $matches);
Copy link
Member

Choose a reason for hiding this comment

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

Please use the ICloudManager::resolve() method instead?

/**
* @return array{id: int|string|null, fullName: string, avatar: string|null, topAction: mixed, actions: array, lastMessage: '', emailAddresses: string[], profileTitle: string|null, profileUrl: string|null, status: string|null, statusMessage: null|string, statusMessageTimestamp: null|int, statusIcon: null|string, isUser: bool, uid: mixed}
* @return array{id: int|string|null, fullName: string, avatar: string|null, topAction: mixed, actions: array, lastMessage: '', emailAddresses: string[], profileTitle: string|null, profileUrl: string|null, status: string|null, statusMessage: null|string, statusMessageTimestamp: null|int, statusIcon: null|string, isUser: bool, uid: mixed, cloud: mixed}
Copy link
Member

Choose a reason for hiding this comment

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

cloud should be called cloudId to be more clear and the type should be the array you define in the other file

/**
* @return array{id: string, user: string, remote: string, displayName: string|null}
*/
public function jsonSerialize(): array {
Copy link
Member

Choose a reason for hiding this comment

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

Should implement the interface JsonSerializable?

Copy link
Member

Choose a reason for hiding this comment

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

That being said, should be on the public interface?

} elseif (!empty($contact['FN'])) {
$avatar = $this->urlGenerator->linkToRouteAbsolute('core.GuestAvatar.getAvatar', ['guestName' => str_replace('/', ' ', $contact['FN']), 'size' => 64]);
} elseif ($username != '') {
$avatar = $this->urlGenerator->linkToRemoteRouteAbsolute($remoteServer, 'core.avatar.getAvatar', ['userId' => str_replace('/', ' ', $username), 'size' => 64]);
Copy link
Member

Choose a reason for hiding this comment

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

This assumes every cloud ID is a nextcloud? 🫣

@@ -115,6 +115,19 @@ public function linkToRouteAbsolute(string $routeName, array $arguments = []): s
return $this->getAbsoluteURL($this->linkToRoute($routeName, $arguments));
}


public function linkToRemoteRouteAbsolute(string $remote, $routeName, array $arguments = []): string {
Copy link
Member

Choose a reason for hiding this comment

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

This should not be here or on the public interface

@nickvergessen
Copy link
Member

does this approach make sense

From my POV it's not okay...

@nfebe
Copy link
Contributor Author

nfebe commented Apr 22, 2024

Based on conversation with @nickvergessen, this needs more effort especially as the content security policy can't changed to allow all trusted servers.

So this would remain in draft in favor of : #44972

Eventually, I could copy the proxy strategy from https://github.com/nextcloud/spreed/blob/main/lib/Controller/AvatarController.php#L244 where the server downloads the image and sends in on the instance URL.

@nfebe nfebe added descoped and removed 2. developing Work in progress labels Apr 22, 2024
@solracsf solracsf added this to the Nextcloud 30 milestone Jun 18, 2024
@skjnldsv skjnldsv added the 2. developing Work in progress label Jul 27, 2024
@skjnldsv skjnldsv modified the milestones: Nextcloud 30, Nextcloud 31 Aug 14, 2024
@susnux susnux added stale Ticket or PR with no recent activity and removed descoped labels Nov 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2. developing Work in progress feature: contacts menu feature: search stale Ticket or PR with no recent activity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants