Birthday calendar is not shared with groups
Steps to reproduce
- The generation of the birthday calendar must be active 2.Share contacts that contain birthday information with group A.
- Log in with a user who is in group A.
- Open the calendar and see if birthdays are displayed
Expected behaviour
Birthdays should be displayed from the shared contacts
Actual behaviour
When sharing contacts with a group, no birthdays are shown in the calendar. However, if you share the contacts directly with the respective user, the birthday display works.
Calendar app
Calendar app version: 2.3.0
CalDAV-clients used: (Thunderbird Lightning, DAVx5, Evolution, macOS Calendar, etc)
Client configuration
Browser: Chrome
Operating system: Windows 10 64bit
Server configuration
Operating system: Hosting Linux
Web server: Apache
Database: MariaDB
PHP version: 7.4.16
Nextcloud Version: 22.0.0
ACK - same issue here...
I am just migrating installation from an OC (10.0)@Raspbian to an actual¹ [email protected].
It's used by my family members, and holds an additional fully shared (contacts, calendar, files) "familiy" account to collect all related data and get rid of redundancy and inconsistencies.
But NC hides the mutual/shared contact birthdays, which is of course one main expected feature, that worked flawlessly on the old (OC-10) server... But I understand, that there are scenarios where one don't want others to be able to alter his "calendar-view" (hardly spoken: to /spam/ the calendar) by simply sharing a contact-list with a bunch of birthday-entries...
So, one needs/should have the option to ex- or include the visibility of such shared contact-birthdays. Hope the issue gets necessary attention... while some dirty hack would do it for me ;-)
¹ Server:
Name Version Rev Tracking Publisher Notes
nextcloud 21.0.3snap1 28404 latest/stable nextcloud✓ -
client: Firefox 90.0(64Bit) for Ubuntu
Any news on this issue?
I have the same issue. If the adressbook is shared with a user, the birthdays events are created correctly, see #28533.
So i investigated the occ dav:sync-birthday-calendar command. This runs the syncUser in BirthdayService.php on a specified user - named here syncuser.
The shared addressbooks (and the cards) are received correctly. Now the function onCardChanged in BirthdayService.php are called.
I think the "bug" is on line 112 in $targetPrincipals: $targetPrincipals[] = $book['principaluri'];
I think $targetPrincipals has to be the principal of the birthday calendar of syncuser and not the principal of the group the addressbook has shared it, hasn’t it?
$targetPrincipals = $this->getAllAffectedPrincipals($addressBookId);
$book = $this->cardDavBackEnd->getAddressBookById($addressBookId);
$targetPrincipals[] = $book['principaluri'];
(...)
foreach ($targetPrincipals as $principalUri) {
(...)
$calendar = $this->ensureCalendarExists($principalUri);
foreach ($datesToSync as $type) {
$this->updateCalendar($cardUri, $cardData, $book, (int) $calendar['id'], $type);
}
In my test the $targetPrincipals has the value:
Array
(
[0] => principals/groups/Groupname
[1] => principals/users/UserWhoSharedTheAddressbookWithAGroupGroupname
)
As I understood the code, the birthday calendar of syncuser gets never updated with the shared addressbook cards, because the calendar gets never selected by $calendar = $this->ensureCalendarExists($principalUri);. But only if the addressbook is shared with a group. Is it shared with a user the $targetPrincipals has the value:
Array
(
[0] => principals/users/SyncUser
[1] => principals/users/UserWhoSharedTheAddressbookWithSyncUser
)
So maybe the principal of syncuser has to hand over to the function onCardChanged. Or modify getAddressBookById in CardDavBackend.php to return the principals of all user who have access to the addressbook.
Sorry for my bad english.
@tcitworld
Is there already a solution for this?
With over 100 users, it's not all that great to manage. In addition, there is the problem with the wrong display. https://github.com/nextcloud/contacts/pull/2503
In addition to my last post, I investigated a little further. I have found three errors (see below) and a possible solution.
Since I am not really familiar with CardDAV/CalDAV and the nextcloud internal functions, I would now need help from the developers, whether this is correct so far.
possible solution
I believe that the function onCardChanged is not purposeful here. This function is probably actually intended for when you change an entry in the address book, that the corresponding birthday calendars are changed. Also, the functions for the principals are probably not consistent for groups. I don't know.
So I used the function updateCalendar in syncUser and copied some code from the onCardChanged function. My changes:
- add
$calendar = $this->ensureCalendarExists($principal);to get the birthday calendar of the user - copy
$datesToSyncfromonCardChanged - copy
foreach ($datesToSync as $type)fromonCardChanged
public function syncUser(string $user):void {
$principal = 'principals/users/'.$user;
$calendar = $this->ensureCalendarExists($principal);
$books = $this->cardDavBackEnd->getAddressBooksForUser($principal);
$datesToSync = [
['postfix' => '', 'field' => 'BDAY'],
['postfix' => '-death', 'field' => 'DEATHDATE'],
['postfix' => '-anniversary', 'field' => 'ANNIVERSARY'],
];
foreach ($books as $book) {
$cards = $this->cardDavBackEnd->getCards($book['id']);
foreach ($cards as $card) {
foreach ($datesToSync as $type) {
$this->updateCalendar($card['uri'], $card['carddata'], $book, (int) $calendar['id'], $type);
}
}
}
}
errors
1. syncuser is not selected from onCardChanged
The function getAllAffectedPrincipals($addressBookId); is called to find out all shares of the addressbook.
the following function sequence is used for this: getAllAffectedPrincipals($addressBookId); => sharingBackend->getShares($addressBookId); => getShares(int $resourceId)
a row of the result in getShares(int $resourceId) is:
Array
(
[principaluri] => principals/groups/GroupName
[access] => 2
)
The check in '{http://owncloud.org/ns}group-share' => is_null($p) is always false because the result of $p = $this->principalBackend->getPrincipalByPath($row['principaluri']); is in my case:
Array
(
[uri] => principals/groups/GroupName
[{DAV:}displayname] => DisplaynameOfGroup
)
So $shares = $this->cardDavBackEnd->getShares($addressBookId); is:
Array
(
[href] => principal:principals/groups/Lehrer
[commonName] => Lehrer:innen
[status] => 1
[readOnly] =>
[{http://owncloud.org/ns}principal] => principals/groups/Lehrer
[{http://owncloud.org/ns}group-share] =>
)
and var_export($share['{http://owncloud.org/ns}group-share']); is false.
Back to getAllAffectedPrincipals. Here in if ($share['{http://owncloud.org/ns}group-share']) the true part is never called, because $share['{http://owncloud.org/ns}group-share'] is always false (see above). The result of getAllAffectedPrincipals is therefore: $targetPrincipals[] = $share['{http://owncloud.org/ns}principal']; In my case
Array
(
[0] => principals/groups/Groupname
[1] => principals/users/UserWhoSharedTheAddressbookWithAGroup
)
For testing i have changed the "group-check" to '{http://owncloud.org/ns}group-share' => str_contains($row['principaluri'], 'group'). But now each group member will go through and update their calendars. See 2.
2. each member of a group is synchronized.
You can give the command dav:sync-birthday-calendar a user for which the calendar should be updated. This information is only used to find out the address books of the corresponding user. But the function onCardChanged will then update all users who have access to the address book.
3. the line $this->ensureCalendarExists($principal); has no benefit, does it?
I wish there was a solution to this.
See https://github.com/nextcloud/server/pull/31859
Thanks, that sounds promising