diff --git a/appinfo/info.xml b/appinfo/info.xml index 8b63f009..606e69aa 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -38,7 +38,7 @@ to join us in shaping a more versatile, stable, and secure app landscape. *Your insights, suggestions, and contributions are invaluable to us.* ]]> - 32.0.0-dev.3 + 32.0.0-dev.4 agpl Andrey Borysenko Alexander Piskun @@ -80,7 +80,6 @@ to join us in shaping a more versatile, stable, and secure app landscape. OCA\AppAPI\Command\ExApp\Enable OCA\AppAPI\Command\ExApp\Disable OCA\AppAPI\Command\ExApp\ListExApps - OCA\AppAPI\Command\ExApp\Notify OCA\AppAPI\Command\ExAppConfig\GetConfig OCA\AppAPI\Command\ExAppConfig\SetConfig OCA\AppAPI\Command\ExAppConfig\DeleteConfig diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 10331d50..6be6d092 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -14,7 +14,6 @@ use OCA\AppAPI\Listener\DeclarativeSettings\GetValueListener; use OCA\AppAPI\Listener\DeclarativeSettings\RegisterDeclarativeSettingsListener; use OCA\AppAPI\Listener\DeclarativeSettings\SetValueListener; -use OCA\AppAPI\Listener\FileEventsListener; use OCA\AppAPI\Listener\GetTaskProcessingProvidersListener; use OCA\AppAPI\Listener\LoadFilesPluginListener; use OCA\AppAPI\Listener\LoadMenuEntriesListener; @@ -32,12 +31,6 @@ use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\EventDispatcher\IEventDispatcher; -use OCP\Files\Events\Node\NodeCopiedEvent; -use OCP\Files\Events\Node\NodeCreatedEvent; -use OCP\Files\Events\Node\NodeDeletedEvent; -use OCP\Files\Events\Node\NodeRenamedEvent; -use OCP\Files\Events\Node\NodeTouchedEvent; -use OCP\Files\Events\Node\NodeWrittenEvent; use OCP\Navigation\Events\LoadAdditionalEntriesEvent; use OCP\SabrePluginEvent; use OCP\Settings\Events\DeclarativeSettingsGetValueEvent; @@ -75,13 +68,6 @@ public function register(IRegistrationContext $context): void { $context->registerEventListener(DeclarativeSettingsGetValueEvent::class, GetValueListener::class); $context->registerEventListener(DeclarativeSettingsSetValueEvent::class, SetValueListener::class); - $context->registerEventListener(NodeCreatedEvent::class, FileEventsListener::class); - $context->registerEventListener(NodeTouchedEvent::class, FileEventsListener::class); - $context->registerEventListener(NodeWrittenEvent::class, FileEventsListener::class); - $context->registerEventListener(NodeDeletedEvent::class, FileEventsListener::class); - $context->registerEventListener(NodeRenamedEvent::class, FileEventsListener::class); - $context->registerEventListener(NodeCopiedEvent::class, FileEventsListener::class); - $context->registerSetupCheck(DaemonCheck::class); } diff --git a/lib/Command/ExApp/Notify.php b/lib/Command/ExApp/Notify.php deleted file mode 100644 index 27ab32e1..00000000 --- a/lib/Command/ExApp/Notify.php +++ /dev/null @@ -1,77 +0,0 @@ -setName('app_api:app:notify'); - $this->setDescription('Notify ExApp about internal event'); - $this->setHidden(true); - $this->addArgument('appid', InputArgument::REQUIRED); - $this->addArgument('route', InputArgument::REQUIRED); - $this->addOption('user-id', null, InputOption::VALUE_REQUIRED, 'User ID'); - $this->addOption('event-json', null, InputOption::VALUE_REQUIRED, 'Event JSON payload'); - } - - protected function execute(InputInterface $input, OutputInterface $output): int { - $appId = $input->getArgument('appid'); - - $exApp = $this->exAppService->getExApp($appId); - if ($exApp === null) { - $output->writeln(sprintf('ExApp %s not found. Failed to notify.', $appId)); - return 1; - } - - $eventJson = $input->getOption('event-json'); - if ($eventJson === null) { - $output->writeln('Event JSON payload is required'); - return 1; - } - - $eventJsonData = json_decode($eventJson, true); - if ($eventJsonData === null) { - $output->writeln('Invalid JSON payload'); - return 1; - } - - $route = $input->getArgument('route'); - $userId = $input->getOption('user-id'); - $response = $this->service->requestToExApp($exApp, $route, $userId, params: $eventJsonData, - options: ['timeout' => 2]); - if (is_array($response) && isset($response['error'])) { - $output->writeln(sprintf('Failed to notify ExApp %s: %s', $appId, $response['error'])); - return 1; - } - - if ($response->getStatusCode() !== 200) { - $output->writeln(sprintf('Failed to notify ExApp %s: %s', $appId, $response->getBody())); - return 1; - } - - $output->writeln(sprintf('ExApp %s notified about event: %s', $appId, $eventJson)); - - return 0; - } -} diff --git a/lib/Controller/EventsListenerController.php b/lib/Controller/EventsListenerController.php deleted file mode 100644 index 22f71ea9..00000000 --- a/lib/Controller/EventsListenerController.php +++ /dev/null @@ -1,67 +0,0 @@ -request = $request; - } - - #[NoCSRFRequired] - #[PublicPage] - #[AppAPIAuth] - public function registerListener(string $eventType, string $actionHandler, array $eventSubtypes = []): DataResponse { - $listener = $this->service->registerEventsListener( - $this->request->getHeader('EX-APP-ID'), $eventType, $actionHandler, $eventSubtypes); - if ($listener === null) { - return new DataResponse([], Http::STATUS_BAD_REQUEST); - } - return new DataResponse(); - } - - #[NoCSRFRequired] - #[PublicPage] - #[AppAPIAuth] - public function unregisterListener(string $eventType): DataResponse { - $unregistered = $this->service->unregisterEventsListener($this->request->getHeader('EX-APP-ID'), $eventType); - if (!$unregistered) { - return new DataResponse([], Http::STATUS_NOT_FOUND); - } - return new DataResponse(); - } - - #[AppAPIAuth] - #[PublicPage] - #[NoCSRFRequired] - public function getListener(string $eventType): DataResponse { - $result = $this->service->getEventsListener($this->request->getHeader('EX-APP-ID'), $eventType); - if (!$result) { - return new DataResponse([], Http::STATUS_NOT_FOUND); - } - return new DataResponse($result, Http::STATUS_OK); - } -} diff --git a/lib/Db/ExAppEventsListener.php b/lib/Db/ExAppEventsListener.php deleted file mode 100644 index 2d80dd01..00000000 --- a/lib/Db/ExAppEventsListener.php +++ /dev/null @@ -1,71 +0,0 @@ -addType('appid', 'string'); - $this->addType('eventType', 'string'); - $this->addType('eventSubtypes', 'json'); - $this->addType('actionHandler', 'string'); - - if (isset($params['id'])) { - $this->setId($params['id']); - } - if (isset($params['appid'])) { - $this->setAppid($params['appid']); - } - if (isset($params['event_type'])) { - $this->setEventType($params['event_type']); - } - if (isset($params['event_subtypes'])) { - $this->setEventSubtypes($params['event_subtypes']); - } - if (isset($params['action_handler'])) { - $this->setActionHandler($params['action_handler']); - } - } - - public function jsonSerialize(): array { - return [ - 'id' => $this->getId(), - 'appid' => $this->getAppid(), - 'event_type' => $this->getEventType(), - 'event_subtypes' => $this->getEventSubtypes(), - 'action_handler' => $this->getActionHandler(), - ]; - } -} diff --git a/lib/Db/ExAppEventsListenerMapper.php b/lib/Db/ExAppEventsListenerMapper.php deleted file mode 100644 index 3ee09912..00000000 --- a/lib/Db/ExAppEventsListenerMapper.php +++ /dev/null @@ -1,90 +0,0 @@ - - */ -class ExAppEventsListenerMapper extends QBMapper { - public function __construct(IDBConnection $db) { - parent::__construct($db, 'ex_event_handlers'); - } - - /** - * @throws Exception - */ - public function findAllEnabled(): array { - $qb = $this->db->getQueryBuilder(); - $result = $qb->select('exs.*') - ->from($this->tableName, 'exs') - ->innerJoin('exs', 'ex_apps', 'exa', $qb->expr()->eq('exa.appid', 'exs.appid')) - ->where( - $qb->expr()->eq('exa.enabled', $qb->createNamedParameter(1, IQueryBuilder::PARAM_INT)) - ) - ->executeQuery(); - return $result->fetchAll(); - } - - public function removeByAppIdEventType(string $appId, string $eventType): bool { - $qb = $this->db->getQueryBuilder(); - $qb->delete($this->tableName) - ->where( - $qb->expr()->eq('appid', $qb->createNamedParameter($appId, IQueryBuilder::PARAM_STR)), - $qb->expr()->eq('event_type', $qb->createNamedParameter($eventType, IQueryBuilder::PARAM_STR)) - ); - try { - $result = $qb->executeStatement(); - if ($result) { - return true; - } - } catch (Exception) { - } - return false; - } - - /** - * @throws Exception - */ - public function removeAllByAppId(string $appId): int { - $qb = $this->db->getQueryBuilder(); - $qb->delete($this->tableName) - ->where( - $qb->expr()->eq('appid', $qb->createNamedParameter($appId, IQueryBuilder::PARAM_STR)) - ); - return $qb->executeStatement(); - } - - /** - * @param string $appId - * @param string $eventType - * - * @return ExAppEventsListener - * @throws Exception - * @throws MultipleObjectsReturnedException if more than one result - * @throws DoesNotExistException if not found - */ - public function findByAppIdEventType(string $appId, string $eventType): ExAppEventsListener { - $qb = $this->db->getQueryBuilder(); - $qb->select('*') - ->from($this->tableName) - ->where( - $qb->expr()->eq('appid', $qb->createNamedParameter($appId, IQueryBuilder::PARAM_STR)), - $qb->expr()->eq('event_type', $qb->createNamedParameter($eventType, IQueryBuilder::PARAM_STR)) - ); - return $this->findEntity($qb); - } -} diff --git a/lib/Listener/FileEventsListener.php b/lib/Listener/FileEventsListener.php deleted file mode 100644 index cad15ba7..00000000 --- a/lib/Listener/FileEventsListener.php +++ /dev/null @@ -1,173 +0,0 @@ - - */ -class FileEventsListener implements IEventListener { - - public function __construct( - private readonly ExAppEventsListenerService $service, - private readonly AppAPIService $appAPIService, - private readonly ExAppService $exAppService, - private readonly IConfig $config, - private readonly LoggerInterface $logger, - private readonly IUserSession $userSession, - private readonly IRootFolder $rootFolder, - ) { - } - - public function handle(Event $event): void { - $filteredNodeEventListeners = array_filter($this->service->getEventsListeners(), function ($eventsListener) { - return $eventsListener->getEventType() === 'node_event'; - }); - if (empty($filteredNodeEventListeners)) { - return; - } - $eventSubtype = ''; - if ($event instanceof NodeCreatedEvent) { - $eventSubtype = 'NodeCreatedEvent'; - } elseif ($event instanceof NodeTouchedEvent) { - $eventSubtype = 'NodeTouchedEvent'; - } elseif ($event instanceof NodeWrittenEvent) { - $eventSubtype = 'NodeWrittenEvent'; - } elseif ($event instanceof NodeDeletedEvent) { - $eventSubtype = 'NodeDeletedEvent'; - } elseif ($event instanceof NodeRenamedEvent) { - $eventSubtype = 'NodeRenamedEvent'; - } elseif ($event instanceof NodeCopiedEvent) { - $eventSubtype = 'NodeCopiedEvent'; - } - if ($eventSubtype === '') { - return; - } - $eventData = [ - 'event_type' => 'node_event', - 'event_subtype' => $eventSubtype, - ]; - try { - if (($event instanceof NodeRenamedEvent) || ($event instanceof NodeCopiedEvent)) { - $eventData['event_data'] = [ - 'target' => $this->serializeNodeInfo($event->getTarget()), - ]; - $eventData['event_data']['source'] = $this->serializeNodeInfo($event->getSource(), $eventData['event_data']['target']); - } elseif ($event instanceof AbstractNodeEvent) { - $eventData['event_data'] = [ - 'target' => $this->serializeNodeInfo($event->getNode()), - ]; - } else { - return; - } - } catch (NotFoundException | NotPermittedException $e) { - $this->logger->error( - sprintf('Failed to serialize NodeInfo: %s', $e->getMessage()), ['exception' => $e] - ); - return; - } - foreach ($filteredNodeEventListeners as $nodeEventListener) { - if ( - empty($nodeEventListener->getEventSubtypes()) || - in_array($eventSubtype, $nodeEventListener->getEventSubtypes()) - ) { - $exApp = $this->exAppService->getExApp($nodeEventListener->getAppid()); - if ($exApp !== null) { - $args = [ - 'app_api:app:notify', - escapeshellarg($exApp->getAppid()), - escapeshellarg($nodeEventListener->getActionHandler()), - '--event-json', - escapeshellarg(json_encode($eventData)) - ]; - $userId = $this->userSession->getUser(); - if ($userId !== null) { - $args[] = '--user-id'; - $args[] = escapeshellarg($userId->getUID()); - } - $this->appAPIService->runOccCommandInternal($args); - } - } - } - } - - /** - * @throws NotFoundException - * @throws NotPermittedException - */ - private function serializeNodeInfo(Node $node, array $fallbackInfo = []): array { - $userPath = $this->getPathForNode($node); - $result = $fallbackInfo; - $result['favorite'] = ''; - $result['name'] = basename($userPath); - $result['directory'] = dirname($userPath); - $result['instanceId'] = $this->config->getSystemValue('instanceid'); - try { - $result['fileId'] = $node->getId(); - $result['etag'] = $node->getEtag(); - $result['mime'] = $node->getMimeType(); - $result['permissions'] = $node->getPermissions(); - $result['fileType'] = $node->getType(); - $result['size'] = $node->getSize(); - $result['mtime'] = $node->getMTime(); - $result['userId'] = $node->getOwner()->getUID(); - } catch (NotFoundException | InvalidPathException) { - } - return $result; - } - - /** - * @throws NotPermittedException - * @throws NotFoundException - */ - private function getPathForNode(Node $node): ?string { - $user = $this->userSession->getUser()?->getUID(); - if ($user) { - $path = $this->rootFolder - ->getUserFolder($user) - ->getRelativePath($node->getPath()); - - if ($path !== null) { - return $path; - } - } - $owner = $node->getOwner()?->getUid(); - if ($owner) { - $path = $this->rootFolder - ->getUserFolder($owner) - ->getRelativePath($node->getPath()); - - if ($path !== null) { - return $path; - } - } - return null; - } -} diff --git a/lib/Migration/Version2204Date20240401104001.php b/lib/Migration/Version2204Date20240401104001.php deleted file mode 100644 index 467eac84..00000000 --- a/lib/Migration/Version2204Date20240401104001.php +++ /dev/null @@ -1,59 +0,0 @@ -hasTable('ex_event_handlers')) { - $table = $schema->createTable('ex_event_handlers'); - - $table->addColumn('id', Types::BIGINT, [ - 'autoincrement' => true, - 'notnull' => true, - ]); - $table->addColumn('appid', Types::STRING, [ - 'notnull' => true, - 'length' => 32, - ]); - $table->addColumn('event_type', Types::STRING, [ - 'notnull' => true, - 'length' => 32, - ]); - $table->addColumn('event_subtypes', Types::JSON, [ - 'notnull' => true, - ]); - $table->addColumn('action_handler', Types::STRING, [ - 'notnull' => true, - 'length' => 410, - ]); - - $table->setPrimaryKey(['id']); - $table->addUniqueIndex(['appid', 'event_type'], 'ex_event_handlers__idx'); - } - - return $schema; - } -} diff --git a/lib/Service/ExAppEventsListenerService.php b/lib/Service/ExAppEventsListenerService.php deleted file mode 100644 index 32097354..00000000 --- a/lib/Service/ExAppEventsListenerService.php +++ /dev/null @@ -1,115 +0,0 @@ -isAvailable()) { - $this->cache = $cacheFactory->createDistributed(Application::APP_ID . '/ex_events_listener'); - } - } - - public function registerEventsListener(string $appId, string $eventType, string $actionHandler, array $eventSubtypes = []): ?ExAppEventsListener { - $eventsListenerEntry = $this->getEventsListener($appId, $eventType); - try { - $newEventsListenerEntry = new ExAppEventsListener([ - 'appid' => $appId, - 'event_type' => $eventType, - 'event_subtypes' => $eventSubtypes, - 'action_handler' => ltrim($actionHandler, '/'), - ]); - if ($eventsListenerEntry !== null) { - $newEventsListenerEntry->setId($eventsListenerEntry->getId()); - } - $eventsListenerEntry = $this->mapper->insertOrUpdate($newEventsListenerEntry); - $this->resetCacheEnabled(); - } catch (Exception $e) { - $this->logger->error( - sprintf('Failed to register Events listener for %s. Error: %s', $appId, $e->getMessage()), ['exception' => $e] - ); - return null; - } - return $eventsListenerEntry; - } - - public function unregisterEventsListener(string $appId, string $eventType): bool { - if (!$this->mapper->removeByAppIdEventType($appId, $eventType)) { - return false; - } - $this->resetCacheEnabled(); - return true; - } - - public function getEventsListener(string $appId, string $eventType): ?ExAppEventsListener { - foreach ($this->getEventsListeners() as $eventsListener) { - if (($eventsListener->getAppid() === $appId) && ($eventsListener->getEventType() === $eventType)) { - return $eventsListener; - } - } - try { - return $this->mapper->findByAppIdEventType($appId, $eventType); - } catch (DoesNotExistException|MultipleObjectsReturnedException|Exception) { - return null; - } - } - - /** - * Get list of registered Events Listeners (only for enabled ExApps) - * - * @return ExAppEventsListener[] - */ - public function getEventsListeners(): array { - try { - $cacheKey = '/ex_events_listener'; - $records = $this->cache?->get($cacheKey); - if ($records === null) { - $records = $this->mapper->findAllEnabled(); - $this->cache?->set($cacheKey, $records); - } - return array_map(function ($record) { - return new ExAppEventsListener($record); - }, $records); - } catch (Exception) { - return []; - } - } - - public function unregisterExAppEventListeners(string $appId): int { - try { - $result = $this->mapper->removeAllByAppId($appId); - } catch (Exception) { - $result = -1; - } - $this->resetCacheEnabled(); - return $result; - } - - public function resetCacheEnabled(): void { - $this->cache?->remove('/ex_events_listener'); - } -} diff --git a/lib/Service/ExAppService.php b/lib/Service/ExAppService.php index 34a0e771..ef9272f0 100644 --- a/lib/Service/ExAppService.php +++ b/lib/Service/ExAppService.php @@ -52,7 +52,6 @@ public function __construct( private readonly TaskProcessingService $taskProcessingService, private readonly TalkBotsService $talkBotsService, private readonly SettingsService $settingsService, - private readonly ExAppEventsListenerService $eventsListenerService, private readonly ExAppOccService $occService, private readonly ExAppDeployOptionsService $deployOptionsService, private readonly IConfig $config, @@ -118,7 +117,6 @@ public function unregisterExApp(string $appId): bool { $this->taskProcessingService->unregisterExAppTaskProcessingProviders($appId); $this->settingsService->unregisterExAppForms($appId); $this->exAppArchiveFetcher->removeExAppFolder($appId); - $this->eventsListenerService->unregisterExAppEventListeners($appId); $this->occService->unregisterExAppOccCommands($appId); $this->deployOptionsService->removeExAppDeployOptions($appId); $this->unregisterExAppWebhooks($appId); @@ -244,7 +242,6 @@ private function resetCaches(): void { $this->topMenuService->resetCacheEnabled(); $this->filesActionsMenuService->resetCacheEnabled(); $this->settingsService->resetCacheEnabled(); - $this->eventsListenerService->resetCacheEnabled(); $this->occService->resetCacheEnabled(); $this->deployOptionsService->resetCache(); } diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml index c6d2d1c9..8c566636 100644 --- a/tests/psalm-baseline.xml +++ b/tests/psalm-baseline.xml @@ -75,13 +75,6 @@ - - - rootFolder]]> - rootFolder]]> - - -