Files
nextcloud-server-mirror/tests/lib/Interaction/RestrictInteractionEventTest.php
Ghassen kefiandClaude Opus 5.5 dc9896f54c feat(core): add operation identifiers to brute force and interaction audit entries
The audit entries for brute force attempts from allow-listed addresses
and for interaction checks had no operation identifier, so they could
only be filtered by their message. They now use
auth.bruteforce.bypassed, users.interaction.allowed and
users.interaction.restricted.

The interaction parameters are now named, so data.params is written as
an object instead of a list.

Assisted-by: ClaudeCode:claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Ghassen kefi <ghassen.kefi.dev@gmail.com>
2026-10-23 11:39:36 +02:00

114 lines
3.3 KiB
PHP

<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\Interaction;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Interaction\InteractionAction;
use OCP\Interaction\InteractionReceiver;
use OCP\Interaction\InteractionResource;
use OCP\Interaction\InteractionRestrictedException;
use OCP\Interaction\RestrictInteractionEvent;
use OCP\IUser;
use OCP\Log\Audit\CriticalActionPerformedEvent;
use OCP\Server;
use PHPUnit\Framework\Attributes\DataProvider;
use Test\TestCase;
final class RestrictInteractionEventTest extends TestCase {
/**
* @return list<array{bool}>
*/
public static function dataIsInteractionRestricted(): array {
return [
[true],
[false],
];
}
#[DataProvider('dataIsInteractionRestricted')]
public function testIsInteractionRestricted(bool $isRestricted): void {
$eventDispatcher = Server::get(IEventDispatcher::class);
$auditEvents = [];
$auditEventListener = function (CriticalActionPerformedEvent $event) use (&$auditEvents): void {
$auditEvents[] = $event;
};
$eventDispatcher->addListener(CriticalActionPerformedEvent::class, $auditEventListener);
/** @psalm-suppress UnusedClosureParam */
$restrictInteractionEventListener = function (RestrictInteractionEvent $event) use ($isRestricted): void {
if ($isRestricted) {
throw new InteractionRestrictedException('my restriction message', 'my restriction hint');
}
};
$eventDispatcher->addListener(RestrictInteractionEvent::class, $restrictInteractionEventListener);
$user = $this->createMock(IUser::class);
$user
->method('getUID')
->willReturn('my-uid');
$resource1 = $this->createMock(InteractionResource::class);
$resource1
->method('getID')
->willReturn('my-resource1');
$resource2 = $this->createMock(InteractionResource::class);
$resource2
->method('getID')
->willReturn('my-resource2');
$action = $this->createStub(InteractionAction::class);
$receiver1 = $this->createMock(InteractionReceiver::class);
$receiver1
->method('getID')
->willReturn('my-receiver1');
$receiver2 = $this->createMock(InteractionReceiver::class);
$receiver2
->method('getID')
->willReturn('my-receiver2');
$event = new RestrictInteractionEvent(
$user->getUID(),
$user,
[$resource1, $resource2],
$action,
[$receiver1, $receiver2],
);
if ($isRestricted) {
$this->assertEquals('my restriction hint', $event->isInteractionRestricted());
} else {
$this->assertFalse($event->isInteractionRestricted());
}
$this->assertEquals([
new CriticalActionPerformedEvent(
$isRestricted
? 'Interaction %s from user %s on %s to %s is restricted: my restriction message'
: 'Interaction %s from user %s on %s to %s is allowed.',
[
'action' => $action::class,
'userId' => 'my-uid',
'resources' => 'my-resource1, my-resource2',
'receivers' => 'my-receiver1, my-receiver2',
],
false,
$isRestricted ? 'users.interaction.restricted' : 'users.interaction.allowed',
),
], $auditEvents);
$eventDispatcher->removeListener(CriticalActionPerformedEvent::class, $auditEventListener);
$eventDispatcher->removeListener(RestrictInteractionEvent::class, $restrictInteractionEventListener);
}
}