diff options
Diffstat (limited to 'core/Controller/ReferenceApiController.php')
-rw-r--r-- | core/Controller/ReferenceApiController.php | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/core/Controller/ReferenceApiController.php b/core/Controller/ReferenceApiController.php new file mode 100644 index 00000000000..d4fb753f404 --- /dev/null +++ b/core/Controller/ReferenceApiController.php @@ -0,0 +1,233 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\Core\Controller; + +use OC\Core\ResponseDefinitions; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\AnonRateLimit; +use OCP\AppFramework\Http\Attribute\ApiRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\PublicPage; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCSController; +use OCP\Collaboration\Reference\IDiscoverableReferenceProvider; +use OCP\Collaboration\Reference\IReferenceManager; +use OCP\Collaboration\Reference\Reference; +use OCP\IRequest; + +/** + * @psalm-import-type CoreReference from ResponseDefinitions + * @psalm-import-type CoreReferenceProvider from ResponseDefinitions + */ +class ReferenceApiController extends OCSController { + private const LIMIT_MAX = 15; + + public function __construct( + string $appName, + IRequest $request, + private IReferenceManager $referenceManager, + private ?string $userId, + ) { + parent::__construct($appName, $request); + } + + /** + * Extract references from a text + * + * @param string $text Text to extract from + * @param bool $resolve Resolve the references + * @param int $limit Maximum amount of references to extract + * @return DataResponse<Http::STATUS_OK, array{references: array<string, CoreReference|null>}, array{}> + * + * 200: References returned + */ + #[NoAdminRequired] + #[ApiRoute(verb: 'POST', url: '/extract', root: '/references')] + public function extract(string $text, bool $resolve = false, int $limit = 1): DataResponse { + $references = $this->referenceManager->extractReferences($text); + + $result = []; + $index = 0; + foreach ($references as $reference) { + if ($index++ >= $limit) { + break; + } + + $result[$reference] = $resolve ? $this->referenceManager->resolveReference($reference)->jsonSerialize() : null; + } + + return new DataResponse([ + 'references' => $result + ]); + } + + /** + * Extract references from a text + * + * @param string $text Text to extract from + * @param string $sharingToken Token of the public share + * @param bool $resolve Resolve the references + * @param int $limit Maximum amount of references to extract, limited to 15 + * @return DataResponse<Http::STATUS_OK, array{references: array<string, CoreReference|null>}, array{}> + * + * 200: References returned + */ + #[ApiRoute(verb: 'POST', url: '/extractPublic', root: '/references')] + #[PublicPage] + #[AnonRateLimit(limit: 10, period: 120)] + public function extractPublic(string $text, string $sharingToken, bool $resolve = false, int $limit = 1): DataResponse { + $references = $this->referenceManager->extractReferences($text); + + $result = []; + $index = 0; + foreach ($references as $reference) { + if ($index++ >= min($limit, self::LIMIT_MAX)) { + break; + } + + $result[$reference] = $resolve ? $this->referenceManager->resolveReference($reference, true, $sharingToken)?->jsonSerialize() : null; + } + + return new DataResponse([ + 'references' => $result + ]); + } + + /** + * Resolve a reference + * + * @param string $reference Reference to resolve + * @return DataResponse<Http::STATUS_OK, array{references: array<string, ?CoreReference>}, array{}> + * + * 200: Reference returned + */ + #[NoAdminRequired] + #[ApiRoute(verb: 'GET', url: '/resolve', root: '/references')] + public function resolveOne(string $reference): DataResponse { + /** @var ?CoreReference $resolvedReference */ + $resolvedReference = $this->referenceManager->resolveReference(trim($reference))?->jsonSerialize(); + + $response = new DataResponse(['references' => [$reference => $resolvedReference]]); + $response->cacheFor(3600, false, true); + return $response; + } + + /** + * Resolve from a public page + * + * @param string $reference Reference to resolve + * @param string $sharingToken Token of the public share + * @return DataResponse<Http::STATUS_OK, array{references: array<string, ?CoreReference>}, array{}> + * + * 200: Reference returned + */ + #[ApiRoute(verb: 'GET', url: '/resolvePublic', root: '/references')] + #[PublicPage] + #[AnonRateLimit(limit: 25, period: 120)] + public function resolveOnePublic(string $reference, string $sharingToken): DataResponse { + /** @var ?CoreReference $resolvedReference */ + $resolvedReference = $this->referenceManager->resolveReference(trim($reference), true, trim($sharingToken))?->jsonSerialize(); + + $response = new DataResponse(['references' => [$reference => $resolvedReference]]); + $response->cacheFor(3600, false, true); + return $response; + } + + /** + * Resolve multiple references + * + * @param list<string> $references References to resolve + * @param int $limit Maximum amount of references to resolve + * @return DataResponse<Http::STATUS_OK, array{references: array<string, CoreReference|null>}, array{}> + * + * 200: References returned + */ + #[NoAdminRequired] + #[ApiRoute(verb: 'POST', url: '/resolve', root: '/references')] + public function resolve(array $references, int $limit = 1): DataResponse { + $result = []; + $index = 0; + foreach ($references as $reference) { + if ($index++ >= $limit) { + break; + } + + $result[$reference] = $this->referenceManager->resolveReference($reference)?->jsonSerialize(); + } + + return new DataResponse([ + 'references' => $result + ]); + } + + /** + * Resolve multiple references from a public page + * + * @param list<string> $references References to resolve + * @param string $sharingToken Token of the public share + * @param int $limit Maximum amount of references to resolve, limited to 15 + * @return DataResponse<Http::STATUS_OK, array{references: array<string, CoreReference|null>}, array{}> + * + * 200: References returned + */ + #[ApiRoute(verb: 'POST', url: '/resolvePublic', root: '/references')] + #[PublicPage] + #[AnonRateLimit(limit: 10, period: 120)] + public function resolvePublic(array $references, string $sharingToken, int $limit = 1): DataResponse { + $result = []; + $index = 0; + foreach ($references as $reference) { + if ($index++ >= min($limit, self::LIMIT_MAX)) { + break; + } + + $result[$reference] = $this->referenceManager->resolveReference($reference, true, $sharingToken)?->jsonSerialize(); + } + + return new DataResponse([ + 'references' => $result + ]); + } + + /** + * Get the providers + * + * @return DataResponse<Http::STATUS_OK, list<CoreReferenceProvider>, array{}> + * + * 200: Providers returned + */ + #[NoAdminRequired] + #[ApiRoute(verb: 'GET', url: '/providers', root: '/references')] + public function getProvidersInfo(): DataResponse { + $providers = $this->referenceManager->getDiscoverableProviders(); + $jsonProviders = array_values(array_map(static function (IDiscoverableReferenceProvider $provider) { + return $provider->jsonSerialize(); + }, $providers)); + return new DataResponse($jsonProviders); + } + + /** + * Touch a provider + * + * @param string $providerId ID of the provider + * @param int|null $timestamp Timestamp of the last usage + * @return DataResponse<Http::STATUS_OK, array{success: bool}, array{}> + * + * 200: Provider touched + */ + #[NoAdminRequired] + #[ApiRoute(verb: 'PUT', url: '/provider/{providerId}', root: '/references')] + public function touchProvider(string $providerId, ?int $timestamp = null): DataResponse { + if ($this->userId !== null) { + $success = $this->referenceManager->touchProvider($this->userId, $providerId, $timestamp); + return new DataResponse(['success' => $success]); + } + return new DataResponse(['success' => false]); + } +} |