From 86fb93bc39a14e78440c976a6ec7fed8f31f0378 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Thu, 7 May 2026 12:27:15 +0545 Subject: [PATCH 1/8] fix: provide required file parent param Signed-off-by: Saw-jan --- lib/Controller/FilesController.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/Controller/FilesController.php b/lib/Controller/FilesController.php index b7078928c..5ef4bae43 100644 --- a/lib/Controller/FilesController.php +++ b/lib/Controller/FilesController.php @@ -20,6 +20,7 @@ use OCP\Files\DavUtil; use OCP\Files\FileInfo; use OCP\Files\IRootFolder; +use OCP\Files\Node; use OCP\IDBConnection; use OCP\IRequest; use OCP\IUser; @@ -185,7 +186,7 @@ private function compileFileInfo($fileId) { // full path is in format `/files/a/b/` // since we don't want to send it with username, only get the `files/a/b` and send it $path = explode('/', $fullpath, 3); - $davPermission = $this->getDavPermissions($file); + $davPermission = $this->getDavPermissions($file, $file->getParent()); if ($file->getMimeType() === FileInfo::MIMETYPE_FOLDER) { $mimeType = 'application/x-op-directory'; $path = $path[2] . '/'; @@ -289,7 +290,7 @@ private function getLastModifier(string $ownerId, int $fileId, int $since = 0): // `davUtils->getDavPermissions` method is static so it cannot be mocked to // creating similar function here for testing purposes - public function getDavPermissions(FileInfo $info): string { - return $this->davUtils->getDavPermissions($info); + public function getDavPermissions(FileInfo $info, Node $parent): string { + return $this->davUtils->getDavPermissions($info, $parent); } } From d0ac313e8182f1a01dcbf1d4525e54385fbbebe2 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Thu, 7 May 2026 12:53:48 +0545 Subject: [PATCH 2/8] fix: use provided single nextcloud version as latest Signed-off-by: Saw-jan --- .github/scripts/generate-matrix.sh | 46 ++++++++++++++++-------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/.github/scripts/generate-matrix.sh b/.github/scripts/generate-matrix.sh index a0a714e70..9ff9816c7 100755 --- a/.github/scripts/generate-matrix.sh +++ b/.github/scripts/generate-matrix.sh @@ -78,27 +78,31 @@ if [ -n "$LATEST_STABLE_NC_VERSION" ]; then latestStableNCVersion="stable$latestStableNCVersion" fi else - # determine latest stable version from the list - # this only takes into account the major version number and stable branches - # e.g. 30, stable30 - for ncVersion in $nextcloudVersions; do - # parse the major version number from stable branch - # e.g. stable30 -> 30 - if [[ "$ncVersion" =~ ^stable[0-9]+$ ]]; then - ncVersion=${ncVersion//stable/} - fi - if ! [[ "$ncVersion" =~ ^[0-9]+$ ]]; then - continue - fi - if [ -z "$latestStableNCVersion" ]; then - latestStableNCVersion=$ncVersion - continue - fi - if [ "$ncVersion" -gt "$latestStableNCVersion" ]; then - latestStableNCVersion=$ncVersion - fi - done - latestStableNCVersion="stable$latestStableNCVersion" + if [ $(echo "$nextcloudVersions" | wc -w) -eq 1 ]; then + latestStableNCVersion="$nextcloudVersions" + else + # determine latest stable version from the list + # this only takes into account the major version number and stable branches + # e.g. 30, stable30 + for ncVersion in $nextcloudVersions; do + # parse the major version number from stable branch + # e.g. stable30 -> 30 + if [[ "$ncVersion" =~ ^stable[0-9]+$ ]]; then + ncVersion=${ncVersion//stable/} + fi + if ! [[ "$ncVersion" =~ ^[0-9]+$ ]]; then + continue + fi + if [ -z "$latestStableNCVersion" ]; then + latestStableNCVersion=$ncVersion + continue + fi + if [ "$ncVersion" -gt "$latestStableNCVersion" ]; then + latestStableNCVersion=$ncVersion + fi + done + latestStableNCVersion="stable$latestStableNCVersion" + fi fi MATRIX="" From 367fa9800fbc44a1baf09f655c6204d627cb2765 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Mon, 11 May 2026 17:48:54 +0545 Subject: [PATCH 3/8] fix: use method signature based on NC version Signed-off-by: Saw-jan --- lib/Controller/FilesController.php | 17 ++++++-- lib/ServerVersion.php | 44 ++++++++++++++++++++ tests/lib/Controller/FilesControllerTest.php | 5 ++- 3 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 lib/ServerVersion.php diff --git a/lib/Controller/FilesController.php b/lib/Controller/FilesController.php index 5ef4bae43..45f1bd9e5 100644 --- a/lib/Controller/FilesController.php +++ b/lib/Controller/FilesController.php @@ -11,6 +11,7 @@ use OCA\Activity\Data; use OCA\Activity\GroupHelperDisabled; use OCA\Activity\UserSettings; +use OCA\OpenProject\ServerVersion; use OCP\Activity\IManager; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; @@ -87,7 +88,8 @@ public function __construct(string $appName, IDBConnection $connection, LoggerInterface $logger, IUserManager $userManager, - DavUtil $davUtils + DavUtil $davUtils, + private ServerVersion $serverVersion, ) { parent::__construct($appName, $request); $this->user = $userSession->getUser(); @@ -186,7 +188,7 @@ private function compileFileInfo($fileId) { // full path is in format `/files/a/b/` // since we don't want to send it with username, only get the `files/a/b` and send it $path = explode('/', $fullpath, 3); - $davPermission = $this->getDavPermissions($file, $file->getParent()); + $davPermission = $this->getDavPermissions($file); if ($file->getMimeType() === FileInfo::MIMETYPE_FOLDER) { $mimeType = 'application/x-op-directory'; $path = $path[2] . '/'; @@ -290,7 +292,14 @@ private function getLastModifier(string $ownerId, int $fileId, int $since = 0): // `davUtils->getDavPermissions` method is static so it cannot be mocked to // creating similar function here for testing purposes - public function getDavPermissions(FileInfo $info, Node $parent): string { - return $this->davUtils->getDavPermissions($info, $parent); + public function getDavPermissions(Node $file): string { + // BREAKING CHANGE (Nextcloud 34): + // "getDavPermissions()" expects parent node as second parameter. + // See: https://github.com/nextcloud/server/pull/57374#issuecomment-4394748935 + if ($this->serverVersion->getMajorVersion() >= 34) { + /** @psalm-suppress TooManyArguments */ + return $this->davUtils->getDavPermissions($file, $file->getParent()); + } + return $this->davUtils->getDavPermissions($file); } } diff --git a/lib/ServerVersion.php b/lib/ServerVersion.php new file mode 100644 index 000000000..d24925ef6 --- /dev/null +++ b/lib/ServerVersion.php @@ -0,0 +1,44 @@ +getVersionString(); + } + + return $this->config->getSystemValueString('version', '0.0.0'); + } + + /** + * Get Nextcloud MAJOR version. + * + * @return string + */ + public function getMajorVersion(): string { + $versionString = $this->getVersion(); + return explode('.', $versionString)[0] ?? '0'; + } +} \ No newline at end of file diff --git a/tests/lib/Controller/FilesControllerTest.php b/tests/lib/Controller/FilesControllerTest.php index ba01f6eca..fd8d4fe6b 100644 --- a/tests/lib/Controller/FilesControllerTest.php +++ b/tests/lib/Controller/FilesControllerTest.php @@ -8,6 +8,7 @@ namespace OCA\OpenProject\Controller; +use OCA\OpenProject\ServerVersion; use OCP\Activity\IManager; use OCP\Files\Config\ICachedMountFileInfo; use OCP\Files\Config\IUserMountCache; @@ -900,6 +901,7 @@ private function createFilesController( $this->createMock(LoggerInterface::class), $this->createMock(IUserManager::class), $this->createMock(DavUtil::class), + $this->createMock(ServerVersion::class), ); return $controller; } @@ -950,7 +952,8 @@ public function getFilesControllerMock( $this->createMock(IDBConnection::class), $this->createMock(LoggerInterface::class), $this->createMock(IUserManager::class), - $davUtilsMock + $davUtilsMock, + $this->createMock(ServerVersion::class), ]) ->onlyMethods($onlyMethods) ->getMock(); From a2181809d839784d68a454703e408d5687efec97 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Tue, 12 May 2026 09:31:30 +0545 Subject: [PATCH 4/8] fix: php code style Signed-off-by: Saw-jan --- lib/Controller/FilesController.php | 1 + lib/ServerVersion.php | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/Controller/FilesController.php b/lib/Controller/FilesController.php index 45f1bd9e5..41ea1ff69 100644 --- a/lib/Controller/FilesController.php +++ b/lib/Controller/FilesController.php @@ -300,6 +300,7 @@ public function getDavPermissions(Node $file): string { /** @psalm-suppress TooManyArguments */ return $this->davUtils->getDavPermissions($file, $file->getParent()); } + /** @psalm-suppress TooFewArguments */ return $this->davUtils->getDavPermissions($file); } } diff --git a/lib/ServerVersion.php b/lib/ServerVersion.php index d24925ef6..f5b7170ac 100644 --- a/lib/ServerVersion.php +++ b/lib/ServerVersion.php @@ -1,4 +1,5 @@ getVersionString(); + return $serverVersion->getVersionString(); } - return $this->config->getSystemValueString('version', '0.0.0'); + return $this->config->getSystemValueString('version', '0.0.0'); } /** @@ -39,6 +39,6 @@ public function getVersion(): string { */ public function getMajorVersion(): string { $versionString = $this->getVersion(); - return explode('.', $versionString)[0] ?? '0'; + return explode('.', $versionString)[0] ?? '0'; } -} \ No newline at end of file +} From 3782cec1c056cd218852b2f9e1011b99239f69d8 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Tue, 12 May 2026 13:26:03 +0545 Subject: [PATCH 5/8] test: fix API tests Signed-off-by: Saw-jan --- .../api/getFileinfoByFileIDAPI.feature | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/acceptance/features/api/getFileinfoByFileIDAPI.feature b/tests/acceptance/features/api/getFileinfoByFileIDAPI.feature index 4a3271d48..d09470dc1 100644 --- a/tests/acceptance/features/api/getFileinfoByFileIDAPI.feature +++ b/tests/acceptance/features/api/getFileinfoByFileIDAPI.feature @@ -1203,11 +1203,11 @@ Feature: retrieve file information of a single file, using the file ID Examples: | share-permission | requester-dav-permissions | owner-dav-permissions | | all | SRGNVW | RGDNVW | - | read | SG | RGDNVW | - | read+share | SRG | RGDNVW | + | read | SGN? | RGDNVW | + | read+share | SRGN? | RGDNVW | | read+update | SGNVW | RGDNVW | | read+update+share | SRGNVW | RGDNVW | - | read+delete | SG | RGDNVW | + | read+delete | SGN? | RGDNVW | | read+delete+update | SGNVW | RGDNVW | @@ -1294,16 +1294,16 @@ Feature: retrieve file information of a single file, using the file ID Examples: | share-permission | requester-dav-permissions | owner-dav-permissions | | all | SRGDNVCK | RGDNVCK | - | read | SG | RGDNVCK | - | read+share | SRG | RGDNVCK | + | read | SGN? | RGDNVCK | + | read+share | SRGN? | RGDNVCK | | read+update | SGNV | RGDNVCK | | read+update+share | SRGNV | RGDNVCK | - | read+delete | SGD | RGDNVCK | + | read+delete | SGDN? | RGDNVCK | | read+delete+update | SGDNV | RGDNVCK | - | read+create | SGCK | RGDNVCK | + | read+create | SGN?CK | RGDNVCK | | read+create+update | SGNVCK | RGDNVCK | - | read+create+share | SRGCK | RGDNVCK | - | read+create+share+delete | SRGDCK | RGDNVCK | + | read+create+share | SRGN?CK | RGDNVCK | + | read+create+share+delete | SRGDN?CK | RGDNVCK | | read+create+update+delete | SGDNVCK | RGDNVCK | | read+create+update+share | SRGNVCK | RGDNVCK | From cfaefa7a0c75890bd66d1db73eca849953a44d36 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Mon, 18 May 2026 14:28:10 +0545 Subject: [PATCH 6/8] chore: fix return type Signed-off-by: Saw-jan --- lib/Service/OpenProjectAPIService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Service/OpenProjectAPIService.php b/lib/Service/OpenProjectAPIService.php index 5fd0a6bec..6b3316a77 100644 --- a/lib/Service/OpenProjectAPIService.php +++ b/lib/Service/OpenProjectAPIService.php @@ -1889,7 +1889,7 @@ public function getAppsName(string $appId): string { return Application::getDefaultAppName($appId); } - return $appInfo['name']; + return (string) $appInfo['name']; } /** From 9f5cf4ebbed1b6980c99a71afa26e30fe4f2b232 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Mon, 18 May 2026 14:50:18 +0545 Subject: [PATCH 7/8] test: fix test version expectation Signed-off-by: Saw-jan --- tests/acceptance/features/api/capabilities.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/acceptance/features/api/capabilities.feature b/tests/acceptance/features/api/capabilities.feature index cb084ed8d..42caed2f8 100644 --- a/tests/acceptance/features/api/capabilities.feature +++ b/tests/acceptance/features/api/capabilities.feature @@ -31,11 +31,11 @@ Feature: get capabilities of the app "properties": { "app_version": { "type": "string", - "pattern": "^\\d+\\.\\d+\\.\\d+(-\\w+.\\d+)?$" + "pattern": "^\\d+\\.\\d+\\.\\d+(-\\w+.\\d+|-\\w+)?$" }, "groupfolder_version": { "type": "string", - "pattern": "^\\d+\\.\\d+\\.\\d+(?:-\\w+.\\d+)?$" + "pattern": "^\\d+\\.\\d+\\.\\d+(-\\w+.\\d+|-\\w+)?$" }, "groupfolders_enabled": { "type": "boolean", From 8a60ea782c5374c8eacd5a92c75db5ba43c96a25 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Mon, 18 May 2026 15:04:12 +0545 Subject: [PATCH 8/8] ci: check server ready first Signed-off-by: Saw-jan --- .github/workflows/shared_workflow.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/shared_workflow.yml b/.github/workflows/shared_workflow.yml index ac03c1ddd..afe994f2e 100644 --- a/.github/workflows/shared_workflow.yml +++ b/.github/workflows/shared_workflow.yml @@ -299,18 +299,6 @@ jobs: min_coverage: '56' path: 'integration_openproject/server/apps/integration_openproject/coverage/php/lcov.info' - - name: Configure Nextcloud server - run: | - # Disable share rate limit protection - docker exec nextcloud /bin/bash -c 'occ config:system:set ratelimit.protection.enabled --value false --type bool' - # Enable apps - if [ "${{matrix.nextcloudVersion}}" == "master" ]; then - # enable app even if it is not compatible with the master branch - docker exec nextcloud /bin/bash -c 'occ a:e -f activity oidc user_oidc groupfolders integration_openproject' - else - docker exec nextcloud /bin/bash -c 'occ a:e activity oidc user_oidc groupfolders integration_openproject' - fi - - name: Wait for Nextcloud server to be ready run: | if ! timeout 5m bash -c ' @@ -323,6 +311,18 @@ jobs: exit 1 fi + - name: Configure Nextcloud server + run: | + # Disable share rate limit protection + docker exec nextcloud /bin/bash -c 'occ config:system:set ratelimit.protection.enabled --value false --type bool' + # Enable apps + if [ "${{matrix.nextcloudVersion}}" == "master" ]; then + # enable app even if it is not compatible with the master branch + docker exec nextcloud /bin/bash -c 'occ a:e -f activity oidc user_oidc groupfolders integration_openproject' + else + docker exec nextcloud /bin/bash -c 'occ a:e activity oidc user_oidc groupfolders integration_openproject' + fi + - name: API Tests env: NEXTCLOUD_BASE_URL: http://localhost