diff options
Diffstat (limited to 'apps')
27 files changed, 206 insertions, 49 deletions
diff --git a/apps/admin_audit/composer/composer/autoload_classmap.php b/apps/admin_audit/composer/composer/autoload_classmap.php index 2373bb90797..fc4be52ebbb 100644 --- a/apps/admin_audit/composer/composer/autoload_classmap.php +++ b/apps/admin_audit/composer/composer/autoload_classmap.php @@ -19,6 +19,8 @@ return array( 'OCA\\AdminAudit\\Actions\\UserManagement' => $baseDir . '/../lib/Actions/UserManagement.php', 'OCA\\AdminAudit\\Actions\\Versions' => $baseDir . '/../lib/Actions/Versions.php', 'OCA\\AdminAudit\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php', + 'OCA\\AdminAudit\\AuditLogger' => $baseDir . '/../lib/AuditLogger.php', 'OCA\\AdminAudit\\BackgroundJobs\\Rotate' => $baseDir . '/../lib/BackgroundJobs/Rotate.php', + 'OCA\\AdminAudit\\IAuditLogger' => $baseDir . '/../lib/IAuditLogger.php', 'OCA\\AdminAudit\\Listener\\CriticalActionPerformedEventListener' => $baseDir . '/../lib/Listener/CriticalActionPerformedEventListener.php', ); diff --git a/apps/admin_audit/composer/composer/autoload_static.php b/apps/admin_audit/composer/composer/autoload_static.php index 829bc2ab049..38518c8a9ba 100644 --- a/apps/admin_audit/composer/composer/autoload_static.php +++ b/apps/admin_audit/composer/composer/autoload_static.php @@ -34,7 +34,9 @@ class ComposerStaticInitAdminAudit 'OCA\\AdminAudit\\Actions\\UserManagement' => __DIR__ . '/..' . '/../lib/Actions/UserManagement.php', 'OCA\\AdminAudit\\Actions\\Versions' => __DIR__ . '/..' . '/../lib/Actions/Versions.php', 'OCA\\AdminAudit\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php', + 'OCA\\AdminAudit\\AuditLogger' => __DIR__ . '/..' . '/../lib/AuditLogger.php', 'OCA\\AdminAudit\\BackgroundJobs\\Rotate' => __DIR__ . '/..' . '/../lib/BackgroundJobs/Rotate.php', + 'OCA\\AdminAudit\\IAuditLogger' => __DIR__ . '/..' . '/../lib/IAuditLogger.php', 'OCA\\AdminAudit\\Listener\\CriticalActionPerformedEventListener' => __DIR__ . '/..' . '/../lib/Listener/CriticalActionPerformedEventListener.php', ); diff --git a/apps/admin_audit/lib/Actions/Action.php b/apps/admin_audit/lib/Actions/Action.php index 17be0fb8197..0eaf06b8c0f 100644 --- a/apps/admin_audit/lib/Actions/Action.php +++ b/apps/admin_audit/lib/Actions/Action.php @@ -28,13 +28,13 @@ declare(strict_types=1); */ namespace OCA\AdminAudit\Actions; -use Psr\Log\LoggerInterface; +use OCA\AdminAudit\IAuditLogger; class Action { - /** @var LoggerInterface */ + /** @var IAuditLogger */ private $logger; - public function __construct(LoggerInterface $logger) { + public function __construct(IAuditLogger $logger) { $this->logger = $logger; } diff --git a/apps/admin_audit/lib/AppInfo/Application.php b/apps/admin_audit/lib/AppInfo/Application.php index 594e1c7f2c4..1160d151710 100644 --- a/apps/admin_audit/lib/AppInfo/Application.php +++ b/apps/admin_audit/lib/AppInfo/Application.php @@ -48,6 +48,8 @@ use OCA\AdminAudit\Actions\Sharing; use OCA\AdminAudit\Actions\Trashbin; use OCA\AdminAudit\Actions\UserManagement; use OCA\AdminAudit\Actions\Versions; +use OCA\AdminAudit\AuditLogger; +use OCA\AdminAudit\IAuditLogger; use OCA\AdminAudit\Listener\CriticalActionPerformedEventListener; use OCP\App\ManagerEvent; use OCP\AppFramework\App; @@ -65,6 +67,7 @@ use OCP\Log\Audit\CriticalActionPerformedEvent; use OCP\Log\ILogFactory; use OCP\Share; use OCP\Util; +use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\GenericEvent; @@ -79,14 +82,16 @@ class Application extends App implements IBootstrap { } public function register(IRegistrationContext $context): void { + $context->registerService(IAuditLogger::class, function (ContainerInterface $c) { + return new AuditLogger($c->get(ILogFactory::class), $c->get(Iconfig::class)); + }); + $context->registerEventListener(CriticalActionPerformedEvent::class, CriticalActionPerformedEventListener::class); } public function boot(IBootContext $context): void { - /** @var LoggerInterface $logger */ - $logger = $context->injectFn( - Closure::fromCallable([$this, 'getLogger']) - ); + /** @var IAuditLogger $logger */ + $logger = $context->getAppContainer()->get(IAuditLogger::class); /* * TODO: once the hooks are migrated to lazy events, this should be done @@ -95,26 +100,10 @@ class Application extends App implements IBootstrap { $this->registerHooks($logger, $context->getServerContainer()); } - private function getLogger(IConfig $config, - ILogFactory $logFactory): LoggerInterface { - $auditType = $config->getSystemValueString('log_type_audit', 'file'); - $defaultTag = $config->getSystemValueString('syslog_tag', 'Nextcloud'); - $auditTag = $config->getSystemValueString('syslog_tag_audit', $defaultTag); - $logFile = $config->getSystemValueString('logfile_audit', ''); - - if ($auditType === 'file' && !$logFile) { - $default = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/audit.log'; - // Legacy way was appconfig, now it's paralleled with the normal log config - $logFile = $config->getAppValue('admin_audit', 'logfile', $default); - } - - return $logFactory->getCustomPsrLogger($logFile, $auditType, $auditTag); - } - /** * Register hooks in order to log them */ - private function registerHooks(LoggerInterface $logger, + private function registerHooks(IAuditLogger $logger, IServerContainer $serverContainer): void { $this->userManagementHooks($logger, $serverContainer->get(IUserSession::class)); $this->groupHooks($logger, $serverContainer->get(IGroupManager::class)); @@ -134,7 +123,7 @@ class Application extends App implements IBootstrap { $this->securityHooks($logger, $eventDispatcher); } - private function userManagementHooks(LoggerInterface $logger, + private function userManagementHooks(IAuditLogger $logger, IUserSession $userSession): void { $userActions = new UserManagement($logger); @@ -148,7 +137,7 @@ class Application extends App implements IBootstrap { $userSession->listen('\OC\User', 'postUnassignedUserId', [$userActions, 'unassign']); } - private function groupHooks(LoggerInterface $logger, + private function groupHooks(IAuditLogger $logger, IGroupManager $groupManager): void { $groupActions = new GroupManagement($logger); @@ -159,7 +148,7 @@ class Application extends App implements IBootstrap { $groupManager->listen('\OC\Group', 'postCreate', [$groupActions, 'createGroup']); } - private function sharingHooks(LoggerInterface $logger): void { + private function sharingHooks(IAuditLogger $logger): void { $shareActions = new Sharing($logger); Util::connectHook(Share::class, 'post_shared', $shareActions, 'shared'); @@ -171,7 +160,7 @@ class Application extends App implements IBootstrap { Util::connectHook(Share::class, 'share_link_access', $shareActions, 'shareAccessed'); } - private function authHooks(LoggerInterface $logger): void { + private function authHooks(IAuditLogger $logger): void { $authActions = new Auth($logger); Util::connectHook('OC_User', 'pre_login', $authActions, 'loginAttempt'); @@ -179,7 +168,7 @@ class Application extends App implements IBootstrap { Util::connectHook('OC_User', 'logout', $authActions, 'logout'); } - private function appHooks(LoggerInterface $logger, + private function appHooks(IAuditLogger $logger, EventDispatcherInterface $eventDispatcher): void { $eventDispatcher->addListener(ManagerEvent::EVENT_APP_ENABLE, function (ManagerEvent $event) use ($logger) { $appActions = new AppManagement($logger); @@ -195,7 +184,7 @@ class Application extends App implements IBootstrap { }); } - private function consoleHooks(LoggerInterface $logger, + private function consoleHooks(IAuditLogger $logger, EventDispatcherInterface $eventDispatcher): void { $eventDispatcher->addListener(ConsoleEvent::EVENT_RUN, function (ConsoleEvent $event) use ($logger) { $appActions = new Console($logger); @@ -203,7 +192,7 @@ class Application extends App implements IBootstrap { }); } - private function fileHooks(LoggerInterface $logger, + private function fileHooks(IAuditLogger $logger, EventDispatcherInterface $eventDispatcher): void { $fileActions = new Files($logger); $eventDispatcher->addListener( @@ -265,19 +254,19 @@ class Application extends App implements IBootstrap { ); } - private function versionsHooks(LoggerInterface $logger): void { + private function versionsHooks(IAuditLogger $logger): void { $versionsActions = new Versions($logger); Util::connectHook('\OCP\Versions', 'rollback', $versionsActions, 'rollback'); Util::connectHook('\OCP\Versions', 'delete', $versionsActions, 'delete'); } - private function trashbinHooks(LoggerInterface $logger): void { + private function trashbinHooks(IAuditLogger $logger): void { $trashActions = new Trashbin($logger); Util::connectHook('\OCP\Trashbin', 'preDelete', $trashActions, 'delete'); Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', $trashActions, 'restore'); } - private function securityHooks(LoggerInterface $logger, + private function securityHooks(IAuditLogger $logger, EventDispatcherInterface $eventDispatcher): void { $eventDispatcher->addListener(IProvider::EVENT_SUCCESS, function (GenericEvent $event) use ($logger) { $security = new Security($logger); diff --git a/apps/admin_audit/lib/AuditLogger.php b/apps/admin_audit/lib/AuditLogger.php new file mode 100644 index 00000000000..0a7a330a743 --- /dev/null +++ b/apps/admin_audit/lib/AuditLogger.php @@ -0,0 +1,88 @@ +<?php +/** + * @copyright Copyright (c) 2022 Carl Schwan <carl@carlschwan.eu> + * + * @author Carl Schwan <carl@carlschwan.eu> + * + * @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\AdminAudit; + +use OCP\IConfig; +use OCP\Log\ILogFactory; +use Psr\Log\LoggerInterface; + +/** + * Logger that logs in the audit log file instead of the normal log file + */ +class AuditLogger implements IAuditLogger { + + /** @var LoggerInterface */ + private $parentLogger; + + public function __construct(ILogFactory $logFactory, IConfig $config) { + $auditType = $config->getSystemValueString('log_type_audit', 'file'); + $defaultTag = $config->getSystemValueString('syslog_tag', 'Nextcloud'); + $auditTag = $config->getSystemValueString('syslog_tag_audit', $defaultTag); + $logFile = $config->getSystemValueString('logfile_audit', ''); + + if ($auditType === 'file' && !$logFile) { + $default = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/audit.log'; + // Legacy way was appconfig, now it's paralleled with the normal log config + $logFile = $config->getAppValue('admin_audit', 'logfile', $default); + } + + $this->parentLogger = $logFactory->getCustomPsrLogger($logFile, $auditType, $auditTag); + } + + public function emergency($message, array $context = array()) { + $this->parentLogger->emergency($message, $context); + } + + public function alert($message, array $context = array()) { + $this->parentLogger->alert($message, $context); + } + + public function critical($message, array $context = array()) { + $this->parentLogger->critical($message, $context); + } + + public function error($message, array $context = array()) { + $this->parentLogger->error($message, $context); + } + + public function warning($message, array $context = array()) { + $this->parentLogger->warning($message, $context); + } + + public function notice($message, array $context = array()) { + $this->parentLogger->notice($message, $context); + } + + public function info($message, array $context = array()) { + $this->parentLogger->info($message, $context); + } + + public function debug($message, array $context = array()) { + $this->parentLogger->debug($message, $context); + } + + public function log($level, $message, array $context = array()) { + $this->parentLogger->log($level, $message, $context); + } +} diff --git a/apps/admin_audit/lib/IAuditLogger.php b/apps/admin_audit/lib/IAuditLogger.php new file mode 100644 index 00000000000..b55d36b942d --- /dev/null +++ b/apps/admin_audit/lib/IAuditLogger.php @@ -0,0 +1,32 @@ +<?php +/** + * @copyright Copyright (c) 2022 Carl Schwan <carl@carlschwan.eu> + * + * @author Carl Schwan <carl@carlschwan.eu> + * + * @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\AdminAudit; + +use Psr\Log\LoggerInterface; + +/** + * Interface for a logger that logs in the audit log file instead of the normal log file + */ +interface IAuditLogger extends LoggerInterface { +} diff --git a/apps/admin_audit/tests/Actions/SecurityTest.php b/apps/admin_audit/tests/Actions/SecurityTest.php index aa9d9713768..604d2276fb2 100644 --- a/apps/admin_audit/tests/Actions/SecurityTest.php +++ b/apps/admin_audit/tests/Actions/SecurityTest.php @@ -44,7 +44,7 @@ class SecurityTest extends TestCase { protected function setUp(): void { parent::setUp(); - $this->logger = $this->createMock(LoggerInterface::class); + $this->logger = $this->createMock(AuditLogger::class); $this->security = new Security($this->logger); $this->user = $this->createMock(IUser::class); diff --git a/apps/dav/l10n/cs.js b/apps/dav/l10n/cs.js index 5b7ea906260..69d0de5f453 100644 --- a/apps/dav/l10n/cs.js +++ b/apps/dav/l10n/cs.js @@ -137,6 +137,7 @@ OC.L10N.register( "Due on %s by %s" : "Termín do %s od %s", "Due on %s" : "Termín do %s", "Migrated calendar (%1$s)" : "Přesunut kalendář (%1$s)", + "Calendars including events, details and attendees" : "Kalendáře včetně událostí, podrobností a účastníků", "Contacts and groups" : "Kontakty a skupiny", "WebDAV" : "WebDAV", "WebDAV endpoint" : "WebDAV endpoint", diff --git a/apps/dav/l10n/cs.json b/apps/dav/l10n/cs.json index 46d083fa035..c3e555519be 100644 --- a/apps/dav/l10n/cs.json +++ b/apps/dav/l10n/cs.json @@ -135,6 +135,7 @@ "Due on %s by %s" : "Termín do %s od %s", "Due on %s" : "Termín do %s", "Migrated calendar (%1$s)" : "Přesunut kalendář (%1$s)", + "Calendars including events, details and attendees" : "Kalendáře včetně událostí, podrobností a účastníků", "Contacts and groups" : "Kontakty a skupiny", "WebDAV" : "WebDAV", "WebDAV endpoint" : "WebDAV endpoint", diff --git a/apps/dav/l10n/pl.js b/apps/dav/l10n/pl.js index 03c14a1b50b..e9fd91268fc 100644 --- a/apps/dav/l10n/pl.js +++ b/apps/dav/l10n/pl.js @@ -137,6 +137,7 @@ OC.L10N.register( "Due on %s by %s" : "Na dzień %s w %s", "Due on %s" : "Na dzień %s", "Migrated calendar (%1$s)" : "Przeniesiony kalendarz (%1$s)", + "Calendars including events, details and attendees" : "Kalendarze zawierające wydarzenia, szczegóły i uczestników", "Contacts and groups" : "Kontakty i grupy", "WebDAV" : "WebDAV", "WebDAV endpoint" : "Adres WebDAV", diff --git a/apps/dav/l10n/pl.json b/apps/dav/l10n/pl.json index 147447993f1..4ea51401e82 100644 --- a/apps/dav/l10n/pl.json +++ b/apps/dav/l10n/pl.json @@ -135,6 +135,7 @@ "Due on %s by %s" : "Na dzień %s w %s", "Due on %s" : "Na dzień %s", "Migrated calendar (%1$s)" : "Przeniesiony kalendarz (%1$s)", + "Calendars including events, details and attendees" : "Kalendarze zawierające wydarzenia, szczegóły i uczestników", "Contacts and groups" : "Kontakty i grupy", "WebDAV" : "WebDAV", "WebDAV endpoint" : "Adres WebDAV", diff --git a/apps/dav/l10n/tr.js b/apps/dav/l10n/tr.js index 8f9f15d1de2..aa21694e64e 100644 --- a/apps/dav/l10n/tr.js +++ b/apps/dav/l10n/tr.js @@ -137,6 +137,8 @@ OC.L10N.register( "Due on %s by %s" : "%s tarihine kadar %s tarafından", "Due on %s" : "%s tarihine kadar", "Migrated calendar (%1$s)" : "Aktarılmış takvim (%1$s)", + "Calendars including events, details and attendees" : "Etkinlikler, bilgiler ve katılımcılar ile takvimler", + "Contacts and groups" : "Kişiler ve gruplar", "WebDAV" : "WebDAV", "WebDAV endpoint" : "WebDAV bağlantı noktası", "Availability" : "Kullanılabilirlik", diff --git a/apps/dav/l10n/tr.json b/apps/dav/l10n/tr.json index 7b640b0178b..b80217bfa8d 100644 --- a/apps/dav/l10n/tr.json +++ b/apps/dav/l10n/tr.json @@ -135,6 +135,8 @@ "Due on %s by %s" : "%s tarihine kadar %s tarafından", "Due on %s" : "%s tarihine kadar", "Migrated calendar (%1$s)" : "Aktarılmış takvim (%1$s)", + "Calendars including events, details and attendees" : "Etkinlikler, bilgiler ve katılımcılar ile takvimler", + "Contacts and groups" : "Kişiler ve gruplar", "WebDAV" : "WebDAV", "WebDAV endpoint" : "WebDAV bağlantı noktası", "Availability" : "Kullanılabilirlik", diff --git a/apps/dav/l10n/zh_TW.js b/apps/dav/l10n/zh_TW.js index 621c28b18bb..414eaad4c01 100644 --- a/apps/dav/l10n/zh_TW.js +++ b/apps/dav/l10n/zh_TW.js @@ -137,6 +137,7 @@ OC.L10N.register( "Due on %s by %s" : "到期於 %s 由 %s", "Due on %s" : "到期於 %s", "Migrated calendar (%1$s)" : "已導入的行事曆 (%1$s)", + "Calendars including events, details and attendees" : "行事曆,包含事件、詳細資訊及參與者", "Contacts and groups" : "聯絡人與群組", "WebDAV" : "WebDAV", "WebDAV endpoint" : "WebDAV 端點", diff --git a/apps/dav/l10n/zh_TW.json b/apps/dav/l10n/zh_TW.json index ff5ee940010..29dd4133fc5 100644 --- a/apps/dav/l10n/zh_TW.json +++ b/apps/dav/l10n/zh_TW.json @@ -135,6 +135,7 @@ "Due on %s by %s" : "到期於 %s 由 %s", "Due on %s" : "到期於 %s", "Migrated calendar (%1$s)" : "已導入的行事曆 (%1$s)", + "Calendars including events, details and attendees" : "行事曆,包含事件、詳細資訊及參與者", "Contacts and groups" : "聯絡人與群組", "WebDAV" : "WebDAV", "WebDAV endpoint" : "WebDAV 端點", diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php index bf7e469a0c0..963a07a55fb 100644 --- a/apps/dav/lib/Connector/Sabre/File.php +++ b/apps/dav/lib/Connector/Sabre/File.php @@ -184,7 +184,23 @@ class File extends Node implements IFile { [$storage, $internalPath] = $this->fileView->resolvePath($this->path); try { if (!$needsPartFile) { - $this->changeLock(ILockingProvider::LOCK_EXCLUSIVE); + try { + $this->changeLock(ILockingProvider::LOCK_EXCLUSIVE); + } catch (LockedException $e) { + // during very large uploads, the shared lock we got at the start might have been expired + // meaning that the above lock can fail not just only because somebody else got a shared lock + // or because there is no existing shared lock to make exclusive + // + // Thus we try to get a new exclusive lock, if the original lock failed because of a different shared + // lock this will still fail, if our original shared lock expired the new lock will be successful and + // the entire operation will be safe + + try { + $this->acquireLock(ILockingProvider::LOCK_EXCLUSIVE); + } catch (LockedException $ex) { + throw new FileLocked($e->getMessage(), $e->getCode(), $e); + } + } } if (!is_resource($data)) { diff --git a/apps/files_sharing/tests/CacheTest.php b/apps/files_sharing/tests/CacheTest.php index 2623b4c34b5..f4f64bc6a32 100644 --- a/apps/files_sharing/tests/CacheTest.php +++ b/apps/files_sharing/tests/CacheTest.php @@ -243,6 +243,9 @@ class CacheTest extends TestCase { public function testGetFolderContentsInRoot() { $results = $this->user2View->getDirectoryContent('/'); + $results = (array_filter($results, function($file) { + return $file->getName() !== 'welcome.txt'; + })); // we should get the shared items "shareddir" and "shared single file.txt" // additional root will always contain the example file "welcome.txt", @@ -250,11 +253,6 @@ class CacheTest extends TestCase { $this->verifyFiles( [ [ - 'name' => 'welcome.txt', - 'path' => 'files/welcome.txt', - 'mimetype' => 'text/plain', - ], - [ 'name' => 'shareddir', 'path' => 'files/shareddir', 'mimetype' => 'httpd/unix-directory', diff --git a/apps/files_trashbin/l10n/tr.js b/apps/files_trashbin/l10n/tr.js index d2998f20d7b..f876ca47621 100644 --- a/apps/files_trashbin/l10n/tr.js +++ b/apps/files_trashbin/l10n/tr.js @@ -3,6 +3,7 @@ OC.L10N.register( { "Deleted files" : "Silinmiş dosyalar", "restored" : "geri yüklendi", + "Deleted files and folders in the trash bin" : "Çöp kutusundaki silinmiş dosya ve klasörler", "This application enables users to restore files that were deleted from the system." : "Bu uygulama kullanıcıların sistem üzerinde sildiği dosyaları geri yükleyebilmesini sağlar.", "This application enables users to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the users file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent a user from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Bu uygulama kullanıcıların sistem üzerinde sildiği dosyaları geri yükleyebilmesini sağlar. Web arayüzünde silinmiş dosyaların listesini ve kullanıcı klasörlerine geri yükleme ya da kalıcı olarak silme seçeneklerini görüntüler. Sürümler uygulaması etkinleştirilmiş ise, geri yüklenen dosyaların önceki sürümleri de geri yüklenir. Paylaşım üzerinden silinen dosyalar da aynı şekilde ancak paylaşılmamış olarak geri yüklenebilir. Silinmiş dosyalar varsayılan olarak 30 gün boyunca çöp kutusunda tutulur.\nSilinmiş dosyalar uygulaması kullanıcıların disk alanının dolmasını engellemek için, kullanıcı depolama alanının en çok %50 oranındaki bölümünü kullanır. Silinmiş dosyaların boyutu bu sınırın üzerine çıkarsa, sınır değerine geri dönülene kadar en eski silinmiş dosyalar silinir. Ayrıntılı bilgi almak için Silinmiş Dosyalar uygulamasının belgelerine bakabilirsiniz.", "Restore" : "Geri yükle", diff --git a/apps/files_trashbin/l10n/tr.json b/apps/files_trashbin/l10n/tr.json index 6aa05e1e504..ab3847d0190 100644 --- a/apps/files_trashbin/l10n/tr.json +++ b/apps/files_trashbin/l10n/tr.json @@ -1,6 +1,7 @@ { "translations": { "Deleted files" : "Silinmiş dosyalar", "restored" : "geri yüklendi", + "Deleted files and folders in the trash bin" : "Çöp kutusundaki silinmiş dosya ve klasörler", "This application enables users to restore files that were deleted from the system." : "Bu uygulama kullanıcıların sistem üzerinde sildiği dosyaları geri yükleyebilmesini sağlar.", "This application enables users to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the users file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent a user from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Bu uygulama kullanıcıların sistem üzerinde sildiği dosyaları geri yükleyebilmesini sağlar. Web arayüzünde silinmiş dosyaların listesini ve kullanıcı klasörlerine geri yükleme ya da kalıcı olarak silme seçeneklerini görüntüler. Sürümler uygulaması etkinleştirilmiş ise, geri yüklenen dosyaların önceki sürümleri de geri yüklenir. Paylaşım üzerinden silinen dosyalar da aynı şekilde ancak paylaşılmamış olarak geri yüklenebilir. Silinmiş dosyalar varsayılan olarak 30 gün boyunca çöp kutusunda tutulur.\nSilinmiş dosyalar uygulaması kullanıcıların disk alanının dolmasını engellemek için, kullanıcı depolama alanının en çok %50 oranındaki bölümünü kullanır. Silinmiş dosyaların boyutu bu sınırın üzerine çıkarsa, sınır değerine geri dönülene kadar en eski silinmiş dosyalar silinir. Ayrıntılı bilgi almak için Silinmiş Dosyalar uygulamasının belgelerine bakabilirsiniz.", "Restore" : "Geri yükle", diff --git a/apps/files_trashbin/tests/StorageTest.php b/apps/files_trashbin/tests/StorageTest.php index 448c3a6adb1..0a7a129ca28 100644 --- a/apps/files_trashbin/tests/StorageTest.php +++ b/apps/files_trashbin/tests/StorageTest.php @@ -33,6 +33,7 @@ namespace OCA\Files_Trashbin\Tests; use OC\Files\Filesystem; use OC\Files\Storage\Common; +use OC\Files\Storage\Local; use OC\Files\Storage\Temporary; use OCA\Files_Trashbin\AppInfo\Application; use OCA\Files_Trashbin\Events\MoveToTrashEvent; @@ -661,6 +662,9 @@ class StorageTest extends \Test\TestCase { } public function testMoveFromStoragePreserveFileId() { + if (!$this->userView->getMount('')->getStorage()->instanceOfStorage(Local::class)) { + $this->markTestSkipped("Skipping on non-local users storage"); + } $this->userView->file_put_contents('test.txt', 'foo'); $fileId = $this->userView->getFileInfo('test.txt')->getId(); diff --git a/apps/settings/l10n/tr.js b/apps/settings/l10n/tr.js index e2729142750..d4e49b47044 100644 --- a/apps/settings/l10n/tr.js +++ b/apps/settings/l10n/tr.js @@ -141,6 +141,8 @@ OC.L10N.register( "MariaDB version \"%s\" is used. Nextcloud 21 will no longer support this version and requires MariaDB 10.2 or higher." : "MariaDB \"%s\" sürümü kullanılıyor. Nextcloud 21 sürümünde bu sürüm desteklenmiyor. MariaDB 10.2 ya da üzerindeki bir sürüm kullanılmalıdır.", "MySQL version \"%s\" is used. Nextcloud 21 will no longer support this version and requires MySQL 8.0 or MariaDB 10.2 or higher." : "MySQL \"%s\" sürümü kullanılıyor. Nextcloud 21 sürümünde bu sürüm desteklenmiyor. MySQL 8 ya da MariaDB 10.2 üzerindeki bir sürüm kullanılmalıdır.", "PostgreSQL version \"%s\" is used. Nextcloud 21 will no longer support this version and requires PostgreSQL 9.6 or higher." : "PostgreSQL \"%s\" sürümü kullanılıyor. Nextcloud 21 sürümünde bu sürüm desteklenmiyor. PostgreSQL 9.6 ya da üzerindeki bir sürüm kullanılmalıdır.", + "Profile information" : "Profil bilgileri", + "Profile picture, full name, email, phone number, address, website, Twitter, organisation, role, headline, biography, and whether your profile is enabled" : "Profil görseli, tam ad, e-posta adresi, telefon numarası, adres, web sitesi, Twitter, kuruluş, rol, başlık, özgeçmi ve profilde etkinleştirilmiş diğer bilgiler", "Nextcloud settings" : "Nextcloud ayarları", "Administration privileges" : "Yönetim yetkileri", "Here you can decide which group can access certain sections of the administration settings." : "Hangi yönetici ayarlarına hangi grubun erişebileceğini bu bölümden belirleyebilirsiniz.", @@ -463,6 +465,8 @@ OC.L10N.register( "Allow username autocompletion to users within the same groups" : "Aynı gruplardaki kullanıcıların kullanıcı adları otomatik olarak tamamlanabilsin", "Allow username autocompletion to users based on phone number integration" : "Telefon numarası bütünleştirmesi eşleşmelerine göre kullanıcı adları otomatik olarak tamamlanabilsin", "If autocompletion \"same group\" and \"phone number integration\" are enabled a match in either is enough to show the user." : "\"Aynı grup\" ve \"telefon numarası bütünleştirmesi\" etkinleştirilmiş ise. Kullanıcının görüntülenmesi için ikisinden birinde eşleşme olması yeterlidir.", + "Allow autocompletion when entering the full name or email address (ignoring missing phonebook match and being in the same group)" : "Tam ad ya da e-posta adresi yazılırken otomatik olarak tamamlanabilsin (aynı grupta olma ya da telefon defteri eşleşmesi yok sayılarak)", + "Match username when restricting to full match" : "Tam eşleşme kısıtlamasında kullanıcı adı ile eşleşilsin", "Show disclaimer text on the public link upload page (only shown when the file list is hidden)" : "Herkese açık bağlantı yükleme sayfasındaki sorumluluk reddi bildirim metni (yalnız dosya listesi gizli iken görüntülenir)", "This text will be shown on the public link upload page when the file list is hidden." : "Dosya listesi gizli iken herkese açık bağlantı yükleme sayfasında görüntülenecek sorumluluk reddi bildirimi metni.", "Default share permissions" : "Varsayılan paylaşım izinleri", diff --git a/apps/settings/l10n/tr.json b/apps/settings/l10n/tr.json index 5505c89eb9b..8ab388a0520 100644 --- a/apps/settings/l10n/tr.json +++ b/apps/settings/l10n/tr.json @@ -139,6 +139,8 @@ "MariaDB version \"%s\" is used. Nextcloud 21 will no longer support this version and requires MariaDB 10.2 or higher." : "MariaDB \"%s\" sürümü kullanılıyor. Nextcloud 21 sürümünde bu sürüm desteklenmiyor. MariaDB 10.2 ya da üzerindeki bir sürüm kullanılmalıdır.", "MySQL version \"%s\" is used. Nextcloud 21 will no longer support this version and requires MySQL 8.0 or MariaDB 10.2 or higher." : "MySQL \"%s\" sürümü kullanılıyor. Nextcloud 21 sürümünde bu sürüm desteklenmiyor. MySQL 8 ya da MariaDB 10.2 üzerindeki bir sürüm kullanılmalıdır.", "PostgreSQL version \"%s\" is used. Nextcloud 21 will no longer support this version and requires PostgreSQL 9.6 or higher." : "PostgreSQL \"%s\" sürümü kullanılıyor. Nextcloud 21 sürümünde bu sürüm desteklenmiyor. PostgreSQL 9.6 ya da üzerindeki bir sürüm kullanılmalıdır.", + "Profile information" : "Profil bilgileri", + "Profile picture, full name, email, phone number, address, website, Twitter, organisation, role, headline, biography, and whether your profile is enabled" : "Profil görseli, tam ad, e-posta adresi, telefon numarası, adres, web sitesi, Twitter, kuruluş, rol, başlık, özgeçmi ve profilde etkinleştirilmiş diğer bilgiler", "Nextcloud settings" : "Nextcloud ayarları", "Administration privileges" : "Yönetim yetkileri", "Here you can decide which group can access certain sections of the administration settings." : "Hangi yönetici ayarlarına hangi grubun erişebileceğini bu bölümden belirleyebilirsiniz.", @@ -461,6 +463,8 @@ "Allow username autocompletion to users within the same groups" : "Aynı gruplardaki kullanıcıların kullanıcı adları otomatik olarak tamamlanabilsin", "Allow username autocompletion to users based on phone number integration" : "Telefon numarası bütünleştirmesi eşleşmelerine göre kullanıcı adları otomatik olarak tamamlanabilsin", "If autocompletion \"same group\" and \"phone number integration\" are enabled a match in either is enough to show the user." : "\"Aynı grup\" ve \"telefon numarası bütünleştirmesi\" etkinleştirilmiş ise. Kullanıcının görüntülenmesi için ikisinden birinde eşleşme olması yeterlidir.", + "Allow autocompletion when entering the full name or email address (ignoring missing phonebook match and being in the same group)" : "Tam ad ya da e-posta adresi yazılırken otomatik olarak tamamlanabilsin (aynı grupta olma ya da telefon defteri eşleşmesi yok sayılarak)", + "Match username when restricting to full match" : "Tam eşleşme kısıtlamasında kullanıcı adı ile eşleşilsin", "Show disclaimer text on the public link upload page (only shown when the file list is hidden)" : "Herkese açık bağlantı yükleme sayfasındaki sorumluluk reddi bildirim metni (yalnız dosya listesi gizli iken görüntülenir)", "This text will be shown on the public link upload page when the file list is hidden." : "Dosya listesi gizli iken herkese açık bağlantı yükleme sayfasında görüntülenecek sorumluluk reddi bildirimi metni.", "Default share permissions" : "Varsayılan paylaşım izinleri", diff --git a/apps/user_ldap/css/settings.css b/apps/user_ldap/css/settings.css index 54d0e2dbb0c..f99310118a9 100644 --- a/apps/user_ldap/css/settings.css +++ b/apps/user_ldap/css/settings.css @@ -9,7 +9,8 @@ } .tablerow { - display: table-row; + display: flex; + align-items: center; white-space: nowrap; text-align: left; } @@ -226,3 +227,8 @@ select[multiple=multiple] + button { #ldapSettings div.ui-accordion-content { background: white; } + +ul.ui-multiselect-checkboxes label { + display: flex; + align-items: center; +} diff --git a/apps/user_ldap/lib/Mapping/AbstractMapping.php b/apps/user_ldap/lib/Mapping/AbstractMapping.php index 16973f76ff4..1a747cc8bfd 100644 --- a/apps/user_ldap/lib/Mapping/AbstractMapping.php +++ b/apps/user_ldap/lib/Mapping/AbstractMapping.php @@ -438,14 +438,14 @@ abstract class AbstractMapping { $picker = $this->dbc->getQueryBuilder(); $picker->select('owncloud_name') ->from($this->getTableName()); - $cursor = $picker->execute(); + $cursor = $picker->executeQuery(); $result = true; - while ($id = $cursor->fetchOne()) { + while (($id = $cursor->fetchOne()) !== false) { $preCallback($id); if ($isUnmapped = $this->unmap($id)) { $postCallback($id); } - $result &= $isUnmapped; + $result = $result && $isUnmapped; } $cursor->closeCursor(); return $result; diff --git a/apps/user_ldap/lib/Migration/Version1130Date20211102154716.php b/apps/user_ldap/lib/Migration/Version1130Date20211102154716.php index 9e9554000d8..024c5801582 100644 --- a/apps/user_ldap/lib/Migration/Version1130Date20211102154716.php +++ b/apps/user_ldap/lib/Migration/Version1130Date20211102154716.php @@ -259,7 +259,7 @@ class Version1130Date20211102154716 extends SimpleMigrationStep { $result = $select->executeQuery(); $idList = []; - while ($id = $result->fetchOne()) { + while (($id = $result->fetchOne()) !== false) { $idList[] = $id; } $result->closeCursor(); @@ -278,7 +278,7 @@ class Version1130Date20211102154716 extends SimpleMigrationStep { ->having($select->expr()->gt($select->func()->count('owncloud_name'), $select->createNamedParameter(1))); $result = $select->executeQuery(); - while ($uuid = $result->fetchOne()) { + while (($uuid = $result->fetchOne()) !== false) { yield $uuid; } $result->closeCursor(); diff --git a/apps/workflowengine/lib/Manager.php b/apps/workflowengine/lib/Manager.php index 178bc87365b..34dbf507b91 100644 --- a/apps/workflowengine/lib/Manager.php +++ b/apps/workflowengine/lib/Manager.php @@ -351,7 +351,7 @@ class Manager implements IManager { $result = $qb->execute(); $this->operationsByScope[$scopeContext->getHash()] = []; - while ($opId = $result->fetchOne()) { + while (($opId = $result->fetchOne()) !== false) { $this->operationsByScope[$scopeContext->getHash()][] = (int)$opId; } $result->closeCursor(); diff --git a/apps/workflowengine/lib/Migration/PopulateNewlyIntroducedDatabaseFields.php b/apps/workflowengine/lib/Migration/PopulateNewlyIntroducedDatabaseFields.php index 019d3ae6bcc..974793e99b2 100644 --- a/apps/workflowengine/lib/Migration/PopulateNewlyIntroducedDatabaseFields.php +++ b/apps/workflowengine/lib/Migration/PopulateNewlyIntroducedDatabaseFields.php @@ -57,7 +57,7 @@ class PopulateNewlyIntroducedDatabaseFields implements IRepairStep { $qb = $this->dbc->getQueryBuilder(); $insertQuery = $qb->insert('flow_operations_scope'); - while ($id = $ids->fetchOne()) { + while (($id = $ids->fetchOne()) !== false) { $insertQuery->values(['operation_id' => $qb->createNamedParameter($id), 'type' => IManager::SCOPE_ADMIN]); $insertQuery->execute(); } |