diff options
Diffstat (limited to 'core')
37 files changed, 266 insertions, 44 deletions
diff --git a/core/AppInfo/ConfigLexicon.php b/core/AppInfo/ConfigLexicon.php index df8243019ad..8f1d89eaace 100644 --- a/core/AppInfo/ConfigLexicon.php +++ b/core/AppInfo/ConfigLexicon.php @@ -22,6 +22,9 @@ use OCP\Config\ValueType; class ConfigLexicon implements ILexicon { public const SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES = 'shareapi_allow_federation_on_public_shares'; public const SHARE_CUSTOM_TOKEN = 'shareapi_allow_custom_tokens'; + public const SHARE_LINK_PASSWORD_DEFAULT = 'shareapi_enable_link_password_by_default'; + public const SHARE_LINK_PASSWORD_ENFORCED = 'shareapi_enforce_links_password'; + public const USER_LANGUAGE = 'lang'; public const LASTCRON_TIMESTAMP = 'lastcron'; @@ -49,6 +52,16 @@ class ConfigLexicon implements ILexicon { lazy: true, note: 'Shares with guessable tokens may be accessed easily. Shares with custom tokens will continue to be accessible after this setting has been disabled.', ), + new Entry(self::SHARE_LINK_PASSWORD_DEFAULT, ValueType::BOOL, false, 'Ask for a password when sharing document by default'), + new Entry( + key: self::SHARE_LINK_PASSWORD_ENFORCED, + type: ValueType::BOOL, + defaultRaw: fn (Preset $p): bool => match ($p) { + Preset::SCHOOL, Preset::UNIVERSITY, Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true, + default => false, + }, + definition: 'Enforce password protection when sharing document' + ), new Entry(self::LASTCRON_TIMESTAMP, ValueType::INT, 0, 'timestamp of last cron execution'), ]; } diff --git a/core/Command/TaskProcessing/Cleanup.php b/core/Command/TaskProcessing/Cleanup.php new file mode 100644 index 00000000000..2ed2cbdec94 --- /dev/null +++ b/core/Command/TaskProcessing/Cleanup.php @@ -0,0 +1,93 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Core\Command\TaskProcessing; + +use OC\Core\Command\Base; +use OC\TaskProcessing\Db\TaskMapper; +use OC\TaskProcessing\Manager; +use OCP\Files\AppData\IAppDataFactory; +use Psr\Log\LoggerInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Cleanup extends Base { + private \OCP\Files\IAppData $appData; + + public function __construct( + protected Manager $taskProcessingManager, + private TaskMapper $taskMapper, + private LoggerInterface $logger, + IAppDataFactory $appDataFactory, + ) { + parent::__construct(); + $this->appData = $appDataFactory->get('core'); + } + + protected function configure() { + $this + ->setName('taskprocessing:task:cleanup') + ->setDescription('cleanup old tasks') + ->addArgument( + 'maxAgeSeconds', + InputArgument::OPTIONAL, + // default is not defined as an argument default value because we want to show a nice "4 months" value + 'delete tasks that are older than this number of seconds, defaults to ' . Manager::MAX_TASK_AGE_SECONDS . ' (4 months)', + ); + parent::configure(); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $maxAgeSeconds = $input->getArgument('maxAgeSeconds') ?? Manager::MAX_TASK_AGE_SECONDS; + $output->writeln('<comment>Cleanup up tasks older than ' . $maxAgeSeconds . ' seconds and the related output files</comment>'); + + $taskIdsToCleanup = []; + try { + $fileCleanupGenerator = $this->taskProcessingManager->cleanupTaskProcessingTaskFiles($maxAgeSeconds); + foreach ($fileCleanupGenerator as $cleanedUpEntry) { + $output->writeln( + "<info>\t - " . 'Deleted appData/core/TaskProcessing/' . $cleanedUpEntry['file_name'] + . ' (fileId: ' . $cleanedUpEntry['file_id'] . ', taskId: ' . $cleanedUpEntry['task_id'] . ')</info>' + ); + } + $taskIdsToCleanup = $fileCleanupGenerator->getReturn(); + } catch (\Exception $e) { + $this->logger->warning('Failed to delete stale task processing tasks files', ['exception' => $e]); + $output->writeln('<warning>Failed to delete stale task processing tasks files</warning>'); + } + try { + $deletedTaskCount = $this->taskMapper->deleteOlderThan($maxAgeSeconds); + foreach ($taskIdsToCleanup as $taskId) { + $output->writeln("<info>\t - " . 'Deleted task ' . $taskId . ' from the database</info>'); + } + $output->writeln("<comment>\t - " . 'Deleted ' . $deletedTaskCount . ' tasks from the database</comment>'); + } catch (\OCP\DB\Exception $e) { + $this->logger->warning('Failed to delete stale task processing tasks', ['exception' => $e]); + $output->writeln('<warning>Failed to delete stale task processing tasks</warning>'); + } + try { + $textToImageDeletedFileNames = $this->taskProcessingManager->clearFilesOlderThan($this->appData->getFolder('text2image'), $maxAgeSeconds); + foreach ($textToImageDeletedFileNames as $entry) { + $output->writeln("<info>\t - " . 'Deleted appData/core/text2image/' . $entry . '</info>'); + } + } catch (\OCP\Files\NotFoundException $e) { + // noop + } + try { + $audioToTextDeletedFileNames = $this->taskProcessingManager->clearFilesOlderThan($this->appData->getFolder('audio2text'), $maxAgeSeconds); + foreach ($audioToTextDeletedFileNames as $entry) { + $output->writeln("<info>\t - " . 'Deleted appData/core/audio2text/' . $entry . '</info>'); + } + } catch (\OCP\Files\NotFoundException $e) { + // noop + } + + return 0; + } +} diff --git a/core/Command/TaskProcessing/EnabledCommand.php b/core/Command/TaskProcessing/EnabledCommand.php index 0d4b831812c..a99e3e001b9 100644 --- a/core/Command/TaskProcessing/EnabledCommand.php +++ b/core/Command/TaskProcessing/EnabledCommand.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/core/Command/TaskProcessing/GetCommand.php b/core/Command/TaskProcessing/GetCommand.php index 5c4fd17f2f8..f97556281a1 100644 --- a/core/Command/TaskProcessing/GetCommand.php +++ b/core/Command/TaskProcessing/GetCommand.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/core/Command/TaskProcessing/ListCommand.php b/core/Command/TaskProcessing/ListCommand.php index 81eb258d35d..50a694c1a6e 100644 --- a/core/Command/TaskProcessing/ListCommand.php +++ b/core/Command/TaskProcessing/ListCommand.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/core/Command/TaskProcessing/Statistics.php b/core/Command/TaskProcessing/Statistics.php index 86478b34db1..6aa4cd5bf52 100644 --- a/core/Command/TaskProcessing/Statistics.php +++ b/core/Command/TaskProcessing/Statistics.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/core/Controller/OCJSController.php b/core/Controller/OCJSController.php index ea372b43b2e..083ad4b209f 100644 --- a/core/Controller/OCJSController.php +++ b/core/Controller/OCJSController.php @@ -20,6 +20,7 @@ use OCP\AppFramework\Http\Attribute\OpenAPI; use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\DataDisplayResponse; use OCP\Defaults; +use OCP\IAppConfig; use OCP\IConfig; use OCP\IGroupManager; use OCP\IInitialStateService; @@ -43,6 +44,7 @@ class OCJSController extends Controller { ISession $session, IUserSession $userSession, IConfig $config, + IAppConfig $appConfig, IGroupManager $groupManager, IniGetWrapper $iniWrapper, IURLGenerator $urlGenerator, @@ -62,6 +64,7 @@ class OCJSController extends Controller { $session, $userSession->getUser(), $config, + $appConfig, $groupManager, $iniWrapper, $urlGenerator, diff --git a/core/Controller/TaskProcessingApiController.php b/core/Controller/TaskProcessingApiController.php index 90a0e9ba14a..82b4d786914 100644 --- a/core/Controller/TaskProcessingApiController.php +++ b/core/Controller/TaskProcessingApiController.php @@ -31,7 +31,6 @@ use OCP\Files\NotPermittedException; use OCP\IL10N; use OCP\IRequest; use OCP\Lock\LockedException; -use OCP\TaskProcessing\EShapeType; use OCP\TaskProcessing\Exception\Exception; use OCP\TaskProcessing\Exception\NotFoundException; use OCP\TaskProcessing\Exception\PreConditionNotMetException; @@ -391,7 +390,7 @@ class TaskProcessingApiController extends OCSController { * @return StreamResponse<Http::STATUS_OK, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}> */ private function getFileContentsInternal(Task $task, int $fileId): StreamResponse|DataResponse { - $ids = $this->extractFileIdsFromTask($task); + $ids = $this->taskProcessingManager->extractFileIdsFromTask($task); if (!in_array($fileId, $ids)) { return new DataResponse(['message' => $this->l->t('Not found')], Http::STATUS_NOT_FOUND); } @@ -429,45 +428,6 @@ class TaskProcessingApiController extends OCSController { } /** - * @param Task $task - * @return list<int> - * @throws NotFoundException - */ - private function extractFileIdsFromTask(Task $task): array { - $ids = []; - $taskTypes = $this->taskProcessingManager->getAvailableTaskTypes(); - if (!isset($taskTypes[$task->getTaskTypeId()])) { - throw new NotFoundException('Could not find task type'); - } - $taskType = $taskTypes[$task->getTaskTypeId()]; - foreach ($taskType['inputShape'] + $taskType['optionalInputShape'] as $key => $descriptor) { - if (in_array(EShapeType::getScalarType($descriptor->getShapeType()), [EShapeType::File, EShapeType::Image, EShapeType::Audio, EShapeType::Video], true)) { - /** @var int|list<int> $inputSlot */ - $inputSlot = $task->getInput()[$key]; - if (is_array($inputSlot)) { - $ids = array_merge($inputSlot, $ids); - } else { - $ids[] = $inputSlot; - } - } - } - if ($task->getOutput() !== null) { - foreach ($taskType['outputShape'] + $taskType['optionalOutputShape'] as $key => $descriptor) { - if (in_array(EShapeType::getScalarType($descriptor->getShapeType()), [EShapeType::File, EShapeType::Image, EShapeType::Audio, EShapeType::Video], true)) { - /** @var int|list<int> $outputSlot */ - $outputSlot = $task->getOutput()[$key]; - if (is_array($outputSlot)) { - $ids = array_merge($outputSlot, $ids); - } else { - $ids[] = $outputSlot; - } - } - } - } - return $ids; - } - - /** * Sets the task progress * * @param int $taskId The id of the task diff --git a/core/Migrations/Version32000Date20250806110519.php b/core/Migrations/Version32000Date20250806110519.php new file mode 100644 index 00000000000..c498a1cc820 --- /dev/null +++ b/core/Migrations/Version32000Date20250806110519.php @@ -0,0 +1,49 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Core\Migrations; + +use Closure; +use OCP\DB\ISchemaWrapper; +use OCP\DB\Types; +use OCP\Migration\Attributes\AddColumn; +use OCP\Migration\Attributes\ColumnType; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + +/** + * + */ +#[AddColumn(table: 'taskprocessing_tasks', name: 'allow_cleanup', type: ColumnType::SMALLINT)] +class Version32000Date20250806110519 extends SimpleMigrationStep { + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * @return null|ISchemaWrapper + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + if ($schema->hasTable('taskprocessing_tasks')) { + $table = $schema->getTable('taskprocessing_tasks'); + if (!$table->hasColumn('allow_cleanup')) { + $table->addColumn('allow_cleanup', Types::SMALLINT, [ + 'notnull' => true, + 'default' => 1, + 'unsigned' => true, + ]); + return $schema; + } + } + + return null; + } +} diff --git a/core/ResponseDefinitions.php b/core/ResponseDefinitions.php index 5fb2502c388..5a0c00524ee 100644 --- a/core/ResponseDefinitions.php +++ b/core/ResponseDefinitions.php @@ -87,6 +87,7 @@ namespace OC\Core; * name: string, * icon: string, * order: int, + * isExternalProvider: bool, * triggers: list<string>, * filters: array<string, string>, * inAppSearch: bool, @@ -200,6 +201,7 @@ namespace OC\Core; * scheduledAt: ?int, * startedAt: ?int, * endedAt: ?int, + * allowCleanup: bool, * } * * @psalm-type CoreProfileAction = array{ diff --git a/core/l10n/de.js b/core/l10n/de.js index ca78017e14b..fa6260109ee 100644 --- a/core/l10n/de.js +++ b/core/l10n/de.js @@ -254,6 +254,7 @@ OC.L10N.register( "Search people" : "Personen suchen", "People" : "Personen", "Filter in current view" : "Filter in aktueller Ansicht", + "Search connected services" : "Verbundene Dienste durchsuchen", "Results" : "Ergebnisse", "Load more results" : "Weitere Ergebnisse laden", "Search in" : "Suche in", diff --git a/core/l10n/de.json b/core/l10n/de.json index 065edb289f6..503cfda5316 100644 --- a/core/l10n/de.json +++ b/core/l10n/de.json @@ -252,6 +252,7 @@ "Search people" : "Personen suchen", "People" : "Personen", "Filter in current view" : "Filter in aktueller Ansicht", + "Search connected services" : "Verbundene Dienste durchsuchen", "Results" : "Ergebnisse", "Load more results" : "Weitere Ergebnisse laden", "Search in" : "Suche in", diff --git a/core/l10n/de_DE.js b/core/l10n/de_DE.js index 7aa73669136..58305e46326 100644 --- a/core/l10n/de_DE.js +++ b/core/l10n/de_DE.js @@ -254,6 +254,7 @@ OC.L10N.register( "Search people" : "Personen suchen", "People" : "Personen", "Filter in current view" : "Filter in aktueller Ansicht", + "Search connected services" : "Verbundene Dienste durchsuchen", "Results" : "Ergebnisse", "Load more results" : "Weitere Ergebnisse laden", "Search in" : "Suche in", diff --git a/core/l10n/de_DE.json b/core/l10n/de_DE.json index db90a92a1ba..1395757c619 100644 --- a/core/l10n/de_DE.json +++ b/core/l10n/de_DE.json @@ -252,6 +252,7 @@ "Search people" : "Personen suchen", "People" : "Personen", "Filter in current view" : "Filter in aktueller Ansicht", + "Search connected services" : "Verbundene Dienste durchsuchen", "Results" : "Ergebnisse", "Load more results" : "Weitere Ergebnisse laden", "Search in" : "Suche in", diff --git a/core/l10n/en_GB.js b/core/l10n/en_GB.js index 665ec6ba17a..35f37856c7c 100644 --- a/core/l10n/en_GB.js +++ b/core/l10n/en_GB.js @@ -254,6 +254,7 @@ OC.L10N.register( "Search people" : "Search people", "People" : "People", "Filter in current view" : "Filter in current view", + "Search connected services" : "Search connected services", "Results" : "Results", "Load more results" : "Load more results", "Search in" : "Search in", diff --git a/core/l10n/en_GB.json b/core/l10n/en_GB.json index d6578743667..358c71632f8 100644 --- a/core/l10n/en_GB.json +++ b/core/l10n/en_GB.json @@ -252,6 +252,7 @@ "Search people" : "Search people", "People" : "People", "Filter in current view" : "Filter in current view", + "Search connected services" : "Search connected services", "Results" : "Results", "Load more results" : "Load more results", "Search in" : "Search in", diff --git a/core/l10n/es.js b/core/l10n/es.js index 0ff5317118c..be8b459626d 100644 --- a/core/l10n/es.js +++ b/core/l10n/es.js @@ -254,6 +254,7 @@ OC.L10N.register( "Search people" : "Buscar personas", "People" : "Personas", "Filter in current view" : "Filtrar en la vista actual", + "Search connected services" : "Buscar servicios conectados", "Results" : "Resultados", "Load more results" : "Cargar más resultados", "Search in" : "Buscar en", diff --git a/core/l10n/es.json b/core/l10n/es.json index 054a0389acb..3b109e41290 100644 --- a/core/l10n/es.json +++ b/core/l10n/es.json @@ -252,6 +252,7 @@ "Search people" : "Buscar personas", "People" : "Personas", "Filter in current view" : "Filtrar en la vista actual", + "Search connected services" : "Buscar servicios conectados", "Results" : "Resultados", "Load more results" : "Cargar más resultados", "Search in" : "Buscar en", diff --git a/core/l10n/et_EE.js b/core/l10n/et_EE.js index 8bc6419636e..5166f1c79d4 100644 --- a/core/l10n/et_EE.js +++ b/core/l10n/et_EE.js @@ -230,6 +230,7 @@ OC.L10N.register( "Federated user" : "Kasutaja liitpilves", "user@your-nextcloud.org" : "kasutaja@sinu-nextcloud.ee", "Create share" : "Lisa jagamine", + "Direct link copied" : "Otselink on kopeeritud", "Please copy the link manually:" : "Palun kopeeri link käsitsi:", "Custom date range" : "Sinu valitud kuupäevavahemik", "Pick start date" : "Vali algkuupäev", @@ -253,6 +254,7 @@ OC.L10N.register( "Search people" : "Otsi inimesi", "People" : "Inimesed", "Filter in current view" : "Filtreeri selles vaates", + "Search connected services" : "Otsi ühendatud seadmeid", "Results" : "Tulemused", "Load more results" : "Laadi veel tulemusi", "Search in" : "Otsi siin:", diff --git a/core/l10n/et_EE.json b/core/l10n/et_EE.json index 05149ea7a23..f35b8a436c7 100644 --- a/core/l10n/et_EE.json +++ b/core/l10n/et_EE.json @@ -228,6 +228,7 @@ "Federated user" : "Kasutaja liitpilves", "user@your-nextcloud.org" : "kasutaja@sinu-nextcloud.ee", "Create share" : "Lisa jagamine", + "Direct link copied" : "Otselink on kopeeritud", "Please copy the link manually:" : "Palun kopeeri link käsitsi:", "Custom date range" : "Sinu valitud kuupäevavahemik", "Pick start date" : "Vali algkuupäev", @@ -251,6 +252,7 @@ "Search people" : "Otsi inimesi", "People" : "Inimesed", "Filter in current view" : "Filtreeri selles vaates", + "Search connected services" : "Otsi ühendatud seadmeid", "Results" : "Tulemused", "Load more results" : "Laadi veel tulemusi", "Search in" : "Otsi siin:", diff --git a/core/l10n/ja.js b/core/l10n/ja.js index 9edebafe544..69f67ebe562 100644 --- a/core/l10n/ja.js +++ b/core/l10n/ja.js @@ -230,6 +230,7 @@ OC.L10N.register( "Federated user" : "フェデレーションユーザー", "user@your-nextcloud.org" : "user@your-nextcloud.org", "Create share" : "共有を作成", + "Direct link copied" : "ダイレクトリンクをコピーしました", "Please copy the link manually:" : "手動でリンクをコピーしてください:", "Custom date range" : "カスタム日付の範囲", "Pick start date" : "開始日を指定", @@ -253,6 +254,7 @@ OC.L10N.register( "Search people" : "人物を検索", "People" : "ユーザー", "Filter in current view" : "現在のビューでフィルタ", + "Search connected services" : "関連サービスを検索", "Results" : "結果", "Load more results" : "次の結果を読み込む", "Search in" : "検索対象", diff --git a/core/l10n/ja.json b/core/l10n/ja.json index 0394920e547..ca4326642f7 100644 --- a/core/l10n/ja.json +++ b/core/l10n/ja.json @@ -228,6 +228,7 @@ "Federated user" : "フェデレーションユーザー", "user@your-nextcloud.org" : "user@your-nextcloud.org", "Create share" : "共有を作成", + "Direct link copied" : "ダイレクトリンクをコピーしました", "Please copy the link manually:" : "手動でリンクをコピーしてください:", "Custom date range" : "カスタム日付の範囲", "Pick start date" : "開始日を指定", @@ -251,6 +252,7 @@ "Search people" : "人物を検索", "People" : "ユーザー", "Filter in current view" : "現在のビューでフィルタ", + "Search connected services" : "関連サービスを検索", "Results" : "結果", "Load more results" : "次の結果を読み込む", "Search in" : "検索対象", diff --git a/core/l10n/pt_BR.js b/core/l10n/pt_BR.js index 3919a9f7eb7..c5b8b84a383 100644 --- a/core/l10n/pt_BR.js +++ b/core/l10n/pt_BR.js @@ -230,6 +230,7 @@ OC.L10N.register( "Federated user" : "Usuário federado", "user@your-nextcloud.org" : "user@your-nextcloud.org", "Create share" : "Criar compartilhamento", + "Direct link copied" : "Link direto copiado", "Please copy the link manually:" : "Copie o link manualmente:", "Custom date range" : "Intervalo personalizado", "Pick start date" : "Escolha uma data de início", diff --git a/core/l10n/pt_BR.json b/core/l10n/pt_BR.json index 743a69027a1..6231bda28fa 100644 --- a/core/l10n/pt_BR.json +++ b/core/l10n/pt_BR.json @@ -228,6 +228,7 @@ "Federated user" : "Usuário federado", "user@your-nextcloud.org" : "user@your-nextcloud.org", "Create share" : "Criar compartilhamento", + "Direct link copied" : "Link direto copiado", "Please copy the link manually:" : "Copie o link manualmente:", "Custom date range" : "Intervalo personalizado", "Pick start date" : "Escolha uma data de início", diff --git a/core/l10n/sr.js b/core/l10n/sr.js index 390e6a89f0f..a0ddaffde6a 100644 --- a/core/l10n/sr.js +++ b/core/l10n/sr.js @@ -230,6 +230,7 @@ OC.L10N.register( "Federated user" : "Федерисани корисник", "user@your-nextcloud.org" : "korisnik@vas-nextcloud.org", "Create share" : "Kreirajte deljenje", + "Direct link copied" : "Директни линк је копиран", "Please copy the link manually:" : "Молимо вас да ручно корпирате линк:", "Custom date range" : "Произвољни опсег датума", "Pick start date" : "Изаберите почетни датум", diff --git a/core/l10n/sr.json b/core/l10n/sr.json index 05c9fb8aa02..448e1d8bf1f 100644 --- a/core/l10n/sr.json +++ b/core/l10n/sr.json @@ -228,6 +228,7 @@ "Federated user" : "Федерисани корисник", "user@your-nextcloud.org" : "korisnik@vas-nextcloud.org", "Create share" : "Kreirajte deljenje", + "Direct link copied" : "Директни линк је копиран", "Please copy the link manually:" : "Молимо вас да ручно корпирате линк:", "Custom date range" : "Произвољни опсег датума", "Pick start date" : "Изаберите почетни датум", diff --git a/core/l10n/zh_CN.js b/core/l10n/zh_CN.js index 8c64035aeea..6cc3c910ebe 100644 --- a/core/l10n/zh_CN.js +++ b/core/l10n/zh_CN.js @@ -230,6 +230,7 @@ OC.L10N.register( "Federated user" : "联合云用户", "user@your-nextcloud.org" : "user@your-nextcloud.org", "Create share" : "创建共享", + "Direct link copied" : "直接链接已复制", "Please copy the link manually:" : "请手动复制链接:", "Custom date range" : "自定义日期范围", "Pick start date" : "选择起始日期", @@ -253,6 +254,7 @@ OC.L10N.register( "Search people" : "搜索用户", "People" : "用户", "Filter in current view" : "在当前视图中筛选", + "Search connected services" : "搜索已连接的服务", "Results" : "结果", "Load more results" : "加载更多结果", "Search in" : "搜索", diff --git a/core/l10n/zh_CN.json b/core/l10n/zh_CN.json index a2e453cad86..ac126df01c9 100644 --- a/core/l10n/zh_CN.json +++ b/core/l10n/zh_CN.json @@ -228,6 +228,7 @@ "Federated user" : "联合云用户", "user@your-nextcloud.org" : "user@your-nextcloud.org", "Create share" : "创建共享", + "Direct link copied" : "直接链接已复制", "Please copy the link manually:" : "请手动复制链接:", "Custom date range" : "自定义日期范围", "Pick start date" : "选择起始日期", @@ -251,6 +252,7 @@ "Search people" : "搜索用户", "People" : "用户", "Filter in current view" : "在当前视图中筛选", + "Search connected services" : "搜索已连接的服务", "Results" : "结果", "Load more results" : "加载更多结果", "Search in" : "搜索", diff --git a/core/l10n/zh_HK.js b/core/l10n/zh_HK.js index fc51c994b6f..7487b4db1f3 100644 --- a/core/l10n/zh_HK.js +++ b/core/l10n/zh_HK.js @@ -254,6 +254,7 @@ OC.L10N.register( "Search people" : "搜尋人仕", "People" : "人物", "Filter in current view" : "目前檢視裡的篩選條件", + "Search connected services" : "搜尋已連結的服務", "Results" : "結果", "Load more results" : "載入更多結果", "Search in" : "搜尋", diff --git a/core/l10n/zh_HK.json b/core/l10n/zh_HK.json index 0d1d227094c..07fd64fcc53 100644 --- a/core/l10n/zh_HK.json +++ b/core/l10n/zh_HK.json @@ -252,6 +252,7 @@ "Search people" : "搜尋人仕", "People" : "人物", "Filter in current view" : "目前檢視裡的篩選條件", + "Search connected services" : "搜尋已連結的服務", "Results" : "結果", "Load more results" : "載入更多結果", "Search in" : "搜尋", diff --git a/core/l10n/zh_TW.js b/core/l10n/zh_TW.js index 7b730c8b827..2ee4df6d897 100644 --- a/core/l10n/zh_TW.js +++ b/core/l10n/zh_TW.js @@ -230,6 +230,7 @@ OC.L10N.register( "Federated user" : "聯盟使用者", "user@your-nextcloud.org" : "user@your-nextcloud.org", "Create share" : "建立分享", + "Direct link copied" : "已複製直接連結", "Please copy the link manually:" : "請手動複製連結:", "Custom date range" : "自訂日期範圍", "Pick start date" : "挑選開始日期", @@ -253,6 +254,7 @@ OC.L10N.register( "Search people" : "搜尋人物", "People" : "人物", "Filter in current view" : "目前檢視中的篩選條件", + "Search connected services" : "搜尋已連結的服務", "Results" : "結果", "Load more results" : "載入更多結果", "Search in" : "搜尋條件", diff --git a/core/l10n/zh_TW.json b/core/l10n/zh_TW.json index c2c548b95f7..1ba4fe09f17 100644 --- a/core/l10n/zh_TW.json +++ b/core/l10n/zh_TW.json @@ -228,6 +228,7 @@ "Federated user" : "聯盟使用者", "user@your-nextcloud.org" : "user@your-nextcloud.org", "Create share" : "建立分享", + "Direct link copied" : "已複製直接連結", "Please copy the link manually:" : "請手動複製連結:", "Custom date range" : "自訂日期範圍", "Pick start date" : "挑選開始日期", @@ -251,6 +252,7 @@ "Search people" : "搜尋人物", "People" : "人物", "Filter in current view" : "目前檢視中的篩選條件", + "Search connected services" : "搜尋已連結的服務", "Results" : "結果", "Load more results" : "載入更多結果", "Search in" : "搜尋條件", diff --git a/core/openapi-ex_app.json b/core/openapi-ex_app.json index 4dad268c1b3..21e349ffbd0 100644 --- a/core/openapi-ex_app.json +++ b/core/openapi-ex_app.json @@ -145,7 +145,8 @@ "progress", "scheduledAt", "startedAt", - "endedAt" + "endedAt", + "allowCleanup" ], "properties": { "id": { @@ -216,6 +217,9 @@ "type": "integer", "format": "int64", "nullable": true + }, + "allowCleanup": { + "type": "boolean" } } } diff --git a/core/openapi-full.json b/core/openapi-full.json index d4f69abf535..b95a88b191a 100644 --- a/core/openapi-full.json +++ b/core/openapi-full.json @@ -639,7 +639,8 @@ "progress", "scheduledAt", "startedAt", - "endedAt" + "endedAt", + "allowCleanup" ], "properties": { "id": { @@ -710,6 +711,9 @@ "type": "integer", "format": "int64", "nullable": true + }, + "allowCleanup": { + "type": "boolean" } } }, @@ -1045,6 +1049,7 @@ "name", "icon", "order", + "isExternalProvider", "triggers", "filters", "inAppSearch" @@ -1066,6 +1071,9 @@ "type": "integer", "format": "int64" }, + "isExternalProvider": { + "type": "boolean" + }, "triggers": { "type": "array", "items": { diff --git a/core/openapi.json b/core/openapi.json index 1a7ddc55c92..1c72bff9f82 100644 --- a/core/openapi.json +++ b/core/openapi.json @@ -639,7 +639,8 @@ "progress", "scheduledAt", "startedAt", - "endedAt" + "endedAt", + "allowCleanup" ], "properties": { "id": { @@ -710,6 +711,9 @@ "type": "integer", "format": "int64", "nullable": true + }, + "allowCleanup": { + "type": "boolean" } } }, @@ -1045,6 +1049,7 @@ "name", "icon", "order", + "isExternalProvider", "triggers", "filters", "inAppSearch" @@ -1066,6 +1071,9 @@ "type": "integer", "format": "int64" }, + "isExternalProvider": { + "type": "boolean" + }, "triggers": { "type": "array", "items": { diff --git a/core/register_command.php b/core/register_command.php index ed64983e762..9fd5b9b611e 100644 --- a/core/register_command.php +++ b/core/register_command.php @@ -253,6 +253,7 @@ if ($config->getSystemValueBool('installed', false)) { $application->add(Server::get(EnabledCommand::class)); $application->add(Server::get(Command\TaskProcessing\ListCommand::class)); $application->add(Server::get(Statistics::class)); + $application->add(Server::get(Command\TaskProcessing\Cleanup::class)); $application->add(Server::get(RedisCommand::class)); $application->add(Server::get(DistributedClear::class)); diff --git a/core/src/components/UnifiedSearch/UnifiedSearchModal.vue b/core/src/components/UnifiedSearch/UnifiedSearchModal.vue index b21c65301c4..e59058bc0f0 100644 --- a/core/src/components/UnifiedSearch/UnifiedSearchModal.vue +++ b/core/src/components/UnifiedSearch/UnifiedSearchModal.vue @@ -86,6 +86,13 @@ <IconFilter :size="20" /> </template> </NcButton> + <NcCheckboxRadioSwitch v-if="hasExternalResources" + v-model="searchExternalResources" + type="switch" + class="unified-search-modal__search-external-resources" + :class="{'unified-search-modal__search-external-resources--aligned': localSearch}"> + {{ t('core', 'Search connected services') }} + </NcCheckboxRadioSwitch> </div> <div class="unified-search-modal__filters-applied"> <FilterChip v-for="filter in filters" @@ -172,6 +179,7 @@ import NcButton from '@nextcloud/vue/components/NcButton' import NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent' import NcInputField from '@nextcloud/vue/components/NcInputField' import NcDialog from '@nextcloud/vue/components/NcDialog' +import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch' import CustomDateRangeModal from './CustomDateRangeModal.vue' import FilterChip from './SearchFilterChip.vue' @@ -198,6 +206,7 @@ export default defineComponent({ NcEmptyContent, NcDialog, NcInputField, + NcCheckboxRadioSwitch, SearchableList, SearchResult, }, @@ -264,6 +273,7 @@ export default defineComponent({ showDateRangeModal: false, internalIsVisible: this.open, initialized: false, + searchExternalResources: false, } }, @@ -301,6 +311,10 @@ export default defineComponent({ debouncedFilterContacts() { return debounce(this.filterContacts, 300) }, + + hasExternalResources() { + return this.providers.some(provider => provider.isExternalProvider) + }, }, watch: { @@ -338,6 +352,12 @@ export default defineComponent({ this.$emit('update:query', this.searchQuery) }, }, + + searchExternalResources() { + if (this.searchQuery) { + this.find(this.searchQuery) + } + }, }, mounted() { @@ -418,6 +438,14 @@ export default defineComponent({ unifiedSearchLogger.debug('Limiting search to', params.limit) } + const shouldSkipSearch = !this.searchExternalResources && provider.isExternalProvider + const wasManuallySelected = this.filteredProviders.some(filteredProvider => filteredProvider.id === provider.id) + // if the provider is an external resource and the user has not manually selected it, skip the search + if (shouldSkipSearch && !wasManuallySelected) { + this.searching = false + return + } + const request = unifiedSearch(params).request request().then((response) => { @@ -742,6 +770,21 @@ export default defineComponent({ padding-top: 4px; } + &__search-external-resources { + :deep(span.checkbox-content) { + padding-top: 0; + padding-bottom: 0; + } + + :deep(.checkbox-content__icon) { + margin: auto !important; + } + + &--aligned { + margin-inline-start: auto; + } + } + &__filters-applied { padding-top: 4px; display: flex; |