From cb333e553c1af7aec1e5f5d1883975070a57795d Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Sun, 30 Aug 2026 12:56:36 +0200 Subject: [PATCH 1/2] fix(users): compare IUser and IGroup against null, not false `IUserManager::get()`, `IGroupManager::get()` and `createGroup()` all return `?IUser` / `?IGroup`. They never return `false`. Nine guards compared against `false`, so the comparison was ALWAYS true and the guard never fired -- a missing user fell straight through to $user->isEnabled() // on null $group->inGroup($user) // on null which is a fatal, not a skipped iteration. The activate/deactivate loops walk usernames read out of contact-person objects, so any username that no longer resolves to an account crashes the whole sweep instead of passing over that one entry. PHPStan flagged four of these (StackiqService 2271, 2281, 2379, 2389). Fixing only those would have left five identical defects in place that it happens not to narrow -- StackiqService 2095 and 2187, and ContactPersonHandler 790, 916 and 1417. All nine are the same class and all nine are fixed here. Also drops two dead comparisons in OrganizationHandler: `getLastLogin()` returns `int`, so `!== null` and `!== false` after `!== 0` can never be anything but true. Behaviour is unchanged; the `!== 0` test is the only one that ever did anything. Verified locally on the same commit CI failed on (deb9fa7a): before: exit 1, "[ERROR] Found 9 errors" after: exit 0, "[OK] No errors" --- lib/Service/Stackiq/ContactPersonHandler.php | 6 +++--- lib/Service/Stackiq/OrganizationHandler.php | 4 ++-- lib/Service/StackiqService.php | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/Service/Stackiq/ContactPersonHandler.php b/lib/Service/Stackiq/ContactPersonHandler.php index 1bbd2601..d07ecd80 100644 --- a/lib/Service/Stackiq/ContactPersonHandler.php +++ b/lib/Service/Stackiq/ContactPersonHandler.php @@ -787,7 +787,7 @@ private function addUserToGroup(\OCP\IUser $user, string $groupName, string $typ } } - if ($group !== false && $group->inGroup($user) === false) { + if ($group !== null && $group->inGroup($user) === false) { $group->addUser($user); $this->_logger->info( 'Added user to group', @@ -913,7 +913,7 @@ public function updateUserGroupsFromContactData(\OCP\IUser $user, array $contact foreach ($allPossibleRoleGroups as $roleGroup) { if ($roleGroup !== $newRoleGroup) { $group = $this->_groupManager->get($roleGroup); - if ($group !== false && $group->inGroup($user) === true) { + if ($group !== null && $group->inGroup($user) === true) { $group->removeUser($user); $this->_logger->info( 'Removed user from old organization type role group', @@ -1414,7 +1414,7 @@ public function assignBeheerderRole(object $contactPersonObject, string $usernam if (empty($maintainerGroup) === false) { $user = $this->_userManager->get($username); - if ($user !== false && $maintainerGroup->inGroup($user) === false) { + if ($user !== null && $maintainerGroup->inGroup($user) === false) { $maintainerGroup->addUser($user); } } diff --git a/lib/Service/Stackiq/OrganizationHandler.php b/lib/Service/Stackiq/OrganizationHandler.php index 3901015f..af63c2fc 100644 --- a/lib/Service/Stackiq/OrganizationHandler.php +++ b/lib/Service/Stackiq/OrganizationHandler.php @@ -699,7 +699,7 @@ function ($a, $b) { $timeA = 0; if ($userA !== null) { $lastLoginA = $userA->getLastLogin(); - if ($lastLoginA !== 0 && $lastLoginA !== null && $lastLoginA !== false) { + if ($lastLoginA !== 0) { $timeA = (int)$lastLoginA; } } @@ -707,7 +707,7 @@ function ($a, $b) { $timeB = 0; if ($userB !== null) { $lastLoginB = $userB->getLastLogin(); - if ($lastLoginB !== 0 && $lastLoginB !== null && $lastLoginB !== false) { + if ($lastLoginB !== 0) { $timeB = (int)$lastLoginB; } } diff --git a/lib/Service/StackiqService.php b/lib/Service/StackiqService.php index 42e4f461..7fa7bcc4 100644 --- a/lib/Service/StackiqService.php +++ b/lib/Service/StackiqService.php @@ -2092,7 +2092,7 @@ private function activateUsersForOrganization(string $organizationUuid): void { if (empty($username) === false) { $user = $userManager->get($username); - if ($user !== false && $user->isEnabled() === false) { + if ($user !== null && $user->isEnabled() === false) { $user->setEnabled(true); $activatedCount++; @@ -2184,7 +2184,7 @@ private function deactivateUsersForOrganization(string $organizationUuid): void if (empty($username) === false) { $user = $userManager->get($username); - if ($user !== false && $user->isEnabled() === true) { + if ($user !== null && $user->isEnabled() === true) { $user->setEnabled(false); $deactivatedCount++; @@ -2268,7 +2268,7 @@ private function activateStackiqUsersForOrganization(string $organizationUuid): foreach ($softwareCatalogUsers as $username) { try { $user = $userManager->get($username); - if ($user !== false && $user->isEnabled() === false) { + if ($user !== null && $user->isEnabled() === false) { $user->setEnabled(true); $activatedUsers[] = $username; $this->_logger->debug( @@ -2278,7 +2278,7 @@ private function activateStackiqUsersForOrganization(string $organizationUuid): 'username' => $username, ] ); - } elseif ($user !== false && $user->isEnabled() === true) { + } elseif ($user !== null && $user->isEnabled() === true) { $this->_logger->debug( 'StackiqService: Stackiq user already active', [ @@ -2376,7 +2376,7 @@ private function deactivateStackiqUsersForOrganization(string $organizationUuid) foreach ($softwareCatalogUsers as $username) { try { $user = $userManager->get($username); - if ($user !== false && $user->isEnabled() === true) { + if ($user !== null && $user->isEnabled() === true) { $user->setEnabled(false); $deactivatedUsers[] = $username; $this->_logger->debug( @@ -2386,7 +2386,7 @@ private function deactivateStackiqUsersForOrganization(string $organizationUuid) 'username' => $username, ] ); - } elseif ($user !== false && $user->isEnabled() === false) { + } elseif ($user !== null && $user->isEnabled() === false) { $this->_logger->debug( 'StackiqService: Stackiq user already inactive', [ From 9d6efac84ce78afd6e5ea891c2105728e7cdb964 Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Sun, 30 Aug 2026 12:59:38 +0200 Subject: [PATCH 2/2] fix(deps): take typescript 6, because typescript-eslint cannot parse TS 7 `Vue Quality (eslint)` has been red on development since 07:59 today, when #812 bumped typescript 5.9.3 -> 7.0.2. ESLint does not report lint findings; it refuses to start: Error: typescript-eslint does not support TS 7.0. at node_modules/typescript-eslint/dist/index.js:52:11 So the whole `eslint src` run aborts and nothing in src/ is linted at all. Upstream tracks TS >= 7.1 support in typescript-eslint#10940; it is not released. 6.0.3 is the newest release typescript-eslint can parse, so the app keeps a current compiler rather than being pinned back to the 5.x line it came from. Reverting to 5.9.3 would also work and gives up more. thematiq took the same bump and is unaffected -- its lint script is the literal no-op `echo 'No JavaScript to lint - thematiq is CSS/PHP only'`, so nothing there ever loads typescript-eslint. Those are the only two fleet apps on TS 7, so this is the single instance. Verified locally on deb9fa7a: typescript 7.0.2 -> exit 1, "does not support TS 7.0", 0 files linted typescript 6.0.3 -> exit 0, 217 problems (0 errors, 217 warnings) --- package-lock.json | 375 +--------------------------------------------- package.json | 2 +- 2 files changed, 8 insertions(+), 369 deletions(-) diff --git a/package-lock.json b/package-lock.json index 14afac51..4ef38073 100644 --- a/package-lock.json +++ b/package-lock.json @@ -88,7 +88,7 @@ "stylelint-webpack-plugin": "^5.0.1", "ts-jest": "^29.2.3", "ts-loader": "^9.5.1", - "typescript": "^7.0.2", + "typescript": "^6.0.3", "vitest": "^3.2.7", "vue-eslint-parser": "^10.3.0" }, @@ -7004,346 +7004,6 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript/typescript-aix-ppc64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", - "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-darwin-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", - "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-darwin-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", - "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-freebsd-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", - "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-freebsd-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", - "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-arm": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", - "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", - "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-loong64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", - "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-mips64el": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", - "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-ppc64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", - "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-riscv64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", - "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-s390x": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", - "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", - "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-netbsd-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", - "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-netbsd-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", - "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-openbsd-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", - "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-openbsd-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", - "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-sunos-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", - "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-win32-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", - "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-win32-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", - "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=16.20.0" - } - }, "node_modules/@uiw/codemirror-theme-github": { "version": "4.25.11", "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-github/-/codemirror-theme-github-4.25.11.tgz", @@ -21987,38 +21647,17 @@ } }, "node_modules/typescript": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", - "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "license": "Apache-2.0", "bin": { - "tsc": "bin/tsc" + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">=16.20.0" - }, - "optionalDependencies": { - "@typescript/typescript-aix-ppc64": "7.0.2", - "@typescript/typescript-darwin-arm64": "7.0.2", - "@typescript/typescript-darwin-x64": "7.0.2", - "@typescript/typescript-freebsd-arm64": "7.0.2", - "@typescript/typescript-freebsd-x64": "7.0.2", - "@typescript/typescript-linux-arm": "7.0.2", - "@typescript/typescript-linux-arm64": "7.0.2", - "@typescript/typescript-linux-loong64": "7.0.2", - "@typescript/typescript-linux-mips64el": "7.0.2", - "@typescript/typescript-linux-ppc64": "7.0.2", - "@typescript/typescript-linux-riscv64": "7.0.2", - "@typescript/typescript-linux-s390x": "7.0.2", - "@typescript/typescript-linux-x64": "7.0.2", - "@typescript/typescript-netbsd-arm64": "7.0.2", - "@typescript/typescript-netbsd-x64": "7.0.2", - "@typescript/typescript-openbsd-arm64": "7.0.2", - "@typescript/typescript-openbsd-x64": "7.0.2", - "@typescript/typescript-sunos-x64": "7.0.2", - "@typescript/typescript-win32-arm64": "7.0.2", - "@typescript/typescript-win32-x64": "7.0.2" + "node": ">=14.17" } }, "node_modules/typescript-eslint": { diff --git a/package.json b/package.json index 2ef4d44c..57f650fc 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "stylelint-webpack-plugin": "^5.0.1", "ts-jest": "^29.2.3", "ts-loader": "^9.5.1", - "typescript": "^7.0.2", + "typescript": "^6.0.3", "vitest": "^3.2.7", "vue-eslint-parser": "^10.3.0" },