aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJonas <jonas@freesources.org>2024-07-08 11:29:26 +0200
committerJonas <jonas@freesources.org>2024-07-17 12:56:41 +0200
commit1671bf3ef219dd641b51b4d154ea701c6a7cf6b9 (patch)
tree70b971f9fea1968d7ec3c48b71dd5d1522500922 /core
parentb06ce832d8f280b9c008b91c41757e8eab37dc77 (diff)
downloadnextcloud-server-1671bf3ef219dd641b51b4d154ea701c6a7cf6b9.tar.gz
nextcloud-server-1671bf3ef219dd641b51b4d154ea701c6a7cf6b9.zip
feat(Reference): Add public API endpoints to get references
Calling the public API endpoints will check for matching registered reference providers that implement `IPublicReferenceProvider` and call their respective functions. If no matching provider is found, the default `LinkReferenceProvider` will be used to provide open graph data. The frontend reference widget components will call these endpoints from unauthorized sessions, e.g. in public shares. If present, the sharing token of the origin URL is passed to `resolveReferencePublic()` as additional information for the reference provider to determine the access scope. This allows the respective reference providers to determine whether the origin share has access to the linked resource. `getCacheKeyPublic` also gets the sharing token so it can scope the cached entry to it. Contributes to #45978 Signed-off-by: Jonas <jonas@freesources.org>
Diffstat (limited to 'core')
-rw-r--r--core/Controller/ReferenceApiController.php89
-rw-r--r--core/openapi-full.json312
-rw-r--r--core/openapi.json312
3 files changed, 713 insertions, 0 deletions
diff --git a/core/Controller/ReferenceApiController.php b/core/Controller/ReferenceApiController.php
index 77b4b43fa3a..a9d15ed4231 100644
--- a/core/Controller/ReferenceApiController.php
+++ b/core/Controller/ReferenceApiController.php
@@ -10,6 +10,7 @@ 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\DataResponse;
use OCP\Collaboration\Reference\IDiscoverableReferenceProvider;
@@ -22,6 +23,8 @@ use OCP\IRequest;
* @psalm-import-type CoreReferenceProvider from ResponseDefinitions
*/
class ReferenceApiController extends \OCP\AppFramework\OCSController {
+ private const LIMIT_MAX = 15;
+
public function __construct(
string $appName,
IRequest $request,
@@ -63,6 +66,39 @@ class ReferenceApiController extends \OCP\AppFramework\OCSController {
}
/**
+ * @PublicPage
+ *
+ * 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')]
+ #[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
+ ]);
+ }
+
+ /**
* @NoAdminRequired
*
* Resolve a reference
@@ -73,6 +109,7 @@ class ReferenceApiController extends \OCP\AppFramework\OCSController {
* 200: Reference returned
*/
#[ApiRoute(verb: 'GET', url: '/resolve', root: '/references')]
+ #[AnonRateLimit(limit: 10, period: 120)]
public function resolveOne(string $reference): DataResponse {
/** @var ?CoreReference $resolvedReference */
$resolvedReference = $this->referenceManager->resolveReference(trim($reference))?->jsonSerialize();
@@ -83,6 +120,28 @@ class ReferenceApiController extends \OCP\AppFramework\OCSController {
}
/**
+ * @PublicPage
+ *
+ * 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')]
+ #[AnonRateLimit(limit: 10, 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;
+ }
+
+ /**
* @NoAdminRequired
*
* Resolve multiple references
@@ -111,6 +170,36 @@ class ReferenceApiController extends \OCP\AppFramework\OCSController {
}
/**
+ * @PublicPage
+ *
+ * Resolve multiple references from a public page
+ *
+ * @param 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')]
+ #[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
+ ]);
+ }
+
+ /**
* @NoAdminRequired
*
* Get the providers
diff --git a/core/openapi-full.json b/core/openapi-full.json
index b70e82c3ee8..a62e587bf06 100644
--- a/core/openapi-full.json
+++ b/core/openapi-full.json
@@ -3059,6 +3059,115 @@
}
}
},
+ "/ocs/v2.php/references/extractPublic": {
+ "post": {
+ "operationId": "reference_api-extract-public",
+ "summary": "Extract references from a text",
+ "tags": [
+ "reference_api"
+ ],
+ "security": [
+ {},
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "text",
+ "sharingToken"
+ ],
+ "properties": {
+ "text": {
+ "type": "string",
+ "description": "Text to extract from"
+ },
+ "sharingToken": {
+ "type": "string",
+ "description": "Token of the public share"
+ },
+ "resolve": {
+ "type": "boolean",
+ "default": false,
+ "description": "Resolve the references"
+ },
+ "limit": {
+ "type": "integer",
+ "format": "int64",
+ "default": 1,
+ "description": "Maximum amount of references to extract, limited to 15"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "References returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "references"
+ ],
+ "properties": {
+ "references": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/components/schemas/Reference",
+ "nullable": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/ocs/v2.php/references/resolve": {
"get": {
"operationId": "reference_api-resolve-one",
@@ -3250,6 +3359,209 @@
}
}
},
+ "/ocs/v2.php/references/resolvePublic": {
+ "get": {
+ "operationId": "reference_api-resolve-one-public",
+ "summary": "Resolve from a public page",
+ "tags": [
+ "reference_api"
+ ],
+ "security": [
+ {},
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "reference",
+ "sharingToken"
+ ],
+ "properties": {
+ "reference": {
+ "type": "string",
+ "description": "Reference to resolve"
+ },
+ "sharingToken": {
+ "type": "string",
+ "description": "Token of the public share"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Reference returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "references"
+ ],
+ "properties": {
+ "references": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/components/schemas/Reference",
+ "nullable": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "reference_api-resolve-public",
+ "summary": "Resolve multiple references from a public page",
+ "tags": [
+ "reference_api"
+ ],
+ "security": [
+ {},
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "references",
+ "sharingToken"
+ ],
+ "properties": {
+ "references": {
+ "type": "array",
+ "description": "References to resolve",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sharingToken": {
+ "type": "string",
+ "description": "Token of the public share"
+ },
+ "limit": {
+ "type": "integer",
+ "format": "int64",
+ "default": 1,
+ "description": "Maximum amount of references to resolve, limited to 15"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "References returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "references"
+ ],
+ "properties": {
+ "references": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/components/schemas/Reference",
+ "nullable": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/ocs/v2.php/references/providers": {
"get": {
"operationId": "reference_api-get-providers-info",
diff --git a/core/openapi.json b/core/openapi.json
index 3310a03b89d..51698f6d430 100644
--- a/core/openapi.json
+++ b/core/openapi.json
@@ -3059,6 +3059,115 @@
}
}
},
+ "/ocs/v2.php/references/extractPublic": {
+ "post": {
+ "operationId": "reference_api-extract-public",
+ "summary": "Extract references from a text",
+ "tags": [
+ "reference_api"
+ ],
+ "security": [
+ {},
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "text",
+ "sharingToken"
+ ],
+ "properties": {
+ "text": {
+ "type": "string",
+ "description": "Text to extract from"
+ },
+ "sharingToken": {
+ "type": "string",
+ "description": "Token of the public share"
+ },
+ "resolve": {
+ "type": "boolean",
+ "default": false,
+ "description": "Resolve the references"
+ },
+ "limit": {
+ "type": "integer",
+ "format": "int64",
+ "default": 1,
+ "description": "Maximum amount of references to extract, limited to 15"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "References returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "references"
+ ],
+ "properties": {
+ "references": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/components/schemas/Reference",
+ "nullable": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/ocs/v2.php/references/resolve": {
"get": {
"operationId": "reference_api-resolve-one",
@@ -3250,6 +3359,209 @@
}
}
},
+ "/ocs/v2.php/references/resolvePublic": {
+ "get": {
+ "operationId": "reference_api-resolve-one-public",
+ "summary": "Resolve from a public page",
+ "tags": [
+ "reference_api"
+ ],
+ "security": [
+ {},
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "reference",
+ "sharingToken"
+ ],
+ "properties": {
+ "reference": {
+ "type": "string",
+ "description": "Reference to resolve"
+ },
+ "sharingToken": {
+ "type": "string",
+ "description": "Token of the public share"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Reference returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "references"
+ ],
+ "properties": {
+ "references": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/components/schemas/Reference",
+ "nullable": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "reference_api-resolve-public",
+ "summary": "Resolve multiple references from a public page",
+ "tags": [
+ "reference_api"
+ ],
+ "security": [
+ {},
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "references",
+ "sharingToken"
+ ],
+ "properties": {
+ "references": {
+ "type": "array",
+ "description": "References to resolve",
+ "items": {
+ "type": "string"
+ }
+ },
+ "sharingToken": {
+ "type": "string",
+ "description": "Token of the public share"
+ },
+ "limit": {
+ "type": "integer",
+ "format": "int64",
+ "default": 1,
+ "description": "Maximum amount of references to resolve, limited to 15"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "References returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "references"
+ ],
+ "properties": {
+ "references": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/components/schemas/Reference",
+ "nullable": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/ocs/v2.php/references/providers": {
"get": {
"operationId": "reference_api-get-providers-info",