mirror of
https://github.com/nextcloud/server.git
synced 2026-06-12 10:10:49 -04:00
feat(dav): Directly access shared calendars by URI
Each time we access a shared calendar details (with getChild), this loads every user's calendars and iterates until the correct one is found. Now we lookup from the shared calendars which ones has the correct URI, just iterating on the possible shares (for instance a calendar can be shared directly through user-to-user share or through user-to-group share). Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
8f0849a317
commit
79adeb8b08
2 changed files with 83 additions and 3 deletions
|
|
@ -389,7 +389,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
|
|||
->where($query->expr()->in('s.principaluri', $query->createParameter('principaluri')))
|
||||
->andWhere($query->expr()->eq('s.type', $query->createParameter('type')))
|
||||
->setParameter('type', 'calendar')
|
||||
->setParameter('principaluri', $principals, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY);
|
||||
->setParameter('principaluri', $principals, IQueryBuilder::PARAM_STR_ARRAY);
|
||||
|
||||
$result = $query->executeQuery();
|
||||
|
||||
|
|
@ -657,6 +657,85 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
|
|||
return $calendar;
|
||||
}
|
||||
|
||||
public function getSharedCalendarByUri(string $principalUri, string $calendarSharedUri): ?array {
|
||||
// query for shared calendars
|
||||
[$calendarUri, ] = explode('_shared_by_', $calendarSharedUri, 2);
|
||||
|
||||
$principals = $this->principalBackend->getGroupMembership($principalUri, true);
|
||||
$principals = array_merge($principals, $this->principalBackend->getCircleMembership($principalUri));
|
||||
|
||||
$principals[] = $principalUri;
|
||||
|
||||
$fields = array_column($this->propertyMap, 0);
|
||||
$fields[] = 'a.id';
|
||||
$fields[] = 'a.uri';
|
||||
$fields[] = 'a.synctoken';
|
||||
$fields[] = 'a.components';
|
||||
$fields[] = 'a.principaluri';
|
||||
$fields[] = 'a.transparent';
|
||||
$fields[] = 's.access';
|
||||
$query = $this->db->getQueryBuilder();
|
||||
$query->select($fields)
|
||||
->from('dav_shares', 's')
|
||||
->join('s', 'calendars', 'a', $query->expr()->eq('s.resourceid', 'a.id'))
|
||||
->where($query->expr()->eq('a.uri', $query->createParameter('uri')))
|
||||
->andWhere($query->expr()->in('s.principaluri', $query->createParameter('principaluri')))
|
||||
->andWhere($query->expr()->eq('s.type', $query->createParameter('type')))
|
||||
->setParameter('uri', $calendarUri)
|
||||
->setParameter('type', 'calendar')
|
||||
->setParameter('principaluri', $principals, IQueryBuilder::PARAM_STR_ARRAY);
|
||||
|
||||
$result = $query->executeQuery();
|
||||
|
||||
$readOnlyPropertyName = '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only';
|
||||
|
||||
$calendar = null;
|
||||
|
||||
while ($row = $result->fetch()) {
|
||||
$row['principaluri'] = (string)$row['principaluri'];
|
||||
if ($row['principaluri'] === $principalUri) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$readOnly = (int)$row['access'] === Backend::ACCESS_READ;
|
||||
if (isset($calendars[$row['id']])) {
|
||||
if ($readOnly) {
|
||||
// New share can not have more permissions then the old one.
|
||||
continue;
|
||||
}
|
||||
if (isset($calendars[$row['id']][$readOnlyPropertyName]) &&
|
||||
$calendars[$row['id']][$readOnlyPropertyName] === 0) {
|
||||
// Old share is already read-write, no more permissions can be gained
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Fixes for shared calendars
|
||||
[, $name] = Uri\split($row['principaluri']);
|
||||
$row['displayname'] = $row['displayname'] . ' (' . ($this->userManager->getDisplayName($name) ?? ($name ?? '')) . ')';
|
||||
|
||||
$components = [];
|
||||
if ($row['components']) {
|
||||
$components = explode(',', $row['components']);
|
||||
}
|
||||
|
||||
$calendar = [
|
||||
'id' => $row['id'],
|
||||
'uri' => $row['uri'] . '_shared_by_' . $name,
|
||||
'principaluri' => $this->convertPrincipal($principalUri, !$this->legacyEndpoint),
|
||||
'{' . Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($row['synctoken'] ?: '0'),
|
||||
'{http://sabredav.org/ns}sync-token' => $row['synctoken'] ?: '0',
|
||||
'{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet($components),
|
||||
'{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent'] ? 'transparent' : 'opaque'),
|
||||
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => $this->convertPrincipal($row['principaluri'], !$this->legacyEndpoint),
|
||||
$readOnlyPropertyName => $readOnly,
|
||||
];
|
||||
}
|
||||
$calendar = $this->rowToCalendar($row, $calendar);
|
||||
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
|
||||
return $this->addResourceTypeToCalendar($row, $calendar);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{id: int, uri: string, '{http://calendarserver.org/ns/}getctag': string, '{http://sabredav.org/ns}sync-token': int, '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set': SupportedCalendarComponentSet, '{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp': ScheduleCalendarTransp, '{urn:ietf:params:xml:ns:caldav}calendar-timezone': ?string }|null
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -169,8 +169,9 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
|
|||
}
|
||||
|
||||
// Fallback to cover shared calendars
|
||||
foreach ($this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']) as $calendar) {
|
||||
if ($calendar['uri'] === $name) {
|
||||
if ($this->caldavBackend instanceof CalDavBackend) {
|
||||
$calendar = $this->caldavBackend->getSharedCalendarByUri($this->principalInfo['uri'], $name);
|
||||
if(!empty($calendar)) {
|
||||
return new Calendar($this->caldavBackend, $calendar, $this->l10n, $this->config, $this->logger);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue