From 32f507c3bd4b12f144b2ba459e282507e14c6857 Mon Sep 17 00:00:00 2001 From: Sawjan Gurung Date: Wed, 8 Jul 2026 14:07:41 +0545 Subject: [PATCH] fix: incompatible AMPF with latest Nextcloud patches (#1097) Signed-off-by: Saw-jan --- CHANGELOG.md | 1 + lib/AppInfo/Application.php | 36 +++++++-------- lib/Listener/UserLoggedInEventListener.php | 45 +++++++++++++++++++ .../features/api/teamFolder.feature | 12 ++--- 4 files changed, 69 insertions(+), 25 deletions(-) create mode 100644 lib/Listener/UserLoggedInEventListener.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 13b4d3a8b..9e15ef697 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Fix: Do not create OAuth client while updating OIDC setup [#1077](https://github.com/nextcloud/integration_openproject/pull/1077) - Fix: Handle invalid boolean auth-method value [#1079](https://github.com/nextcloud/integration_openproject/pull/1079) - Fix: False integration setup status even after complete oauth setup [#1088](https://github.com/nextcloud/integration_openproject/pull/1088) +- Fix: Incompatible AMPF with the latest Nextcloud patch releases [#1098](https://github.com/nextcloud/integration_openproject/pull/1098) ## 3.1.0 - 2026-06-18 diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 30ce90f87..a9a161bd4 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -21,6 +21,7 @@ use OCA\OpenProject\Listener\OpenProjectReferenceListener; use OCA\OpenProject\Listener\TermsOfServiceEventListener; use OCA\OpenProject\Listener\UserChangedListener; +use OCA\OpenProject\Listener\UserLoggedInEventListener; use OCA\OpenProject\Reference\WorkPackageReferenceProvider; use OCA\OpenProject\Search\OpenProjectSearchProvider; use OCA\TermsOfService\Events\SignaturesResetEvent; @@ -32,7 +33,6 @@ use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\AppFramework\OCS\OCSBadRequestException; use OCP\Collaboration\Reference\RenderReferenceEvent; -use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Events\Node\BeforeNodeDeletedEvent; use OCP\Files\Events\Node\BeforeNodeRenamedEvent; use OCP\Group\Events\BeforeGroupDeletedEvent; @@ -46,6 +46,7 @@ use OCP\IUserSession; use OCP\User\Events\BeforeUserDeletedEvent; use OCP\User\Events\UserChangedEvent; +use OCP\User\Events\UserLoggedInEvent; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; @@ -117,18 +118,26 @@ public function register(IRegistrationContext $context): void { $context->registerSearchProvider(OpenProjectSearchProvider::class); // register sidebar tab - $context->registerEventListener( - LoadSidebar::class, - LoadSidebarScript::class - ); + $context->registerEventListener(LoadSidebar::class, LoadSidebarScript::class); $context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadAdditionalScriptsListener::class); - $context->registerEventListener( - BeforeNodeDeletedEvent::class, BeforeNodeInsideOpenProjectGroupfilderChangedListener::class + BeforeNodeDeletedEvent::class, + BeforeNodeInsideOpenProjectGroupfilderChangedListener::class, ); $context->registerEventListener( - BeforeNodeRenamedEvent::class, BeforeNodeInsideOpenProjectGroupfilderChangedListener::class + BeforeNodeRenamedEvent::class, + BeforeNodeInsideOpenProjectGroupfilderChangedListener::class, ); + $context->registerEventListener(BeforeUserDeletedEvent::class, BeforeUserDeletedListener::class); + $context->registerEventListener(BeforeGroupDeletedEvent::class, BeforeGroupDeletedListener::class); + $context->registerEventListener(UserChangedEvent::class, UserChangedListener::class); + $context->registerEventListener(UserLoggedInEvent::class, UserLoggedInEventListener::class); + $context->registerEventListener(AppEnableEvent::class, TermsOfServiceEventListener::class); + + /** @psalm-suppress InvalidArgument */ + $context->registerEventListener(SignaturesResetEvent::class, TermsOfServiceEventListener::class); + /** @psalm-suppress InvalidArgument */ + $context->registerEventListener(TermsCreatedEvent::class, TermsOfServiceEventListener::class); if (version_compare($this->config->getSystemValueString('version', '0.0.0'), '26.0.0', '>=')) { $context->registerReferenceProvider(WorkPackageReferenceProvider::class); @@ -141,17 +150,6 @@ public function register(IRegistrationContext $context): void { public function boot(IBootContext $context): void { $context->injectFn(Closure::fromCallable([$this, 'listenRemoveUserFromGroupRequest'])); $context->injectFn(Closure::fromCallable([$this, 'registerNavigation'])); - /** @var IEventDispatcher $dispatcher */ - $dispatcher = $context->getAppContainer()->get(IEventDispatcher::class); - $dispatcher->addServiceListener(BeforeUserDeletedEvent::class, BeforeUserDeletedListener::class); - $dispatcher->addServiceListener(BeforeGroupDeletedEvent::class, BeforeGroupDeletedListener::class); - $dispatcher->addServiceListener(UserChangedEvent::class, UserChangedListener::class); - /** @psalm-suppress InvalidArgument AppEnableEvent event is not in stable25 so making psalm not complain*/ - $dispatcher->addServiceListener(AppEnableEvent::class, TermsOfServiceEventListener::class); - /** @psalm-suppress InvalidArgument TermsCreatedEvent event is not yet registered in terms_of_service app, so making psalm not complain */ - $dispatcher->addServiceListener(TermsCreatedEvent::class, TermsOfServiceEventListener::class); - /** @psalm-suppress InvalidArgument SignaturesResetEvent event is not yet registered in terms_of_service app, so making psalm not complain*/ - $dispatcher->addServiceListener(SignaturesResetEvent::class, TermsOfServiceEventListener::class); } public function registerNavigation(IUserSession $userSession): void { diff --git a/lib/Listener/UserLoggedInEventListener.php b/lib/Listener/UserLoggedInEventListener.php new file mode 100644 index 000000000..c8758a159 --- /dev/null +++ b/lib/Listener/UserLoggedInEventListener.php @@ -0,0 +1,45 @@ + + */ +class UserLoggedInEventListener implements IEventListener { + public function __construct( + private ISession $session, + private ITimeFactory $timeFactory, + ) { + } + + /** + * @param UserLoggedInEvent $event + * + * @return void + */ + public function handle(Event $event): void { + if (!($event instanceof UserLoggedInEvent)) { + return; + } + + if ($event->getUid() === Application::OPEN_PROJECT_ENTITIES_NAME && $event->isTokenLogin()) { + // set the last-password-confirm session variable to allow OpenProject user + // to perform actions using app-password without requiring password confirmation + $this->session->set('last-password-confirm', $this->timeFactory->getTime()); + } + } +} diff --git a/tests/acceptance/features/api/teamFolder.feature b/tests/acceptance/features/api/teamFolder.feature index a9fddc85b..21f23b08d 100644 --- a/tests/acceptance/features/api/teamFolder.feature +++ b/tests/acceptance/features/api/teamFolder.feature @@ -50,7 +50,7 @@ Feature: setup the integration through an API When user "Carol" deletes folder "/OpenProject/OpenProject/project-test" Then the HTTP status code should be 204 - @expect-fail + Scenario: check OpenProjectNoAutomaticProjectFolders group after user is removed from OpenProject group (removed by group admin) Given user "Carol" has been created And user "Carol" has been added to the group "OpenProject" @@ -59,7 +59,7 @@ Feature: setup the integration through an API And user "Carol" should belong to group "OpenProjectNoAutomaticProjectFolders" And user "Carol" should not belong to group "OpenProject" - @expect-fail + Scenario: user not in OpenProject group is removed from another group (removed by group admin) Given group "grp1" has been created And user "Carol" has been created @@ -74,7 +74,7 @@ Feature: setup the integration through an API And user "Carol" should belong to group "grp1" And user "Carol" should not belong to group "OpenProjectNoAutomaticProjectFolders" - @expect-fail + Scenario: user not in OpenProject group but has multiple group memberships is removed from one group (removed by group admin) Given group "grp1" has been created And group "grp2" has been created @@ -94,7 +94,7 @@ Feature: setup the integration through an API | Carol | OpenProjectNoAutomaticProjectFolders | And user "Carol" should belong to group "grp2" - @expect-fail + Scenario: user in OpenProject and other groups (removed by group admin) Given group "grp1" has been created And user "Carol" has been created @@ -118,7 +118,7 @@ Feature: setup the integration through an API And user "Carol" should belong to group "OpenProjectNoAutomaticProjectFolders" And user "Carol" should not belong to group "OpenProject" - @expect-fail + Scenario: multiple user in OpenProject groups and only one gets removed (removed by group admin) Given user "Alex" has been created And user "Brian" has been created @@ -137,7 +137,7 @@ Feature: setup the integration through an API | Brian | OpenProjectNoAutomaticProjectFolders | | Carol | OpenProject | - @expect-fail + Scenario: user is in multiple groups including OpenProject and is removed from another group (removed by group admin) Given group "grp1" has been created And user "Carol" has been created