aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorCôme Chilliet <come.chilliet@nextcloud.com>2024-06-24 16:19:03 +0200
committerCôme Chilliet <come.chilliet@nextcloud.com>2024-07-02 11:24:33 +0200
commit44d707c97b54ed3b2ae352f6ddfa8caa213e27e8 (patch)
treeb556ab63123b52224754158f1cdb881a733501ef /apps
parent164f4a3ea3a3ae8f8adc05b766782f49d7e69832 (diff)
downloadnextcloud-server-44d707c97b54ed3b2ae352f6ddfa8caa213e27e8.tar.gz
nextcloud-server-44d707c97b54ed3b2ae352f6ddfa8caa213e27e8.zip
feat(webhooks): Add support for a userid filter
This allows to register a userId to filter on along with the webhooks. This webhook will then only be triggered if the given userId is the one in session. This is more efficient than filtering by user in the event filter because the listener is not even registered if the user id does not match. Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
Diffstat (limited to 'apps')
-rw-r--r--apps/webhook_listeners/lib/AppInfo/Application.php4
-rw-r--r--apps/webhook_listeners/lib/Controller/WebhooksController.php4
-rw-r--r--apps/webhook_listeners/lib/Db/WebhookListener.php7
-rw-r--r--apps/webhook_listeners/lib/Db/WebhookListenerMapper.php28
-rwxr-xr-xapps/webhook_listeners/lib/Migration/Version1000Date20240527153425.php4
-rw-r--r--apps/webhook_listeners/lib/ResponseDefinitions.php1
-rw-r--r--apps/webhook_listeners/tests/Db/WebhookListenerMapperTest.php4
7 files changed, 42 insertions, 10 deletions
diff --git a/apps/webhook_listeners/lib/AppInfo/Application.php b/apps/webhook_listeners/lib/AppInfo/Application.php
index d1ffa5db49b..30f2e0969f6 100644
--- a/apps/webhook_listeners/lib/AppInfo/Application.php
+++ b/apps/webhook_listeners/lib/AppInfo/Application.php
@@ -16,6 +16,7 @@ use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\EventDispatcher\IEventDispatcher;
+use OCP\IUserSession;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
@@ -40,9 +41,10 @@ class Application extends App implements IBootstrap {
): void {
/** @var WebhookListenerMapper */
$mapper = $container->get(WebhookListenerMapper::class);
+ $userSession = $container->get(IUserSession::class);
/* Listen to all events with at least one webhook configured */
- $configuredEvents = $mapper->getAllConfiguredEvents();
+ $configuredEvents = $mapper->getAllConfiguredEvents($userSession->getUser()?->getUID());
foreach ($configuredEvents as $eventName) {
$logger->debug("Listening to {$eventName}");
$dispatcher->addServiceListener(
diff --git a/apps/webhook_listeners/lib/Controller/WebhooksController.php b/apps/webhook_listeners/lib/Controller/WebhooksController.php
index 5b097c84a3c..a4de0c8d342 100644
--- a/apps/webhook_listeners/lib/Controller/WebhooksController.php
+++ b/apps/webhook_listeners/lib/Controller/WebhooksController.php
@@ -126,6 +126,7 @@ class WebhooksController extends OCSController {
string $uri,
string $event,
?array $eventFilter,
+ ?string $userIdFilter,
?array $headers,
?string $authMethod,
#[\SensitiveParameter]
@@ -150,6 +151,7 @@ class WebhooksController extends OCSController {
$uri,
$event,
$eventFilter,
+ $userIdFilter,
$headers,
$authMethod,
$authData,
@@ -193,6 +195,7 @@ class WebhooksController extends OCSController {
string $uri,
string $event,
?array $eventFilter,
+ ?string $userIdFilter,
?array $headers,
?string $authMethod,
#[\SensitiveParameter]
@@ -218,6 +221,7 @@ class WebhooksController extends OCSController {
$uri,
$event,
$eventFilter,
+ $userIdFilter,
$headers,
$authMethod,
$authData,
diff --git a/apps/webhook_listeners/lib/Db/WebhookListener.php b/apps/webhook_listeners/lib/Db/WebhookListener.php
index e9b63e01472..680d47798d5 100644
--- a/apps/webhook_listeners/lib/Db/WebhookListener.php
+++ b/apps/webhook_listeners/lib/Db/WebhookListener.php
@@ -60,6 +60,12 @@ class WebhookListener extends Entity implements \JsonSerializable {
protected $eventFilter;
/**
+ * @var string
+ * If not empty, id of the user that needs to be connected for the webhook to trigger
+ */
+ protected $userIdFilter;
+
+ /**
* @var ?array
*/
protected $headers = null;
@@ -90,6 +96,7 @@ class WebhookListener extends Entity implements \JsonSerializable {
$this->addType('uri', 'string');
$this->addType('event', 'string');
$this->addType('eventFilter', 'json');
+ $this->addType('userIdFilter', 'string');
$this->addType('headers', 'json');
$this->addType('authMethod', 'string');
$this->addType('authData', 'string');
diff --git a/apps/webhook_listeners/lib/Db/WebhookListenerMapper.php b/apps/webhook_listeners/lib/Db/WebhookListenerMapper.php
index a1fe4ceee8d..ad8c287ad43 100644
--- a/apps/webhook_listeners/lib/Db/WebhookListenerMapper.php
+++ b/apps/webhook_listeners/lib/Db/WebhookListenerMapper.php
@@ -25,7 +25,7 @@ use OCP\IDBConnection;
class WebhookListenerMapper extends QBMapper {
public const TABLE_NAME = 'webhook_listeners';
- private const EVENTS_CACHE_KEY = 'eventsUsedInWebhooks';
+ private const EVENTS_CACHE_KEY_PREFIX = 'eventsUsedInWebhooks';
private ?ICache $cache = null;
@@ -77,6 +77,7 @@ class WebhookListenerMapper extends QBMapper {
string $uri,
string $event,
?array $eventFilter,
+ ?string $userIdFilter,
?array $headers,
AuthMethod $authMethod,
#[\SensitiveParameter]
@@ -95,12 +96,13 @@ class WebhookListenerMapper extends QBMapper {
'uri' => $uri,
'event' => $event,
'eventFilter' => $eventFilter ?? [],
+ 'userIdFilter' => $userIdFilter ?? '',
'headers' => $headers,
'authMethod' => $authMethod->value,
]
);
$webhookListener->setAuthDataClear($authData);
- $this->cache?->remove(self::EVENTS_CACHE_KEY);
+ $this->cache?->remove($this->buildCacheKey($userIdFilter));
return $this->insert($webhookListener);
}
@@ -115,6 +117,7 @@ class WebhookListenerMapper extends QBMapper {
string $uri,
string $event,
?array $eventFilter,
+ ?string $userIdFilter,
?array $headers,
AuthMethod $authMethod,
#[\SensitiveParameter]
@@ -134,12 +137,13 @@ class WebhookListenerMapper extends QBMapper {
'uri' => $uri,
'event' => $event,
'eventFilter' => $eventFilter ?? [],
+ 'userIdFilter' => $userIdFilter ?? '',
'headers' => $headers,
'authMethod' => $authMethod->value,
]
);
$webhookListener->setAuthDataClear($authData);
- $this->cache?->remove(self::EVENTS_CACHE_KEY);
+ $this->cache?->remove($this->buildCacheKey($userIdFilter));
return $this->update($webhookListener);
}
@@ -159,11 +163,12 @@ class WebhookListenerMapper extends QBMapper {
* @throws Exception
* @return list<string>
*/
- private function getAllConfiguredEventsFromDatabase(): array {
+ private function getAllConfiguredEventsFromDatabase(string $userId): array {
$qb = $this->db->getQueryBuilder();
$qb->selectDistinct('event')
- ->from($this->getTableName());
+ ->from($this->getTableName())
+ ->where($qb->expr()->in('user_id_filter', $qb->createNamedParameter(['',$userId], IQueryBuilder::PARAM_STR_ARRAY), IQueryBuilder::PARAM_STR));
$result = $qb->executeQuery();
@@ -181,14 +186,15 @@ class WebhookListenerMapper extends QBMapper {
* @throws Exception
* @return list<string>
*/
- public function getAllConfiguredEvents(): array {
- $events = $this->cache?->get(self::EVENTS_CACHE_KEY);
+ public function getAllConfiguredEvents(?string $userId = null): array {
+ $cacheKey = $this->buildCacheKey($userId);
+ $events = $this->cache?->get($cacheKey);
if ($events !== null) {
return json_decode($events);
}
- $events = $this->getAllConfiguredEventsFromDatabase();
+ $events = $this->getAllConfiguredEventsFromDatabase($userId ?? '');
// cache for 5 minutes
- $this->cache?->set(self::EVENTS_CACHE_KEY, json_encode($events), 300);
+ $this->cache?->set($cacheKey, json_encode($events), 300);
return $events;
}
@@ -217,4 +223,8 @@ class WebhookListenerMapper extends QBMapper {
return $this->findEntities($qb);
}
+
+ private function buildCacheKey(?string $userIdFilter = ''): string {
+ return self::EVENTS_CACHE_KEY_PREFIX.'_'.($userIdFilter ?? '');
+ }
}
diff --git a/apps/webhook_listeners/lib/Migration/Version1000Date20240527153425.php b/apps/webhook_listeners/lib/Migration/Version1000Date20240527153425.php
index 44f2476dd44..6693c8ecf3f 100755
--- a/apps/webhook_listeners/lib/Migration/Version1000Date20240527153425.php
+++ b/apps/webhook_listeners/lib/Migration/Version1000Date20240527153425.php
@@ -53,6 +53,10 @@ class Version1000Date20240527153425 extends SimpleMigrationStep {
$table->addColumn('event_filter', Types::TEXT, [
'notnull' => false,
]);
+ $table->addColumn('user_id_filter', Types::STRING, [
+ 'notnull' => true,
+ 'length' => 64,
+ ]);
$table->addColumn('headers', Types::TEXT, [
'notnull' => false,
]);
diff --git a/apps/webhook_listeners/lib/ResponseDefinitions.php b/apps/webhook_listeners/lib/ResponseDefinitions.php
index cb33f93e8ff..725e00b118a 100644
--- a/apps/webhook_listeners/lib/ResponseDefinitions.php
+++ b/apps/webhook_listeners/lib/ResponseDefinitions.php
@@ -17,6 +17,7 @@ namespace OCA\WebhookListeners;
* uri: string,
* event?: string,
* eventFilter?: array<string,mixed>,
+ * userIdFilter?: string,
* headers?: array<string,string>,
* authMethod: string,
* authData?: array<string,mixed>,
diff --git a/apps/webhook_listeners/tests/Db/WebhookListenerMapperTest.php b/apps/webhook_listeners/tests/Db/WebhookListenerMapperTest.php
index fc42a0a9597..327d5740077 100644
--- a/apps/webhook_listeners/tests/Db/WebhookListenerMapperTest.php
+++ b/apps/webhook_listeners/tests/Db/WebhookListenerMapperTest.php
@@ -58,6 +58,7 @@ class WebhookListenerMapperTest extends TestCase {
UserCreatedEvent::class,
null,
null,
+ null,
AuthMethod::None,
null,
);
@@ -72,6 +73,7 @@ class WebhookListenerMapperTest extends TestCase {
NodeWrittenEvent::class,
null,
null,
+ null,
AuthMethod::None,
null,
);
@@ -92,6 +94,7 @@ class WebhookListenerMapperTest extends TestCase {
NodeWrittenEvent::class,
null,
null,
+ null,
AuthMethod::None,
null,
);
@@ -111,6 +114,7 @@ class WebhookListenerMapperTest extends TestCase {
NodeWrittenEvent::class,
null,
null,
+ null,
AuthMethod::Header,
['secretHeader' => 'header'],
);