From cf508c1e4730f3590b956735678413484e2c008c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 29 Nov 2022 16:29:12 +0100 Subject: [PATCH 01/10] Use strict typing in base.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- lib/base.php | 91 +++++++++++------------ lib/private/AppFramework/Http/Request.php | 25 ++----- 2 files changed, 50 insertions(+), 66 deletions(-) diff --git a/lib/base.php b/lib/base.php index 7098fb19fdd..bffa0585811 100644 --- a/lib/base.php +++ b/lib/base.php @@ -1,4 +1,7 @@ * @author Björn Schießle * @author Christoph Wurst + * @author Côme Chilliet * @author Damjan Georgievski * @author Daniel Kesselberg * @author davidgumberg @@ -62,15 +66,15 @@ * */ +use OC\Encryption\HookManager; use OC\EventDispatcher\SymfonyAdapter; +use OC\Files\Filesystem; +use OC\Share20\Hooks; use OCP\EventDispatcher\IEventDispatcher; use OCP\Group\Events\UserRemovedEvent; use OCP\ILogger; use OCP\Server; use OCP\Share; -use OC\Encryption\HookManager; -use OC\Files\Filesystem; -use OC\Share20\Hooks; use OCP\User\Events\UserChangedEvent; use function OCP\Log\logger; @@ -85,51 +89,46 @@ class OC { /** * Associative array for autoloading. classname => filename */ - public static $CLASSPATH = []; + public static array $CLASSPATH = []; /** * The installation path for Nextcloud on the server (e.g. /srv/http/nextcloud) */ - public static $SERVERROOT = ''; + public static string $SERVERROOT = ''; /** * the current request path relative to the Nextcloud root (e.g. files/index.php) */ - private static $SUBURI = ''; + private static string $SUBURI = ''; /** * the Nextcloud root path for http requests (e.g. nextcloud/) */ - public static $WEBROOT = ''; + public static string $WEBROOT = ''; /** * The installation path array of the apps folder on the server (e.g. /srv/http/nextcloud) 'path' and * web path in 'url' */ - public static $APPSROOTS = []; + public static array $APPSROOTS = []; - /** - * @var string - */ - public static $configDir; + public static string $configDir; /** * requested app */ - public static $REQUESTEDAPP = ''; + public static string $REQUESTEDAPP = ''; /** * check if Nextcloud runs in cli mode */ - public static $CLI = false; + public static bool $CLI = false; /** - * @var \OC\Autoloader $loader + * @var \OC\Autoloader */ public static $loader = null; - /** @var \Composer\Autoload\ClassLoader $composerAutoloader */ + /** @var \Composer\Autoload\ClassLoader */ public static $composerAutoloader = null; - /** - * @var \OC\Server - */ + /** @var \OC\Server */ public static $server = null; /** @@ -141,7 +140,7 @@ class OC { * @throws \RuntimeException when the 3rdparty directory is missing or * the app path list is empty or contains an invalid path */ - public static function initPaths() { + public static function initPaths(): void { if (defined('PHPUNIT_CONFIG_DIR')) { self::$configDir = OC::$SERVERROOT . '/' . PHPUNIT_CONFIG_DIR . '/'; } elseif (defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) { @@ -153,15 +152,15 @@ class OC { } self::$config = new \OC\Config(self::$configDir); - OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT))); + OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"] ?? ''), strlen(OC::$SERVERROOT))); /** * FIXME: The following lines are required because we can't yet instantiate * \OC::$server->getRequest() since \OC::$server does not yet exist. */ $params = [ 'server' => [ - 'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'], - 'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'], + 'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'] ?? null, + 'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'] ?? null, ], ]; $fakeRequest = new \OC\AppFramework\Http\Request( @@ -241,7 +240,7 @@ class OC { ); } - public static function checkConfig() { + public static function checkConfig(): void { $l = \OC::$server->getL10N('lib'); // Create config if it does not already exist @@ -275,7 +274,7 @@ class OC { } } - public static function checkInstalled(\OC\SystemConfig $systemConfig) { + public static function checkInstalled(\OC\SystemConfig $systemConfig): void { if (defined('OC_CONSOLE')) { return; } @@ -291,7 +290,7 @@ class OC { } } - public static function checkMaintenanceMode(\OC\SystemConfig $systemConfig) { + public static function checkMaintenanceMode(\OC\SystemConfig $systemConfig): void { // Allow ajax update script to execute without being stopped if (((bool) $systemConfig->getValue('maintenance', false)) && OC::$SUBURI != '/core/ajax/update.php') { // send http status 503 @@ -310,10 +309,8 @@ class OC { /** * Prints the upgrade page - * - * @param \OC\SystemConfig $systemConfig */ - private static function printUpgradePage(\OC\SystemConfig $systemConfig) { + private static function printUpgradePage(\OC\SystemConfig $systemConfig): void { $disableWebUpdater = $systemConfig->getValue('upgrade.disable-web', false); $tooBig = false; if (!$disableWebUpdater) { @@ -415,7 +412,7 @@ class OC { $tmpl->printPage(); } - public static function initSession() { + public static function initSession(): void { if (self::$server->getRequest()->getServerProtocol() === 'https') { ini_set('session.cookie_secure', 'true'); } @@ -464,10 +461,7 @@ class OC { $session->close(); } - /** - * @return string - */ - private static function getSessionLifeTime() { + private static function getSessionLifeTime(): string { return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24); } @@ -481,7 +475,7 @@ class OC { /** * Try to set some values to the required Nextcloud default */ - public static function setRequiredIniValues() { + public static function setRequiredIniValues(): void { @ini_set('default_charset', 'UTF-8'); @ini_set('gd.jpeg_ignore_warning', '1'); } @@ -489,7 +483,7 @@ class OC { /** * Send the same site cookies */ - private static function sendSameSiteCookies() { + private static function sendSameSiteCookies(): void { $cookieParams = session_get_cookie_params(); $secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : ''; $policies = [ @@ -526,7 +520,7 @@ class OC { * We use an additional cookie since we want to protect logout CSRF and * also we can't directly interfere with PHP's session mechanism. */ - private static function performSameSiteCookieProtection(\OCP\IConfig $config) { + private static function performSameSiteCookieProtection(\OCP\IConfig $config): void { $request = \OC::$server->getRequest(); // Some user agents are notorious and don't really properly follow HTTP @@ -574,7 +568,7 @@ class OC { } } - public static function init() { + public static function init(): void { // calculate the root directories OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4)); @@ -680,7 +674,7 @@ class OC { } /** @var \OC\AppFramework\Bootstrap\Coordinator $bootstrapCoordinator */ - $bootstrapCoordinator = \OC::$server->query(\OC\AppFramework\Bootstrap\Coordinator::class); + $bootstrapCoordinator = \OC::$server->get(\OC\AppFramework\Bootstrap\Coordinator::class); $bootstrapCoordinator->runInitialRegistration(); $eventLogger->start('init_session', 'Initialize session'); @@ -843,10 +837,9 @@ class OC { /** * register hooks for the cleanup of cache and bruteforce protection */ - public static function registerCleanupHooks(\OC\SystemConfig $systemConfig) { + public static function registerCleanupHooks(\OC\SystemConfig $systemConfig): void { //don't try to do this before we are properly setup if ($systemConfig->getValue('installed', false) && !\OCP\Util::needUpgrade()) { - // NOTE: This will be replaced to use OCP $userSession = self::$server->getUserSession(); $userSession->listen('\OC\User', 'postLogin', function () use ($userSession) { @@ -879,7 +872,7 @@ class OC { } } - private static function registerEncryptionWrapperAndHooks() { + private static function registerEncryptionWrapperAndHooks(): void { $manager = self::$server->getEncryptionManager(); \OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage'); @@ -892,13 +885,13 @@ class OC { } } - private static function registerAccountHooks() { + private static function registerAccountHooks(): void { /** @var IEventDispatcher $dispatcher */ $dispatcher = \OC::$server->get(IEventDispatcher::class); $dispatcher->addServiceListener(UserChangedEvent::class, \OC\Accounts\Hooks::class); } - private static function registerAppRestrictionsHooks() { + private static function registerAppRestrictionsHooks(): void { /** @var \OC\Group\Manager $groupManager */ $groupManager = self::$server->query(\OCP\IGroupManager::class); $groupManager->listen('\OC\Group', 'postDelete', function (\OCP\IGroup $group) { @@ -921,18 +914,18 @@ class OC { }); } - private static function registerResourceCollectionHooks() { + private static function registerResourceCollectionHooks(): void { \OC\Collaboration\Resources\Listener::register(Server::get(SymfonyAdapter::class), Server::get(IEventDispatcher::class)); } - private static function registerFileReferenceEventListener() { + private static function registerFileReferenceEventListener(): void { \OC\Collaboration\Reference\File\FileReferenceEventListener::register(Server::get(IEventDispatcher::class)); } /** * register hooks for sharing */ - public static function registerShareHooks(\OC\SystemConfig $systemConfig) { + public static function registerShareHooks(\OC\SystemConfig $systemConfig): void { if ($systemConfig->getValue('installed')) { OC_Hook::connect('OC_User', 'post_deleteUser', Hooks::class, 'post_deleteUser'); OC_Hook::connect('OC_User', 'post_deleteGroup', Hooks::class, 'post_deleteGroup'); @@ -943,7 +936,7 @@ class OC { } } - protected static function registerAutoloaderCache(\OC\SystemConfig $systemConfig) { + protected static function registerAutoloaderCache(\OC\SystemConfig $systemConfig): void { // The class loader takes an optional low-latency cache, which MUST be // namespaced. The instanceid is used for namespacing, but might be // unavailable at this point. Furthermore, it might not be possible to @@ -1133,7 +1126,7 @@ class OC { return false; } - protected static function handleAuthHeaders() { + protected static function handleAuthHeaders(): void { //copy http auth headers for apache+php-fcgid work around if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) { $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION']; diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php index 286187c696c..32cce8a88e1 100644 --- a/lib/private/AppFramework/Http/Request.php +++ b/lib/private/AppFramework/Http/Request.php @@ -50,7 +50,6 @@ use OC\Security\TrustedDomainHelper; use OCP\IConfig; use OCP\IRequest; use OCP\IRequestId; -use OCP\Security\ICrypto; use Symfony\Component\HttpFoundation\IpUtils; /** @@ -79,10 +78,10 @@ class Request implements \ArrayAccess, \Countable, IRequest { public const USER_AGENT_FREEBOX = '#^Mozilla/5\.0$#'; public const REGEX_LOCALHOST = '/^(127\.0\.0\.1|localhost|\[::1\])$/'; - protected $inputStream; + protected string $inputStream; protected $content; - protected $items = []; - protected $allowedKeys = [ + protected array $items = []; + protected array $allowedKeys = [ 'get', 'post', 'files', @@ -94,17 +93,11 @@ class Request implements \ArrayAccess, \Countable, IRequest { 'method', 'requesttoken', ]; - /** @var RequestId */ - protected $requestId; - /** @var IConfig */ - protected $config; - /** @var ICrypto */ - protected $crypto; - /** @var CsrfTokenManager|null */ - protected $csrfTokenManager; + protected IRequestId $requestId; + protected IConfig $config; + protected ?CsrfTokenManager $csrfTokenManager; - /** @var bool */ - protected $contentDecoded = false; + protected bool $contentDecoded = false; /** * @param array $vars An associative array with the following optional values: @@ -139,9 +132,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { } foreach ($this->allowedKeys as $name) { - $this->items[$name] = isset($vars[$name]) - ? $vars[$name] - : []; + $this->items[$name] = $vars[$name] ?? []; } $this->items['parameters'] = array_merge( From 444811b0feecdb78b083dd1a5d2e35a0d4ce7528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 29 Nov 2022 16:53:27 +0100 Subject: [PATCH 02/10] Use Server::get some more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- lib/base.php | 77 ++++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/lib/base.php b/lib/base.php index bffa0585811..3a5a6d4e3fc 100644 --- a/lib/base.php +++ b/lib/base.php @@ -73,6 +73,8 @@ use OC\Share20\Hooks; use OCP\EventDispatcher\IEventDispatcher; use OCP\Group\Events\UserRemovedEvent; use OCP\ILogger; +use OCP\IURLGenerator; +use OCP\IUserSession; use OCP\Server; use OCP\Share; use OCP\User\Events\UserChangedEvent; @@ -241,7 +243,7 @@ class OC { } public static function checkConfig(): void { - $l = \OC::$server->getL10N('lib'); + $l = Server::get(\OCP\L10N\IFactory::class)->get('lib'); // Create config if it does not already exist $configFilePath = self::$configDir .'/config.php'; @@ -253,7 +255,7 @@ class OC { $configFileWritable = is_writable($configFilePath); if (!$configFileWritable && !OC_Helper::isReadOnlyConfigEnabled() || !$configFileWritable && \OCP\Util::needUpgrade()) { - $urlGenerator = \OC::$server->getURLGenerator(); + $urlGenerator = Server::get(IURLGenerator::class); if (self::$CLI) { echo $l->t('Cannot write into "config" directory!')."\n"; @@ -314,13 +316,13 @@ class OC { $disableWebUpdater = $systemConfig->getValue('upgrade.disable-web', false); $tooBig = false; if (!$disableWebUpdater) { - $apps = \OC::$server->getAppManager(); + $apps = Server::get(\OCP\App\IAppManager::class); if ($apps->isInstalled('user_ldap')) { $qb = \OC::$server->getDatabaseConnection()->getQueryBuilder(); $result = $qb->select($qb->func()->count('*', 'user_count')) ->from('ldap_user_mapping') - ->execute(); + ->executeQuery(); $row = $result->fetch(); $result->closeCursor(); @@ -331,7 +333,7 @@ class OC { $result = $qb->select($qb->func()->count('*', 'user_count')) ->from('user_saml_users') - ->execute(); + ->executeQuery(); $row = $result->fetch(); $result->closeCursor(); @@ -377,7 +379,7 @@ class OC { \OCP\Util::addScript('core', 'update'); /** @var \OC\App\AppManager $appManager */ - $appManager = \OC::$server->getAppManager(); + $appManager = Server::get(\OCP\App\IAppManager::class); $tmpl = new OC_Template('', 'update.admin', 'guest'); $tmpl->assign('version', OC_Util::getVersionString()); @@ -395,7 +397,7 @@ class OC { } if (!empty($incompatibleShippedApps)) { - $l = \OC::$server->getL10N('core'); + $l = Server::get(\OCP\L10N\IFactory::class)->get('core'); $hint = $l->t('The files of the app %1$s were not replaced correctly. Make sure it is a version compatible with the server.', [implode(', ', $incompatibleShippedApps)]); throw new \OCP\HintException('The files of the app ' . implode(', ', $incompatibleShippedApps) . ' were not replaced correctly. Make sure it is a version compatible with the server.', $hint); } @@ -445,14 +447,14 @@ class OC { //try to set the session lifetime $sessionLifeTime = self::getSessionLifeTime(); - @ini_set('gc_maxlifetime', (string)$sessionLifeTime); + @ini_set('gc_maxlifetime', $sessionLifeTime); // session timeout if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) { if (isset($_COOKIE[session_name()])) { setcookie(session_name(), '', -1, self::$WEBROOT ? : '/'); } - \OC::$server->getUserSession()->logout(); + Server::get(IUserSession::class)->logout(); } if (!self::hasSessionRelaxedExpiry()) { @@ -649,13 +651,13 @@ class OC { self::setRequiredIniValues(); self::handleAuthHeaders(); - $systemConfig = \OC::$server->get(\OC\SystemConfig::class); + $systemConfig = Server::get(\OC\SystemConfig::class); self::registerAutoloaderCache($systemConfig); // initialize intl fallback if necessary OC_Util::isSetLocaleWorking(); - $config = \OC::$server->get(\OCP\IConfig::class); + $config = Server::get(\OCP\IConfig::class); if (!defined('PHPUNIT_RUN')) { $errorHandler = new OC\Log\ErrorHandler( \OCP\Server::get(\Psr\Log\LoggerInterface::class), @@ -674,7 +676,7 @@ class OC { } /** @var \OC\AppFramework\Bootstrap\Coordinator $bootstrapCoordinator */ - $bootstrapCoordinator = \OC::$server->get(\OC\AppFramework\Bootstrap\Coordinator::class); + $bootstrapCoordinator = Server::get(\OC\AppFramework\Bootstrap\Coordinator::class); $bootstrapCoordinator->runInitialRegistration(); $eventLogger->start('init_session', 'Initialize session'); @@ -763,7 +765,7 @@ class OC { if ($systemConfig->getValue("installed", false)) { OC_App::loadApp('settings'); /* Build core application to make sure that listeners are registered */ - self::$server->get(\OC\Core\Application::class); + Server::get(\OC\Core\Application::class); } //make sure temporary files are cleaned up @@ -774,7 +776,7 @@ class OC { // Check whether the sample configuration has been copied if ($systemConfig->getValue('copied_sample_config', false)) { - $l = \OC::$server->getL10N('lib'); + $l = Server::get(\OCP\L10N\IFactory::class)->get('lib'); OC_Template::printErrorPage( $l->t('Sample configuration detected'), $l->t('It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php'), @@ -819,7 +821,7 @@ class OC { ); $tmpl = new OCP\Template('core', 'untrustedDomain', 'guest'); - $tmpl->assign('docUrl', \OC::$server->getURLGenerator()->linkToDocs('admin-trusted-domains')); + $tmpl->assign('docUrl', Server::get(IURLGenerator::class)->linkToDocs('admin-trusted-domains')); $tmpl->printPage(); exit(); @@ -841,11 +843,11 @@ class OC { //don't try to do this before we are properly setup if ($systemConfig->getValue('installed', false) && !\OCP\Util::needUpgrade()) { // NOTE: This will be replaced to use OCP - $userSession = self::$server->getUserSession(); + $userSession = Server::get(IUserSession::class); $userSession->listen('\OC\User', 'postLogin', function () use ($userSession) { if (!defined('PHPUNIT_RUN') && $userSession->isLoggedIn()) { // reset brute force delay for this IP address and username - $uid = \OC::$server->getUserSession()->getUser()->getUID(); + $uid = $userSession->getUser()->getUID(); $request = \OC::$server->getRequest(); $throttler = \OC::$server->getBruteForceThrottler(); $throttler->resetDelay($request->getRemoteAddress(), 'login', ['user' => $uid]); @@ -887,15 +889,15 @@ class OC { private static function registerAccountHooks(): void { /** @var IEventDispatcher $dispatcher */ - $dispatcher = \OC::$server->get(IEventDispatcher::class); + $dispatcher = Server::get(IEventDispatcher::class); $dispatcher->addServiceListener(UserChangedEvent::class, \OC\Accounts\Hooks::class); } private static function registerAppRestrictionsHooks(): void { /** @var \OC\Group\Manager $groupManager */ - $groupManager = self::$server->query(\OCP\IGroupManager::class); + $groupManager = Server::get(\OCP\IGroupManager::class); $groupManager->listen('\OC\Group', 'postDelete', function (\OCP\IGroup $group) { - $appManager = self::$server->getAppManager(); + $appManager = Server::get(\OCP\App\IAppManager::class); $apps = $appManager->getEnabledAppsForGroup($group); foreach ($apps as $appId) { $restrictions = $appManager->getAppRestriction($appId); @@ -931,7 +933,7 @@ class OC { OC_Hook::connect('OC_User', 'post_deleteGroup', Hooks::class, 'post_deleteGroup'); /** @var IEventDispatcher $dispatcher */ - $dispatcher = \OC::$server->get(IEventDispatcher::class); + $dispatcher = Server::get(IEventDispatcher::class); $dispatcher->addServiceListener(UserRemovedEvent::class, \OC\Share20\UserRemovedListener::class); } } @@ -965,12 +967,12 @@ class OC { \OC::$server->getSession()->clear(); $setupHelper = new OC\Setup( $systemConfig, - \OC::$server->get(\bantu\IniGetWrapper\IniGetWrapper::class), - \OC::$server->getL10N('lib'), - \OC::$server->query(\OCP\Defaults::class), - \OC::$server->get(\Psr\Log\LoggerInterface::class), + Server::get(\bantu\IniGetWrapper\IniGetWrapper::class), + Server::get(\OCP\L10N\IFactory::class)->get('lib'), + Server::get(\OCP\Defaults::class), + Server::get(\Psr\Log\LoggerInterface::class), \OC::$server->getSecureRandom(), - \OC::$server->query(\OC\Installer::class) + Server::get(\OC\Installer::class) ); $controller = new OC\Core\Controller\SetupController($setupHelper); $controller->run($_POST); @@ -1006,7 +1008,7 @@ class OC { $appIds = (array)$request->getParam('appid'); foreach ($appIds as $appId) { $appId = \OC_App::cleanAppId($appId); - \OC::$server->getAppManager()->disableApp($appId); + Server::get(\OCP\App\IAppManager::class)->disableApp($appId); } \OC_JSON::success(); exit(); @@ -1019,7 +1021,7 @@ class OC { if (!\OCP\Util::needUpgrade() && !((bool) $systemConfig->getValue('maintenance', false))) { // For logged-in users: Load everything - if (\OC::$server->getUserSession()->isLoggedIn()) { + if (Server::get(IUserSession::class)->isLoggedIn()) { OC_App::loadApps(); } else { // For guests: Load only filesystem and logging @@ -1040,7 +1042,7 @@ class OC { OC_App::loadApps(['filesystem', 'logging']); OC_App::loadApps(); } - OC::$server->get(\OC\Route\Router::class)->match($request->getRawPathInfo()); + Server::get(\OC\Route\Router::class)->match($request->getRawPathInfo()); return; } catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) { //header('HTTP/1.0 404 Not Found'); @@ -1078,20 +1080,20 @@ class OC { // Redirect to the default app or login only as an entry point if ($requestPath === '') { // Someone is logged in - if (\OC::$server->getUserSession()->isLoggedIn()) { - header('Location: ' . \OC::$server->getURLGenerator()->linkToDefaultPageUrl()); + if (Server::get(IUserSession::class)->isLoggedIn()) { + header('Location: ' . Server::get(IURLGenerator::class)->linkToDefaultPageUrl()); } else { // Not handled and not logged in - header('Location: ' . \OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm')); + header('Location: ' . Server::get(IURLGenerator::class)->linkToRouteAbsolute('core.login.showLoginForm')); } return; } try { - return OC::$server->get(\OC\Route\Router::class)->match('/error/404'); + return Server::get(\OC\Route\Router::class)->match('/error/404'); } catch (\Exception $e) { logger('core')->emergency($e->getMessage(), ['exception' => $e]); - $l = \OC::$server->getL10N('lib'); + $l = Server::get(\OCP\L10N\IFactory::class)->get('lib'); OC_Template::printErrorPage( $l->t('404'), $l->t('The page could not be found on the server.'), @@ -1102,12 +1104,9 @@ class OC { /** * Check login: apache auth, auth token, basic auth - * - * @param OCP\IRequest $request - * @return boolean */ - public static function handleLogin(OCP\IRequest $request) { - $userSession = self::$server->getUserSession(); + public static function handleLogin(OCP\IRequest $request): bool { + $userSession = Server::get(IUserSession::class); if (OC_User::handleApacheAuth()) { return true; } From 7372da6c6d0905c2abf5cec9e87262ebd07e75ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 29 Nov 2022 18:07:27 +0100 Subject: [PATCH 03/10] Fixing more psalm errors from lib/base.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- lib/base.php | 63 ++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/lib/base.php b/lib/base.php index 3a5a6d4e3fc..49df9e87d24 100644 --- a/lib/base.php +++ b/lib/base.php @@ -157,7 +157,7 @@ class OC { OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"] ?? ''), strlen(OC::$SERVERROOT))); /** * FIXME: The following lines are required because we can't yet instantiate - * \OC::$server->getRequest() since \OC::$server does not yet exist. + * Server::get(\OCP\IRequest::class) since \OC::$server does not yet exist. */ $params = [ 'server' => [ @@ -318,7 +318,7 @@ class OC { if (!$disableWebUpdater) { $apps = Server::get(\OCP\App\IAppManager::class); if ($apps->isInstalled('user_ldap')) { - $qb = \OC::$server->getDatabaseConnection()->getQueryBuilder(); + $qb = Server::get(\OCP\IDBConnection::class)->getQueryBuilder(); $result = $qb->select($qb->func()->count('*', 'user_count')) ->from('ldap_user_mapping') @@ -329,7 +329,7 @@ class OC { $tooBig = ($row['user_count'] > 50); } if (!$tooBig && $apps->isInstalled('user_saml')) { - $qb = \OC::$server->getDatabaseConnection()->getQueryBuilder(); + $qb = Server::get(\OCP\IDBConnection::class)->getQueryBuilder(); $result = $qb->select($qb->func()->count('*', 'user_count')) ->from('user_saml_users') @@ -341,7 +341,7 @@ class OC { } if (!$tooBig) { // count users - $stats = \OC::$server->getUserManager()->countUsers(); + $stats = Server::get(\OCP\IUserManager::class)->countUsers(); $totalUsers = array_sum($stats); $tooBig = ($totalUsers > 50); } @@ -415,7 +415,7 @@ class OC { } public static function initSession(): void { - if (self::$server->getRequest()->getServerProtocol() === 'https') { + if (Server::get(\OCP\IRequest::class)->getServerProtocol() === 'https') { ini_set('session.cookie_secure', 'true'); } @@ -433,7 +433,7 @@ class OC { // set the session name to the instance id - which is unique $session = new \OC\Session\Internal($sessionName); - $cryptoWrapper = \OC::$server->getSessionCryptoWrapper(); + $cryptoWrapper = Server::get(\OC\Session\CryptoWrapper::class); $session = $cryptoWrapper->wrapSession($session); self::$server->setSession($session); @@ -463,15 +463,15 @@ class OC { $session->close(); } - private static function getSessionLifeTime(): string { - return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24); + private static function getSessionLifeTime(): int { + return Server::get(\OC\AllConfig::class)->getSystemValueInt('session_lifetime', 60 * 60 * 24); } /** * @return bool true if the session expiry should only be done by gc instead of an explicit timeout */ public static function hasSessionRelaxedExpiry(): bool { - return \OC::$server->getConfig()->getSystemValue('session_relaxed_expiry', false); + return Server::get(\OC\AllConfig::class)->getSystemValueBool('session_relaxed_expiry', false); } /** @@ -523,7 +523,7 @@ class OC { * also we can't directly interfere with PHP's session mechanism. */ private static function performSameSiteCookieProtection(\OCP\IConfig $config): void { - $request = \OC::$server->getRequest(); + $request = Server::get(\OCP\IRequest::class); // Some user agents are notorious and don't really properly follow HTTP // specifications. For those, have an automated opt-out. Since the protection @@ -614,7 +614,7 @@ class OC { self::$server = new \OC\Server(\OC::$WEBROOT, self::$config); self::$server->boot(); - $eventLogger = \OC::$server->getEventLogger(); + $eventLogger = Server::get(\OCP\Diagnostics\IEventLogger::class); $eventLogger->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd); $eventLogger->start('boot', 'Initialize'); @@ -735,7 +735,7 @@ class OC { } OC_User::useBackend(new \OC\User\Database()); - \OC::$server->getGroupManager()->addBackend(new \OC\Group\Database()); + Server::get(\OCP\IGroupManager::class)->addBackend(new \OC\Group\Database()); // Subscribe to the hook \OCP\Util::connectHook( @@ -769,9 +769,9 @@ class OC { } //make sure temporary files are cleaned up - $tmpManager = \OC::$server->getTempManager(); + $tmpManager = Server::get(\OCP\ITempManager::class); register_shutdown_function([$tmpManager, 'clean']); - $lockProvider = \OC::$server->getLockingProvider(); + $lockProvider = Server::get(\OCP\Lock\ILockingProvider::class); register_shutdown_function([$lockProvider, 'releaseAll']); // Check whether the sample configuration has been copied @@ -785,19 +785,19 @@ class OC { return; } - $request = \OC::$server->getRequest(); + $request = Server::get(\OCP\IRequest::class); $host = $request->getInsecureServerHost(); /** * if the host passed in headers isn't trusted * FIXME: Should not be in here at all :see_no_evil: */ if (!OC::$CLI - && !\OC::$server->getTrustedDomainHelper()->isTrustedDomain($host) + && !Server::get(\OC\Security\TrustedDomainHelper::class)->isTrustedDomain($host) && $config->getSystemValue('installed', false) ) { // Allow access to CSS resources $isScssRequest = false; - if (strpos($request->getPathInfo(), '/css/') === 0) { + if (strpos($request->getPathInfo() ?: '', '/css/') === 0) { $isScssRequest = true; } @@ -843,13 +843,13 @@ class OC { //don't try to do this before we are properly setup if ($systemConfig->getValue('installed', false) && !\OCP\Util::needUpgrade()) { // NOTE: This will be replaced to use OCP - $userSession = Server::get(IUserSession::class); + $userSession = Server::get(\OC\User\Session::class); $userSession->listen('\OC\User', 'postLogin', function () use ($userSession) { if (!defined('PHPUNIT_RUN') && $userSession->isLoggedIn()) { // reset brute force delay for this IP address and username $uid = $userSession->getUser()->getUID(); - $request = \OC::$server->getRequest(); - $throttler = \OC::$server->getBruteForceThrottler(); + $request = Server::get(\OCP\IRequest::class); + $throttler = Server::get(\OC\Security\Bruteforce\Throttler::class); $throttler->resetDelay($request->getRemoteAddress(), 'login', ['user' => $uid]); } @@ -875,7 +875,7 @@ class OC { } private static function registerEncryptionWrapperAndHooks(): void { - $manager = self::$server->getEncryptionManager(); + $manager = Server::get(\OCP\Encryption\IManager::class); \OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage'); $enabled = $manager->isEnabled(); @@ -948,7 +948,7 @@ class OC { $instanceId = $systemConfig->getValue('instanceid', null); if ($instanceId) { try { - $memcacheFactory = \OC::$server->getMemCacheFactory(); + $memcacheFactory = Server::get(\OCP\ICacheFactory::class); self::$loader->setMemoryCache($memcacheFactory->createLocal('Autoloader')); } catch (\Exception $ex) { } @@ -958,9 +958,9 @@ class OC { /** * Handle the request */ - public static function handleRequest() { - \OC::$server->getEventLogger()->start('handle_request', 'Handle request'); - $systemConfig = \OC::$server->getSystemConfig(); + public static function handleRequest(): void { + Server::get(\OCP\Diagnostics\IEventLogger::class)->start('handle_request', 'Handle request'); + $systemConfig = Server::get(\OC\SystemConfig::class); // Check if Nextcloud is installed or in maintenance (update) mode if (!$systemConfig->getValue('installed', false)) { @@ -971,7 +971,7 @@ class OC { Server::get(\OCP\L10N\IFactory::class)->get('lib'), Server::get(\OCP\Defaults::class), Server::get(\Psr\Log\LoggerInterface::class), - \OC::$server->getSecureRandom(), + Server::get(\OCP\Security\ISecureRandom::class), Server::get(\OC\Installer::class) ); $controller = new OC\Core\Controller\SetupController($setupHelper); @@ -979,7 +979,7 @@ class OC { exit(); } - $request = \OC::$server->getRequest(); + $request = Server::get(\OCP\IRequest::class); $requestPath = $request->getRawPathInfo(); if ($requestPath === '/heartbeat') { return; @@ -1001,7 +1001,6 @@ class OC { // emergency app disabling if ($requestPath === '/disableapp' && $request->getMethod() === 'POST' - && ((array)$request->getParam('appid')) !== '' ) { \OC_JSON::callCheck(); \OC_JSON::checkAdminUser(); @@ -1090,7 +1089,7 @@ class OC { } try { - return Server::get(\OC\Route\Router::class)->match('/error/404'); + Server::get(\OC\Route\Router::class)->match('/error/404'); } catch (\Exception $e) { logger('core')->emergency($e->getMessage(), ['exception' => $e]); $l = Server::get(\OCP\L10N\IFactory::class)->get('lib'); @@ -1106,7 +1105,7 @@ class OC { * Check login: apache auth, auth token, basic auth */ public static function handleLogin(OCP\IRequest $request): bool { - $userSession = Server::get(IUserSession::class); + $userSession = Server::get(\OC\User\Session::class); if (OC_User::handleApacheAuth()) { return true; } @@ -1119,7 +1118,7 @@ class OC { && $userSession->loginWithCookie($_COOKIE['nc_username'], $_COOKIE['nc_token'], $_COOKIE['nc_session_id'])) { return true; } - if ($userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) { + if ($userSession->tryBasicAuthLogin($request, Server::get(\OC\Security\Bruteforce\Throttler::class))) { return true; } return false; @@ -1137,7 +1136,7 @@ class OC { 'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative ]; foreach ($vars as $var) { - if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) { + if (isset($_SERVER[$var]) && is_string($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) { $credentials = explode(':', base64_decode($matches[1]), 2); if (count($credentials) === 2) { $_SERVER['PHP_AUTH_USER'] = $credentials[0]; From 26d75add8f48933538ec39419752bc94bfc078ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 29 Nov 2022 18:13:51 +0100 Subject: [PATCH 04/10] Put back cast to string now that timelimit is an int MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- lib/base.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/base.php b/lib/base.php index 49df9e87d24..b216ef86f9b 100644 --- a/lib/base.php +++ b/lib/base.php @@ -447,7 +447,7 @@ class OC { //try to set the session lifetime $sessionLifeTime = self::getSessionLifeTime(); - @ini_set('gc_maxlifetime', $sessionLifeTime); + @ini_set('gc_maxlifetime', (string)$sessionLifeTime); // session timeout if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) { From e1d324f7ebb311b1e0ed094ec13de43163d7cc68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 1 Dec 2022 11:21:57 +0100 Subject: [PATCH 05/10] Migrate lib/base.php to LoggerInterface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- lib/base.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/base.php b/lib/base.php index b216ef86f9b..751e6c305fb 100644 --- a/lib/base.php +++ b/lib/base.php @@ -78,6 +78,7 @@ use OCP\IUserSession; use OCP\Server; use OCP\Share; use OCP\User\Events\UserChangedEvent; +use Psr\Log\LoggerInterface; use function OCP\Log\logger; require_once 'public/Constants.php'; @@ -439,7 +440,7 @@ class OC { // if session can't be started break with http 500 error } catch (Exception $e) { - \OC::$server->getLogger()->logException($e, ['app' => 'base']); + Server::get(LoggerInterface::class)->error($e->getMessage(), ['app' => 'base','exception' => $e]); //show the user a detailed error page OC_Template::printExceptionErrorPage($e, 500); die(); @@ -810,8 +811,7 @@ class OC { if (!$isScssRequest) { http_response_code(400); - - \OC::$server->getLogger()->info( + Server::get(LoggerInterface::class)->info( 'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.', [ 'app' => 'core', @@ -864,10 +864,9 @@ class OC { } catch (\Exception $e) { // a GC exception should not prevent users from using OC, // so log the exception - \OC::$server->getLogger()->logException($e, [ - 'message' => 'Exception when running cache gc.', - 'level' => ILogger::WARN, + Server::get(LoggerInterface::class)->warning('Exception when running cache gc.', [ 'app' => 'core', + 'exception' => $e, ]); } }); From a529aa79d8136ec66db78f1b552940b7e374e12f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 1 Dec 2022 11:43:17 +0100 Subject: [PATCH 06/10] Strong type singletons from lib/base.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- lib/base.php | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/lib/base.php b/lib/base.php index 751e6c305fb..a847373ea2b 100644 --- a/lib/base.php +++ b/lib/base.php @@ -123,21 +123,13 @@ class OC { */ public static bool $CLI = false; - /** - * @var \OC\Autoloader - */ - public static $loader = null; + public static \OC\Autoloader $loader; - /** @var \Composer\Autoload\ClassLoader */ - public static $composerAutoloader = null; + public static \Composer\Autoload\ClassLoader $composerAutoloader; - /** @var \OC\Server */ - public static $server = null; + public static \OC\Server $server; - /** - * @var \OC\Config - */ - private static $config = null; + private static \OC\Config $config; /** * @throws \RuntimeException when the 3rdparty directory is missing or From 7996a12aef25b7ac8bd9a61f7b09f6806cef5ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 5 Dec 2022 16:40:46 +0100 Subject: [PATCH 07/10] Silence false-positive from psalm in lib/public/Log/functions.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- build/psalm-baseline.xml | 6 ------ lib/public/Log/functions.php | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index e77d3cbee80..b4162099598 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -1789,12 +1789,6 @@ getAppsNeedingUpgrade getIncompatibleApps - - $restrictions - - - ((array)$request->getParam('appid')) !== '' - diff --git a/lib/public/Log/functions.php b/lib/public/Log/functions.php index cc6961d8fba..ac043b4d958 100644 --- a/lib/public/Log/functions.php +++ b/lib/public/Log/functions.php @@ -49,6 +49,7 @@ use function class_exists; * @since 24.0.0 */ function logger(string $appId = null): LoggerInterface { + /** @psalm-suppress TypeDoesNotContainNull false-positive, it may contain null if we are logging from initialization */ if (!class_exists(OC::class) || OC::$server === null) { // If someone calls this log before Nextcloud is initialized, there is // no logging available. In that case we return a noop implementation From 3cce9aa547d44cdb9ead142bb792a67be789b0e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 1 Dec 2022 11:41:54 +0100 Subject: [PATCH 08/10] Just use string for groups in enableAppForGroups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- lib/private/App/AppManager.php | 16 ++++------------ lib/public/App/IAppManager.php | 7 +++---- lib/public/App/ManagerEvent.php | 21 +++++++++------------ 3 files changed, 16 insertions(+), 28 deletions(-) diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index 6d2fe51d0ed..3b352001dac 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -52,7 +52,6 @@ use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; class AppManager implements IAppManager { - /** * Apps with these types can not be enabled for certain groups only * @var string[] @@ -184,7 +183,7 @@ class AppManager implements IAppManager { /** * @param string $appId - * @return array + * @return string[] */ public function getAppRestriction(string $appId): array { $values = $this->getInstalledAppsValues(); @@ -346,7 +345,7 @@ class AppManager implements IAppManager { * Enable an app only for specific groups * * @param string $appId - * @param \OCP\IGroup[] $groups + * @param string[] $groups * @param bool $forceEnable * @throws \InvalidArgumentException if app can't be enabled for groups * @throws AppPathNotFoundException @@ -364,15 +363,8 @@ class AppManager implements IAppManager { $this->ignoreNextcloudRequirementForApp($appId); } - $groupIds = array_map(function ($group) { - /** @var \OCP\IGroup $group */ - return ($group instanceof IGroup) - ? $group->getGID() - : $group; - }, $groups); - - $this->installedAppsCache[$appId] = json_encode($groupIds); - $this->appConfig->setValue($appId, 'enabled', json_encode($groupIds)); + $this->installedAppsCache[$appId] = json_encode($groups); + $this->appConfig->setValue($appId, 'enabled', json_encode($groups)); $this->dispatcher->dispatch(ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, new ManagerEvent( ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, $appId, $groups )); diff --git a/lib/public/App/IAppManager.php b/lib/public/App/IAppManager.php index f7c9d848099..764b3b0a5b5 100644 --- a/lib/public/App/IAppManager.php +++ b/lib/public/App/IAppManager.php @@ -42,7 +42,6 @@ use OCP\IUser; * @since 8.0.0 */ interface IAppManager { - /** * Returns the app information from "appinfo/info.xml". * @@ -117,7 +116,7 @@ interface IAppManager { * Enable an app only for specific groups * * @param string $appId - * @param \OCP\IGroup[] $groups + * @param string[] $groups * @param bool $forceEnable * @throws \Exception * @since 8.0.0 @@ -197,13 +196,13 @@ interface IAppManager { /** * @param \OCP\IGroup $group - * @return String[] + * @return string[] * @since 17.0.0 */ public function getEnabledAppsForGroup(IGroup $group): array; /** - * @param String $appId + * @param string $appId * @return string[] * @since 17.0.0 */ diff --git a/lib/public/App/ManagerEvent.php b/lib/public/App/ManagerEvent.php index 0069e57db42..9f2ef58b21d 100644 --- a/lib/public/App/ManagerEvent.php +++ b/lib/public/App/ManagerEvent.php @@ -53,21 +53,21 @@ class ManagerEvent extends Event { public const EVENT_APP_UPDATE = 'OCP\App\IAppManager::updateApp'; /** @var string */ - protected $event; + protected string $event; /** @var string */ - protected $appID; - /** @var \OCP\IGroup[]|null */ - protected $groups; + protected string $appID; + /** @var string[]|null */ + protected ?array $groups; /** * DispatcherEvent constructor. * * @param string $event - * @param $appID - * @param \OCP\IGroup[]|null $groups + * @param string $appID + * @param string[]|null $groups * @since 9.0.0 */ - public function __construct($event, $appID, array $groups = null) { + public function __construct($event, $appID, ?array $groups = null) { $this->event = $event; $this->appID = $appID; $this->groups = $groups; @@ -91,13 +91,10 @@ class ManagerEvent extends Event { /** * returns the group Ids - * @return string[] + * @return string[]|null * @since 9.0.0 */ public function getGroups() { - return array_map(function ($group) { - /** @var \OCP\IGroup $group */ - return $group->getGID(); - }, $this->groups); + return $this->groups; } } From a1301de7fa5cb2d4ac2a894689cb22cb5c8f494e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 6 Dec 2022 12:09:52 +0100 Subject: [PATCH 09/10] Revert "Just use string for groups in enableAppForGroups" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e17244e92fb316d2f2e3fd1ae343bd47b54395b8. Signed-off-by: Côme Chilliet --- lib/private/App/AppManager.php | 16 ++++++++++++---- lib/public/App/IAppManager.php | 7 ++++--- lib/public/App/ManagerEvent.php | 21 ++++++++++++--------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index 3b352001dac..6d2fe51d0ed 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -52,6 +52,7 @@ use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; class AppManager implements IAppManager { + /** * Apps with these types can not be enabled for certain groups only * @var string[] @@ -183,7 +184,7 @@ class AppManager implements IAppManager { /** * @param string $appId - * @return string[] + * @return array */ public function getAppRestriction(string $appId): array { $values = $this->getInstalledAppsValues(); @@ -345,7 +346,7 @@ class AppManager implements IAppManager { * Enable an app only for specific groups * * @param string $appId - * @param string[] $groups + * @param \OCP\IGroup[] $groups * @param bool $forceEnable * @throws \InvalidArgumentException if app can't be enabled for groups * @throws AppPathNotFoundException @@ -363,8 +364,15 @@ class AppManager implements IAppManager { $this->ignoreNextcloudRequirementForApp($appId); } - $this->installedAppsCache[$appId] = json_encode($groups); - $this->appConfig->setValue($appId, 'enabled', json_encode($groups)); + $groupIds = array_map(function ($group) { + /** @var \OCP\IGroup $group */ + return ($group instanceof IGroup) + ? $group->getGID() + : $group; + }, $groups); + + $this->installedAppsCache[$appId] = json_encode($groupIds); + $this->appConfig->setValue($appId, 'enabled', json_encode($groupIds)); $this->dispatcher->dispatch(ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, new ManagerEvent( ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, $appId, $groups )); diff --git a/lib/public/App/IAppManager.php b/lib/public/App/IAppManager.php index 764b3b0a5b5..f7c9d848099 100644 --- a/lib/public/App/IAppManager.php +++ b/lib/public/App/IAppManager.php @@ -42,6 +42,7 @@ use OCP\IUser; * @since 8.0.0 */ interface IAppManager { + /** * Returns the app information from "appinfo/info.xml". * @@ -116,7 +117,7 @@ interface IAppManager { * Enable an app only for specific groups * * @param string $appId - * @param string[] $groups + * @param \OCP\IGroup[] $groups * @param bool $forceEnable * @throws \Exception * @since 8.0.0 @@ -196,13 +197,13 @@ interface IAppManager { /** * @param \OCP\IGroup $group - * @return string[] + * @return String[] * @since 17.0.0 */ public function getEnabledAppsForGroup(IGroup $group): array; /** - * @param string $appId + * @param String $appId * @return string[] * @since 17.0.0 */ diff --git a/lib/public/App/ManagerEvent.php b/lib/public/App/ManagerEvent.php index 9f2ef58b21d..0069e57db42 100644 --- a/lib/public/App/ManagerEvent.php +++ b/lib/public/App/ManagerEvent.php @@ -53,21 +53,21 @@ class ManagerEvent extends Event { public const EVENT_APP_UPDATE = 'OCP\App\IAppManager::updateApp'; /** @var string */ - protected string $event; + protected $event; /** @var string */ - protected string $appID; - /** @var string[]|null */ - protected ?array $groups; + protected $appID; + /** @var \OCP\IGroup[]|null */ + protected $groups; /** * DispatcherEvent constructor. * * @param string $event - * @param string $appID - * @param string[]|null $groups + * @param $appID + * @param \OCP\IGroup[]|null $groups * @since 9.0.0 */ - public function __construct($event, $appID, ?array $groups = null) { + public function __construct($event, $appID, array $groups = null) { $this->event = $event; $this->appID = $appID; $this->groups = $groups; @@ -91,10 +91,13 @@ class ManagerEvent extends Event { /** * returns the group Ids - * @return string[]|null + * @return string[] * @since 9.0.0 */ public function getGroups() { - return $this->groups; + return array_map(function ($group) { + /** @var \OCP\IGroup $group */ + return $group->getGID(); + }, $this->groups); } } From 585cf0022c589f85c05de67e82f0234f77dd9dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 6 Dec 2022 15:21:28 +0100 Subject: [PATCH 10/10] Put back baseline for the enableAppForGroups type mismatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- build/psalm-baseline.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index b4162099598..fce42b059b5 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -1789,6 +1789,9 @@ getAppsNeedingUpgrade getIncompatibleApps + + $restrictions +