Browse Source

Add typing to Sharing Backend

Signed-off-by: Carl Schwan <carl@carlschwan.eu>
tags/v25.0.0beta1
Carl Schwan 1 year ago
parent
commit
3598ec4028

+ 29
- 29
apps/dav/lib/CalDAV/CalDavBackend.php View File

@@ -674,10 +674,9 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}

/**
* @param $calendarId
* @return array|null
* @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 }|null
*/
public function getCalendarById($calendarId) {
public function getCalendarById(int $calendarId): ?array {
$fields = array_column($this->propertyMap, 0);
$fields[] = 'id';
$fields[] = 'uri';
@@ -710,7 +709,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'uri' => $row['uri'],
'principaluri' => $this->convertPrincipal($row['principaluri'], !$this->legacyEndpoint),
'{' . Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($row['synctoken']?$row['synctoken']:'0'),
'{http://sabredav.org/ns}sync-token' => $row['synctoken']?$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'),
];
@@ -866,7 +865,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription

$calendarData = $this->getCalendarById($calendarId);
$shares = $this->getShares($calendarId);
$this->dispatcher->dispatchTyped(new CalendarUpdatedEvent((int)$calendarId, $calendarData, $shares, $mutations));
$this->dispatcher->dispatchTyped(new CalendarUpdatedEvent($calendarId, $calendarData, $shares, $mutations));

return true;
});
@@ -916,7 +915,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription

// Only dispatch if we actually deleted anything
if ($calendarData) {
$this->dispatcher->dispatchTyped(new CalendarDeletedEvent((int)$calendarId, $calendarData, $shares));
$this->dispatcher->dispatchTyped(new CalendarDeletedEvent($calendarId, $calendarData, $shares));
}
} else {
$qbMarkCalendarDeleted = $this->db->getQueryBuilder();
@@ -929,7 +928,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$shares = $this->getShares($calendarId);
if ($calendarData) {
$this->dispatcher->dispatchTyped(new CalendarMovedToTrashEvent(
(int)$calendarId,
$calendarId,
$calendarData,
$shares
));
@@ -1265,15 +1264,17 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$this->addChange($calendarId, $objectUri, 1, $calendarType);

$objectRow = $this->getCalendarObject($calendarId, $objectUri, $calendarType);
assert($objectRow !== null);

if ($calendarType === self::CALENDAR_TYPE_CALENDAR) {
$calendarRow = $this->getCalendarById($calendarId);
$shares = $this->getShares($calendarId);

$this->dispatcher->dispatchTyped(new CalendarObjectCreatedEvent((int)$calendarId, $calendarRow, $shares, $objectRow));
$this->dispatcher->dispatchTyped(new CalendarObjectCreatedEvent($calendarId, $calendarRow, $shares, $objectRow));
} else {
$subscriptionRow = $this->getSubscriptionById($calendarId);

$this->dispatcher->dispatchTyped(new CachedCalendarObjectCreatedEvent((int)$calendarId, $subscriptionRow, [], $objectRow));
$this->dispatcher->dispatchTyped(new CachedCalendarObjectCreatedEvent($calendarId, $subscriptionRow, [], $objectRow));
}

return '"' . $extraData['etag'] . '"';
@@ -1325,11 +1326,11 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$calendarRow = $this->getCalendarById($calendarId);
$shares = $this->getShares($calendarId);

$this->dispatcher->dispatchTyped(new CalendarObjectUpdatedEvent((int)$calendarId, $calendarRow, $shares, $objectRow));
$this->dispatcher->dispatchTyped(new CalendarObjectUpdatedEvent($calendarId, $calendarRow, $shares, $objectRow));
} else {
$subscriptionRow = $this->getSubscriptionById($calendarId);

$this->dispatcher->dispatchTyped(new CachedCalendarObjectUpdatedEvent((int)$calendarId, $subscriptionRow, [], $objectRow));
$this->dispatcher->dispatchTyped(new CachedCalendarObjectUpdatedEvent($calendarId, $subscriptionRow, [], $objectRow));
}
}

@@ -1435,11 +1436,11 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$calendarRow = $this->getCalendarById($calendarId);
$shares = $this->getShares($calendarId);

$this->dispatcher->dispatchTyped(new CalendarObjectDeletedEvent((int)$calendarId, $calendarRow, $shares, $data));
$this->dispatcher->dispatchTyped(new CalendarObjectDeletedEvent($calendarId, $calendarRow, $shares, $data));
} else {
$subscriptionRow = $this->getSubscriptionById($calendarId);

$this->dispatcher->dispatchTyped(new CachedCalendarObjectDeletedEvent((int)$calendarId, $subscriptionRow, [], $data));
$this->dispatcher->dispatchTyped(new CachedCalendarObjectDeletedEvent($calendarId, $subscriptionRow, [], $data));
}
} else {
$pathInfo = pathinfo($data['uri']);
@@ -1479,7 +1480,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
if ($calendarData !== null) {
$this->dispatcher->dispatchTyped(
new CalendarObjectMovedToTrashEvent(
(int)$calendarId,
$calendarId,
$calendarData,
$this->getShares($calendarId),
$data
@@ -2799,25 +2800,26 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}

/**
* @param IShareable $shareable
* @param array $add
* @param array $remove
* @param list<array{href: string, commonName: string, readOnly: bool}> $add
* @param list<string> $remove
*/
public function updateShares($shareable, $add, $remove) {
public function updateShares(IShareable $shareable, array $add, array $remove): void {
$calendarId = $shareable->getResourceId();
$calendarRow = $this->getCalendarById($calendarId);
if ($calendarRow === null) {
throw new \RuntimeException('Trying to update shares for innexistant calendar: ' . $calendarId);
}
$oldShares = $this->getShares($calendarId);

$this->calendarSharingBackend->updateShares($shareable, $add, $remove);

$this->dispatcher->dispatchTyped(new CalendarShareUpdatedEvent((int)$calendarId, $calendarRow, $oldShares, $add, $remove));
$this->dispatcher->dispatchTyped(new CalendarShareUpdatedEvent($calendarId, $calendarRow, $oldShares, $add, $remove));
}

/**
* @param int $resourceId
* @return array
* @return list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}>
*/
public function getShares($resourceId) {
public function getShares(int $resourceId): array {
return $this->calendarSharingBackend->getShares($resourceId);
}

@@ -2843,7 +2845,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
]);
$query->executeStatement();

$this->dispatcher->dispatchTyped(new CalendarPublishedEvent((int)$calendarId, $calendarData, $publicUri));
$this->dispatcher->dispatchTyped(new CalendarPublishedEvent($calendarId, $calendarData, $publicUri));
return $publicUri;
}
$query->delete('dav_shares')
@@ -2851,7 +2853,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC)));
$query->executeStatement();

$this->dispatcher->dispatchTyped(new CalendarUnpublishedEvent((int)$calendarId, $calendarData));
$this->dispatcher->dispatchTyped(new CalendarUnpublishedEvent($calendarId, $calendarData));
return null;
}

@@ -2874,15 +2876,13 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription

/**
* @param int $resourceId
* @param array $acl
* @return array
* @param list<array{privilege: string, principal: string, protected: bool}> $acl
* @return list<array{privilege: string, principal: string, protected: bool}>
*/
public function applyShareAcl($resourceId, $acl) {
public function applyShareAcl(int $resourceId, array $acl): array {
return $this->calendarSharingBackend->applyShareAcl($resourceId, $acl);
}



/**
* update properties table
*

+ 16
- 46
apps/dav/lib/CalDAV/Calendar.php View File

@@ -51,27 +51,11 @@ use Sabre\DAV\PropPatch;
* @property CalDavBackend $caldavBackend
*/
class Calendar extends \Sabre\CalDAV\Calendar implements IRestorable, IShareable, IMoveTarget {
private IConfig $config;
protected IL10N $l10n;
private bool $useTrashbin = true;
private LoggerInterface $logger;

/** @var IConfig */
private $config;

/** @var IL10N */
protected $l10n;

/** @var bool */
private $useTrashbin = true;

/** @var LoggerInterface */
private $logger;

/**
* Calendar constructor.
*
* @param BackendInterface $caldavBackend
* @param $calendarInfo
* @param IL10N $l10n
* @param IConfig $config
*/
public function __construct(BackendInterface $caldavBackend, $calendarInfo, IL10N $l10n, IConfig $config, LoggerInterface $logger) {
// Convert deletion date to ISO8601 string
if (isset($calendarInfo[TrashbinPlugin::PROPERTY_DELETED_AT])) {
@@ -96,25 +80,10 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IRestorable, IShareable
}

/**
* Updates the list of shares.
*
* The first array is a list of people that are to be added to the
* resource.
*
* Every element in the add array has the following properties:
* * href - A url. Usually a mailto: address
* * commonName - Usually a first and last name, or false
* * summary - A description of the share, can also be false
* * readOnly - A boolean value
*
* Every element in the remove array is just the address string.
*
* @param array $add
* @param array $remove
* @return void
* {@inheritdoc}
* @throws Forbidden
*/
public function updateShares(array $add, array $remove) {
public function updateShares(array $add, array $remove): void {
if ($this->isShared()) {
throw new Forbidden();
}
@@ -131,19 +100,16 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IRestorable, IShareable
* * readOnly - boolean
* * summary - Optional, a description for the share
*
* @return array
* @return list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}>
*/
public function getShares() {
public function getShares(): array {
if ($this->isShared()) {
return [];
}
return $this->caldavBackend->getShares($this->getResourceId());
}

/**
* @return int
*/
public function getResourceId() {
public function getResourceId(): int {
return $this->calendarInfo['id'];
}

@@ -155,7 +121,9 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IRestorable, IShareable
}

/**
* @return array
* @param int $resourceId
* @param list<array{privilege: string, principal: string, protected: bool}> $acl
* @return list<array{privilege: string, principal: ?string, protected: bool}>
*/
public function getACL() {
$acl = [
@@ -246,16 +214,18 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IRestorable, IShareable
parent::getOwner(),
'principals/system/public'
];
return array_filter($acl, function ($rule) use ($allowedPrincipals) {
/** @var list<array{privilege: string, principal: string, protected: bool}> $acl */
$acl = array_filter($acl, function (array $rule) use ($allowedPrincipals): bool {
return \in_array($rule['principal'], $allowedPrincipals, true);
});
return $acl;
}

public function getChildACL() {
return $this->getACL();
}

public function getOwner() {
public function getOwner(): ?string {
if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) {
return $this->calendarInfo['{http://owncloud.org/ns}owner-principal'];
}

+ 9
- 15
apps/dav/lib/CardDAV/AddressBook.php View File

@@ -67,17 +67,15 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable {
* Every element in the add array has the following properties:
* * href - A url. Usually a mailto: address
* * commonName - Usually a first and last name, or false
* * summary - A description of the share, can also be false
* * readOnly - A boolean value
*
* Every element in the remove array is just the address string.
*
* @param array $add
* @param array $remove
* @return void
* @param list<array{href: string, commonName: string, readOnly: bool}> $add
* @param list<string> $remove
* @throws Forbidden
*/
public function updateShares(array $add, array $remove) {
public function updateShares(array $add, array $remove): void {
if ($this->isShared()) {
throw new Forbidden();
}
@@ -92,11 +90,10 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable {
* * commonName - Optional, for example a first + last name
* * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
* * readOnly - boolean
* * summary - Optional, a description for the share
*
* @return array
* @return list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}>
*/
public function getShares() {
public function getShares(): array {
if ($this->isShared()) {
return [];
}
@@ -163,14 +160,11 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable {
return new Card($this->carddavBackend, $this->addressBookInfo, $obj);
}

/**
* @return int
*/
public function getResourceId() {
public function getResourceId(): int {
return $this->addressBookInfo['id'];
}

public function getOwner() {
public function getOwner(): ?string {
if (isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) {
return $this->addressBookInfo['{http://owncloud.org/ns}owner-principal'];
}
@@ -207,7 +201,7 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable {
return $this->carddavBackend->collectCardProperties($this->getResourceId(), 'CATEGORIES');
}

private function isShared() {
private function isShared(): bool {
if (!isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) {
return false;
}
@@ -215,7 +209,7 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable {
return $this->addressBookInfo['{http://owncloud.org/ns}owner-principal'] !== $this->addressBookInfo['principaluri'];
}

private function canWrite() {
private function canWrite(): bool {
if (isset($this->addressBookInfo['{http://owncloud.org/ns}read-only'])) {
return !$this->addressBookInfo['{http://owncloud.org/ns}read-only'];
}

+ 27
- 32
apps/dav/lib/CardDAV/CardDavBackend.php View File

@@ -371,12 +371,12 @@ class CardDavBackend implements BackendInterface, SyncSupport {
$query->set($key, $query->createNamedParameter($value));
}
$query->where($query->expr()->eq('id', $query->createNamedParameter($addressBookId)))
->execute();
->executeStatement();

$this->addChange($addressBookId, "", 2);

$addressBookRow = $this->getAddressBookById((int)$addressBookId);
$shares = $this->getShares($addressBookId);
$shares = $this->getShares((int)$addressBookId);
$this->dispatcher->dispatchTyped(new AddressBookUpdatedEvent((int)$addressBookId, $addressBookRow, $shares, $mutations));

return true;
@@ -446,30 +446,31 @@ class CardDavBackend implements BackendInterface, SyncSupport {
* @return void
*/
public function deleteAddressBook($addressBookId) {
$addressBookId = (int)$addressBookId;
$addressBookData = $this->getAddressBookById($addressBookId);
$shares = $this->getShares($addressBookId);

$query = $this->db->getQueryBuilder();
$query->delete($this->dbCardsTable)
->where($query->expr()->eq('addressbookid', $query->createParameter('addressbookid')))
->setParameter('addressbookid', $addressBookId)
->execute();
->setParameter('addressbookid', $addressBookId, IQueryBuilder::PARAM_INT)
->executeStatement();

$query->delete('addressbookchanges')
->where($query->expr()->eq('addressbookid', $query->createParameter('addressbookid')))
->setParameter('addressbookid', $addressBookId)
->execute();
->setParameter('addressbookid', $addressBookId, IQueryBuilder::PARAM_INT)
->executeStatement();

$query->delete('addressbooks')
->where($query->expr()->eq('id', $query->createParameter('id')))
->setParameter('id', $addressBookId)
->execute();
->setParameter('id', $addressBookId, IQueryBuilder::PARAM_INT)
->executeStatement();

$this->sharingBackend->deleteAllShares($addressBookId);

$query->delete($this->dbCardsPropertiesTable)
->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId)))
->execute();
->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId, IQueryBuilder::PARAM_INT)))
->executeStatement();

if ($addressBookData) {
$this->dispatcher->dispatchTyped(new AddressBookDeletedEvent($addressBookId, $addressBookData, $shares));
@@ -964,11 +965,10 @@ class CardDavBackend implements BackendInterface, SyncSupport {
}

/**
* @param IShareable $shareable
* @param string[] $add
* @param string[] $remove
* @param list<array{href: string, commonName: string, readOnly: bool}> $add
* @param list<string> $remove
*/
public function updateShares(IShareable $shareable, $add, $remove) {
public function updateShares(IShareable $shareable, array $add, array $remove): void {
$addressBookId = $shareable->getResourceId();
$addressBookData = $this->getAddressBookById($addressBookId);
$oldShares = $this->getShares($addressBookId);
@@ -1199,11 +1199,10 @@ class CardDavBackend implements BackendInterface, SyncSupport {
* * commonName - Optional, for example a first + last name
* * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
* * readOnly - boolean
* * summary - Optional, a description for the share
*
* @return array
* @return list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}>
*/
public function getShares($addressBookId) {
public function getShares(int $addressBookId): array {
return $this->sharingBackend->getShares($addressBookId);
}

@@ -1283,13 +1282,9 @@ class CardDavBackend implements BackendInterface, SyncSupport {
}

/**
* get ID from a given contact
*
* @param int $addressBookId
* @param string $uri
* @return int
* Get ID from a given contact
*/
protected function getCardId($addressBookId, $uri) {
protected function getCardId(int $addressBookId, string $uri): int {
$query = $this->db->getQueryBuilder();
$query->select('id')->from($this->dbCardsTable)
->where($query->expr()->eq('uri', $query->createNamedParameter($uri)))
@@ -1309,15 +1304,15 @@ class CardDavBackend implements BackendInterface, SyncSupport {
/**
* For shared address books the sharee is set in the ACL of the address book
*
* @param $addressBookId
* @param $acl
* @return array
* @param int $addressBookId
* @param list<array{privilege: string, principal: string, protected: bool}> $acl
* @return list<array{privilege: string, principal: string, protected: bool}>
*/
public function applyShareAcl($addressBookId, $acl) {
public function applyShareAcl(int $addressBookId, array $acl): array {
return $this->sharingBackend->applyShareAcl($addressBookId, $acl);
}

private function convertPrincipal($principalUri, $toV2) {
private function convertPrincipal(string $principalUri, bool $toV2): string {
if ($this->principalBackend->getPrincipalPrefix() === 'principals') {
[, $name] = \Sabre\Uri\split($principalUri);
if ($toV2 === true) {
@@ -1328,7 +1323,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
return $principalUri;
}

private function addOwnerPrincipal(&$addressbookInfo) {
private function addOwnerPrincipal(array &$addressbookInfo): void {
$ownerPrincipalKey = '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal';
$displaynameKey = '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}owner-displayname';
if (isset($addressbookInfo[$ownerPrincipalKey])) {
@@ -1348,10 +1343,10 @@ class CardDavBackend implements BackendInterface, SyncSupport {
*
* @param string $cardData the vcard raw data
* @return string the uid
* @throws BadRequest if no UID is available
* @throws BadRequest if no UID is available or vcard is empty
*/
private function getUID($cardData) {
if ($cardData != '') {
private function getUID(string $cardData): string {
if ($cardData !== '') {
$vCard = Reader::read($cardData);
if ($vCard->UID) {
$uid = $vCard->UID->getValue();

+ 10
- 34
apps/dav/lib/Command/MoveCalendar.php View File

@@ -42,41 +42,17 @@ use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

class MoveCalendar extends Command {

/** @var IUserManager */
private $userManager;

/** @var IGroupManager */
private $groupManager;

/** @var IShareManager */
private $shareManager;

/** @var IConfig $config */
private $config;

/** @var IL10N */
private $l10n;

/** @var SymfonyStyle */
private $io;

/** @var CalDavBackend */
private $calDav;

/** @var LoggerInterface */
private $logger;
private IUserManager $userManager;
private IGroupManager $groupManager;
private IShareManager $shareManager;
private IConfig $config;
private IL10N $l10n;
private ?SymfonyStyle $io = null;
private CalDavBackend $calDav;
private LoggerInterface $logger;

public const URI_USERS = 'principals/users/';

/**
* @param IUserManager $userManager
* @param IGroupManager $groupManager
* @param IShareManager $shareManager
* @param IConfig $config
* @param IL10N $l10n
* @param CalDavBackend $calDav
*/
public function __construct(
IUserManager $userManager,
IGroupManager $groupManager,
@@ -224,7 +200,7 @@ class MoveCalendar extends Command {
*/
if ($this->shareManager->shareWithGroupMembersOnly() === true && 'groups' === $prefix && !$this->groupManager->isInGroup($userDestination, $userOrGroup)) {
if ($force) {
$this->calDav->updateShares(new Calendar($this->calDav, $calendar, $this->l10n, $this->config, $this->logger), [], ['href' => 'principal:principals/groups/' . $userOrGroup]);
$this->calDav->updateShares(new Calendar($this->calDav, $calendar, $this->l10n, $this->config, $this->logger), [], ['principal:principals/groups/' . $userOrGroup]);
} else {
throw new \InvalidArgumentException("User <$userDestination> is not part of the group <$userOrGroup> with whom the calendar <" . $calendar['uri'] . "> was shared. You may use -f to move the calendar while deleting this share.");
}
@@ -235,7 +211,7 @@ class MoveCalendar extends Command {
*/
if ($userOrGroup === $userDestination) {
if ($force) {
$this->calDav->updateShares(new Calendar($this->calDav, $calendar, $this->l10n, $this->config, $this->logger), [], ['href' => 'principal:principals/users/' . $userOrGroup]);
$this->calDav->updateShares(new Calendar($this->calDav, $calendar, $this->l10n, $this->config, $this->logger), [], ['principal:principals/users/' . $userOrGroup]);
} else {
throw new \InvalidArgumentException("The calendar <" . $calendar['uri'] . "> is already shared to user <$userDestination>.You may use -f to move the calendar while deleting this share.");
}

+ 29
- 51
apps/dav/lib/DAV/Sharing/Backend.php View File

@@ -32,32 +32,20 @@ use OCA\DAV\Connector\Sabre\Principal;
use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IUserManager;
use OCP\DB\QueryBuilder\IQueryBuilder;

class Backend {

/** @var IDBConnection */
private $db;
/** @var IUserManager */
private $userManager;
/** @var IGroupManager */
private $groupManager;
/** @var Principal */
private $principalBackend;
/** @var string */
private $resourceType;
private IDBConnection $db;
private IUserManager $userManager;
private IGroupManager $groupManager;
private Principal $principalBackend;
private string $resourceType;

public const ACCESS_OWNER = 1;
public const ACCESS_READ_WRITE = 2;
public const ACCESS_READ = 3;

/**
* @param IDBConnection $db
* @param IUserManager $userManager
* @param IGroupManager $groupManager
* @param Principal $principalBackend
* @param string $resourceType
*/
public function __construct(IDBConnection $db, IUserManager $userManager, IGroupManager $groupManager, Principal $principalBackend, $resourceType) {
public function __construct(IDBConnection $db, IUserManager $userManager, IGroupManager $groupManager, Principal $principalBackend, string $resourceType) {
$this->db = $db;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
@@ -66,11 +54,10 @@ class Backend {
}

/**
* @param IShareable $shareable
* @param string[] $add
* @param string[] $remove
* @param list<array{href: string, commonName: string, readOnly: bool}> $add
* @param list<string> $remove
*/
public function updateShares(IShareable $shareable, array $add, array $remove) {
public function updateShares(IShareable $shareable, array $add, array $remove): void {
foreach ($add as $element) {
$principal = $this->principalBackend->findByUri($element['href'], '');
if ($principal !== '') {
@@ -86,10 +73,9 @@ class Backend {
}

/**
* @param IShareable $shareable
* @param string $element
* @param array{href: string, commonName: string, readOnly: bool} $element
*/
private function shareWith($shareable, $element) {
private function shareWith(IShareable $shareable, array $element): void {
$user = $element['href'];
$parts = explode(':', $user, 2);
if ($parts[0] !== 'principal') {
@@ -129,33 +115,26 @@ class Backend {
'access' => $query->createNamedParameter($access),
'resourceid' => $query->createNamedParameter($shareable->getResourceId())
]);
$query->execute();
$query->executeStatement();
}

/**
* @param $resourceId
*/
public function deleteAllShares($resourceId) {
public function deleteAllShares(int $resourceId): void {
$query = $this->db->getQueryBuilder();
$query->delete('dav_shares')
->where($query->expr()->eq('resourceid', $query->createNamedParameter($resourceId)))
->andWhere($query->expr()->eq('type', $query->createNamedParameter($this->resourceType)))
->execute();
->executeStatement();
}

public function deleteAllSharesByUser($principaluri) {
public function deleteAllSharesByUser(string $principaluri): void {
$query = $this->db->getQueryBuilder();
$query->delete('dav_shares')
->where($query->expr()->eq('principaluri', $query->createNamedParameter($principaluri)))
->andWhere($query->expr()->eq('type', $query->createNamedParameter($this->resourceType)))
->execute();
->executeStatement();
}

/**
* @param IShareable $shareable
* @param string $element
*/
private function unshare($shareable, $element) {
private function unshare(IShareable $shareable, string $element): void {
$parts = explode(':', $element, 2);
if ($parts[0] !== 'principal') {
return;
@@ -172,7 +151,7 @@ class Backend {
->andWhere($query->expr()->eq('type', $query->createNamedParameter($this->resourceType)))
->andWhere($query->expr()->eq('principaluri', $query->createNamedParameter($parts[1])))
;
$query->execute();
$query->executeStatement();
}

/**
@@ -183,29 +162,28 @@ class Backend {
* * commonName - Optional, for example a first + last name
* * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
* * readOnly - boolean
* * summary - Optional, a description for the share
*
* @param int $resourceId
* @return array
* @return list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}>
*/
public function getShares($resourceId) {
public function getShares(int $resourceId): array {
$query = $this->db->getQueryBuilder();
$result = $query->select(['principaluri', 'access'])
->from('dav_shares')
->where($query->expr()->eq('resourceid', $query->createNamedParameter($resourceId)))
->where($query->expr()->eq('resourceid', $query->createNamedParameter($resourceId, IQueryBuilder::PARAM_INT)))
->andWhere($query->expr()->eq('type', $query->createNamedParameter($this->resourceType)))
->groupBy(['principaluri', 'access'])
->execute();
->executeQuery();

$shares = [];
while ($row = $result->fetch()) {
$p = $this->principalBackend->getPrincipalByPath($row['principaluri']);
$shares[] = [
'href' => "principal:{$row['principaluri']}",
'commonName' => isset($p['{DAV:}displayname']) ? $p['{DAV:}displayname'] : '',
'href' => "principal:${row['principaluri']}",
'commonName' => isset($p['{DAV:}displayname']) ? (string)$p['{DAV:}displayname'] : '',
'status' => 1,
'readOnly' => (int) $row['access'] === self::ACCESS_READ,
'{http://owncloud.org/ns}principal' => $row['principaluri'],
'{http://owncloud.org/ns}principal' => (string)$row['principaluri'],
'{http://owncloud.org/ns}group-share' => is_null($p)
];
}
@@ -217,10 +195,10 @@ class Backend {
* For shared resources the sharee is set in the ACL of the resource
*
* @param int $resourceId
* @param array $acl
* @return array
* @param list<array{privilege: string, principal: string, protected: bool}> $acl
* @return list<array{privilege: string, principal: string, protected: bool}>
*/
public function applyShareAcl($resourceId, $acl) {
public function applyShareAcl(int $resourceId, array $acl): array {
$shares = $this->getShares($resourceId);
foreach ($shares as $share) {
$acl[] = [

+ 7
- 13
apps/dav/lib/DAV/Sharing/IShareable.php View File

@@ -40,16 +40,14 @@ interface IShareable extends INode {
* Every element in the add array has the following properties:
* * href - A url. Usually a mailto: address
* * commonName - Usually a first and last name, or false
* * summary - A description of the share, can also be false
* * readOnly - A boolean value
*
* Every element in the remove array is just the address string.
*
* @param array $add
* @param array $remove
* @return void
* @param list<array{href: string, commonName: string, readOnly: bool}> $add
* @param list<string> $remove
*/
public function updateShares(array $add, array $remove);
public function updateShares(array $add, array $remove): void;

/**
* Returns the list of people whom this resource is shared with.
@@ -59,19 +57,15 @@ interface IShareable extends INode {
* * commonName - Optional, for example a first + last name
* * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
* * readOnly - boolean
* * summary - Optional, a description for the share
*
* @return array
* @return list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}>
*/
public function getShares();
public function getShares(): array;

/**
* @return int
*/
public function getResourceId();
public function getResourceId(): int;

/**
* @return string
* @return ?string
*/
public function getOwner();
}

+ 19
- 20
apps/dav/lib/Events/CalendarShareUpdatedEvent.php View File

@@ -26,6 +26,8 @@ declare(strict_types=1);
namespace OCA\DAV\Events;

use OCP\EventDispatcher\Event;
use Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp;
use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet;

/**
* Class CalendarShareUpdatedEvent
@@ -34,30 +36,28 @@ use OCP\EventDispatcher\Event;
* @since 20.0.0
*/
class CalendarShareUpdatedEvent extends Event {
private int $calendarId;

/** @var int */
private $calendarId;
/** @var 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 } */
private array $calendarData;

/** @var array */
private $calendarData;
/** @var list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}> */
private array $oldShares;

/** @var array */
private $oldShares;
/** @var list<array{href: string, commonName: string, readOnly: bool}> */
private array $added;

/** @var array */
private $added;

/** @var array */
private $removed;
/** @var list<string> */
private array $removed;

/**
* CalendarShareUpdatedEvent constructor.
*
* @param int $calendarId
* @param array $calendarData
* @param array $oldShares
* @param array $added
* @param array $removed
* @param 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 } $calendarData
* @param list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}> $oldShares
* @param list<array{href: string, commonName: string, readOnly: bool}> $added
* @param list<string> $removed
* @since 20.0.0
*/
public function __construct(int $calendarId,
@@ -74,7 +74,6 @@ class CalendarShareUpdatedEvent extends Event {
}

/**
* @return int
* @since 20.0.0
*/
public function getCalendarId(): int {
@@ -82,7 +81,7 @@ class CalendarShareUpdatedEvent extends Event {
}

/**
* @return array
* @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 }
* @since 20.0.0
*/
public function getCalendarData(): array {
@@ -90,7 +89,7 @@ class CalendarShareUpdatedEvent extends Event {
}

/**
* @return array
* @return list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}>
* @since 20.0.0
*/
public function getOldShares(): array {
@@ -98,7 +97,7 @@ class CalendarShareUpdatedEvent extends Event {
}

/**
* @return array
* @return list<array{href: string, commonName: string, readOnly: bool}>
* @since 20.0.0
*/
public function getAdded(): array {
@@ -106,7 +105,7 @@ class CalendarShareUpdatedEvent extends Event {
}

/**
* @return array
* @return list<string>
* @since 20.0.0
*/
public function getRemoved(): array {

+ 4
- 2
apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php View File

@@ -32,6 +32,7 @@ namespace OCA\DAV\Tests\unit\BackgroundJob;
use OCA\DAV\BackgroundJob\CleanupInvitationTokenJob;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\QueryBuilder\IQueryFunction;
use OCP\IDBConnection;
use Test\TestCase;

@@ -77,10 +78,11 @@ class CleanupInvitationTokenJobTest extends TestCase {
[1337, \PDO::PARAM_STR, null, 'namedParameter1337']
]);

$function = $this->createMock(IQueryFunction::class);
$expr->expects($this->once())
->method('lt')
->with('expiration', 'namedParameter1337')
->willReturn('LT STATEMENT');
->willReturn($function);

$this->dbConnection->expects($this->once())
->method('getQueryBuilder')
@@ -93,7 +95,7 @@ class CleanupInvitationTokenJobTest extends TestCase {
->willReturn($queryBuilder);
$queryBuilder->expects($this->at(3))
->method('where')
->with('LT STATEMENT')
->with($function)
->willReturn($queryBuilder);
$queryBuilder->expects($this->at(4))
->method('execute')

+ 4
- 2
apps/dav/tests/unit/Controller/InvitationResponseControllerTest.php View File

@@ -37,6 +37,7 @@ use OCP\AppFramework\Utility\ITimeFactory;
use OCP\DB\IResult;
use OCP\DB\QueryBuilder\IExpressionBuilder;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\QueryBuilder\IQueryFunction;
use OCP\IDBConnection;
use OCP\IRequest;
use Sabre\VObject\ITip\Message;
@@ -477,10 +478,11 @@ EOF;
->with(\PDO::FETCH_ASSOC)
->willReturn($return);

$function = $this->createMock(IQueryFunction::class);
$expr->expects($this->once())
->method('eq')
->with('token', 'namedParameterToken')
->willReturn('EQ STATEMENT');
->willReturn($function);

$this->dbConnection->expects($this->once())
->method('getQueryBuilder')
@@ -497,7 +499,7 @@ EOF;
->willReturn($queryBuilder);
$queryBuilder->expects($this->at(4))
->method('where')
->with('EQ STATEMENT')
->with($function)
->willReturn($queryBuilder);
$queryBuilder->expects($this->at(5))
->method('execute')

+ 2
- 55
build/psalm-baseline.xml View File

@@ -136,16 +136,6 @@
</ParamNameMismatch>
</file>
<file src="apps/dav/lib/CalDAV/CalDavBackend.php">
<InvalidArgument occurrences="8">
<code>'\OCA\DAV\CalDAV\CalDavBackend::createCachedCalendarObject'</code>
<code>'\OCA\DAV\CalDAV\CalDavBackend::createSubscription'</code>
<code>'\OCA\DAV\CalDAV\CalDavBackend::deleteCachedCalendarObject'</code>
<code>'\OCA\DAV\CalDAV\CalDavBackend::deleteSubscription'</code>
<code>'\OCA\DAV\CalDAV\CalDavBackend::publishCalendar'</code>
<code>'\OCA\DAV\CalDAV\CalDavBackend::updateCachedCalendarObject'</code>
<code>'\OCA\DAV\CalDAV\CalDavBackend::updateShares'</code>
<code>'\OCA\DAV\CalDAV\CalDavBackend::updateSubscription'</code>
</InvalidArgument>
<InvalidNullableReturnType occurrences="2">
<code>array</code>
<code>array</code>
@@ -161,16 +151,6 @@
<RedundantCast occurrences="1">
<code>(int)$calendarId</code>
</RedundantCast>
<TooManyArguments occurrences="8">
<code>dispatch</code>
<code>dispatch</code>
<code>dispatch</code>
<code>dispatch</code>
<code>dispatch</code>
<code>dispatch</code>
<code>dispatch</code>
<code>dispatch</code>
</TooManyArguments>
<UndefinedFunction occurrences="4">
<code>Uri\split($principalUri)</code>
<code>Uri\split($row['principaluri'])</code>
@@ -341,9 +321,6 @@
</InvalidArgument>
</file>
<file src="apps/dav/lib/CardDAV/AddressBookImpl.php">
<InvalidArgument occurrences="1">
<code>$id</code>
</InvalidArgument>
<InvalidScalarArgument occurrences="2">
<code>$this-&gt;getKey()</code>
<code>$this-&gt;getKey()</code>
@@ -358,16 +335,6 @@
<FalsableReturnStatement occurrences="1">
<code>false</code>
</FalsableReturnStatement>
<InvalidArgument occurrences="3">
<code>'\OCA\DAV\CardDAV\CardDavBackend::createCard'</code>
<code>'\OCA\DAV\CardDAV\CardDavBackend::deleteCard'</code>
<code>'\OCA\DAV\CardDAV\CardDavBackend::updateCard'</code>
</InvalidArgument>
<TooManyArguments occurrences="3">
<code>dispatch</code>
<code>dispatch</code>
<code>dispatch</code>
</TooManyArguments>
<TypeDoesNotContainType occurrences="1">
<code>$addressBooks[$row['id']][$readOnlyPropertyName] === 0</code>
</TypeDoesNotContainType>
@@ -672,14 +639,6 @@
<code>null</code>
</NullableReturnStatement>
</file>
<file src="apps/dav/lib/DAV/Sharing/Backend.php">
<InvalidArrayOffset occurrences="4">
<code>$element['href']</code>
<code>$element['href']</code>
<code>$element['href']</code>
<code>$element['readOnly']</code>
</InvalidArrayOffset>
</file>
<file src="apps/dav/lib/DAV/SystemPrincipalBackend.php">
<InvalidNullableReturnType occurrences="1">
<code>array</code>
@@ -889,7 +848,6 @@
</RedundantCondition>
<TypeDoesNotContainType occurrences="2">
<code>get_class($res) === 'OpenSSLAsymmetricKey'</code>
<code>is_object($res)</code>
</TypeDoesNotContainType>
</file>
<file src="apps/encryption/lib/Crypto/EncryptAll.php">
@@ -1732,14 +1690,6 @@
<code>0</code>
</InvalidScalarArgument>
</file>
<file src="apps/updatenotification/lib/ResetTokenBackgroundJob.php">
<InvalidOperand occurrences="1">
<code>$this-&gt;config-&gt;getAppValue('core', 'updater.secret.created', $this-&gt;timeFactory-&gt;getTime())</code>
</InvalidOperand>
<InvalidScalarArgument occurrences="1">
<code>$this-&gt;timeFactory-&gt;getTime()</code>
</InvalidScalarArgument>
</file>
<file src="apps/updatenotification/lib/Settings/Admin.php">
<InvalidScalarArgument occurrences="1">
<code>$lastUpdateCheckTimestamp</code>
@@ -3366,16 +3316,13 @@
<code>$result</code>
<code>$this-&gt;copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file, false, $isRename)</code>
</InvalidOperand>
<InvalidReturnStatement occurrences="6">
<InvalidReturnStatement occurrences="4">
<code>$newUnencryptedSize</code>
<code>$result</code>
<code>$stat</code>
<code>$this-&gt;storage-&gt;file_get_contents($path)</code>
<code>$this-&gt;storage-&gt;filesize($path)</code>
<code>$this-&gt;storage-&gt;getLocalFile($path)</code>
</InvalidReturnStatement>
<InvalidReturnType occurrences="5">
<code>array</code>
<InvalidReturnType occurrences="3">
<code>bool</code>
<code>int</code>
<code>string</code>

Loading…
Cancel
Save