Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Fix: Handle invalid boolean auth-method value [#1074](https://github.com/nextcloud/integration_openproject/pull/1074)
- Fix: Update OpenProject icon [#1078](https://github.com/nextcloud/integration_openproject/pull/1078)
- Fix: False integration setup status even after complete oauth setup [#1086](https://github.com/nextcloud/integration_openproject/pull/1086)
- Fix: Incompatible AMPF with the latest Nextcloud patch releases [#1097](https://github.com/nextcloud/integration_openproject/pull/1097)

## 2.11.3 - 2026-06-18

Expand Down
36 changes: 17 additions & 19 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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,
Comment thread
saw-jan marked this conversation as resolved.
);
$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);
Expand All @@ -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 {
Expand Down
45 changes: 45 additions & 0 deletions lib/Listener/UserLoggedInEventListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Jankari Tech Pvt. Ltd.
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\OpenProject\Listener;

use OCA\OpenProject\AppInfo\Application;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\ISession;
use OCP\User\Events\UserLoggedInEvent;

/**
* @template-implements IEventListener<UserLoggedInEvent>
*/
class UserLoggedInEventListener implements IEventListener {
Comment thread
saw-jan marked this conversation as resolved.
public function __construct(
private ISession $session,
private ITimeFactory $timeFactory,
) {
}
Comment thread
saw-jan marked this conversation as resolved.

/**
* @param UserLoggedInEvent $event
*
* @return void
*/
public function handle(Event $event): void {
if (!($event instanceof UserLoggedInEvent)) {
return;
}
Comment thread
saw-jan marked this conversation as resolved.

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());
}
}
}
12 changes: 6 additions & 6 deletions tests/acceptance/features/api/teamFolder.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
Loading