diff --git a/lib/GroupBackend.php b/lib/GroupBackend.php index 522f8dda4..a758c58aa 100644 --- a/lib/GroupBackend.php +++ b/lib/GroupBackend.php @@ -23,6 +23,7 @@ use OCP\Group\Backend\ISearchableGroupBackend; use OCP\Group\Backend\ISetDisplayNameBackend; use OCP\IDBConnection; +use OCP\IUser; use OCP\IUserManager; use OCP\Server; use PDO; @@ -428,8 +429,8 @@ public function getGroupsDetails(array $gids): array { return $details; } - public function setupSearchQuery(string $search, IQueryBuilder $query): void { - if ($search !== '') { + public function setupSearchQuery(string $search, IQueryBuilder $query, bool $includeMetadata = false): void { + if ($includeMetadata || $search !== '') { $query->leftJoin('m', 'accounts_data', 'dn', $query->expr()->andX( $query->expr()->eq('dn.uid', 'm.uid'), @@ -442,7 +443,9 @@ public function setupSearchQuery(string $search, IQueryBuilder $query): void { $query->expr()->eq('em.name', $query->createNamedParameter('email')) ) ); + } + if ($search !== '') { $searchParam1 = $query->createNamedParameter('%' . $this->dbc->escapeLikeParameter($search) . '%'); $searchParam2 = $query->createNamedParameter('%' . $this->dbc->escapeLikeParameter($search) . '%'); $searchParam3 = $query->createNamedParameter('%' . $this->dbc->escapeLikeParameter($search) . '%'); @@ -464,36 +467,7 @@ public function searchInGroup(string $gid, string $search = '', int $limit = -1, ->where($query->expr()->eq('gid', $query->createNamedParameter($gid))) ->orderBy('g.uid', 'ASC'); - // Join displayname and email from oc_accounts_data - $query->leftJoin('g', 'accounts_data', 'dn', - $query->expr()->andX( - $query->expr()->eq('dn.uid', 'g.uid'), - $query->expr()->eq('dn.name', $query->expr()->literal('displayname')) - ) - ); - - $query->leftJoin('g', 'accounts_data', 'em', - $query->expr()->andX( - $query->expr()->eq('em.uid', 'g.uid'), - $query->expr()->eq('em.name', $query->expr()->literal('email')) - ) - ); - - if ($search !== '') { - // sqlite doesn't like re-using a single named parameter here - $searchParam1 = $query->createNamedParameter('%' . $this->dbc->escapeLikeParameter($search) . '%'); - $searchParam2 = $query->createNamedParameter('%' . $this->dbc->escapeLikeParameter($search) . '%'); - $searchParam3 = $query->createNamedParameter('%' . $this->dbc->escapeLikeParameter($search) . '%'); - - $query->andWhere( - $query->expr()->orX( - $query->expr()->ilike('g.uid', $searchParam1), - $query->expr()->ilike('dn.value', $searchParam2), - $query->expr()->ilike('em.value', $searchParam3) - ) - ) - ->orderBy('g.uid', 'ASC'); - } + $this->setupSearchQuery($search, $query, includeMetadata: true); if ($limit !== -1) { $query->setMaxResults($limit); @@ -507,11 +481,14 @@ public function searchInGroup(string $gid, string $search = '', int $limit = -1, $users = []; $userManager = Server::get(IUserManager::class); while ($row = $result->fetch()) { + /** @psalm-suppress RedundantConditionGivenDocblockType */ if (method_exists($userManager, 'getExistingUser')) { - $users[$row['uid']] = $userManager->getExistingUser($row['uid'], $row['displayname'] ?? null); + $users[(string)$row['uid']] = $userManager->getExistingUser($row['uid'], $row['displayname'] ?? null); } else { /** @psalm-suppress UndefinedClass */ - $users[$row['uid']] = new LazyUser($row['uid'], $userManager, $row['displayname'] ?? null); + $user = new LazyUser($row['uid'], $userManager, $row['displayname'] ?? null); + /** @var IUser $user */ + $users[(string)$row['uid']] = $user; } } $result->closeCursor(); diff --git a/lib/UserBackend.php b/lib/UserBackend.php index c71eb7324..eb797cf8b 100644 --- a/lib/UserBackend.php +++ b/lib/UserBackend.php @@ -262,23 +262,19 @@ public function isSessionActive(): bool { return $this->session->get(SessionData::KEY_IDENTITY_PROVIDER_ID) !== null; } + /** @psalm-suppress LessSpecificImplementedReturnType */ #[Override] public function getLogoutUrl(): string { $id = $this->settings->getProviderId(); $settings = $this->settings->get($id); $slo = $settings['idp-singleLogoutService.url'] ?? ''; - - if ($slo === '') { - return ''; - } - $tokenManager = Server::get(CsrfTokenManager::class); - return $this->urlGenerator->linkToRouteAbsolute( - 'user_saml.SAML.singleLogoutService', - [ - 'requesttoken' => $tokenManager->getToken()->getEncryptedValue(), - ] - ); + + $logoutUrl = $this->urlGenerator->linkToRouteAbsolute($slo === '' ? 'core.login.logout' : 'user_saml.SAML.singleLogoutService', [ + 'requesttoken' => $tokenManager->getToken()->getEncryptedValue(), + ]); + /** @var non-empty-string $logoutUrl */ + return $logoutUrl; } /** diff --git a/tests/integration/composer.json b/tests/integration/composer.json index 1fb64ff1c..ae12eb229 100644 --- a/tests/integration/composer.json +++ b/tests/integration/composer.json @@ -9,7 +9,7 @@ }, "require-dev": { "behat/behat": "^3.3", - "guzzlehttp/guzzle": "^7.0" + "guzzlehttp/guzzle": "^8.0" }, "conflict": { "psr/container": ">=1.1" diff --git a/tests/integration/composer.lock b/tests/integration/composer.lock index bec1ebc08..1f1b04875 100644 --- a/tests/integration/composer.lock +++ b/tests/integration/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0790f547feacc83c12ade22c943855c3", + "content-hash": "1b90f680988090a4b533787a6cc8e7c7", "packages": [], "packages-dev": [ { @@ -207,26 +207,27 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.15.1", + "version": "8.0.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "61443dfb33c62f308ee8add20f45b4d6e4bf8d2f" + "reference": "643356760d8efce521dfce2587d63fd9d0c70d72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/61443dfb33c62f308ee8add20f45b4d6e4bf8d2f", - "reference": "61443dfb33c62f308ee8add20f45b4d6e4bf8d2f", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/643356760d8efce521dfce2587d63fd9d0c70d72", + "reference": "643356760d8efce521dfce2587d63fd9d0c70d72", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^2.5.1", - "guzzlehttp/psr7": "^2.13", - "php": "^7.2.5 || ^8.0", + "guzzlehttp/promises": "^3.0", + "guzzlehttp/psr7": "^3.0", + "php": "^7.4 || ^8.0", "psr/http-client": "^1.0", - "symfony/deprecation-contracts": "^2.5 || ^3.0", - "symfony/polyfill-php80": "^1.25" + "psr/http-factory": "^1.0", + "symfony/polyfill-php80": "^1.25", + "symfony/polyfill-php82": "^1.27" }, "provide": { "psr/http-client-implementation": "1.0" @@ -234,10 +235,10 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "guzzle/client-integration-tests": "3.0.3", - "guzzlehttp/test-server": "^0.7", + "guzzle/client-integration-tests": "4.0.1", + "guzzlehttp/test-server": "^1.0@dev", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.52 || ^9.6.34", + "phpunit/phpunit": "^9.6.34", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -253,9 +254,6 @@ } }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { "GuzzleHttp\\": "src/" } @@ -315,7 +313,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.15.1" + "source": "https://github.com/guzzle/guzzle/tree/8.0.0" }, "funding": [ { @@ -331,29 +329,28 @@ "type": "tidelift" } ], - "time": "2026-07-18T11:23:11+00:00" + "time": "2026-07-20T13:53:10+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.5.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "9ad1e4fc607446a055b95870c7f668e93b5cff29" + "reference": "d961a21387cd680ec1cc6f52aa1fdcef33105e24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/9ad1e4fc607446a055b95870c7f668e93b5cff29", - "reference": "9ad1e4fc607446a055b95870c7f668e93b5cff29", + "url": "https://api.github.com/repos/guzzle/promises/zipball/d961a21387cd680ec1cc6f52aa1fdcef33105e24", + "reference": "d961a21387cd680ec1cc6f52aa1fdcef33105e24", "shasum": "" }, "require": { - "php": "^7.2.5 || ^8.0", - "symfony/deprecation-contracts": "^2.5 || ^3.0" + "php": "^7.4 || ^8.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.52 || ^9.6.34" + "phpunit/phpunit": "^9.6.34" }, "type": "library", "extra": { @@ -399,7 +396,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.5.1" + "source": "https://github.com/guzzle/promises/tree/3.0.0" }, "funding": [ { @@ -415,39 +412,39 @@ "type": "tidelift" } ], - "time": "2026-07-08T15:48:39+00:00" + "time": "2026-07-20T13:44:17+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.13.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "dad89620b7a6edb60c15858442eb2e408b45d8f4" + "reference": "b094ded77ee97a6027ad6cf0e8c7b9f88381814c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/dad89620b7a6edb60c15858442eb2e408b45d8f4", - "reference": "dad89620b7a6edb60c15858442eb2e408b45d8f4", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/b094ded77ee97a6027ad6cf0e8c7b9f88381814c", + "reference": "b094ded77ee97a6027ad6cf0e8c7b9f88381814c", "shasum": "" }, "require": { - "php": "^7.2.5 || ^8.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.1 || ^2.0", - "ralouphie/getallheaders": "^3.0", - "symfony/deprecation-contracts": "^2.5 || ^3.0", - "symfony/polyfill-php80": "^1.25" + "php": "^7.4 || ^8.0", + "psr/http-factory": "^1.1", + "psr/http-message": "^2.0", + "symfony/polyfill-php80": "^1.25", + "symfony/polyfill-php82": "^1.27" }, "provide": { - "psr/http-factory-implementation": "1.0", - "psr/http-message-implementation": "1.0" + "psr/http-factory-implementation": "1.1", + "psr/http-message-implementation": "2.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "1.1.0", "jshttp/mime-db": "1.54.0.1", - "phpunit/phpunit": "^8.5.52 || ^9.6.34" + "php-http/psr7-integration-tests": "^1.5.1", + "phpunit/phpunit": "^9.6.34" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -518,7 +515,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.13.0" + "source": "https://github.com/guzzle/psr7/tree/3.0.0" }, "funding": [ { @@ -534,7 +531,7 @@ "type": "tidelift" } ], - "time": "2026-07-16T22:23:49+00:00" + "time": "2026-07-20T13:48:31+00:00" }, { "name": "psr/container", @@ -799,50 +796,6 @@ }, "time": "2023-04-04T09:54:51+00:00" }, - { - "name": "ralouphie/getallheaders", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "120b605dfeb996808c31b6477290a714d356e822" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", - "reference": "120b605dfeb996808c31b6477290a714d356e822", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "require-dev": { - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^5 || ^6.5" - }, - "type": "library", - "autoload": { - "files": [ - "src/getallheaders.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" - } - ], - "description": "A polyfill for getallheaders.", - "support": { - "issues": "https://github.com/ralouphie/getallheaders/issues", - "source": "https://github.com/ralouphie/getallheaders/tree/develop" - }, - "time": "2019-03-08T08:55:37+00:00" - }, { "name": "symfony/config", "version": "v5.4.45", @@ -1964,6 +1917,86 @@ ], "time": "2024-09-09T11:45:10+00:00" }, + { + "name": "symfony/polyfill-php82", + "version": "v1.38.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php82.git", + "reference": "002dc0cfe5fd4ed6033d48f27d4f19a486c4b04b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php82/zipball/002dc0cfe5fd4ed6033d48f27d4f19a486c4b04b", + "reference": "002dc0cfe5fd4ed6033d48f27d4f19a486c4b04b", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php82\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php82/tree/v1.38.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-05-26T12:45:58+00:00" + }, { "name": "symfony/service-contracts", "version": "v2.2.0", diff --git a/tests/integration/features/bootstrap/FeatureContext.php b/tests/integration/features/bootstrap/FeatureContext.php index 746778eba..82f1b1607 100644 --- a/tests/integration/features/bootstrap/FeatureContext.php +++ b/tests/integration/features/bootstrap/FeatureContext.php @@ -460,7 +460,7 @@ public function theGroupHasExactlyTheMembers(string $group, string $memberList): 'admin', 'admin' ], - 'cookies' => '', + 'cookies' => false, ] );