diff options
Diffstat (limited to 'apps')
35 files changed, 322 insertions, 254 deletions
diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index 4f56f3f066f..90db8c68f45 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -5,7 +5,7 @@ <name>WebDAV</name> <summary>WebDAV endpoint</summary> <description>WebDAV endpoint</description> - <version>1.30.0</version> + <version>1.30.1</version> <licence>agpl</licence> <author>owncloud.org</author> <namespace>DAV</namespace> diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index d10cf4af867..01f750f7727 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -315,6 +315,7 @@ return array( 'OCA\\DAV\\Migration\\Version1017Date20210216083742' => $baseDir . '/../lib/Migration/Version1017Date20210216083742.php', 'OCA\\DAV\\Migration\\Version1018Date20210312100735' => $baseDir . '/../lib/Migration/Version1018Date20210312100735.php', 'OCA\\DAV\\Migration\\Version1024Date20211221144219' => $baseDir . '/../lib/Migration/Version1024Date20211221144219.php', + 'OCA\\DAV\\Migration\\Version1025Date20240308063933' => $baseDir . '/../lib/Migration/Version1025Date20240308063933.php', 'OCA\\DAV\\Migration\\Version1027Date20230504122946' => $baseDir . '/../lib/Migration/Version1027Date20230504122946.php', 'OCA\\DAV\\Migration\\Version1029Date20221114151721' => $baseDir . '/../lib/Migration/Version1029Date20221114151721.php', 'OCA\\DAV\\Migration\\Version1029Date20231004091403' => $baseDir . '/../lib/Migration/Version1029Date20231004091403.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index c8455965480..481b95c432a 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -330,6 +330,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Migration\\Version1017Date20210216083742' => __DIR__ . '/..' . '/../lib/Migration/Version1017Date20210216083742.php', 'OCA\\DAV\\Migration\\Version1018Date20210312100735' => __DIR__ . '/..' . '/../lib/Migration/Version1018Date20210312100735.php', 'OCA\\DAV\\Migration\\Version1024Date20211221144219' => __DIR__ . '/..' . '/../lib/Migration/Version1024Date20211221144219.php', + 'OCA\\DAV\\Migration\\Version1025Date20240308063933' => __DIR__ . '/..' . '/../lib/Migration/Version1025Date20240308063933.php', 'OCA\\DAV\\Migration\\Version1027Date20230504122946' => __DIR__ . '/..' . '/../lib/Migration/Version1027Date20230504122946.php', 'OCA\\DAV\\Migration\\Version1029Date20221114151721' => __DIR__ . '/..' . '/../lib/Migration/Version1029Date20221114151721.php', 'OCA\\DAV\\Migration\\Version1029Date20231004091403' => __DIR__ . '/..' . '/../lib/Migration/Version1029Date20231004091403.php', diff --git a/apps/dav/lib/BackgroundJob/PruneOutdatedSyncTokensJob.php b/apps/dav/lib/BackgroundJob/PruneOutdatedSyncTokensJob.php index 74969069387..d5a877a1742 100644 --- a/apps/dav/lib/BackgroundJob/PruneOutdatedSyncTokensJob.php +++ b/apps/dav/lib/BackgroundJob/PruneOutdatedSyncTokensJob.php @@ -52,9 +52,10 @@ class PruneOutdatedSyncTokensJob extends TimedJob { public function run($argument) { $limit = max(1, (int) $this->config->getAppValue(Application::APP_ID, 'totalNumberOfSyncTokensToKeep', '10000')); + $retention = max(7, (int) $this->config->getAppValue(Application::APP_ID, 'syncTokensRetentionDays', '60')) * 24 * 3600; - $prunedCalendarSyncTokens = $this->calDavBackend->pruneOutdatedSyncTokens($limit); - $prunedAddressBookSyncTokens = $this->cardDavBackend->pruneOutdatedSyncTokens($limit); + $prunedCalendarSyncTokens = $this->calDavBackend->pruneOutdatedSyncTokens($limit, $retention); + $prunedAddressBookSyncTokens = $this->cardDavBackend->pruneOutdatedSyncTokens($limit, $retention); $this->logger->info('Pruned {calendarSyncTokensNumber} calendar sync tokens and {addressBooksSyncTokensNumber} address book sync tokens', [ 'calendarSyncTokensNumber' => $prunedCalendarSyncTokens, diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index b1ff7419751..3abb9d584c1 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -2785,6 +2785,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription 'calendarid' => $query->createNamedParameter($calendarId), 'operation' => $query->createNamedParameter($operation), 'calendartype' => $query->createNamedParameter($calendarType), + 'created_at' => time(), ]); foreach ($objectUris as $uri) { $query->setParameter('uri', $uri); @@ -3259,7 +3260,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription /** * @throws \InvalidArgumentException */ - public function pruneOutdatedSyncTokens(int $keep = 10_000): int { + public function pruneOutdatedSyncTokens(int $keep, int $retention): int { if ($keep < 0) { throw new \InvalidArgumentException(); } @@ -3277,7 +3278,10 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $query = $this->db->getQueryBuilder(); $query->delete('calendarchanges') - ->where($query->expr()->lte('id', $query->createNamedParameter($maxId - $keep, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT)); + ->where( + $query->expr()->lte('id', $query->createNamedParameter($maxId - $keep, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT), + $query->expr()->lte('created_at', $query->createNamedParameter($retention)), + ); return $query->executeStatement(); } diff --git a/apps/dav/lib/CalDAV/CalendarObject.php b/apps/dav/lib/CalDAV/CalendarObject.php index 7f4bd9054e0..0d82e5ffa76 100644 --- a/apps/dav/lib/CalDAV/CalendarObject.php +++ b/apps/dav/lib/CalDAV/CalendarObject.php @@ -116,9 +116,13 @@ class CalendarObject extends \Sabre\CalDAV\CalendarObject { case 'CREATED': case 'DTSTART': case 'RRULE': + case 'RECURRENCE-ID': + case 'RDATE': case 'DURATION': case 'DTEND': case 'CLASS': + case 'EXRULE': + case 'EXDATE': case 'UID': break; case 'SUMMARY': diff --git a/apps/dav/lib/CardDAV/AddressBook.php b/apps/dav/lib/CardDAV/AddressBook.php index 468961b958e..4f589031f06 100644 --- a/apps/dav/lib/CardDAV/AddressBook.php +++ b/apps/dav/lib/CardDAV/AddressBook.php @@ -118,7 +118,7 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable, IMov ], [ 'privilege' => '{DAV:}write-properties', - 'principal' => '{DAV:}authenticated', + 'principal' => $this->getOwner(), 'protected' => true, ], ]; @@ -129,6 +129,11 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable, IMov 'principal' => '{DAV:}authenticated', 'protected' => true, ]; + $acl[] = [ + 'privilege' => '{DAV:}write-properties', + 'principal' => '{DAV:}authenticated', + 'protected' => true, + ]; } if (!$this->isShared()) { diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index f51049b7833..e9ffe6f25e9 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -983,6 +983,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { 'synctoken' => $query->createNamedParameter($syncToken), 'addressbookid' => $query->createNamedParameter($addressBookId), 'operation' => $query->createNamedParameter($operation), + 'created_at' => time(), ]) ->executeStatement(); @@ -1415,7 +1416,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { /** * @throws \InvalidArgumentException */ - public function pruneOutdatedSyncTokens(int $keep = 10_000): int { + public function pruneOutdatedSyncTokens(int $keep, int $retention): int { if ($keep < 0) { throw new \InvalidArgumentException(); } @@ -1433,7 +1434,10 @@ class CardDavBackend implements BackendInterface, SyncSupport { $query = $this->db->getQueryBuilder(); $query->delete('addressbookchanges') - ->where($query->expr()->lte('id', $query->createNamedParameter($maxId - $keep, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT)); + ->where( + $query->expr()->lte('id', $query->createNamedParameter($maxId - $keep, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT), + $query->expr()->lte('created_at', $query->createNamedParameter($retention)), + ); return $query->executeStatement(); } diff --git a/apps/dav/lib/DAV/Sharing/Backend.php b/apps/dav/lib/DAV/Sharing/Backend.php index f77be9211bf..b467479bc1e 100644 --- a/apps/dav/lib/DAV/Sharing/Backend.php +++ b/apps/dav/lib/DAV/Sharing/Backend.php @@ -214,7 +214,7 @@ abstract class Backend { 'principal' => $share['{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}principal'], 'protected' => true, ]; - } elseif ($this->service->getResourceType() === 'calendar') { + } elseif (in_array($this->service->getResourceType(), ['calendar','addressbook'])) { // Allow changing the properties of read only calendars, // so users can change the visibility. $acl[] = [ diff --git a/apps/dav/lib/Migration/Version1025Date20240308063933.php b/apps/dav/lib/Migration/Version1025Date20240308063933.php new file mode 100644 index 00000000000..a75fc85eccc --- /dev/null +++ b/apps/dav/lib/Migration/Version1025Date20240308063933.php @@ -0,0 +1,84 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2024 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\DAV\Migration; + +use Closure; +use OCP\DB\ISchemaWrapper; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\DB\Types; +use OCP\IDBConnection; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + +class Version1025Date20240308063933 extends SimpleMigrationStep { + + private IDBConnection $db; + + public function __construct(IDBConnection $db) { + $this->db = $db; + } + + /** + * @param IOutput $output + * @param Closure(): ISchemaWrapper $schemaClosure + * @param array $options + * @return null|ISchemaWrapper + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + foreach (['addressbookchanges', 'calendarchanges'] as $tableName) { + $table = $schema->getTable($tableName); + if (!$table->hasColumn('created_at')) { + $table->addColumn('created_at', Types::INTEGER, [ + 'notnull' => true, + 'length' => 4, + 'default' => 0, + ]); + } + } + + return $schema; + } + + public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options): void { + foreach (['addressbookchanges', 'calendarchanges'] as $tableName) { + $qb = $this->db->getQueryBuilder(); + + $update = $qb->update($tableName) + ->set('created_at', $qb->createNamedParameter(time(), IQueryBuilder::PARAM_INT)) + ->where( + $qb->expr()->eq('created_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)), + ); + + $updated = $update->executeStatement(); + $output->debug('Added a default creation timestamp to ' . $updated . ' rows in ' . $tableName); + } + } + +} diff --git a/apps/dav/lib/SystemTag/SystemTagMappingNode.php b/apps/dav/lib/SystemTag/SystemTagMappingNode.php index 9762b6e1db9..113c8d82836 100644 --- a/apps/dav/lib/SystemTag/SystemTagMappingNode.php +++ b/apps/dav/lib/SystemTag/SystemTagMappingNode.php @@ -37,62 +37,15 @@ use Sabre\DAV\Exception\NotFound; * Mapping node for system tag to object id */ class SystemTagMappingNode implements \Sabre\DAV\INode { - /** - * @var ISystemTag - */ - protected $tag; - - /** - * @var string - */ - private $objectId; - - /** - * @var string - */ - private $objectType; - - /** - * User - * - * @var IUser - */ - protected $user; - - /** - * @var ISystemTagManager - */ - protected $tagManager; - - /** - * @var ISystemTagObjectMapper - */ - private $tagMapper; - - /** - * Sets up the node, expects a full path name - * - * @param ISystemTag $tag system tag - * @param string $objectId - * @param string $objectType - * @param IUser $user user - * @param ISystemTagManager $tagManager - * @param ISystemTagObjectMapper $tagMapper - */ public function __construct( - ISystemTag $tag, - $objectId, - $objectType, - IUser $user, - ISystemTagManager $tagManager, - ISystemTagObjectMapper $tagMapper + private ISystemTag $tag, + private string $objectId, + private string $objectType, + private IUser $user, + private ISystemTagManager $tagManager, + private ISystemTagObjectMapper $tagMapper, + private \Closure $childWriteAccessFunction, ) { - $this->tag = $tag; - $this->objectId = $objectId; - $this->objectType = $objectType; - $this->user = $user; - $this->tagManager = $tagManager; - $this->tagMapper = $tagMapper; } /** @@ -166,6 +119,10 @@ class SystemTagMappingNode implements \Sabre\DAV\INode { if (!$this->tagManager->canUserAssignTag($this->tag, $this->user)) { throw new Forbidden('No permission to unassign tag ' . $this->tag->getId()); } + $writeAccessFunction = $this->childWriteAccessFunction; + if (!$writeAccessFunction($this->objectId)) { + throw new Forbidden('No permission to unassign tag to ' . $this->objectId); + } $this->tagMapper->unassignTags($this->objectId, $this->objectType, $this->tag->getId()); } catch (TagNotFoundException $e) { // can happen if concurrent deletion occurred diff --git a/apps/dav/lib/SystemTag/SystemTagsObjectMappingCollection.php b/apps/dav/lib/SystemTag/SystemTagsObjectMappingCollection.php index 4d73c17d7dd..b45ef6c3f71 100644 --- a/apps/dav/lib/SystemTag/SystemTagsObjectMappingCollection.php +++ b/apps/dav/lib/SystemTag/SystemTagsObjectMappingCollection.php @@ -40,56 +40,14 @@ use Sabre\DAV\ICollection; * Collection containing tags by object id */ class SystemTagsObjectMappingCollection implements ICollection { - - /** - * @var string - */ - private $objectId; - - /** - * @var string - */ - private $objectType; - - /** - * @var ISystemTagManager - */ - private $tagManager; - - /** - * @var ISystemTagObjectMapper - */ - private $tagMapper; - - /** - * User - * - * @var IUser - */ - private $user; - - - /** - * Constructor - * - * @param string $objectId object id - * @param string $objectType object type - * @param IUser $user user - * @param ISystemTagManager $tagManager tag manager - * @param ISystemTagObjectMapper $tagMapper tag mapper - */ public function __construct( - $objectId, - $objectType, - IUser $user, - ISystemTagManager $tagManager, - ISystemTagObjectMapper $tagMapper + private string $objectId, + private string $objectType, + private IUser $user, + private ISystemTagManager $tagManager, + private ISystemTagObjectMapper $tagMapper, + protected \Closure $childWriteAccessFunction, ) { - $this->tagManager = $tagManager; - $this->tagMapper = $tagMapper; - $this->objectId = $objectId; - $this->objectType = $objectType; - $this->user = $user; } /** @@ -106,7 +64,10 @@ class SystemTagsObjectMappingCollection implements ICollection { if (!$this->tagManager->canUserAssignTag($tag, $this->user)) { throw new Forbidden('No permission to assign tag ' . $tagId); } - + $writeAccessFunction = $this->childWriteAccessFunction; + if (!$writeAccessFunction($this->objectId)) { + throw new Forbidden('No permission to assign tag to ' . $this->objectId); + } $this->tagMapper->assignTags($this->objectId, $this->objectType, $tagId); } catch (TagNotFoundException $e) { throw new PreconditionFailed('Tag with id ' . $tagId . ' does not exist, cannot assign'); @@ -224,7 +185,8 @@ class SystemTagsObjectMappingCollection implements ICollection { $this->objectType, $this->user, $this->tagManager, - $this->tagMapper + $this->tagMapper, + $this->childWriteAccessFunction, ); } } diff --git a/apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php b/apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php index 3fa40278cdb..f1d5fc06c99 100644 --- a/apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php +++ b/apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php @@ -38,61 +38,15 @@ use Sabre\DAV\ICollection; * Collection containing object ids by object type */ class SystemTagsObjectTypeCollection implements ICollection { - - /** - * @var string - */ - private $objectType; - - /** - * @var ISystemTagManager - */ - private $tagManager; - - /** - * @var ISystemTagObjectMapper - */ - private $tagMapper; - - /** - * @var IGroupManager - */ - private $groupManager; - - /** - * @var IUserSession - */ - private $userSession; - - /** - * @var \Closure - **/ - protected $childExistsFunction; - - /** - * Constructor - * - * @param string $objectType object type - * @param ISystemTagManager $tagManager - * @param ISystemTagObjectMapper $tagMapper - * @param IUserSession $userSession - * @param IGroupManager $groupManager - * @param \Closure $childExistsFunction - */ public function __construct( - $objectType, - ISystemTagManager $tagManager, - ISystemTagObjectMapper $tagMapper, - IUserSession $userSession, - IGroupManager $groupManager, - \Closure $childExistsFunction + private string $objectType, + private ISystemTagManager $tagManager, + private ISystemTagObjectMapper $tagMapper, + private IUserSession $userSession, + private IGroupManager $groupManager, + protected \Closure $childExistsFunction, + protected \Closure $childWriteAccessFunction, ) { - $this->tagManager = $tagManager; - $this->tagMapper = $tagMapper; - $this->objectType = $objectType; - $this->userSession = $userSession; - $this->groupManager = $groupManager; - $this->childExistsFunction = $childExistsFunction; } /** @@ -134,7 +88,8 @@ class SystemTagsObjectTypeCollection implements ICollection { $this->objectType, $this->userSession->getUser(), $this->tagManager, - $this->tagMapper + $this->tagMapper, + $this->childWriteAccessFunction, ); } diff --git a/apps/dav/lib/SystemTag/SystemTagsRelationsCollection.php b/apps/dav/lib/SystemTag/SystemTagsRelationsCollection.php index 6911d40e208..989c4640a61 100644 --- a/apps/dav/lib/SystemTag/SystemTagsRelationsCollection.php +++ b/apps/dav/lib/SystemTag/SystemTagsRelationsCollection.php @@ -26,6 +26,7 @@ */ namespace OCA\DAV\SystemTag; +use OCP\Constants; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\IRootFolder; use OCP\IGroupManager; @@ -60,7 +61,21 @@ class SystemTagsRelationsCollection extends SimpleCollection { } else { return false; } - } + }, + function (string $name) use ($rootFolder, $userSession): bool { + $user = $userSession->getUser(); + if ($user) { + $nodes = $rootFolder->getUserFolder($user->getUID())->getById((int)$name); + foreach ($nodes as $node) { + if (($node->getPermissions() & Constants::PERMISSION_UPDATE) === Constants::PERMISSION_UPDATE) { + return true; + } + } + return false; + } else { + return false; + } + }, ), ]; @@ -75,7 +90,8 @@ class SystemTagsRelationsCollection extends SimpleCollection { $tagMapper, $userSession, $groupManager, - $entityExistsFunction + $entityExistsFunction, + fn ($name) => true, ); } diff --git a/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php b/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php index be6298b3372..20169072687 100644 --- a/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php +++ b/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php @@ -29,6 +29,7 @@ declare(strict_types=1); */ namespace OCA\DAV\Tests\unit\BackgroundJob; +use InvalidArgumentException; use OCA\DAV\AppInfo\Application; use OCA\DAV\BackgroundJob\PruneOutdatedSyncTokensJob; use OCA\DAV\CalDAV\CalDavBackend; @@ -72,18 +73,27 @@ class PruneOutdatedSyncTokensJobTest extends TestCase { /** * @dataProvider dataForTestRun */ - public function testRun(string $configValue, int $actualLimit, int $deletedCalendarSyncTokens, int $deletedAddressBookSyncTokens): void { - $this->config->expects($this->once()) + public function testRun(string $configToKeep, string $configRetentionDays, int $actualLimit, int $retentionDays, int $deletedCalendarSyncTokens, int $deletedAddressBookSyncTokens): void { + $this->config->expects($this->exactly(2)) ->method('getAppValue') - ->with(Application::APP_ID, 'totalNumberOfSyncTokensToKeep', '10000') - ->willReturn($configValue); + ->with(Application::APP_ID, self::anything(), self::anything()) + ->willReturnCallback(function ($app, $key) use ($configToKeep, $configRetentionDays) { + switch ($key) { + case 'totalNumberOfSyncTokensToKeep': + return $configToKeep; + case 'syncTokensRetentionDays': + return $configRetentionDays; + default: + throw new InvalidArgumentException(); + } + }); $this->calDavBackend->expects($this->once()) ->method('pruneOutdatedSyncTokens') ->with($actualLimit) ->willReturn($deletedCalendarSyncTokens); $this->cardDavBackend->expects($this->once()) ->method('pruneOutdatedSyncTokens') - ->with($actualLimit) + ->with($actualLimit, $retentionDays) ->willReturn($deletedAddressBookSyncTokens); $this->logger->expects($this->once()) ->method('info') @@ -97,8 +107,9 @@ class PruneOutdatedSyncTokensJobTest extends TestCase { public function dataForTestRun(): array { return [ - ['100', 100, 2, 3], - ['0', 1, 0, 0] + ['100', '2', 100, 7 * 24 * 3600, 2, 3], + ['100', '14', 100, 14 * 24 * 3600, 2, 3], + ['0', '60', 1, 60 * 24 * 3600, 0, 0] ]; } } diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php index c85c13e3f21..ef4cfb2aaab 100644 --- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php +++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php @@ -46,6 +46,7 @@ use Sabre\DAV\Exception\NotFound; use Sabre\DAV\PropPatch; use Sabre\DAV\Xml\Property\Href; use Sabre\DAVACL\IACL; +use function time; /** * Class CalDavBackendTest @@ -1357,7 +1358,12 @@ END:VEVENT END:VCALENDAR EOD; $this->backend->updateCalendarObject($calendarId, $uri, $calData); - $deleted = $this->backend->pruneOutdatedSyncTokens(0); + + // Keep everything + $deleted = $this->backend->pruneOutdatedSyncTokens(0, 0); + self::assertSame(0, $deleted); + + $deleted = $this->backend->pruneOutdatedSyncTokens(0, time()); // At least one from the object creation and one from the object update $this->assertGreaterThanOrEqual(2, $deleted); $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 1); @@ -1423,7 +1429,7 @@ EOD; $this->assertEmpty($changes['deleted']); // Delete all but last change - $deleted = $this->backend->pruneOutdatedSyncTokens(1); + $deleted = $this->backend->pruneOutdatedSyncTokens(1, time()); $this->assertEquals(1, $deleted); // We had two changes before, now one // Only update should remain @@ -1433,7 +1439,8 @@ EOD; $this->assertEmpty($changes['deleted']); // Check that no crash occurs when prune is called without current changes - $deleted = $this->backend->pruneOutdatedSyncTokens(1); + $deleted = $this->backend->pruneOutdatedSyncTokens(1, time()); + self::assertSame(0, $deleted); } public function testSearchAndExpandRecurrences() { diff --git a/apps/dav/tests/unit/CardDAV/AddressBookTest.php b/apps/dav/tests/unit/CardDAV/AddressBookTest.php index f9cba4e6a83..fa312f98797 100644 --- a/apps/dav/tests/unit/CardDAV/AddressBookTest.php +++ b/apps/dav/tests/unit/CardDAV/AddressBookTest.php @@ -169,7 +169,7 @@ class AddressBookTest extends TestCase { 'protected' => true ], [ 'privilege' => '{DAV:}write-properties', - 'principal' => '{DAV:}authenticated', + 'principal' => $hasOwnerSet ? 'user1' : 'user2', 'protected' => true ]]; if ($hasOwnerSet) { diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php index ea80187f554..942718f7ce5 100644 --- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php +++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php @@ -60,6 +60,7 @@ use Sabre\DAV\PropPatch; use Sabre\VObject\Component\VCard; use Sabre\VObject\Property\Text; use Test\TestCase; +use function time; /** * Class CardDavBackendTest @@ -880,7 +881,12 @@ class CardDavBackendTest extends TestCase { $uri = $this->getUniqueID('card'); $this->backend->createCard($addressBookId, $uri, $this->vcardTest0); $this->backend->updateCard($addressBookId, $uri, $this->vcardTest1); - $deleted = $this->backend->pruneOutdatedSyncTokens(0); + + // Do not delete anything if week data as old as ts=0 + $deleted = $this->backend->pruneOutdatedSyncTokens(0, 0); + self::assertSame(0, $deleted); + + $deleted = $this->backend->pruneOutdatedSyncTokens(0, time()); // At least one from the object creation and one from the object update $this->assertGreaterThanOrEqual(2, $deleted); $changes = $this->backend->getChangesForAddressBook($addressBookId, $syncToken, 1); @@ -912,7 +918,7 @@ class CardDavBackendTest extends TestCase { $this->assertEmpty($changes['deleted']); // Delete all but last change - $deleted = $this->backend->pruneOutdatedSyncTokens(1); + $deleted = $this->backend->pruneOutdatedSyncTokens(1, time()); $this->assertEquals(1, $deleted); // We had two changes before, now one // Only update should remain @@ -920,8 +926,8 @@ class CardDavBackendTest extends TestCase { $this->assertEmpty($changes['added']); $this->assertEquals(1, count($changes['modified'])); $this->assertEmpty($changes['deleted']); - + // Check that no crash occurs when prune is called without current changes - $deleted = $this->backend->pruneOutdatedSyncTokens(1); + $deleted = $this->backend->pruneOutdatedSyncTokens(1, time()); } } diff --git a/apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php b/apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php index 6599c574dd9..97020cf7fa1 100644 --- a/apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php +++ b/apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php @@ -33,21 +33,9 @@ use OCP\SystemTag\ISystemTagObjectMapper; use OCP\SystemTag\TagNotFoundException; class SystemTagMappingNodeTest extends \Test\TestCase { - - /** - * @var \OCP\SystemTag\ISystemTagManager - */ - private $tagManager; - - /** - * @var \OCP\SystemTag\ISystemTagObjectMapper - */ - private $tagMapper; - - /** - * @var \OCP\IUser - */ - private $user; + private ISystemTagManager $tagManager; + private ISystemTagObjectMapper $tagMapper; + private IUser $user; protected function setUp(): void { parent::setUp(); @@ -60,7 +48,7 @@ class SystemTagMappingNodeTest extends \Test\TestCase { ->getMock(); } - public function getMappingNode($tag = null) { + public function getMappingNode($tag = null, array $writableNodeIds = []) { if ($tag === null) { $tag = new SystemTag(1, 'Test', true, true); } @@ -70,7 +58,8 @@ class SystemTagMappingNodeTest extends \Test\TestCase { 'files', $this->user, $this->tagManager, - $this->tagMapper + $this->tagMapper, + fn ($id): bool => in_array($id, $writableNodeIds), ); } @@ -84,7 +73,7 @@ class SystemTagMappingNodeTest extends \Test\TestCase { } public function testDeleteTag(): void { - $node = $this->getMappingNode(); + $node = $this->getMappingNode(null, [123]); $this->tagManager->expects($this->once()) ->method('canUserSeeTag') ->with($node->getSystemTag()) @@ -102,6 +91,25 @@ class SystemTagMappingNodeTest extends \Test\TestCase { $node->delete(); } + public function testDeleteTagForbidden(): void { + $node = $this->getMappingNode(); + $this->tagManager->expects($this->once()) + ->method('canUserSeeTag') + ->with($node->getSystemTag()) + ->willReturn(true); + $this->tagManager->expects($this->once()) + ->method('canUserAssignTag') + ->with($node->getSystemTag()) + ->willReturn(true); + $this->tagManager->expects($this->never()) + ->method('deleteTags'); + $this->tagMapper->expects($this->never()) + ->method('unassignTags'); + + $this->expectException(\Sabre\DAV\Exception\Forbidden::class); + $node->delete(); + } + public function tagNodeDeleteProviderPermissionException() { return [ [ @@ -144,7 +152,7 @@ class SystemTagMappingNodeTest extends \Test\TestCase { $this->assertInstanceOf($expectedException, $thrown); } - + public function testDeleteTagNotFound(): void { $this->expectException(\Sabre\DAV\Exception\NotFound::class); @@ -164,6 +172,6 @@ class SystemTagMappingNodeTest extends \Test\TestCase { ->with(123, 'files', 1) ->will($this->throwException(new TagNotFoundException())); - $this->getMappingNode($tag)->delete(); + $this->getMappingNode($tag, [123])->delete(); } } diff --git a/apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php b/apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php index 22f2e69b740..d0703229ea7 100644 --- a/apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php +++ b/apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php @@ -32,21 +32,9 @@ use OCP\SystemTag\ISystemTagObjectMapper; use OCP\SystemTag\TagNotFoundException; class SystemTagsObjectMappingCollectionTest extends \Test\TestCase { - - /** - * @var \OCP\SystemTag\ISystemTagManager - */ - private $tagManager; - - /** - * @var \OCP\SystemTag\ISystemTagObjectMapper - */ - private $tagMapper; - - /** - * @var \OCP\IUser - */ - private $user; + private ISystemTagManager $tagManager; + private ISystemTagObjectMapper $tagMapper; + private IUser $user; protected function setUp(): void { parent::setUp(); @@ -60,13 +48,14 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase { ->getMock(); } - public function getNode() { + public function getNode(array $writableNodeIds = []) { return new \OCA\DAV\SystemTag\SystemTagsObjectMappingCollection( 111, 'files', $this->user, $this->tagManager, - $this->tagMapper + $this->tagMapper, + fn ($id): bool => in_array($id, $writableNodeIds), ); } @@ -89,6 +78,28 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase { ->method('assignTags') ->with(111, 'files', '555'); + $this->getNode([111])->createFile('555'); + } + + public function testAssignTagForbidden(): void { + $tag = new SystemTag('1', 'Test', true, true); + $this->tagManager->expects($this->once()) + ->method('canUserSeeTag') + ->with($tag) + ->willReturn(true); + $this->tagManager->expects($this->once()) + ->method('canUserAssignTag') + ->with($tag) + ->willReturn(true); + + $this->tagManager->expects($this->once()) + ->method('getTagsByIds') + ->with(['555']) + ->willReturn([$tag]); + $this->tagMapper->expects($this->never()) + ->method('assignTags'); + + $this->expectException(\Sabre\DAV\Exception\Forbidden::class); $this->getNode()->createFile('555'); } @@ -132,7 +143,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase { $this->assertInstanceOf($expectedException, $thrown); } - + public function testAssignTagNotFound(): void { $this->expectException(\Sabre\DAV\Exception\PreconditionFailed::class); @@ -144,7 +155,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase { $this->getNode()->createFile('555'); } - + public function testForbiddenCreateDirectory(): void { $this->expectException(\Sabre\DAV\Exception\Forbidden::class); @@ -174,7 +185,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase { $this->assertEquals('555', $childNode->getName()); } - + public function testGetChildNonVisible(): void { $this->expectException(\Sabre\DAV\Exception\NotFound::class); @@ -197,7 +208,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase { $this->getNode()->getChild('555'); } - + public function testGetChildRelationNotFound(): void { $this->expectException(\Sabre\DAV\Exception\NotFound::class); @@ -209,7 +220,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase { $this->getNode()->getChild('777'); } - + public function testGetChildInvalidId(): void { $this->expectException(\Sabre\DAV\Exception\BadRequest::class); @@ -221,7 +232,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase { $this->getNode()->getChild('badid'); } - + public function testGetChildTagDoesNotExist(): void { $this->expectException(\Sabre\DAV\Exception\NotFound::class); @@ -325,7 +336,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase { $this->assertFalse($this->getNode()->childExists('555')); } - + public function testChildExistsInvalidId(): void { $this->expectException(\Sabre\DAV\Exception\BadRequest::class); @@ -337,14 +348,14 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase { $this->getNode()->childExists('555'); } - + public function testDelete(): void { $this->expectException(\Sabre\DAV\Exception\Forbidden::class); $this->getNode()->delete(); } - + public function testSetName(): void { $this->expectException(\Sabre\DAV\Exception\Forbidden::class); diff --git a/apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php b/apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php index 143d598fd2d..780b16858f1 100644 --- a/apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php +++ b/apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php @@ -87,6 +87,15 @@ class SystemTagsObjectTypeCollectionTest extends \Test\TestCase { $node = $userFolder->getFirstNodeById(intval($name)); return $node !== null; }; + $writeAccessClosure = function ($name) use ($userFolder) { + $nodes = $userFolder->getById((int)$name); + foreach ($nodes as $node) { + if (($node->getPermissions() & Constants::PERMISSION_UPDATE) === Constants::PERMISSION_UPDATE) { + return true; + } + } + return false; + }; $this->node = new \OCA\DAV\SystemTag\SystemTagsObjectTypeCollection( 'files', @@ -94,7 +103,8 @@ class SystemTagsObjectTypeCollectionTest extends \Test\TestCase { $this->tagMapper, $userSession, $groupManager, - $closure + $closure, + $writeAccessClosure, ); } diff --git a/apps/files/lib/ResponseDefinitions.php b/apps/files/lib/ResponseDefinitions.php index 5e565cc356d..a3b62549bcc 100644 --- a/apps/files/lib/ResponseDefinitions.php +++ b/apps/files/lib/ResponseDefinitions.php @@ -44,6 +44,7 @@ namespace OCA\Files; * label: string, * extension: string, * iconClass: ?string, + * iconSvgInline: ?string, * mimetypes: string[], * ratio: ?float, * actionLabel: string, diff --git a/apps/files/openapi.json b/apps/files/openapi.json index f9cdb67783d..b2ac9efe6c8 100644 --- a/apps/files/openapi.json +++ b/apps/files/openapi.json @@ -151,6 +151,7 @@ "label", "extension", "iconClass", + "iconSvgInline", "mimetypes", "ratio", "actionLabel" @@ -169,6 +170,10 @@ "type": "string", "nullable": true }, + "iconSvgInline": { + "type": "string", + "nullable": true + }, "mimetypes": { "type": "array", "items": { diff --git a/apps/files/src/newMenu/newFromTemplate.ts b/apps/files/src/newMenu/newFromTemplate.ts index 5e69181995e..42e24c59de0 100644 --- a/apps/files/src/newMenu/newFromTemplate.ts +++ b/apps/files/src/newMenu/newFromTemplate.ts @@ -64,8 +64,8 @@ export function registerTemplateEntries() { addNewFileMenuEntry({ id: `template-new-${provider.app}-${index}`, displayName: provider.label, - // TODO: migrate to inline svg iconClass: provider.iconClass || 'icon-file', + iconSvgInline: provider.iconSvgInline, enabled(context: Folder): boolean { return (context.permissions & Permission.CREATE) !== 0 }, diff --git a/apps/files/src/types.ts b/apps/files/src/types.ts index 0e9dd6fb531..aa9164c873f 100644 --- a/apps/files/src/types.ts +++ b/apps/files/src/types.ts @@ -117,6 +117,7 @@ export interface TemplateFile { label: string extension: string iconClass?: string + iconSvgInline?: string mimetypes: string[] ratio?: number templates?: Record<string, unknown>[] diff --git a/apps/files_external/lib/Migration/DummyUserSession.php b/apps/files_external/lib/Migration/DummyUserSession.php index e1b2b500188..ce987b3c575 100644 --- a/apps/files_external/lib/Migration/DummyUserSession.php +++ b/apps/files_external/lib/Migration/DummyUserSession.php @@ -29,10 +29,7 @@ use OCP\IUserSession; class DummyUserSession implements IUserSession { - /** - * @var IUser - */ - private $user; + private ?IUser $user = null; public function login($uid, $password) { } @@ -44,6 +41,10 @@ class DummyUserSession implements IUserSession { $this->user = $user; } + public function setVolatileActiveUser(?IUser $user): void { + $this->user = $user; + } + public function getUser() { return $this->user; } diff --git a/apps/files_sharing/l10n/fr.js b/apps/files_sharing/l10n/fr.js index 74ef37f3bd8..03382af81d0 100644 --- a/apps/files_sharing/l10n/fr.js +++ b/apps/files_sharing/l10n/fr.js @@ -151,6 +151,7 @@ OC.L10N.register( "Create share" : "Créer un partage", "Cancel" : "Annuler", "Customize link" : "Personnaliser le lien", + "Generate QR code" : "Générer un QR code", "Add another link" : "Ajouter un autre lien", "Create a new share link" : "Créer un nouveau lien de partage", "{shareWith} by {initiator}" : "{shareWith} par {initiator}", @@ -164,6 +165,7 @@ OC.L10N.register( "Error, please enter proper password and/or expiration date" : "Erreur. Merci d'entrer un mot de passe valide et/ou une date d'expiration", "Link share created" : "Lien de partage créé", "Error while creating the share" : "Erreur lors de la création du partage", + "Quick share options, the current selected is \"{selectedOption}\"" : "Options de partage rapide, l'option actuellement sélectionnée est « {selectedOption} »", "View only" : "Afficher seulement", "Can edit" : "Peut modifier", "File drop" : "Dépôt de fichier", diff --git a/apps/files_sharing/l10n/fr.json b/apps/files_sharing/l10n/fr.json index 0d2657e7680..661eb1814b4 100644 --- a/apps/files_sharing/l10n/fr.json +++ b/apps/files_sharing/l10n/fr.json @@ -149,6 +149,7 @@ "Create share" : "Créer un partage", "Cancel" : "Annuler", "Customize link" : "Personnaliser le lien", + "Generate QR code" : "Générer un QR code", "Add another link" : "Ajouter un autre lien", "Create a new share link" : "Créer un nouveau lien de partage", "{shareWith} by {initiator}" : "{shareWith} par {initiator}", @@ -162,6 +163,7 @@ "Error, please enter proper password and/or expiration date" : "Erreur. Merci d'entrer un mot de passe valide et/ou une date d'expiration", "Link share created" : "Lien de partage créé", "Error while creating the share" : "Erreur lors de la création du partage", + "Quick share options, the current selected is \"{selectedOption}\"" : "Options de partage rapide, l'option actuellement sélectionnée est « {selectedOption} »", "View only" : "Afficher seulement", "Can edit" : "Peut modifier", "File drop" : "Dépôt de fichier", diff --git a/apps/files_sharing/l10n/ko.js b/apps/files_sharing/l10n/ko.js index c1942f51ba5..2e1a38ae7e0 100644 --- a/apps/files_sharing/l10n/ko.js +++ b/apps/files_sharing/l10n/ko.js @@ -161,7 +161,7 @@ OC.L10N.register( "Link share created" : "링크 공유가 만들어짐", "Error while creating the share" : "공유를 만드는 중 오류 발생", "View only" : "읽기 전용", - "Can edit" : "편집할 수 있음", + "Can edit" : "수정할 수 있음", "File drop" : "업로드만 허용", "Custom permissions" : "사용자 지정 권한", "Search for share recipients" : "공유 받는이 검색", @@ -179,10 +179,10 @@ OC.L10N.register( "Deck board" : "Deck 보드", "on {server}" : "{server}에서", "Allow upload and editing" : "업로드와 수정 허용", - "Allow editing" : "Allow editing", + "Allow editing" : "수정 허용", "Upload only" : "업로드만", "Advanced settings" : "고급 설정", - "Share label" : "레이블 공유", + "Share label" : "공유 이름", "Set password" : "비밀번호 설정", "Password" : "암호", "Password expires {passwordExpirationTime}" : "암호가 {passwordExpirationTime}에 만료됨", diff --git a/apps/files_sharing/l10n/ko.json b/apps/files_sharing/l10n/ko.json index 3b46ba0d6c2..0b5c2f6248d 100644 --- a/apps/files_sharing/l10n/ko.json +++ b/apps/files_sharing/l10n/ko.json @@ -159,7 +159,7 @@ "Link share created" : "링크 공유가 만들어짐", "Error while creating the share" : "공유를 만드는 중 오류 발생", "View only" : "읽기 전용", - "Can edit" : "편집할 수 있음", + "Can edit" : "수정할 수 있음", "File drop" : "업로드만 허용", "Custom permissions" : "사용자 지정 권한", "Search for share recipients" : "공유 받는이 검색", @@ -177,10 +177,10 @@ "Deck board" : "Deck 보드", "on {server}" : "{server}에서", "Allow upload and editing" : "업로드와 수정 허용", - "Allow editing" : "Allow editing", + "Allow editing" : "수정 허용", "Upload only" : "업로드만", "Advanced settings" : "고급 설정", - "Share label" : "레이블 공유", + "Share label" : "공유 이름", "Set password" : "비밀번호 설정", "Password" : "암호", "Password expires {passwordExpirationTime}" : "암호가 {passwordExpirationTime}에 만료됨", diff --git a/apps/files_versions/composer/composer/autoload_classmap.php b/apps/files_versions/composer/composer/autoload_classmap.php index 49ef00a733b..c7fa952de27 100644 --- a/apps/files_versions/composer/composer/autoload_classmap.php +++ b/apps/files_versions/composer/composer/autoload_classmap.php @@ -21,7 +21,7 @@ return array( 'OCA\\Files_Versions\\Listener\\FileEventsListener' => $baseDir . '/../lib/Listener/FileEventsListener.php', 'OCA\\Files_Versions\\Listener\\LoadAdditionalListener' => $baseDir . '/../lib/Listener/LoadAdditionalListener.php', 'OCA\\Files_Versions\\Listener\\LoadSidebarListener' => $baseDir . '/../lib/Listener/LoadSidebarListener.php', - 'OCA\\Files_Versions\\Listener\\MetadataFileEvents' => $baseDir . '/../lib/Listener/MetadataFileEvents.php', + 'OCA\\Files_Versions\\Listener\\VersionAuthorListener' => $baseDir . '/../lib/Listener/VersionAuthorListener.php', 'OCA\\Files_Versions\\Migration\\Version1020Date20221114144058' => $baseDir . '/../lib/Migration/Version1020Date20221114144058.php', 'OCA\\Files_Versions\\Sabre\\Plugin' => $baseDir . '/../lib/Sabre/Plugin.php', 'OCA\\Files_Versions\\Sabre\\RestoreFolder' => $baseDir . '/../lib/Sabre/RestoreFolder.php', diff --git a/apps/files_versions/composer/composer/autoload_static.php b/apps/files_versions/composer/composer/autoload_static.php index 78175ea1fba..988b8e27cbe 100644 --- a/apps/files_versions/composer/composer/autoload_static.php +++ b/apps/files_versions/composer/composer/autoload_static.php @@ -36,7 +36,7 @@ class ComposerStaticInitFiles_Versions 'OCA\\Files_Versions\\Listener\\FileEventsListener' => __DIR__ . '/..' . '/../lib/Listener/FileEventsListener.php', 'OCA\\Files_Versions\\Listener\\LoadAdditionalListener' => __DIR__ . '/..' . '/../lib/Listener/LoadAdditionalListener.php', 'OCA\\Files_Versions\\Listener\\LoadSidebarListener' => __DIR__ . '/..' . '/../lib/Listener/LoadSidebarListener.php', - 'OCA\\Files_Versions\\Listener\\MetadataFileEvents' => __DIR__ . '/..' . '/../lib/Listener/MetadataFileEvents.php', + 'OCA\\Files_Versions\\Listener\\VersionAuthorListener' => __DIR__ . '/..' . '/../lib/Listener/VersionAuthorListener.php', 'OCA\\Files_Versions\\Migration\\Version1020Date20221114144058' => __DIR__ . '/..' . '/../lib/Migration/Version1020Date20221114144058.php', 'OCA\\Files_Versions\\Sabre\\Plugin' => __DIR__ . '/..' . '/../lib/Sabre/Plugin.php', 'OCA\\Files_Versions\\Sabre\\RestoreFolder' => __DIR__ . '/..' . '/../lib/Sabre/RestoreFolder.php', diff --git a/apps/files_versions/lib/AppInfo/Application.php b/apps/files_versions/lib/AppInfo/Application.php index 7e1960da1eb..e6870139ee2 100644 --- a/apps/files_versions/lib/AppInfo/Application.php +++ b/apps/files_versions/lib/AppInfo/Application.php @@ -36,7 +36,7 @@ use OCA\Files_Versions\Capabilities; use OCA\Files_Versions\Listener\FileEventsListener; use OCA\Files_Versions\Listener\LoadAdditionalListener; use OCA\Files_Versions\Listener\LoadSidebarListener; -use OCA\Files_Versions\Listener\MetadataFileEvents; +use OCA\Files_Versions\Listener\VersionAuthorListener; use OCA\Files_Versions\Versions\IVersionManager; use OCA\Files_Versions\Versions\VersionManager; use OCP\Accounts\IAccountManager; @@ -120,8 +120,8 @@ class Application extends App implements IBootstrap { $context->registerEventListener(NodeCopiedEvent::class, FileEventsListener::class); $context->registerEventListener(BeforeNodeRenamedEvent::class, FileEventsListener::class); $context->registerEventListener(BeforeNodeCopiedEvent::class, FileEventsListener::class); - - $context->registerEventListener(NodeWrittenEvent::class, MetadataFileEvents::class); + + $context->registerEventListener(NodeWrittenEvent::class, VersionAuthorListener::class); } public function boot(IBootContext $context): void { diff --git a/apps/files_versions/lib/Listener/MetadataFileEvents.php b/apps/files_versions/lib/Listener/VersionAuthorListener.php index c8a38da588d..158f039d555 100644 --- a/apps/files_versions/lib/Listener/MetadataFileEvents.php +++ b/apps/files_versions/lib/Listener/VersionAuthorListener.php @@ -32,7 +32,7 @@ use OCP\Files\Node; use OCP\IUserSession; /** @template-implements IEventListener<NodeWrittenEvent> */ -class MetadataFileEvents implements IEventListener { +class VersionAuthorListener implements IEventListener { public function __construct( private IVersionManager $versionManager, private IUserSession $userSession, diff --git a/apps/workflowengine/src/components/Checks/RequestUserGroup.vue b/apps/workflowengine/src/components/Checks/RequestUserGroup.vue index 2b248153aa6..ee774b7939f 100644 --- a/apps/workflowengine/src/components/Checks/RequestUserGroup.vue +++ b/apps/workflowengine/src/components/Checks/RequestUserGroup.vue @@ -22,21 +22,26 @@ <template> <div> - <NcSelect :value="currentValue" + <NcSelect :aria-label-combobox="t('workflowengine', 'Select groups')" + :aria-label-listbox="t('workflowengine', 'Groups')" + :clearable="false" :loading="status.isLoading && groups.length === 0" + :placeholder="t('workflowengine', 'Type to search for group …')" :options="groups" - :clearable="false" + :value="currentValue" label="displayname" - @search-change="searchAsync" + @search="searchAsync" @input="(value) => $emit('input', value.id)" /> </div> </template> <script> -import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js' -import axios from '@nextcloud/axios' +import { translate as t } from '@nextcloud/l10n' import { generateOcsUrl } from '@nextcloud/router' +import axios from '@nextcloud/axios' +import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js' + const groups = [] const status = { isLoading: false, @@ -69,14 +74,18 @@ export default { }, }, async mounted() { + // If empty, load first chunk of groups if (this.groups.length === 0) { await this.searchAsync('') } - if (this.currentValue === null) { + // If a current group is set but not in our list of groups then search for that group + if (this.currentValue === null && this.value) { await this.searchAsync(this.value) } }, methods: { + t, + searchAsync(searchQuery) { if (this.status.isLoading) { return |