From cfd289e30f73253266dc8415ff329ce1bfe6f3df Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 21 Feb 2024 13:03:26 +0100 Subject: [PATCH 01/15] feat(Contexts): API endpoint for getting Contexts Signed-off-by: Arthur Schiwon --- appinfo/info.xml | 1 + appinfo/routes.php | 1 + lib/Command/ListContexts.php | 89 + lib/Controller/ContextController.php | 68 + lib/Db/Context.php | 43 + lib/Db/ContextMapper.php | 66 + lib/ResponseDefinitions.php | 9 + lib/Service/ContextService.php | 45 + openapi.json | 7858 -------------------------- psalm.xml | 1 + 10 files changed, 323 insertions(+), 7858 deletions(-) create mode 100644 lib/Command/ListContexts.php create mode 100644 lib/Controller/ContextController.php create mode 100644 lib/Db/Context.php create mode 100644 lib/Db/ContextMapper.php create mode 100644 lib/Service/ContextService.php delete mode 100644 openapi.json diff --git a/appinfo/info.xml b/appinfo/info.xml index e6f1c544c..2ebaaa3ec 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -56,6 +56,7 @@ Have a good time and manage whatever you want. OCA\Tables\Command\RemoveTable OCA\Tables\Command\RenameTable OCA\Tables\Command\ChangeOwnershipTable + OCA\Tables\Command\ListContexts OCA\Tables\Command\Clean OCA\Tables\Command\CleanLegacy OCA\Tables\Command\TransferLegacyRows diff --git a/appinfo/routes.php b/appinfo/routes.php index f3c58beb5..0e1e75518 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -128,5 +128,6 @@ ['name' => 'ApiFavorite#create', 'url' => '/api/2/favorites/{nodeType}/{nodeId}', 'verb' => 'POST', 'requirements' => ['nodeType' => '(\d+)', 'nodeId' => '(\d+)']], ['name' => 'ApiFavorite#destroy', 'url' => '/api/2/favorites/{nodeType}/{nodeId}', 'verb' => 'DELETE', 'requirements' => ['nodeType' => '(\d+)', 'nodeId' => '(\d+)']], + ['name' => 'Context#index', 'url' => '/api/2/contexts', 'verb' => 'GET'], ] ]; diff --git a/lib/Command/ListContexts.php b/lib/Command/ListContexts.php new file mode 100644 index 000000000..3af8e1b52 --- /dev/null +++ b/lib/Command/ListContexts.php @@ -0,0 +1,89 @@ +contextService = $contextService; + $this->logger = $logger; + $this->config = $config; + } + + protected function configure(): void { + parent::configure(); + $this + ->setName('tables:contexts:list') + ->setDescription('Get all contexts or contexts available to a specified user') + ->addArgument( + 'user-id', + InputArgument::OPTIONAL, + 'User ID of the user' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $userId = trim($input->getArgument('user-id')); + if ($userId === '') { + $userId = null; + } + + try { + $contexts = $this->contextService->findAll($userId); + } catch (InternalError|Exception $e) { + $output->writeln('Error while reading contexts from DB.'); + $this->logger->warning('Following error occurred during executing occ command "{class}"', + [ + 'app' => 'tables', + 'class' => self::class, + 'exception' => $e, + ] + ); + if ($this->config->getSystemValueBool('debug', false)) { + $output->writeln(sprintf('%s', $e->getMessage())); + $output->writeln(''); + debug_print_backtrace(); + $output->writeln(''); + } + return 1; + } + + foreach ($contexts as $context) { + $contextArray = json_decode(json_encode($context), true); + + $contextArray['ownerType'] = match ($contextArray['ownerType']) { + 1 => 'group', + default => 'user', + }; + + $out = ['ID ' . $contextArray['id'] => $contextArray]; + unset($out[$contextArray['id']]['id']); + $this->writeArrayInOutputFormat($input, $output, $out); + } + + return 0; + } +} diff --git a/lib/Controller/ContextController.php b/lib/Controller/ContextController.php new file mode 100644 index 000000000..4fe5d0318 --- /dev/null +++ b/lib/Controller/ContextController.php @@ -0,0 +1,68 @@ +contextService = $contextService; + $this->userId = $userId; + } + + /** + * [api v3] Get all contexts available to the requesting person + * + * Return an empty array if no contexts were found + * + * @return DataResponse|DataResponse + * + * 200: reporting in available contexts + * + * @NoAdminRequired + */ + public function index(): DataResponse { + try { + $contexts = $this->contextService->findAll($this->userId); + return new DataResponse($this->contextsToArray($contexts)); + } catch (InternalError|Exception $e) { + return $this->handleError($e); + } + } + + /** + * @param Context[] $contexts + * @return array + */ + protected function contextsToArray(array $contexts): array { + $result = []; + foreach ($contexts as $context) { + $result[] = $context->jsonSerialize(); + } + return $result; + } +} diff --git a/lib/Db/Context.php b/lib/Db/Context.php new file mode 100644 index 000000000..5d3983370 --- /dev/null +++ b/lib/Db/Context.php @@ -0,0 +1,43 @@ +addType('id', 'integer'); + } + + public function jsonSerialize(): array { + return [ + 'id' => $this->getId(), + 'name' => $this->getName(), + 'iconName' => $this->getIcon(), + 'description' => $this->getDescription(), + 'owner' => $this->getOwnerId(), + 'ownerType' => $this->getOwnerType() + ]; + } +} diff --git a/lib/Db/ContextMapper.php b/lib/Db/ContextMapper.php new file mode 100644 index 000000000..d6257a699 --- /dev/null +++ b/lib/Db/ContextMapper.php @@ -0,0 +1,66 @@ + */ +class ContextMapper extends QBMapper { + protected string $table = 'tables_contexts_context'; + private UserHelper $userHelper; + + public function __construct(IDBConnection $db, UserHelper $userHelper) { + $this->userHelper = $userHelper; + parent::__construct($db, $this->table, Context::class); + } + + /** + * @return Context[] + * @throws Exception + */ + public function findAll(?string $userId = null): array { + $qb = $this->db->getQueryBuilder(); + $qb->select('c.*') + ->from($this->table, 'c'); + if ($userId !== null) { + $sharedToConditions = $qb->expr()->orX(); + + // shared to user clause + $userShare = $qb->expr()->andX( + $qb->expr()->eq('s.receiver_type', $qb->createNamedParameter('user')), + $qb->expr()->eq('s.receiver', $qb->createNamedParameter($userId)), + ); + $sharedToConditions->add($userShare); + + // shared to group clause + $groupIDs = $this->userHelper->getGroupIdsForUser($userId); + if (!empty($groupIDs)) { + $groupShares = $qb->expr()->andX( + $qb->expr()->eq('s.receiver_type', $qb->createNamedParameter('group')), + $qb->expr()->in('s.receiver', $qb->createNamedParameter($groupIDs, IQueryBuilder::PARAM_STR_ARRAY)), + ); + $sharedToConditions->add($groupShares); + } + + // owned contexts + apply share conditions + $qb->leftJoin('c', 'tables_shares', 's', $qb->expr()->andX( + $qb->expr()->eq('c.id', 's.node_id'), + $qb->expr()->eq('s.node_type', $qb->createNamedParameter('context')), + $sharedToConditions, + )); + + $qb->where($qb->expr()->orX( + $qb->expr()->eq('owner_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)), + $qb->expr()->isNotNull('s.receiver'), + )); + } + + return $this->findEntities($qb); + } +} diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php index 172b760a0..d738a3c0d 100644 --- a/lib/ResponseDefinitions.php +++ b/lib/ResponseDefinitions.php @@ -128,6 +128,15 @@ * errors_parsing_count: int, * errors_count: int, * } + * + * @psalm-type TablesContext = array{ + * id: int, + * name: string, + * iconName: string, + * description: string, + * owner: string, + * ownerType: int, + * } */ class ResponseDefinitions { } diff --git a/lib/Service/ContextService.php b/lib/Service/ContextService.php new file mode 100644 index 000000000..49468bbdd --- /dev/null +++ b/lib/Service/ContextService.php @@ -0,0 +1,45 @@ +mapper = $mapper; + $this->isCLI = $isCLI; + $this->logger = $logger; + } + + /** + * @throws InternalError + * @throws Exception + * @return Context[] + */ + public function findAll(?string $userId): array { + if ($userId !== null && trim($userId) === '') { + $userId = null; + } + if ($userId === null && !$this->isCLI) { + $error = 'Try to set no user in context, but request is not allowed.'; + $this->logger->warning($error); + throw new InternalError($error); + } + return $this->mapper->findAll($userId); + } +} diff --git a/openapi.json b/openapi.json deleted file mode 100644 index 864136c15..000000000 --- a/openapi.json +++ /dev/null @@ -1,7858 +0,0 @@ -{ - "openapi": "3.0.3", - "info": { - "title": "tables", - "version": "0.0.1", - "description": "Manage data the way you need it.", - "license": { - "name": "agpl" - } - }, - "components": { - "securitySchemes": { - "basic_auth": { - "type": "http", - "scheme": "basic" - }, - "bearer_auth": { - "type": "http", - "scheme": "bearer" - } - }, - "schemas": { - "Capabilities": { - "type": "object", - "required": [ - "tables" - ], - "properties": { - "tables": { - "type": "object", - "required": [ - "enabled", - "version", - "apiVersions", - "features", - "column_types" - ], - "properties": { - "enabled": { - "type": "boolean" - }, - "version": { - "type": "string" - }, - "apiVersions": { - "type": "array", - "items": { - "type": "string" - } - }, - "features": { - "type": "array", - "items": { - "type": "string" - } - }, - "column_types": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "Column": { - "type": "object", - "required": [ - "id", - "title", - "tableId", - "createdBy", - "createdAt", - "lastEditBy", - "lastEditAt", - "type", - "subtype", - "mandatory", - "description", - "orderWeight", - "numberDefault", - "numberMin", - "numberMax", - "numberDecimals", - "numberPrefix", - "numberSuffix", - "textDefault", - "textAllowedPattern", - "textMaxLength", - "selectionOptions", - "selectionDefault", - "datetimeDefault" - ], - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "title": { - "type": "string" - }, - "tableId": { - "type": "integer", - "format": "int64" - }, - "createdBy": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "lastEditBy": { - "type": "string" - }, - "lastEditAt": { - "type": "string" - }, - "type": { - "type": "string" - }, - "subtype": { - "type": "string" - }, - "mandatory": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "orderWeight": { - "type": "integer", - "format": "int64" - }, - "numberDefault": { - "type": "number", - "format": "float" - }, - "numberMin": { - "type": "number", - "format": "float" - }, - "numberMax": { - "type": "number", - "format": "float" - }, - "numberDecimals": { - "type": "integer", - "format": "int64" - }, - "numberPrefix": { - "type": "string" - }, - "numberSuffix": { - "type": "string" - }, - "textDefault": { - "type": "string" - }, - "textAllowedPattern": { - "type": "string" - }, - "textMaxLength": { - "type": "integer", - "format": "int64" - }, - "selectionOptions": { - "type": "string" - }, - "selectionDefault": { - "type": "string" - }, - "datetimeDefault": { - "type": "string" - } - } - }, - "ImportState": { - "type": "object", - "required": [ - "found_columns_count", - "matching_columns_count", - "created_columns_count", - "inserted_rows_count", - "errors_parsing_count", - "errors_count" - ], - "properties": { - "found_columns_count": { - "type": "integer", - "format": "int64" - }, - "matching_columns_count": { - "type": "integer", - "format": "int64" - }, - "created_columns_count": { - "type": "integer", - "format": "int64" - }, - "inserted_rows_count": { - "type": "integer", - "format": "int64" - }, - "errors_parsing_count": { - "type": "integer", - "format": "int64" - }, - "errors_count": { - "type": "integer", - "format": "int64" - } - } - }, - "Index": { - "type": "object", - "required": [ - "tables", - "views" - ], - "properties": { - "tables": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Table" - } - }, - "views": { - "type": "array", - "items": { - "$ref": "#/components/schemas/View" - } - } - } - }, - "OCSMeta": { - "type": "object", - "required": [ - "status", - "statuscode" - ], - "properties": { - "status": { - "type": "string" - }, - "statuscode": { - "type": "integer" - }, - "message": { - "type": "string" - }, - "totalitems": { - "type": "string" - }, - "itemsperpage": { - "type": "string" - } - } - }, - "Row": { - "type": "object", - "required": [ - "id", - "tableId", - "createdBy", - "createdAt", - "lastEditBy", - "lastEditAt", - "data" - ], - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "tableId": { - "type": "integer", - "format": "int64" - }, - "createdBy": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "lastEditBy": { - "type": "string" - }, - "lastEditAt": { - "type": "string" - }, - "data": { - "type": "object", - "nullable": true, - "required": [ - "columnId", - "value" - ], - "properties": { - "columnId": { - "type": "integer", - "format": "int64" - }, - "value": { - "type": "object" - } - } - } - } - }, - "Share": { - "type": "object", - "required": [ - "id", - "sender", - "receiver", - "receiverDisplayName", - "receiverType", - "nodeId", - "nodeType", - "permissionRead", - "permissionCreate", - "permissionUpdate", - "permissionDelete", - "permissionManage", - "createdAt", - "createdBy" - ], - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "sender": { - "type": "string" - }, - "receiver": { - "type": "string" - }, - "receiverDisplayName": { - "type": "string" - }, - "receiverType": { - "type": "string" - }, - "nodeId": { - "type": "integer", - "format": "int64" - }, - "nodeType": { - "type": "string" - }, - "permissionRead": { - "type": "boolean" - }, - "permissionCreate": { - "type": "boolean" - }, - "permissionUpdate": { - "type": "boolean" - }, - "permissionDelete": { - "type": "boolean" - }, - "permissionManage": { - "type": "boolean" - }, - "createdAt": { - "type": "string" - }, - "createdBy": { - "type": "string" - } - } - }, - "Table": { - "type": "object", - "required": [ - "id", - "title", - "emoji", - "ownership", - "ownerDisplayName", - "createdBy", - "createdAt", - "lastEditBy", - "lastEditAt", - "archived", - "favorite", - "isShared", - "onSharePermissions", - "hasShares", - "rowsCount", - "views", - "columnsCount" - ], - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "title": { - "type": "string" - }, - "emoji": { - "type": "string", - "nullable": true - }, - "ownership": { - "type": "string" - }, - "ownerDisplayName": { - "type": "string" - }, - "createdBy": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "lastEditBy": { - "type": "string" - }, - "lastEditAt": { - "type": "string" - }, - "archived": { - "type": "boolean" - }, - "favorite": { - "type": "boolean" - }, - "isShared": { - "type": "boolean" - }, - "onSharePermissions": { - "type": "object", - "nullable": true, - "required": [ - "read", - "create", - "update", - "delete", - "manage" - ], - "properties": { - "read": { - "type": "boolean" - }, - "create": { - "type": "boolean" - }, - "update": { - "type": "boolean" - }, - "delete": { - "type": "boolean" - }, - "manage": { - "type": "boolean" - } - } - }, - "hasShares": { - "type": "boolean" - }, - "rowsCount": { - "type": "integer", - "format": "int64" - }, - "views": { - "type": "array", - "items": { - "$ref": "#/components/schemas/View" - } - }, - "columnsCount": { - "type": "integer", - "format": "int64" - } - } - }, - "View": { - "type": "object", - "required": [ - "id", - "title", - "emoji", - "tableId", - "ownership", - "ownerDisplayName", - "createdBy", - "createdAt", - "lastEditBy", - "lastEditAt", - "description", - "columns", - "sort", - "filter", - "isShared", - "favorite", - "onSharePermissions", - "hasShares", - "rowsCount" - ], - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "title": { - "type": "string" - }, - "emoji": { - "type": "string", - "nullable": true - }, - "tableId": { - "type": "integer", - "format": "int64" - }, - "ownership": { - "type": "string" - }, - "ownerDisplayName": { - "type": "string", - "nullable": true - }, - "createdBy": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "lastEditBy": { - "type": "string" - }, - "lastEditAt": { - "type": "string" - }, - "description": { - "type": "string", - "nullable": true - }, - "columns": { - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - "sort": { - "type": "array", - "items": { - "type": "object", - "required": [ - "columnId", - "mode" - ], - "properties": { - "columnId": { - "type": "integer", - "format": "int64" - }, - "mode": { - "type": "string", - "enum": [ - "ASC", - "DESC" - ] - } - } - } - }, - "filter": { - "type": "array", - "items": { - "type": "array", - "items": { - "type": "object", - "required": [ - "columnId", - "operator", - "value" - ], - "properties": { - "columnId": { - "type": "integer", - "format": "int64" - }, - "operator": { - "type": "string", - "enum": [ - "begins-with", - "ends-with", - "contains", - "is-equal", - "is-greater-than", - "is-greater-than-or-equal", - "is-lower-than", - "is-lower-than-or-equal", - "is-empty" - ] - }, - "value": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer", - "format": "int64" - }, - { - "type": "number", - "format": "float" - } - ] - } - } - } - } - }, - "isShared": { - "type": "boolean" - }, - "favorite": { - "type": "boolean" - }, - "onSharePermissions": { - "type": "object", - "nullable": true, - "required": [ - "read", - "create", - "update", - "delete", - "manage" - ], - "properties": { - "read": { - "type": "boolean" - }, - "create": { - "type": "boolean" - }, - "update": { - "type": "boolean" - }, - "delete": { - "type": "boolean" - }, - "manage": { - "type": "boolean" - } - } - }, - "hasShares": { - "type": "boolean" - }, - "rowsCount": { - "type": "integer", - "format": "int64" - } - } - } - } - }, - "paths": { - "/index.php/apps/tables/api/1/tables": { - "get": { - "operationId": "api1-list", - "summary": "Returns all Tables", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "responses": { - "200": { - "description": "Tables returned", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Table" - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "post": { - "operationId": "api1-create-table", - "summary": "Create a new table and return it", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "title", - "in": "query", - "description": "Title of the table", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "emoji", - "in": "query", - "description": "Emoji for the table", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "template", - "in": "query", - "description": "Template to use if wanted", - "schema": { - "type": "string", - "default": "custom" - } - } - ], - "responses": { - "200": { - "description": "Tables returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Table" - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/tables/{tableId}": { - "put": { - "operationId": "api1-update-table", - "summary": "Update tables properties", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "title", - "in": "query", - "description": "New table title", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "emoji", - "in": "query", - "description": "New table emoji", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "archived", - "in": "query", - "description": "Whether the table is archived", - "schema": { - "type": "integer", - "default": 0, - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "tableId", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Tables returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Table" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "get": { - "operationId": "api1-get-table", - "summary": "Get a table object", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "tableId", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Table returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Table" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "delete": { - "operationId": "api1-delete-table", - "summary": "Delete a table", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "tableId", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Deleted table returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Table" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/tables/{tableId}/views": { - "get": { - "operationId": "api1-list-views", - "summary": "Get all views for a table", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "tableId", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Views returned", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/View" - } - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "post": { - "operationId": "api1-create-view", - "summary": "Create a new view for a table", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "title", - "in": "query", - "description": "Title for the view", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "emoji", - "in": "query", - "description": "Emoji for the view", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "tableId", - "in": "path", - "description": "Table ID that will hold the view", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "View created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/View" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/views/{viewId}": { - "get": { - "operationId": "api1-get-view", - "summary": "Get a view object", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "viewId", - "in": "path", - "description": "View ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "View returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/View" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "put": { - "operationId": "api1-update-view", - "summary": "Update a view via key-value sets", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "data", - "in": "query", - "description": "key-value pairs", - "required": true, - "schema": { - "oneOf": [ - { - "type": "object", - "required": [ - "key", - "value" - ], - "properties": { - "key": { - "type": "string", - "enum": [ - "title", - "emoji", - "description" - ] - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "key", - "value" - ], - "properties": { - "key": { - "type": "string", - "enum": [ - "columns" - ] - }, - "value": { - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - } - } - }, - { - "type": "object", - "required": [ - "key", - "value" - ], - "properties": { - "key": { - "type": "string", - "enum": [ - "sort" - ] - }, - "value": { - "type": "object", - "required": [ - "columnId", - "mode" - ], - "properties": { - "columnId": { - "type": "integer", - "format": "int64" - }, - "mode": { - "type": "string", - "enum": [ - "ASC", - "DESC" - ] - } - } - } - } - }, - { - "type": "object", - "required": [ - "key", - "value" - ], - "properties": { - "key": { - "type": "string", - "enum": [ - "filter" - ] - }, - "value": { - "type": "object", - "required": [ - "columnId", - "operator", - "value" - ], - "properties": { - "columnId": { - "type": "integer", - "format": "int64" - }, - "operator": { - "type": "string", - "enum": [ - "begins-with", - "ends-with", - "contains", - "is-equal", - "is-greater-than", - "is-greater-than-or-equal", - "is-lower-than", - "is-lower-than-or-equal", - "is-empty" - ] - }, - "value": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer", - "format": "int64" - }, - { - "type": "number", - "format": "float" - } - ] - } - } - } - } - } - ] - } - }, - { - "name": "viewId", - "in": "path", - "description": "View ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "View updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/View" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "delete": { - "operationId": "api1-delete-view", - "summary": "Delete a view", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "viewId", - "in": "path", - "description": "View ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "View deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/View" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/shares/{shareId}": { - "get": { - "operationId": "api1-get-share", - "summary": "Get a share object", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "shareId", - "in": "path", - "description": "Share ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Share returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Share" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "delete": { - "operationId": "api1-delete-share", - "summary": "Delete a share", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "shareId", - "in": "path", - "description": "Share ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "View deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Share" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "put": { - "operationId": "api1-update-share-permissions", - "summary": "Update a share permission", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "permissionType", - "in": "query", - "description": "Permission type that should be changed", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "permissionValue", - "in": "query", - "description": "New permission value", - "required": true, - "schema": { - "type": "integer", - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "shareId", - "in": "path", - "description": "Share ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "View deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Share" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/views/{viewId}/shares": { - "get": { - "operationId": "api1-list-view-shares", - "summary": "Get all shares for a view Will be empty if view does not exist", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "viewId", - "in": "path", - "description": "View ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Shares returned", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Share" - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/tables/{tableId}/shares": { - "get": { - "operationId": "api1-list-table-shares", - "summary": "Get all shares for a table Will be empty if table does not exist", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "tableId", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Shares returned", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Share" - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "post": { - "operationId": "api1-create-table-share", - "summary": "Create a share for a table", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "receiver", - "in": "query", - "description": "Receiver ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "receiverType", - "in": "query", - "description": "Receiver type", - "required": true, - "schema": { - "type": "string", - "enum": [ - "user", - "group" - ] - } - }, - { - "name": "permissionRead", - "in": "query", - "description": "Permission if receiver can read data", - "required": true, - "schema": { - "type": "integer", - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "permissionCreate", - "in": "query", - "description": "Permission if receiver can create data", - "required": true, - "schema": { - "type": "integer", - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "permissionUpdate", - "in": "query", - "description": "Permission if receiver can update data", - "required": true, - "schema": { - "type": "integer", - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "permissionDelete", - "in": "query", - "description": "Permission if receiver can delete data", - "required": true, - "schema": { - "type": "integer", - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "permissionManage", - "in": "query", - "description": "Permission if receiver can manage table", - "required": true, - "schema": { - "type": "integer", - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "tableId", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "View deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Share" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/shares": { - "post": { - "operationId": "api1-create-share", - "summary": "Create a new share", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "nodeId", - "in": "query", - "description": "Node ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "nodeType", - "in": "query", - "description": "Node type", - "required": true, - "schema": { - "type": "string", - "enum": [ - "table", - "view" - ] - } - }, - { - "name": "receiver", - "in": "query", - "description": "Receiver ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "receiverType", - "in": "query", - "description": "Receiver type", - "required": true, - "schema": { - "type": "string", - "enum": [ - "user", - "group" - ] - } - }, - { - "name": "permissionRead", - "in": "query", - "description": "Permission if receiver can read data", - "schema": { - "type": "integer", - "default": 0, - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "permissionCreate", - "in": "query", - "description": "Permission if receiver can create data", - "schema": { - "type": "integer", - "default": 0, - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "permissionUpdate", - "in": "query", - "description": "Permission if receiver can update data", - "schema": { - "type": "integer", - "default": 0, - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "permissionDelete", - "in": "query", - "description": "Permission if receiver can delete data", - "schema": { - "type": "integer", - "default": 0, - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "permissionManage", - "in": "query", - "description": "Permission if receiver can manage node", - "schema": { - "type": "integer", - "default": 0, - "enum": [ - 0, - 1 - ] - } - } - ], - "responses": { - "200": { - "description": "Share returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Share" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/tables/{tableId}/columns": { - "get": { - "operationId": "api1-list-table-columns", - "summary": "Get all columns for a table or a underlying view Return an empty array if no columns were found", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "viewId", - "in": "query", - "description": "View ID", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "tableId", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "View deleted", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Column" - } - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "post": { - "operationId": "api1-create-table-column", - "summary": "Create a new column for a table", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "title", - "in": "query", - "description": "Title", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "type", - "in": "query", - "description": "Column main type", - "required": true, - "schema": { - "type": "string", - "enum": [ - "text", - "number", - "datetime", - "select" - ] - } - }, - { - "name": "subtype", - "in": "query", - "description": "Column sub type", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "mandatory", - "in": "query", - "description": "Is the column mandatory", - "required": true, - "schema": { - "type": "integer", - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "description", - "in": "query", - "description": "Description", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "numberPrefix", - "in": "query", - "description": "Prefix if the column is a number field", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "numberSuffix", - "in": "query", - "description": "Suffix if the column is a number field", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "numberDefault", - "in": "query", - "description": "Default number, if column is a number", - "schema": { - "type": "number", - "format": "float", - "nullable": true - } - }, - { - "name": "numberMin", - "in": "query", - "description": "Min value, if column is a number", - "schema": { - "type": "number", - "format": "float", - "nullable": true - } - }, - { - "name": "numberMax", - "in": "query", - "description": "Max number, if column is a number", - "schema": { - "type": "number", - "format": "float", - "nullable": true - } - }, - { - "name": "numberDecimals", - "in": "query", - "description": "Number of decimals, if column is a number", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "textDefault", - "in": "query", - "description": "Default text, if column is a text", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "textAllowedPattern", - "in": "query", - "description": "Allowed pattern (regex) for text columns (not yet implemented)", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "textMaxLength", - "in": "query", - "description": "Max length, if column is a text", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "selectionOptions", - "in": "query", - "description": "Options for a selection (json array{id: int, label: string})", - "schema": { - "type": "string", - "nullable": true, - "default": "" - } - }, - { - "name": "selectionDefault", - "in": "query", - "description": "Default option IDs for a selection (json int[])", - "schema": { - "type": "string", - "nullable": true, - "default": "" - } - }, - { - "name": "datetimeDefault", - "in": "query", - "description": "Default value, if column is datetime", - "schema": { - "type": "string", - "nullable": true, - "default": "" - } - }, - { - "name": "selectedViewIds[]", - "in": "query", - "description": "View IDs where this column should be added to be presented", - "schema": { - "type": "array", - "nullable": true, - "default": [], - "items": { - "type": "integer", - "format": "int64" - } - } - }, - { - "name": "tableId", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Column created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Column" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/views/{viewId}/columns": { - "get": { - "operationId": "api1-list-view-columns", - "summary": "Get all columns for a view Return an empty array if no columns were found", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "viewId", - "in": "path", - "description": "View ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "View deleted", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Column" - } - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/columns": { - "post": { - "operationId": "api1-create-column", - "summary": "Create a column", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "tableId", - "in": "query", - "description": "Table ID", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "viewId", - "in": "query", - "description": "View ID", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "title", - "in": "query", - "description": "Title", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "type", - "in": "query", - "description": "Column main type", - "required": true, - "schema": { - "type": "string", - "enum": [ - "text", - "number", - "datetime", - "select" - ] - } - }, - { - "name": "subtype", - "in": "query", - "description": "Column sub type", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "mandatory", - "in": "query", - "description": "Is the column mandatory", - "required": true, - "schema": { - "type": "integer", - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "description", - "in": "query", - "description": "Description", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "numberPrefix", - "in": "query", - "description": "Prefix if the column is a number field", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "numberSuffix", - "in": "query", - "description": "Suffix if the column is a number field", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "numberDefault", - "in": "query", - "description": "Default number, if column is a number", - "schema": { - "type": "number", - "format": "float", - "nullable": true - } - }, - { - "name": "numberMin", - "in": "query", - "description": "Min value, if column is a number", - "schema": { - "type": "number", - "format": "float", - "nullable": true - } - }, - { - "name": "numberMax", - "in": "query", - "description": "Max number, if column is a number", - "schema": { - "type": "number", - "format": "float", - "nullable": true - } - }, - { - "name": "numberDecimals", - "in": "query", - "description": "Number of decimals, if column is a number", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "textDefault", - "in": "query", - "description": "Default text, if column is a text", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "textAllowedPattern", - "in": "query", - "description": "Allowed pattern (regex) for text columns (not yet implemented)", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "textMaxLength", - "in": "query", - "description": "Max length, if column is a text", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "selectionOptions", - "in": "query", - "description": "Options for a selection (json array{id: int, label: string})", - "schema": { - "type": "string", - "nullable": true, - "default": "" - } - }, - { - "name": "selectionDefault", - "in": "query", - "description": "Default option IDs for a selection (json int[])", - "schema": { - "type": "string", - "nullable": true, - "default": "" - } - }, - { - "name": "datetimeDefault", - "in": "query", - "description": "Default value, if column is datetime", - "schema": { - "type": "string", - "nullable": true, - "default": "" - } - }, - { - "name": "selectedViewIds[]", - "in": "query", - "description": "View IDs where this column should be added to be presented", - "schema": { - "type": "array", - "nullable": true, - "default": [], - "items": { - "type": "integer", - "format": "int64" - } - } - } - ], - "responses": { - "200": { - "description": "Column created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Column" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/columns/{columnId}": { - "put": { - "operationId": "api1-update-column", - "summary": "Update a column", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "title", - "in": "query", - "description": "Title", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "subtype", - "in": "query", - "description": "Column sub type", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "mandatory", - "in": "query", - "description": "Is the column mandatory", - "required": true, - "schema": { - "type": "integer", - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "description", - "in": "query", - "description": "Description", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "numberPrefix", - "in": "query", - "description": "Prefix if the column is a number field", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "numberSuffix", - "in": "query", - "description": "Suffix if the column is a number field", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "numberDefault", - "in": "query", - "description": "Default number, if column is a number", - "schema": { - "type": "number", - "format": "float", - "nullable": true - } - }, - { - "name": "numberMin", - "in": "query", - "description": "Min value, if column is a number", - "schema": { - "type": "number", - "format": "float", - "nullable": true - } - }, - { - "name": "numberMax", - "in": "query", - "description": "Max number, if column is a number", - "schema": { - "type": "number", - "format": "float", - "nullable": true - } - }, - { - "name": "numberDecimals", - "in": "query", - "description": "Number of decimals, if column is a number", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "textDefault", - "in": "query", - "description": "Default text, if column is a text", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "textAllowedPattern", - "in": "query", - "description": "Allowed pattern (regex) for text columns (not yet implemented)", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "textMaxLength", - "in": "query", - "description": "Max length, if column is a text", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "selectionOptions", - "in": "query", - "description": "Options for a selection (json array{id: int, label: string})", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "selectionDefault", - "in": "query", - "description": "Default option IDs for a selection (json int[])", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "datetimeDefault", - "in": "query", - "description": "Default value, if column is datetime", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "columnId", - "in": "path", - "description": "Column ID that will be updated", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Updated column", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Column" - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "get": { - "operationId": "api1-get-column", - "summary": "Returns a column object", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "columnId", - "in": "path", - "description": "Wanted Column ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Column returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Column" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "delete": { - "operationId": "api1-delete-column", - "summary": "Delete a column", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "columnId", - "in": "path", - "description": "Wanted Column ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Deleted column returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Column" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/tables/{tableId}/rows/simple": { - "get": { - "operationId": "api1-list-table-rows-simple", - "summary": "List all rows values for a table, first row are the column titles", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "limit", - "in": "query", - "description": "Limit", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "offset", - "in": "query", - "description": "Offset", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "tableId", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Row values returned", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/tables/{tableId}/rows": { - "get": { - "operationId": "api1-list-table-rows", - "summary": "List all rows for a table", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "limit", - "in": "query", - "description": "Limit", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "offset", - "in": "query", - "description": "Offset", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "tableId", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Rows returned", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Row" - } - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "post": { - "operationId": "api1-create-row-in-table", - "summary": "Create a row within a table", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "data", - "in": "query", - "description": "Data as key - value store", - "required": true, - "schema": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "object", - "required": [ - "columnId", - "value" - ], - "properties": { - "columnId": { - "type": "integer", - "format": "int64" - }, - "value": { - "type": "object" - } - } - } - ] - } - }, - { - "name": "tableId", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Row returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Row" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/views/{viewId}/rows": { - "get": { - "operationId": "api1-list-view-rows", - "summary": "List all rows for a view", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "limit", - "in": "query", - "description": "Limit", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "offset", - "in": "query", - "description": "Offset", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "viewId", - "in": "path", - "description": "View ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Rows returned", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Row" - } - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "post": { - "operationId": "api1-create-row-in-view", - "summary": "Create a row within a view", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "data", - "in": "query", - "description": "Data as key - value store", - "required": true, - "schema": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "object", - "required": [ - "columnId", - "value" - ], - "properties": { - "columnId": { - "type": "integer", - "format": "int64" - }, - "value": { - "type": "object" - } - } - } - ] - } - }, - { - "name": "viewId", - "in": "path", - "description": "View ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Row returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Row" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/rows/{rowId}": { - "get": { - "operationId": "api1-get-row", - "summary": "Get a row", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "rowId", - "in": "path", - "description": "Row ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Row returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Row" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "put": { - "operationId": "api1-update-row", - "summary": "Update a row", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "viewId", - "in": "query", - "description": "View ID", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "data", - "in": "query", - "description": "Data as key - value store", - "required": true, - "schema": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "object", - "required": [ - "columnId", - "value" - ], - "properties": { - "columnId": { - "type": "integer", - "format": "int64" - }, - "value": { - "type": "object" - } - } - } - ] - } - }, - { - "name": "rowId", - "in": "path", - "description": "Row ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Updated row returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Row" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "delete": { - "operationId": "api1-delete-row", - "summary": "Delete a row", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "rowId", - "in": "path", - "description": "Row ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Deleted row returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Row" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/views/{viewId}/rows/{rowId}": { - "delete": { - "operationId": "api1-delete-row-by-view", - "summary": "Delete a row within a view", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "viewId", - "in": "path", - "description": "View ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "rowId", - "in": "path", - "description": "Row ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Deleted row returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Row" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/import/table/{tableId}": { - "post": { - "operationId": "api1-import-in-table", - "summary": "Import from file in to a table", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "path", - "in": "query", - "description": "Path to file", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "createMissingColumns", - "in": "query", - "description": "Create missing columns", - "schema": { - "type": "integer", - "default": 1, - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "tableId", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Import status returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ImportState" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/index.php/apps/tables/api/1/import/views/{viewId}": { - "post": { - "operationId": "api1-import-in-view", - "summary": "Import from file in to a table", - "tags": [ - "api1" - ], - "security": [ - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "path", - "in": "query", - "description": "Path to file", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "createMissingColumns", - "in": "query", - "description": "Create missing columns", - "schema": { - "type": "integer", - "default": 1, - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "viewId", - "in": "path", - "description": "View ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Import status returned", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ImportState" - } - } - } - }, - "403": { - "description": "No permissions", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "500": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "/ocs/v2.php/apps/tables/api/2/init": { - "get": { - "operationId": "api_general-list", - "summary": "[api v2] Returns all main resources", - "description": "Tables and views incl. shares", - "tags": [ - "api_general" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "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": "Index returned", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "$ref": "#/components/schemas/Index" - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - } - }, - "/ocs/v2.php/apps/tables/api/2/tables": { - "get": { - "operationId": "api_tables-list", - "summary": "[api v2] Returns all Tables", - "tags": [ - "api_tables" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "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": "Tables returned", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Table" - } - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - }, - "post": { - "operationId": "api_tables-create", - "summary": "[api v2] Create a new table and return it", - "tags": [ - "api_tables" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "title", - "in": "query", - "description": "Title of the table", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "emoji", - "in": "query", - "description": "Emoji for the table", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "template", - "in": "query", - "description": "Template to use if wanted", - "schema": { - "type": "string", - "default": "custom" - } - }, - { - "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": "Tables returned", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "$ref": "#/components/schemas/Table" - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - } - }, - "/ocs/v2.php/apps/tables/api/2/tables/{id}": { - "get": { - "operationId": "api_tables-show", - "summary": "[api v2] Get a table object", - "tags": [ - "api_tables" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "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": "Table returned", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "$ref": "#/components/schemas/Table" - } - } - } - } - } - } - } - }, - "403": { - "description": "No permissions", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "404": { - "description": "Not found", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - }, - "put": { - "operationId": "api_tables-update", - "summary": "[api v2] Update tables properties", - "tags": [ - "api_tables" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "title", - "in": "query", - "description": "New table title", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "emoji", - "in": "query", - "description": "New table emoji", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "archived", - "in": "query", - "description": "whether the table is archived", - "schema": { - "type": "integer", - "default": 0, - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "id", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "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": "Tables returned", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "$ref": "#/components/schemas/Table" - } - } - } - } - } - } - } - }, - "403": { - "description": "No permissions", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "404": { - "description": "Not found", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - }, - "delete": { - "operationId": "api_tables-destroy", - "summary": "[api v2] Delete a table", - "tags": [ - "api_tables" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "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": "Deleted table returned", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "$ref": "#/components/schemas/Table" - } - } - } - } - } - } - } - }, - "403": { - "description": "No permissions", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "404": { - "description": "Not found", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - } - }, - "/ocs/v2.php/apps/tables/api/2/tables/{id}/transfer": { - "put": { - "operationId": "api_tables-transfer", - "summary": "[api v2] Transfer table", - "description": "Transfer table from one user to another", - "tags": [ - "api_tables" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "newOwnerUserId", - "in": "query", - "description": "New user ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "id", - "in": "path", - "description": "Table ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "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": "Ownership changed", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "$ref": "#/components/schemas/Table" - } - } - } - } - } - } - } - }, - "403": { - "description": "No permissions", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "404": { - "description": "Not found", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - } - }, - "/ocs/v2.php/apps/tables/api/2/columns/{nodeType}/{nodeId}": { - "get": { - "operationId": "api_columns-list", - "summary": "[api v2] Get all columns for a table or a view", - "description": "Return an empty array if no columns were found", - "tags": [ - "api_columns" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "nodeType", - "in": "path", - "description": "Node type", - "required": true, - "schema": { - "type": "string", - "enum": [ - "table", - "view" - ] - } - }, - { - "name": "nodeId", - "in": "path", - "description": "Node ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "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": "View deleted", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Column" - } - } - } - } - } - } - } - } - }, - "403": { - "description": "No permissions", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "404": { - "description": "Not found", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - } - }, - "/ocs/v2.php/apps/tables/api/2/columns/{id}": { - "get": { - "operationId": "api_columns-show", - "summary": "[api v2] Get a column object", - "tags": [ - "api_columns" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Column ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "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": "Column returned", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "$ref": "#/components/schemas/Column" - } - } - } - } - } - } - } - }, - "403": { - "description": "No permissions", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "404": { - "description": "Not found", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - } - }, - "/ocs/v2.php/apps/tables/api/2/columns/number": { - "post": { - "operationId": "api_columns-create-number-column", - "summary": "[api v2] Create new numbered column", - "description": "Specify a subtype to use any special numbered column", - "tags": [ - "api_columns" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "baseNodeId", - "in": "query", - "description": "Context of the column creation", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "title", - "in": "query", - "description": "Title", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "numberDefault", - "in": "query", - "description": "Default value for new rows", - "schema": { - "type": "number", - "format": "float", - "nullable": true - } - }, - { - "name": "numberDecimals", - "in": "query", - "description": "Decimals", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "numberPrefix", - "in": "query", - "description": "Prefix", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "numberSuffix", - "in": "query", - "description": "Suffix", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "numberMin", - "in": "query", - "description": "Min", - "schema": { - "type": "number", - "format": "float", - "nullable": true - } - }, - { - "name": "numberMax", - "in": "query", - "description": "Max", - "schema": { - "type": "number", - "format": "float", - "nullable": true - } - }, - { - "name": "subtype", - "in": "query", - "description": "Subtype for the new column", - "schema": { - "type": "string", - "nullable": true, - "enum": [ - "progress", - "stars" - ] - } - }, - { - "name": "description", - "in": "query", - "description": "Description", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "selectedViewIds[]", - "in": "query", - "description": "View IDs where this columns should be added", - "schema": { - "type": "array", - "nullable": true, - "default": [], - "items": { - "type": "integer", - "format": "int64" - } - } - }, - { - "name": "mandatory", - "in": "query", - "description": "Is mandatory", - "schema": { - "type": "integer", - "default": 0, - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "baseNodeType", - "in": "query", - "description": "Context type of the column creation", - "schema": { - "type": "string", - "default": "table", - "enum": [ - "table", - "view" - ] - } - }, - { - "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": "Column created", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "$ref": "#/components/schemas/Column" - } - } - } - } - } - } - } - }, - "403": { - "description": "No permission", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "text/plain": { - "schema": { - "type": "string" - } - } - } - }, - "404": { - "description": "Not found", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - } - }, - "/ocs/v2.php/apps/tables/api/2/columns/text": { - "post": { - "operationId": "api_columns-create-text-column", - "summary": "[api v2] Create new text column", - "description": "Specify a subtype to use any special text column", - "tags": [ - "api_columns" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "baseNodeId", - "in": "query", - "description": "Context of the column creation", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "title", - "in": "query", - "description": "Title", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "textDefault", - "in": "query", - "description": "Default", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "textAllowedPattern", - "in": "query", - "description": "Allowed regex pattern", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "textMaxLength", - "in": "query", - "description": "Max raw text length", - "schema": { - "type": "integer", - "format": "int64", - "nullable": true - } - }, - { - "name": "subtype", - "in": "query", - "description": "Subtype for the new column", - "schema": { - "type": "string", - "nullable": true, - "enum": [ - "progress", - "stars" - ] - } - }, - { - "name": "description", - "in": "query", - "description": "Description", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "selectedViewIds[]", - "in": "query", - "description": "View IDs where this columns should be added", - "schema": { - "type": "array", - "nullable": true, - "default": [], - "items": { - "type": "integer", - "format": "int64" - } - } - }, - { - "name": "mandatory", - "in": "query", - "description": "Is mandatory", - "schema": { - "type": "integer", - "default": 0, - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "baseNodeType", - "in": "query", - "description": "Context type of the column creation", - "schema": { - "type": "string", - "default": "table", - "enum": [ - "table", - "view" - ] - } - }, - { - "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": "Column created", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "$ref": "#/components/schemas/Column" - } - } - } - } - } - } - } - }, - "403": { - "description": "No permission", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "text/plain": { - "schema": { - "type": "string" - } - } - } - }, - "404": { - "description": "Not found", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - } - }, - "/ocs/v2.php/apps/tables/api/2/columns/selection": { - "post": { - "operationId": "api_columns-create-selection-column", - "summary": "[api v2] Create new selection column", - "description": "Specify a subtype to use any special selection column", - "tags": [ - "api_columns" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "baseNodeId", - "in": "query", - "description": "Context of the column creation", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "title", - "in": "query", - "description": "Title", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "selectionOptions", - "in": "query", - "description": "Json array{id: int, label: string} with options that can be selected, eg [{\"id\": 1, \"label\": \"first\"},{\"id\": 2, \"label\": \"second\"}]", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "selectionDefault", - "in": "query", - "description": "Json int|int[] for default selected option(s), eg 5 or [\"1\", \"8\"]", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "subtype", - "in": "query", - "description": "Subtype for the new column", - "schema": { - "type": "string", - "nullable": true, - "enum": [ - "progress", - "stars" - ] - } - }, - { - "name": "description", - "in": "query", - "description": "Description", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "selectedViewIds[]", - "in": "query", - "description": "View IDs where this columns should be added", - "schema": { - "type": "array", - "nullable": true, - "default": [], - "items": { - "type": "integer", - "format": "int64" - } - } - }, - { - "name": "mandatory", - "in": "query", - "description": "Is mandatory", - "schema": { - "type": "integer", - "default": 0, - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "baseNodeType", - "in": "query", - "description": "Context type of the column creation", - "schema": { - "type": "string", - "default": "table", - "enum": [ - "table", - "view" - ] - } - }, - { - "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": "Column created", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "$ref": "#/components/schemas/Column" - } - } - } - } - } - } - } - }, - "403": { - "description": "No permission", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "text/plain": { - "schema": { - "type": "string" - } - } - } - }, - "404": { - "description": "Not found", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - } - }, - "/ocs/v2.php/apps/tables/api/2/columns/datetime": { - "post": { - "operationId": "api_columns-create-datetime-column", - "summary": "[api v2] Create new datetime column", - "description": "Specify a subtype to use any special datetime column", - "tags": [ - "api_columns" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "baseNodeId", - "in": "query", - "description": "Context of the column creation", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "title", - "in": "query", - "description": "Title", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "datetimeDefault", - "in": "query", - "description": "For a subtype 'date' you can set 'today'. For a main type or subtype 'time' you can set to 'now'.", - "schema": { - "type": "string", - "nullable": true, - "enum": [ - "today", - "now" - ] - } - }, - { - "name": "subtype", - "in": "query", - "description": "Subtype for the new column", - "schema": { - "type": "string", - "nullable": true, - "enum": [ - "progress", - "stars" - ] - } - }, - { - "name": "description", - "in": "query", - "description": "Description", - "schema": { - "type": "string", - "nullable": true - } - }, - { - "name": "selectedViewIds[]", - "in": "query", - "description": "View IDs where this columns should be added", - "schema": { - "type": "array", - "nullable": true, - "default": [], - "items": { - "type": "integer", - "format": "int64" - } - } - }, - { - "name": "mandatory", - "in": "query", - "description": "Is mandatory", - "schema": { - "type": "integer", - "default": 0, - "enum": [ - 0, - 1 - ] - } - }, - { - "name": "baseNodeType", - "in": "query", - "description": "Context type of the column creation", - "schema": { - "type": "string", - "default": "table", - "enum": [ - "table", - "view" - ] - } - }, - { - "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": "Column created", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "$ref": "#/components/schemas/Column" - } - } - } - } - } - } - } - }, - "403": { - "description": "No permission", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - }, - "text/plain": { - "schema": { - "type": "string" - } - } - } - }, - "404": { - "description": "Not found", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - } - }, - "/ocs/v2.php/apps/tables/api/2/favorites/{nodeType}/{nodeId}": { - "post": { - "operationId": "api_favorite-create", - "summary": "[api v2] Add a node (table or view) to user favorites", - "tags": [ - "api_favorite" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "nodeType", - "in": "path", - "description": "any Application::NODE_TYPE_* constant", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "nodeId", - "in": "path", - "description": "identifier of the node", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "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": "Tables 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" - } - } - } - } - } - } - } - }, - "403": { - "description": "No permissions", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "404": { - "description": "Not found", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - }, - "delete": { - "operationId": "api_favorite-destroy", - "summary": "[api v2] Remove a node (table or view) to from favorites", - "tags": [ - "api_favorite" - ], - "security": [ - { - "bearer_auth": [] - }, - { - "basic_auth": [] - } - ], - "parameters": [ - { - "name": "nodeType", - "in": "path", - "description": "any Application::NODE_TYPE_* constant", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "nodeId", - "in": "path", - "description": "identifier of the node", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "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": "Deleted table 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" - } - } - } - } - } - } - } - }, - "403": { - "description": "No permissions", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "500": { - "description": "", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "404": { - "description": "Not found", - "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": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - } - } - } - } - } - } - } - } - } - } - } - }, - "tags": [] -} \ No newline at end of file diff --git a/psalm.xml b/psalm.xml index 745419a77..651516ea3 100644 --- a/psalm.xml +++ b/psalm.xml @@ -36,6 +36,7 @@ + From c24074f91683cc39d51b47e80cbe5491ebf76300 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 21 Feb 2024 22:10:38 +0100 Subject: [PATCH 02/15] feat(Contexts): API to get full context info Signed-off-by: Arthur Schiwon --- appinfo/info.xml | 1 + appinfo/routes.php | 1 + lib/Command/ShowContext.php | 98 +++++++++++++++ lib/Controller/ContextController.php | 19 +++ lib/Db/Context.php | 22 +++- lib/Db/ContextMapper.php | 172 +++++++++++++++++++++++---- lib/Service/ContextService.php | 17 +++ 7 files changed, 304 insertions(+), 26 deletions(-) create mode 100644 lib/Command/ShowContext.php diff --git a/appinfo/info.xml b/appinfo/info.xml index 2ebaaa3ec..53672fbe8 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -57,6 +57,7 @@ Have a good time and manage whatever you want. OCA\Tables\Command\RenameTable OCA\Tables\Command\ChangeOwnershipTable OCA\Tables\Command\ListContexts + OCA\Tables\Command\ShowContext OCA\Tables\Command\Clean OCA\Tables\Command\CleanLegacy OCA\Tables\Command\TransferLegacyRows diff --git a/appinfo/routes.php b/appinfo/routes.php index 0e1e75518..4e438ee6c 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -129,5 +129,6 @@ ['name' => 'ApiFavorite#create', 'url' => '/api/2/favorites/{nodeType}/{nodeId}', 'verb' => 'POST', 'requirements' => ['nodeType' => '(\d+)', 'nodeId' => '(\d+)']], ['name' => 'ApiFavorite#destroy', 'url' => '/api/2/favorites/{nodeType}/{nodeId}', 'verb' => 'DELETE', 'requirements' => ['nodeType' => '(\d+)', 'nodeId' => '(\d+)']], ['name' => 'Context#index', 'url' => '/api/2/contexts', 'verb' => 'GET'], + ['name' => 'Context#show', 'url' => '/api/2/contexts/{contextId}', 'verb' => 'GET'], ] ]; diff --git a/lib/Command/ShowContext.php b/lib/Command/ShowContext.php new file mode 100644 index 000000000..239483c51 --- /dev/null +++ b/lib/Command/ShowContext.php @@ -0,0 +1,98 @@ +contextService = $contextService; + $this->logger = $logger; + $this->config = $config; + } + + protected function configure(): void { + parent::configure(); + $this + ->setName('tables:contexts:show') + ->setDescription('Get all contexts or contexts available to a specified user') + ->addArgument( + 'context-id', + InputArgument::REQUIRED, + 'The ID of the context to show' + ) + ->addArgument( + 'user-id', + InputArgument::OPTIONAL, + 'Optionally, showing the context from the perspective of the given user' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $contextId = trim($input->getArgument('context-id')); + if ($contextId === '' || !is_numeric($contextId)) { + $output->writeln('Invalid Context ID'); + return 1; + } + + $userId = trim($input->getArgument('user-id')); + if ($userId === '') { + $userId = null; + } + + try { + $context = $this->contextService->findById($contextId, $userId); + } catch (InternalError|Exception $e) { + $output->writeln('Error while reading contexts from DB.'); + $this->logger->warning('Following error occurred during executing occ command "{class}"', + [ + 'app' => 'tables', + 'class' => self::class, + 'exception' => $e, + ] + ); + if ($this->config->getSystemValueBool('debug', false)) { + $output->writeln(sprintf('%s', $e->getMessage())); + $output->writeln(''); + debug_print_backtrace(); + $output->writeln(''); + } + return 1; + } + + $contextArray = json_decode(json_encode($context), true); + + $contextArray['ownerType'] = match ($contextArray['ownerType']) { + 1 => 'group', + default => 'user', + }; + + $out = ['ID ' . $contextArray['id'] => $contextArray]; + unset($out[$contextArray['id']]['id']); + $this->writeArrayInOutputFormat($input, $output, $out); + + return 0; + } +} diff --git a/lib/Controller/ContextController.php b/lib/Controller/ContextController.php index 4fe5d0318..5a09ab0b4 100644 --- a/lib/Controller/ContextController.php +++ b/lib/Controller/ContextController.php @@ -54,6 +54,25 @@ public function index(): DataResponse { } } + /** + * [api v3] Get information about the requests context + * + * @return DataResponse|DataResponse + * + * 200: returning the full context information + * 404: context not found or not available anymore + * + * @NoAdminRequired + */ + public function show(int $contextId): DataResponse { + try { + $context = $this->contextService->findById($contextId, $this->userId); + return new DataResponse($context->jsonSerialize()); + } catch (InternalError|Exception $e) { + return $this->handleError($e); + } + } + /** * @param Context[] $contexts * @return array diff --git a/lib/Db/Context.php b/lib/Db/Context.php index 5d3983370..8da45c6b3 100644 --- a/lib/Db/Context.php +++ b/lib/Db/Context.php @@ -18,6 +18,13 @@ * @method setOwnerId(string $value): void * @method getOwnerType(): int * @method setOwnerType(int $value): void + * + * @method getSharing(): array + * @method setSharing(array $value): void + * @method getNodes(): array + * @method setNodes(array $value): void + * @method getPages(): array + * @method setPages(array $value): void */ class Context extends Entity implements JsonSerializable { protected ?string $name = null; @@ -25,13 +32,17 @@ class Context extends Entity implements JsonSerializable { protected ?string $description = null; protected ?string $ownerId = null; protected ?int $ownerType = null; + protected ?array $sharing = null; + protected ?array $nodes = null; + protected ?array $pages = null; public function __construct() { $this->addType('id', 'integer'); } public function jsonSerialize(): array { - return [ + // basic information + $data = [ 'id' => $this->getId(), 'name' => $this->getName(), 'iconName' => $this->getIcon(), @@ -39,5 +50,14 @@ public function jsonSerialize(): array { 'owner' => $this->getOwnerId(), 'ownerType' => $this->getOwnerType() ]; + + // extended data + if (is_array($this->sharing) || is_array($this->nodes) || is_array($this->pages)) { + $data['sharing'] = $this->getSharing(); + $data['nodes'] = $this->getNodes(); + $data['pages'] = $this->getPages(); + } + + return $data; } } diff --git a/lib/Db/ContextMapper.php b/lib/Db/ContextMapper.php index d6257a699..f0048bcce 100644 --- a/lib/Db/ContextMapper.php +++ b/lib/Db/ContextMapper.php @@ -5,6 +5,8 @@ namespace OCA\Tables\Db; use OCA\Tables\Helper\UserHelper; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\AppFramework\Db\QBMapper; use OCP\DB\Exception; use OCP\DB\QueryBuilder\IQueryBuilder; @@ -19,7 +21,6 @@ public function __construct(IDBConnection $db, UserHelper $userHelper) { $this->userHelper = $userHelper; parent::__construct($db, $this->table, Context::class); } - /** * @return Context[] * @throws Exception @@ -29,38 +30,159 @@ public function findAll(?string $userId = null): array { $qb->select('c.*') ->from($this->table, 'c'); if ($userId !== null) { - $sharedToConditions = $qb->expr()->orX(); + $this->applyOwnedOrSharedQuery($qb, $userId); + } - // shared to user clause - $userShare = $qb->expr()->andX( - $qb->expr()->eq('s.receiver_type', $qb->createNamedParameter('user')), - $qb->expr()->eq('s.receiver', $qb->createNamedParameter($userId)), - ); - $sharedToConditions->add($userShare); - - // shared to group clause - $groupIDs = $this->userHelper->getGroupIdsForUser($userId); - if (!empty($groupIDs)) { - $groupShares = $qb->expr()->andX( - $qb->expr()->eq('s.receiver_type', $qb->createNamedParameter('group')), - $qb->expr()->in('s.receiver', $qb->createNamedParameter($groupIDs, IQueryBuilder::PARAM_STR_ARRAY)), - ); - $sharedToConditions->add($groupShares); - } + return $this->findEntities($qb); + } - // owned contexts + apply share conditions + /** + * @throws DoesNotExistException + * @throws MultipleObjectsReturnedException + * @throws Exception + */ + public function findById(int $contextId, ?string $userId = null): Context { + $qb = $this->db->getQueryBuilder(); + + $qb->select( + 'c.*', + 'r.id as node_rel_id', 'r.node_id', 'r.node_type', 'r.permissions', + 'p.page_type', + 'pc.id as content_id', 'pc.page_id', 'pc.order', + 'n.display_mode as display_mode_default', + 's.id as share_id', 's.receiver', 's.receiver_type' + ) + ->from($this->table, 'c') + ->where($qb->expr()->eq('c.id', $qb->createNamedParameter($contextId, IQueryBuilder::PARAM_INT))); + + if ($userId !== null) { + $this->applyOwnedOrSharedQuery($qb, $userId); + $qb->addSelect('n2.display_mode'); + $qb->leftJoin('s', 'tables_contexts_navigation', 'n2', $qb->expr()->andX( + $qb->expr()->eq('s.id', 'n2.share_id'), + $qb->expr()->eq('n2.user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)), + )); + } else { $qb->leftJoin('c', 'tables_shares', 's', $qb->expr()->andX( $qb->expr()->eq('c.id', 's.node_id'), $qb->expr()->eq('s.node_type', $qb->createNamedParameter('context')), - $sharedToConditions, )); + } - $qb->where($qb->expr()->orX( - $qb->expr()->eq('owner_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)), - $qb->expr()->isNotNull('s.receiver'), - )); + $qb->leftJoin('c', 'tables_contexts_page', 'p', $qb->expr()->eq('c.id', 'p.context_id')); + $qb->leftJoin('p', 'tables_contexts_page_content', 'pc', $qb->expr()->eq('p.id', 'pc.page_id')); + $qb->leftJoin('c', 'tables_contexts_rel_context_node', 'r', $qb->expr()->eq('c.id', 'r.context_id')); + $qb->leftJoin('s', 'tables_contexts_navigation', 'n', $qb->expr()->andX( + $qb->expr()->eq('s.id', 'n.share_id'), + $qb->expr()->eq('n.user_id', $qb->createNamedParameter('')), + )); + + $qb->andWhere($qb->expr()->orX( + $qb->expr()->eq('pc.node_rel_id', 'r.id'), + $qb->expr()->isNull('pc.node_rel_id'), + )); + + $qb->orderBy('pc.order', 'ASC'); + + $result = $qb->executeQuery(); + $r = $result->fetchAll(); + + $formatted = [ + 'id' => $r[0]['id'], + 'name' => $r[0]['name'], + 'icon' => $r[0]['icon'], + 'description' => $r[0]['description'], + 'owner_id' => $r[0]['owner_id'], + 'owner_type' => $r[0]['owner_type'], + ]; + + $formatted['sharing'] = array_reduce($r, function (array $carry, array $item) use ($userId) { + if ($item['share_id'] === null) { + // empty Context + return $carry; + } + $carry[$item['share_id']] = [ + 'share_id' => $item['share_id'], + 'receiver' => $item['receiver'], + 'receiver_type' => $item['receiver_type'], + 'display_mode_default' => $item['display_mode_default'], + ]; + if ($userId !== null) { + $carry[$item['share_id']]['display_mode'] = $item['display_mode']; + } + return $carry; + }, []); + + $formatted['nodes'] = array_reduce($r, function (array $carry, array $item) { + if ($item['node_rel_id'] === null) { + // empty Context + return $carry; + } + $carry[$item['node_rel_id']] = [ + 'id' => $item['node_rel_id'], + 'node_id' => $item['node_id'], + 'node_type' => $item['node_type'], + 'permissions' => $item['permissions'], + ]; + return $carry; + }, []); + + $formatted['pages'] = array_reduce($r, function (array $carry, array $item) { + if ($item['page_id'] === null) { + // empty Context + return $carry; + } + if (!isset($carry[$item['page_id']])) { + $carry[$item['page_id']] = ['content' => []]; + } + $carry[$item['page_id']]['id'] = $item['page_id']; + $carry[$item['page_id']]['page_type'] = $item['page_type']; + $carry[$item['page_id']]['content'][$item['content_id']] = [ + 'order' => $item['order'], + 'node_rel_id' => $item['node_rel_id'] + ]; + + return $carry; + }, []); + + return $this->mapRowToEntity($formatted); + } + + protected function applyOwnedOrSharedQuery(IQueryBuilder $qb, string $userId): void { + $sharedToConditions = $qb->expr()->orX(); + + // shared to user clause + $userShare = $qb->expr()->andX( + $qb->expr()->eq('s.receiver_type', $qb->createNamedParameter('user')), + $qb->expr()->eq('s.receiver', $qb->createNamedParameter($userId)), + ); + $sharedToConditions->add($userShare); + + // shared to group clause + $groupIDs = $this->userHelper->getGroupIdsForUser($userId); + if (!empty($groupIDs)) { + $groupShares = $qb->expr()->andX( + $qb->expr()->eq('s.receiver_type', $qb->createNamedParameter('group')), + $qb->expr()->in('s.receiver', $qb->createNamedParameter($groupIDs, IQueryBuilder::PARAM_STR_ARRAY)), + ); + $sharedToConditions->add($groupShares); } - return $this->findEntities($qb); + // owned contexts + apply share conditions + $qb->leftJoin('c', 'tables_shares', 's', $qb->expr()->andX( + $qb->expr()->eq('c.id', 's.node_id'), + $qb->expr()->eq('s.node_type', $qb->createNamedParameter('context')), + $sharedToConditions, + )); + + $whereExpression = $qb->expr()->orX( + $qb->expr()->eq('owner_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)), + $qb->expr()->isNotNull('s.receiver'), + ); + if ($qb->getQueryPart('where') === null) { + $qb->where($whereExpression); + } else { + $qb->andWhere($whereExpression); + } } } diff --git a/lib/Service/ContextService.php b/lib/Service/ContextService.php index 49468bbdd..16790ebbd 100644 --- a/lib/Service/ContextService.php +++ b/lib/Service/ContextService.php @@ -42,4 +42,21 @@ public function findAll(?string $userId): array { } return $this->mapper->findAll($userId); } + + /** + * @return Context + * @throws InternalError + */ + public function findById(int $id, ?string $userId): Context { + if ($userId !== null && trim($userId) === '') { + $userId = null; + } + if ($userId === null && !$this->isCLI) { + $error = 'Try to set no user in context, but request is not allowed.'; + $this->logger->warning($error); + throw new InternalError($error); + } + + return $this->mapper->findById($id, $userId); + } } From bb935b1301be08424e8b5dbf178230f3111bc378 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Mon, 26 Feb 2024 18:04:28 +0100 Subject: [PATCH 03/15] feat(Contexts): API to create a new Context Signed-off-by: Arthur Schiwon --- appinfo/routes.php | 2 + lib/AppInfo/Application.php | 2 + lib/Controller/ContextController.php | 22 +++++ lib/Db/ContextNodeRelation.php | 39 +++++++++ lib/Db/ContextNodeRelationMapper.php | 18 +++++ lib/Db/Page.php | 32 ++++++++ lib/Db/PageContent.php | 34 ++++++++ lib/Db/PageContentMapper.php | 15 ++++ lib/Db/PageMapper.php | 15 ++++ lib/Service/ContextService.php | 117 ++++++++++++++++++++++++--- 10 files changed, 287 insertions(+), 9 deletions(-) create mode 100644 lib/Db/ContextNodeRelation.php create mode 100644 lib/Db/ContextNodeRelationMapper.php create mode 100644 lib/Db/Page.php create mode 100644 lib/Db/PageContent.php create mode 100644 lib/Db/PageContentMapper.php create mode 100644 lib/Db/PageMapper.php diff --git a/appinfo/routes.php b/appinfo/routes.php index 4e438ee6c..545814cb6 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -130,5 +130,7 @@ ['name' => 'ApiFavorite#destroy', 'url' => '/api/2/favorites/{nodeType}/{nodeId}', 'verb' => 'DELETE', 'requirements' => ['nodeType' => '(\d+)', 'nodeId' => '(\d+)']], ['name' => 'Context#index', 'url' => '/api/2/contexts', 'verb' => 'GET'], ['name' => 'Context#show', 'url' => '/api/2/contexts/{contextId}', 'verb' => 'GET'], + ['name' => 'Context#create', 'url' => '/api/2/contexts', 'verb' => 'POST'], + ] ]; diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 738534a66..74bf17ecf 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -32,6 +32,8 @@ class Application extends App implements IBootstrap { public const NODE_TYPE_TABLE = 0; public const NODE_TYPE_VIEW = 1; + public const OWNER_TYPE_USER = 0; + public function __construct() { parent::__construct(self::APP_ID); } diff --git a/lib/Controller/ContextController.php b/lib/Controller/ContextController.php index 5a09ab0b4..6e807841f 100644 --- a/lib/Controller/ContextController.php +++ b/lib/Controller/ContextController.php @@ -73,6 +73,28 @@ public function show(int $contextId): DataResponse { } } + /** + * [api v2] Create a new context and return it + * + * @NoAdminRequired + * + * @param string $name Name of the context + * @param string $iconName Material design icon name of the context + * @param string $description Descriptive text of the context + * @param array $nodes optional nodes to be connected to this context + * + * @return DataResponse|DataResponse + * + * 200: Tables returned + */ + public function create(string $name, string $iconName, string $description = '', array $nodes = []): DataResponse { + try { + return new DataResponse($this->contextService->create($name, $iconName, $description, $nodes, $this->userId, 0)->jsonSerialize()); + } catch (Exception $e) { + return $this->handleError($e); + } + } + /** * @param Context[] $contexts * @return array diff --git a/lib/Db/ContextNodeRelation.php b/lib/Db/ContextNodeRelation.php new file mode 100644 index 000000000..02b8e618d --- /dev/null +++ b/lib/Db/ContextNodeRelation.php @@ -0,0 +1,39 @@ +addType('id', 'integer'); + } + + public function jsonSerialize(): array { + return [ + 'id' => $this->getId(), + 'contextId' => $this->getContextId(), + 'nodeId' => $this->getNodeId(), + 'nodeType' => $this->getNodeType(), + 'permissions' => $this->getPermissions() + ]; + } +} diff --git a/lib/Db/ContextNodeRelationMapper.php b/lib/Db/ContextNodeRelationMapper.php new file mode 100644 index 000000000..5630b60ea --- /dev/null +++ b/lib/Db/ContextNodeRelationMapper.php @@ -0,0 +1,18 @@ + */ +class ContextNodeRelationMapper extends QBMapper { + protected string $table = 'tables_contexts_rel_context_node'; + + public function __construct(IDBConnection $db) { + parent::__construct($db, $this->table, ContextNodeRelation::class); + } + +} diff --git a/lib/Db/Page.php b/lib/Db/Page.php new file mode 100644 index 000000000..a7757fb1e --- /dev/null +++ b/lib/Db/Page.php @@ -0,0 +1,32 @@ +addType('id', 'integer'); + } + + public function jsonSerialize(): array { + return [ + 'id' => $this->getId(), + 'contextId' => $this->getContextId(), + 'pageType' => $this->getPageType(), + ]; + } +} diff --git a/lib/Db/PageContent.php b/lib/Db/PageContent.php new file mode 100644 index 000000000..45bb1e735 --- /dev/null +++ b/lib/Db/PageContent.php @@ -0,0 +1,34 @@ +addType('id', 'integer'); + } + + public function jsonSerialize(): array { + return [ + 'id' => $this->getId(), + 'pageId' => $this->getPageId(), + 'nodeRelId' => $this->getNodeRelId(), + 'order' => $this->getOrder(), + ]; + } +} diff --git a/lib/Db/PageContentMapper.php b/lib/Db/PageContentMapper.php new file mode 100644 index 000000000..38bed77ab --- /dev/null +++ b/lib/Db/PageContentMapper.php @@ -0,0 +1,15 @@ + */ +class PageContentMapper extends QBMapper { + protected string $table = 'tables_contexts_page_content'; + + public function __construct(IDBConnection $db) { + parent::__construct($db, $this->table, PageContent::class); + } +} diff --git a/lib/Db/PageMapper.php b/lib/Db/PageMapper.php new file mode 100644 index 000000000..6ade694f1 --- /dev/null +++ b/lib/Db/PageMapper.php @@ -0,0 +1,15 @@ + */ +class PageMapper extends QBMapper { + protected string $table = 'tables_contexts_page'; + + public function __construct(IDBConnection $db) { + parent::__construct($db, $this->table, Page::class); + } +} diff --git a/lib/Service/ContextService.php b/lib/Service/ContextService.php index 16790ebbd..98c28bc95 100644 --- a/lib/Service/ContextService.php +++ b/lib/Service/ContextService.php @@ -4,32 +4,52 @@ namespace OCA\Tables\Service; +use OCA\Tables\AppInfo\Application; use OCA\Tables\Db\Context; use OCA\Tables\Db\ContextMapper; +use OCA\Tables\Db\ContextNodeRelation; +use OCA\Tables\Db\ContextNodeRelationMapper; +use OCA\Tables\Db\Page; +use OCA\Tables\Db\PageContent; +use OCA\Tables\Db\PageContentMapper; +use OCA\Tables\Db\PageMapper; use OCA\Tables\Errors\InternalError; +use OCA\Tables\Errors\PermissionError; use OCP\DB\Exception; use Psr\Log\LoggerInterface; class ContextService { - private ContextMapper $mapper; + private ContextMapper $contextMapper; private bool $isCLI; private LoggerInterface $logger; + private ContextNodeRelationMapper $contextNodeRelMapper; + private PageMapper $pageMapper; + private PageContentMapper $pageContentMapper; + private PermissionsService $permissionsService; public function __construct( - ContextMapper $mapper, - LoggerInterface $logger, - bool $isCLI, + ContextMapper $contextMapper, + ContextNodeRelationMapper $contextNodeRelationMapper, + PageMapper $pageMapper, + PageContentMapper $pageContentMapper, + LoggerInterface $logger, + PermissionsService $permissionsService, + bool $isCLI, ) { - $this->mapper = $mapper; + $this->contextMapper = $contextMapper; $this->isCLI = $isCLI; $this->logger = $logger; + $this->contextNodeRelMapper = $contextNodeRelationMapper; + $this->pageMapper = $pageMapper; + $this->pageContentMapper = $pageContentMapper; + $this->permissionsService = $permissionsService; } /** - * @throws InternalError - * @throws Exception * @return Context[] + * @throws Exception + * @throws InternalError */ public function findAll(?string $userId): array { if ($userId !== null && trim($userId) === '') { @@ -40,7 +60,7 @@ public function findAll(?string $userId): array { $this->logger->warning($error); throw new InternalError($error); } - return $this->mapper->findAll($userId); + return $this->contextMapper->findAll($userId); } /** @@ -57,6 +77,85 @@ public function findById(int $id, ?string $userId): Context { throw new InternalError($error); } - return $this->mapper->findById($id, $userId); + return $this->contextMapper->findById($id, $userId); + } + + /** + * @throws Exception + */ + public function create(string $name, string $iconName, string $description, array $nodes, string $ownerId, int $ownerType): Context { + $context = new Context(); + $context->setName(trim($name)); + $context->setIcon(trim($iconName)); + $context->setDescription(trim($description)); + $context->setOwnerId($ownerId); + $context->setOwnerType($ownerType); + + $this->contextMapper->insert($context); + + if (!empty($nodes)) { + $context->resetUpdatedFields(); + $this->insertNodesFromArray($context, $nodes); + $this->insertPage($context); + } + + return $context; + } + + + protected function insertPage(Context $context): void { + $page = new Page(); + $page->setContextId($context->getId()); + $page->setPageType(Page::TYPE_STARTPAGE); + $this->pageMapper->insert($page); + + $addedPage = $page->jsonSerialize(); + + $i = 1; + foreach ($context->getNodes() as $node) { + $pageContent = new PageContent(); + $pageContent->setPageId($page->getId()); + $pageContent->setNodeRelId($node['id']); + $pageContent->setOrder(10 * $i++); + + $this->pageContentMapper->insert($pageContent); + + $addedPage['content'][$pageContent->getId()] = $pageContent->jsonSerialize(); + // the content is already embedded in the page + unset($addedPage['content'][$pageContent->getId()]['pageId']); + } + + $context->setPages($addedPage); + } + + protected function insertNodesFromArray(Context $context, array $nodes): void { + $addedNodes = []; + + $userId = $context->getOwnerType() === Application::OWNER_TYPE_USER ? $context->getOwnerId() : null; + foreach ($nodes as $node) { + $contextNodeRel = new ContextNodeRelation(); + $contextNodeRel->setContextId($context->getId()); + $contextNodeRel->setNodeId($node['id']); + $contextNodeRel->setNodeType($node['type']); + $contextNodeRel->setPermissions($node['permissions'] ?? 660); + + try { + if (!$this->permissionsService->canManageNodeById($node['type'], $node['id'], $userId)) { + throw new PermissionError(sprintf('Owner cannot manage node %d (type %d)', $node['id'], $node['type'])); + } + + $this->contextNodeRelMapper->insert($contextNodeRel); + $addedNodes[] = $contextNodeRel->jsonSerialize(); + } catch (Exception $e) { + $this->logger->warning('Could not add node {ntype}/{nid} to context {cid}, skipping.', [ + 'app' => Application::APP_ID, + 'ntype' => $node['type'], + 'nid' => $node['id'], + 'cid' => $context['id'], + 'exception' => $e, + ]); + } + } + $context->setNodes($addedNodes); } } From 5adb71417af904b3c52a2fe0808dc5fc7fc89d87 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Tue, 27 Feb 2024 14:07:32 +0100 Subject: [PATCH 04/15] feat(Contexts): API to add and remove a node to a Context Signed-off-by: Arthur Schiwon --- appinfo/routes.php | 2 + lib/AppInfo/Application.php | 3 + lib/Controller/AOCSController.php | 10 +++ lib/Controller/ContextController.php | 46 +++++++++++++ lib/Db/ContextNodeRelation.php | 6 +- lib/Db/ContextNodeRelationMapper.php | 17 +++++ lib/Db/PageContentMapper.php | 29 ++++++++ lib/Errors/BadRequestError.php | 6 ++ lib/Middleware/PermissionMiddleware.php | 89 ++++++++++++++++++++++++ lib/Service/ContextService.php | 92 ++++++++++++++++++++++--- lib/Service/PermissionsService.php | 38 +++++++++- 11 files changed, 325 insertions(+), 13 deletions(-) create mode 100644 lib/Errors/BadRequestError.php create mode 100644 lib/Middleware/PermissionMiddleware.php diff --git a/appinfo/routes.php b/appinfo/routes.php index 545814cb6..77e0bd992 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -131,6 +131,8 @@ ['name' => 'Context#index', 'url' => '/api/2/contexts', 'verb' => 'GET'], ['name' => 'Context#show', 'url' => '/api/2/contexts/{contextId}', 'verb' => 'GET'], ['name' => 'Context#create', 'url' => '/api/2/contexts', 'verb' => 'POST'], + ['name' => 'Context#addNode', 'url' => '/api/2/contexts/{contextId}/nodes', 'verb' => 'POST'], + ['name' => 'Context#removeNode', 'url' => '/api/2/contexts/{contextId}/nodes/{nodeRelId}', 'verb' => 'DELETE'], ] ]; diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 74bf17ecf..c5d12b859 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -9,6 +9,7 @@ use OCA\Tables\Listener\LoadAdditionalListener; use OCA\Tables\Listener\TablesReferenceListener; use OCA\Tables\Listener\UserDeletedListener; +use OCA\Tables\Middleware\PermissionMiddleware; use OCA\Tables\Reference\ContentReferenceProvider; use OCA\Tables\Reference\LegacyReferenceProvider; use OCA\Tables\Reference\ReferenceProvider; @@ -67,6 +68,8 @@ public function register(IRegistrationContext $context): void { } $context->registerCapability(Capabilities::class); + + $context->registerMiddleware(PermissionMiddleware::class); } public function boot(IBootContext $context): void { diff --git a/lib/Controller/AOCSController.php b/lib/Controller/AOCSController.php index 8308a615e..54cd1411f 100644 --- a/lib/Controller/AOCSController.php +++ b/lib/Controller/AOCSController.php @@ -4,6 +4,7 @@ use Exception; use OCA\Tables\AppInfo\Application; +use OCA\Tables\Errors\BadRequestError; use OCA\Tables\Errors\InternalError; use OCA\Tables\Errors\NotFoundError; use OCA\Tables\Errors\PermissionError; @@ -59,4 +60,13 @@ protected function handleNotFoundError(NotFoundError $e): DataResponse { return new DataResponse(['message' => $this->n->t('A not found error occurred. More details can be found in the logs. Please reach out to your administration.')], Http::STATUS_NOT_FOUND); } + /** + * @param BadRequestError $e + * @return DataResponse + */ + protected function handleBadRequestError(BadRequestError $e): DataResponse { + $this->logger->warning('An bad request was encountered: ['. $e->getCode() . ']' . $e->getMessage()); + return new DataResponse(['message' => $this->n->t('An error caused by an invalid request occurred. More details can be found in the logs. Please reach out to your administration.')], Http::STATUS_BAD_REQUEST); + } + } diff --git a/lib/Controller/ContextController.php b/lib/Controller/ContextController.php index 6e807841f..b380c3474 100644 --- a/lib/Controller/ContextController.php +++ b/lib/Controller/ContextController.php @@ -5,9 +5,13 @@ namespace OCA\Tables\Controller; use OCA\Tables\Db\Context; +use OCA\Tables\Errors\BadRequestError; use OCA\Tables\Errors\InternalError; +use OCA\Tables\Errors\NotFoundError; use OCA\Tables\ResponseDefinitions; use OCA\Tables\Service\ContextService; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\DB\Exception; @@ -95,6 +99,48 @@ public function create(string $name, string $iconName, string $description = '', } } + /** + * @NoAdminRequired + * @CanManageNode + */ + public function addNode(int $contextId, int $nodeId, int $nodeType, int $permissions, ?int $order = null): DataResponse { + try { + $rel = $this->contextService->addNodeToContextById($contextId, $nodeId, $nodeType, $permissions, $this->userId); + $this->contextService->addNodeRelToPage($rel, $order); + $context = $this->contextService->findById($rel->getContextId(), $this->userId); + return new DataResponse($context->jsonSerialize()); + } catch (DoesNotExistException $e) { + return $this->handleNotFoundError(new NotFoundError($e->getMessage(), $e->getCode(), $e)); + } catch (MultipleObjectsReturnedException|Exception|InternalError $e) { + return $this->handleError($e); + } + } + + /** + * @NoAdminRequired + * @CanManageContext + */ + public function removeNode(int $contextId, int $nodeRelId): DataResponse { + // we could do without the contextId, however it is used by the Permission Middleware + // and also results in a more consistent endpoint url + try { + $context = $this->contextService->findById($contextId, $this->userId); + if (!isset($context->getNodes()[$nodeRelId])) { + return $this->handleBadRequestError(new BadRequestError('Node Relation ID not found in given Context')); + } + $nodeRelation = $this->contextService->removeNodeFromContextById($nodeRelId); + $this->contextService->removeNodeRelFromAllPages($nodeRelation); + $context = $this->contextService->findById($contextId, $this->userId); + return new DataResponse($context->jsonSerialize()); + } catch (DoesNotExistException $e) { + $this->handleNotFoundError(new NotFoundError($e->getMessage(), $e->getCode(), $e)); + } catch (MultipleObjectsReturnedException|Exception $e) { + $this->handleError($e); + } + + return new DataResponse(); + } + /** * @param Context[] $contexts * @return array diff --git a/lib/Db/ContextNodeRelation.php b/lib/Db/ContextNodeRelation.php index 02b8e618d..7981ffcd1 100644 --- a/lib/Db/ContextNodeRelation.php +++ b/lib/Db/ContextNodeRelation.php @@ -11,8 +11,8 @@ * @method setContextId(int $value): void * @method getNodeId(): int * @method setNodeId(int $value): void - * @method getNodeType(): string - * @method setNodeType(string $value): void + * @method getNodeType(): int + * @method setNodeType(int $value): void * @method getPermissions(): int * @method setPermissions(int $value): void */ @@ -20,7 +20,7 @@ class ContextNodeRelation extends Entity implements \JsonSerializable { protected ?int $contextId = null; protected ?int $nodeId = null; - protected ?string $nodeType = null; + protected ?int $nodeType = null; protected ?int $permissions = null; public function __construct() { diff --git a/lib/Db/ContextNodeRelationMapper.php b/lib/Db/ContextNodeRelationMapper.php index 5630b60ea..7709ca5de 100644 --- a/lib/Db/ContextNodeRelationMapper.php +++ b/lib/Db/ContextNodeRelationMapper.php @@ -4,7 +4,10 @@ namespace OCA\Tables\Db; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\AppFramework\Db\QBMapper; +use OCP\DB\Exception; use OCP\IDBConnection; /** @template-extends QBMapper */ @@ -15,4 +18,18 @@ public function __construct(IDBConnection $db) { parent::__construct($db, $this->table, ContextNodeRelation::class); } + /** + * @throws MultipleObjectsReturnedException + * @throws DoesNotExistException + * @throws Exception + */ + public function findById(int $nodeRelId): ContextNodeRelation { + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->tableName) + ->where($qb->expr()->eq('id', $qb->createNamedParameter($nodeRelId))); + + $row = $this->findOneQuery($qb); + return $this->mapRowToEntity($row); + } } diff --git a/lib/Db/PageContentMapper.php b/lib/Db/PageContentMapper.php index 38bed77ab..5a6810aab 100644 --- a/lib/Db/PageContentMapper.php +++ b/lib/Db/PageContentMapper.php @@ -3,6 +3,7 @@ namespace OCA\Tables\Db; use OCP\AppFramework\Db\QBMapper; +use OCP\DB\Exception; use OCP\IDBConnection; /** @template-extends QBMapper */ @@ -12,4 +13,32 @@ class PageContentMapper extends QBMapper { public function __construct(IDBConnection $db) { parent::__construct($db, $this->table, PageContent::class); } + + /** + * @throws Exception + */ + public function findByPageAndNodeRelation(int $pageId, int $nodeRelId): ?PageContent { + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->table) + ->where($qb->expr()->andX( + $qb->expr()->eq('page_id', $qb->createNamedParameter($pageId)), + $qb->expr()->eq('node_rel_id', $qb->createNamedParameter($nodeRelId)), + )); + + $result = $qb->executeQuery(); + $r = $result->fetch(); + return $r ? $this->mapRowToEntity($r) : null; + } + + public function findByNodeRelation(int $nodeRelId): array { + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->table) + ->where($qb->expr()->andX( + $qb->expr()->eq('node_rel_id', $qb->createNamedParameter($nodeRelId)), + )); + + return $this->findEntities($qb); + } } diff --git a/lib/Errors/BadRequestError.php b/lib/Errors/BadRequestError.php new file mode 100644 index 000000000..71fdb8949 --- /dev/null +++ b/lib/Errors/BadRequestError.php @@ -0,0 +1,6 @@ +reflector = $reflector; + $this->permissionsService = $permissionsService; + $this->userId = $userId; + $this->request = $request; + } + + /** + * @throws PermissionError + * @throws InternalError + */ + public function beforeController(Controller $controller, string $methodName): void { + $this->assertCanManageNode(); + $this->assertCanManageContext(); + } + + /** + * @throws PermissionError + * @throws InternalError + */ + protected function assertCanManageNode(): void { + if ($this->reflector->hasAnnotation('CanManageNode')) { + $nodeId = $this->request->getParam('nodeId'); + $nodeType = $this->request->getParam('nodeType'); + + if (!is_numeric($nodeId) || !is_numeric($nodeType)) { + throw new InternalError('Cannot identify node'); + } + + if ($this->userId === null) { + throw new PermissionError('User not authenticated'); + } + + if (!$this->permissionsService->canManageNodeById((int)$nodeType, (int)$nodeId, $this->userId)) { + throw new PermissionError(sprintf('User %s cannot manage node %d (type %d)', + $this->userId, (int)$nodeId, (int)$nodeType + )); + } + } + } + + /** + * @throws PermissionError + * @throws InternalError + */ + protected function assertCanManageContext(): void { + if ($this->reflector->hasAnnotation('CanManageContext')) { + $contextId = $this->request->getParam('contextId'); + + if (!is_numeric($contextId)) { + throw new InternalError('Cannot identify context'); + } + + if ($this->userId === null) { + throw new PermissionError('User not authenticated'); + } + + if (!$this->permissionsService->canManageContextById((int)$contextId, $this->userId)) { + throw new PermissionError(sprintf('User %s cannot manage context %d', + $this->userId, (int)$contextId + )); + } + } + } +} diff --git a/lib/Service/ContextService.php b/lib/Service/ContextService.php index 98c28bc95..4f4d091f9 100644 --- a/lib/Service/ContextService.php +++ b/lib/Service/ContextService.php @@ -15,6 +15,8 @@ use OCA\Tables\Db\PageMapper; use OCA\Tables\Errors\InternalError; use OCA\Tables\Errors\PermissionError; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\DB\Exception; use Psr\Log\LoggerInterface; @@ -102,6 +104,87 @@ public function create(string $name, string $iconName, string $description, arra return $context; } + /** + * @throws MultipleObjectsReturnedException + * @throws DoesNotExistException + * @throws Exception + */ + public function addNodeToContextById(int $contextId, int $nodeId, int $nodeType, int $permissions, ?string $userId): ContextNodeRelation { + $context = $this->contextMapper->findById($contextId, $userId); + return $this->addNodeToContext($context, $nodeId, $nodeType, $permissions); + } + + /** + * @throws Exception + */ + public function removeNodeFromContext(ContextNodeRelation $nodeRelation): ContextNodeRelation { + return $this->contextNodeRelMapper->delete($nodeRelation); + } + + /** + * @throws DoesNotExistException + * @throws MultipleObjectsReturnedException + * @throws Exception + */ + public function removeNodeFromContextById(int $nodeRelationId): ContextNodeRelation { + $nodeRelation = $this->contextNodeRelMapper->findById($nodeRelationId); + return $this->contextNodeRelMapper->delete($nodeRelation); + } + + /** + * @throws Exception + */ + public function addNodeToContext(Context $context, int $nodeId, int $nodeType, int $permissions): ContextNodeRelation { + $contextNodeRel = new ContextNodeRelation(); + $contextNodeRel->setContextId($context->getId()); + $contextNodeRel->setNodeId($nodeId); + $contextNodeRel->setNodeType($nodeType); + $contextNodeRel->setPermissions($permissions); + + return $this->contextNodeRelMapper->insert($contextNodeRel); + } + + public function addNodeRelToPage(ContextNodeRelation $nodeRel, int $order = null, ?int $pageId = null): PageContent { + if ($pageId === null) { + // when no page is given, find the startpage to add it to + $context = $this->contextMapper->findById($nodeRel->getContextId()); + $pages = $context->getPages(); + foreach ($pages as $page) { + if ($page['page_type'] === 'startpage') { + $pageId = $page['id']; + break; + } + } + } + + $pageContent = $this->pageContentMapper->findByPageAndNodeRelation($pageId, $nodeRel->getId()); + + if ($pageContent === null) { + $pageContent = new PageContent(); + $pageContent->setPageId($pageId); + $pageContent->setNodeRelId($nodeRel->getId()); + $pageContent->setOrder($order ?? 100); //FIXME: demand or calc order + + $pageContent = $this->pageContentMapper->insert($pageContent); + } + return $pageContent; + } + + public function removeNodeRelFromAllPages(ContextNodeRelation $nodeRelation): array { + $contents = $this->pageContentMapper->findByNodeRelation($nodeRelation->getId()); + /** @var PageContent $content */ + foreach ($contents as $content) { + try { + $this->pageContentMapper->delete($content); + } catch (Exception $e) { + $this->logger->warning('Failed to delete Contexts page content with ID {pcId}', [ + 'pcId' => $content->getId(), + 'exception' => $e, + ]); + } + } + return $contents; + } protected function insertPage(Context $context): void { $page = new Page(); @@ -133,18 +216,11 @@ protected function insertNodesFromArray(Context $context, array $nodes): void { $userId = $context->getOwnerType() === Application::OWNER_TYPE_USER ? $context->getOwnerId() : null; foreach ($nodes as $node) { - $contextNodeRel = new ContextNodeRelation(); - $contextNodeRel->setContextId($context->getId()); - $contextNodeRel->setNodeId($node['id']); - $contextNodeRel->setNodeType($node['type']); - $contextNodeRel->setPermissions($node['permissions'] ?? 660); - try { if (!$this->permissionsService->canManageNodeById($node['type'], $node['id'], $userId)) { throw new PermissionError(sprintf('Owner cannot manage node %d (type %d)', $node['id'], $node['type'])); } - - $this->contextNodeRelMapper->insert($contextNodeRel); + $contextNodeRel = $this->addNodeToContext($context, $node['id'], $node['type'], $node['permissions'] ?? 660); $addedNodes[] = $contextNodeRel->jsonSerialize(); } catch (Exception $e) { $this->logger->warning('Could not add node {ntype}/{nid} to context {cid}, skipping.', [ diff --git a/lib/Service/PermissionsService.php b/lib/Service/PermissionsService.php index 8911867bd..922bd4685 100644 --- a/lib/Service/PermissionsService.php +++ b/lib/Service/PermissionsService.php @@ -3,6 +3,7 @@ namespace OCA\Tables\Service; use OCA\Tables\AppInfo\Application; +use OCA\Tables\Db\ContextMapper; use OCA\Tables\Db\Share; use OCA\Tables\Db\ShareMapper; use OCA\Tables\Db\Table; @@ -31,8 +32,18 @@ class PermissionsService { protected ?string $userId = null; protected bool $isCli = false; - - public function __construct(LoggerInterface $logger, ?string $userId, TableMapper $tableMapper, ViewMapper $viewMapper, ShareMapper $shareMapper, UserHelper $userHelper, bool $isCLI) { + private ContextMapper $contextMapper; + + public function __construct( + LoggerInterface $logger, + ?string $userId, + TableMapper $tableMapper, + ViewMapper $viewMapper, + ShareMapper $shareMapper, + ContextMapper $contextMapper, + UserHelper $userHelper, + bool $isCLI + ) { $this->tableMapper = $tableMapper; $this->viewMapper = $viewMapper; $this->shareMapper = $shareMapper; @@ -40,6 +51,7 @@ public function __construct(LoggerInterface $logger, ?string $userId, TableMappe $this->logger = $logger; $this->userId = $userId; $this->isCli = $isCLI; + $this->contextMapper = $contextMapper; } @@ -118,6 +130,28 @@ public function canManageNodeById(int $nodeType, int $nodeId, ?string $userId = return false; } + public function canManageContextById(int $contextId, ?string $userId = null): bool { + try { + $context = $this->contextMapper->findById($contextId, $userId); + } catch (DoesNotExistException $e) { + $this->logger->warning('Context does not exist'); + return false; + } catch (MultipleObjectsReturnedException $e) { + $this->logger->warning('Multiple contexts found for this ID'); + return false; + } catch (Exception $e) { + $this->logger->warning($e->getMessage()); + return false; + } + + if ($context->getOwnerType() !== Application::OWNER_TYPE_USER) { + $this->logger->warning('Unsupported owner type'); + return false; + } + + return $context->getOwnerId() === $userId; + } + public function canAccessView(View $view, ?string $userId = null): bool { if($this->basisCheck($view, 'view', $userId)) { return true; From 7cab142e9546965a44109d2e43ec28dc572fb467 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 29 Feb 2024 16:07:43 +0100 Subject: [PATCH 05/15] feat(Contexts): API endpoint to update basic information of a Context Signed-off-by: Arthur Schiwon --- appinfo/routes.php | 1 + lib/Controller/ContextController.php | 14 ++++++++++++++ lib/Service/ContextService.php | 21 +++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/appinfo/routes.php b/appinfo/routes.php index 77e0bd992..1a5e1798e 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -131,6 +131,7 @@ ['name' => 'Context#index', 'url' => '/api/2/contexts', 'verb' => 'GET'], ['name' => 'Context#show', 'url' => '/api/2/contexts/{contextId}', 'verb' => 'GET'], ['name' => 'Context#create', 'url' => '/api/2/contexts', 'verb' => 'POST'], + ['name' => 'Context#update', 'url' => '/api/2/contexts/{contextId}', 'verb' => 'PUT'], ['name' => 'Context#addNode', 'url' => '/api/2/contexts/{contextId}/nodes', 'verb' => 'POST'], ['name' => 'Context#removeNode', 'url' => '/api/2/contexts/{contextId}/nodes/{nodeRelId}', 'verb' => 'DELETE'], diff --git a/lib/Controller/ContextController.php b/lib/Controller/ContextController.php index b380c3474..08e00d32e 100644 --- a/lib/Controller/ContextController.php +++ b/lib/Controller/ContextController.php @@ -99,6 +99,20 @@ public function create(string $name, string $iconName, string $description = '', } } + /** + * @NoAdminRequired + * @CanManageContext + */ + public function update(int $contextId, ?string $name, ?string $iconName, ?string $description): DataResponse { + try { + return new DataResponse($this->contextService->update($contextId, $name, $iconName, $description)->jsonSerialize()); + } catch (Exception|MultipleObjectsReturnedException $e) { + return $this->handleError($e); + } catch (DoesNotExistException $e) { + return $this->handleNotFoundError(new NotFoundError($e->getMessage(), $e->getCode(), $e)); + } + } + /** * @NoAdminRequired * @CanManageNode diff --git a/lib/Service/ContextService.php b/lib/Service/ContextService.php index 4f4d091f9..7d09e0f3f 100644 --- a/lib/Service/ContextService.php +++ b/lib/Service/ContextService.php @@ -104,6 +104,27 @@ public function create(string $name, string $iconName, string $description, arra return $context; } + /** + * @throws Exception + * @throws DoesNotExistException + * @throws MultipleObjectsReturnedException + */ + public function update(int $contextId, ?string $name, ?string $iconName, ?string $description): Context { + $context = $this->contextMapper->findById($contextId); + + if ($name !== null) { + $context->setName(trim($name)); + } + if ($iconName !== null) { + $context->setIcon(trim($iconName)); + } + if ($description !== null) { + $context->setDescription(trim($description)); + } + + return $this->contextMapper->update($context); + } + /** * @throws MultipleObjectsReturnedException * @throws DoesNotExistException From c25413882095c9a76d057cb133238323ad25d048 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 29 Feb 2024 20:47:26 +0100 Subject: [PATCH 06/15] feat(Contexts): API to modify content order on a page Signed-off-by: Arthur Schiwon --- appinfo/routes.php | 2 +- lib/Controller/ContextController.php | 13 ++++++++++++ lib/Db/PageContentMapper.php | 16 ++++++++++++++ lib/Service/ContextService.php | 31 ++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index 1a5e1798e..521b39c26 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -134,6 +134,6 @@ ['name' => 'Context#update', 'url' => '/api/2/contexts/{contextId}', 'verb' => 'PUT'], ['name' => 'Context#addNode', 'url' => '/api/2/contexts/{contextId}/nodes', 'verb' => 'POST'], ['name' => 'Context#removeNode', 'url' => '/api/2/contexts/{contextId}/nodes/{nodeRelId}', 'verb' => 'DELETE'], - + ['name' => 'Context#updateContentOrder', 'url' => '/api/2/contexts/{contextId}/pages/{pageId}', 'verb' => 'PUT'], ] ]; diff --git a/lib/Controller/ContextController.php b/lib/Controller/ContextController.php index 08e00d32e..8f749ffdd 100644 --- a/lib/Controller/ContextController.php +++ b/lib/Controller/ContextController.php @@ -155,6 +155,19 @@ public function removeNode(int $contextId, int $nodeRelId): DataResponse { return new DataResponse(); } + /** + * @NoAdminRequired + * @CanManageContext + */ + public function updateContentOrder(int $contextId, int $pageId, array $content): DataResponse { + $context = $this->contextService->findById($contextId, $this->userId); + if (!isset($context->getPages()[$pageId])) { + return $this->handleBadRequestError(new BadRequestError('Page not found in given Context')); + } + + return new DataResponse($this->contextService->updateContentOrder($pageId, $content)); + } + /** * @param Context[] $contexts * @return array diff --git a/lib/Db/PageContentMapper.php b/lib/Db/PageContentMapper.php index 5a6810aab..dcd88fc01 100644 --- a/lib/Db/PageContentMapper.php +++ b/lib/Db/PageContentMapper.php @@ -2,6 +2,8 @@ namespace OCA\Tables\Db; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\AppFramework\Db\QBMapper; use OCP\DB\Exception; use OCP\IDBConnection; @@ -14,6 +16,20 @@ public function __construct(IDBConnection $db) { parent::__construct($db, $this->table, PageContent::class); } + /** + * @throws DoesNotExistException + * @throws MultipleObjectsReturnedException + * @throws Exception + */ + public function findById(int $pageContentId): PageContent { + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->tableName) + ->where($qb->expr()->eq('id', $qb->createNamedParameter($pageContentId))); + + return $this->mapRowToEntity($this->findOneQuery($qb)); + } + /** * @throws Exception */ diff --git a/lib/Service/ContextService.php b/lib/Service/ContextService.php index 7d09e0f3f..43dbdc6f1 100644 --- a/lib/Service/ContextService.php +++ b/lib/Service/ContextService.php @@ -4,6 +4,7 @@ namespace OCA\Tables\Service; +use InvalidArgumentException; use OCA\Tables\AppInfo\Application; use OCA\Tables\Db\Context; use OCA\Tables\Db\ContextMapper; @@ -207,6 +208,36 @@ public function removeNodeRelFromAllPages(ContextNodeRelation $nodeRelation): ar return $contents; } + public function updateContentOrder(int $pageId, array $contents): array { + $updated = []; + foreach ($contents as $content) { + try { + $updated[] = $this->updatePageContent($pageId, $content['id'], $content['order']); + } catch (DoesNotExistException|MultipleObjectsReturnedException|Exception|InvalidArgumentException $e) { + $this->logger->info('Could not updated order of content with ID {cID}', [ + 'cID' => $content['id'], + 'exception' => $e, + ]); + } + } + return $updated; + } + + /** + * @throws MultipleObjectsReturnedException + * @throws DoesNotExistException + * @throws Exception + * @throws InvalidArgumentException + */ + protected function updatePageContent(int $pageId, int $contentId, int $order): PageContent { + $pageContent = $this->pageContentMapper->findById($contentId); + if ($pageContent->getPageId() !== $pageId) { + throw new InvalidArgumentException('Content does not belong to given page'); + } + $pageContent->setOrder($order); + return $this->pageContentMapper->update($pageContent); + } + protected function insertPage(Context $context): void { $page = new Page(); $page->setContextId($context->getId()); From b25ad7836a71e07d351e4f0c2a6277184b659049 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Mon, 4 Mar 2024 12:00:10 +0100 Subject: [PATCH 07/15] feat(Contexts): API endpoint for Contexts ownership transfer - also emits an Event for admin_audit Signed-off-by: Arthur Schiwon --- appinfo/routes.php | 1 + lib/Controller/ContextController.php | 19 ++++++++++++ lib/Service/ContextService.php | 45 ++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/appinfo/routes.php b/appinfo/routes.php index 521b39c26..da22566e5 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -132,6 +132,7 @@ ['name' => 'Context#show', 'url' => '/api/2/contexts/{contextId}', 'verb' => 'GET'], ['name' => 'Context#create', 'url' => '/api/2/contexts', 'verb' => 'POST'], ['name' => 'Context#update', 'url' => '/api/2/contexts/{contextId}', 'verb' => 'PUT'], + ['name' => 'Context#transfer', 'url' => '/api/2/contexts/{contextId}/transfer', 'verb' => 'PUT'], ['name' => 'Context#addNode', 'url' => '/api/2/contexts/{contextId}/nodes', 'verb' => 'POST'], ['name' => 'Context#removeNode', 'url' => '/api/2/contexts/{contextId}/nodes/{nodeRelId}', 'verb' => 'DELETE'], ['name' => 'Context#updateContentOrder', 'url' => '/api/2/contexts/{contextId}/pages/{pageId}', 'verb' => 'PUT'], diff --git a/lib/Controller/ContextController.php b/lib/Controller/ContextController.php index 8f749ffdd..efd70cb40 100644 --- a/lib/Controller/ContextController.php +++ b/lib/Controller/ContextController.php @@ -113,6 +113,25 @@ public function update(int $contextId, ?string $name, ?string $iconName, ?string } } + /** + * @NoAdminRequired + * @CanManageContext + * + * @psalm-param int<0, max> $contextId + * @psalm-param int<0, 0> $newOwnerType + */ + public function transfer(int $contextId, string $newOwnerId, int $newOwnerType = 0): DataResponse { + try { + return new DataResponse($this->contextService->transfer($contextId, $newOwnerId, $newOwnerType)->jsonSerialize()); + } catch (Exception|MultipleObjectsReturnedException $e) { + return $this->handleError($e); + } catch (DoesNotExistException $e) { + return $this->handleNotFoundError(new NotFoundError($e->getMessage(), $e->getCode(), $e)); + } catch (BadRequestError $e) { + return $this->handleBadRequestError($e); + } + } + /** * @NoAdminRequired * @CanManageNode diff --git a/lib/Service/ContextService.php b/lib/Service/ContextService.php index 43dbdc6f1..2d4f7b358 100644 --- a/lib/Service/ContextService.php +++ b/lib/Service/ContextService.php @@ -14,11 +14,15 @@ use OCA\Tables\Db\PageContent; use OCA\Tables\Db\PageContentMapper; use OCA\Tables\Db\PageMapper; +use OCA\Tables\Errors\BadRequestError; use OCA\Tables\Errors\InternalError; use OCA\Tables\Errors\PermissionError; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\DB\Exception; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\IUserManager; +use OCP\Log\Audit\CriticalActionPerformedEvent; use Psr\Log\LoggerInterface; class ContextService { @@ -30,6 +34,8 @@ class ContextService { private PageMapper $pageMapper; private PageContentMapper $pageContentMapper; private PermissionsService $permissionsService; + private IUserManager $userManager; + private IEventDispatcher $eventDispatcher; public function __construct( ContextMapper $contextMapper, @@ -38,6 +44,8 @@ public function __construct( PageContentMapper $pageContentMapper, LoggerInterface $logger, PermissionsService $permissionsService, + IUserManager $userManager, + IEventDispatcher $eventDispatcher, bool $isCLI, ) { $this->contextMapper = $contextMapper; @@ -47,6 +55,8 @@ public function __construct( $this->pageMapper = $pageMapper; $this->pageContentMapper = $pageContentMapper; $this->permissionsService = $permissionsService; + $this->userManager = $userManager; + $this->eventDispatcher = $eventDispatcher; } /** @@ -126,6 +136,41 @@ public function update(int $contextId, ?string $name, ?string $iconName, ?string return $this->contextMapper->update($context); } + /** + * @throws MultipleObjectsReturnedException + * @throws DoesNotExistException + * @throws Exception + * @throws BadRequestError + */ + public function transfer(int $contextId, string $newOwnerId, int $newOwnerType): Context { + $context = $this->contextMapper->findById($contextId); + + // the owner type check can be dropped as soon as NC 29 is the lowest supported version, + // as the int range as defined in the Controller will be enforced by the Http/Dispatcher. + if ($newOwnerType !== Application::OWNER_TYPE_USER) { + throw new BadRequestError('Unsupported owner type'); + } + + if (!$this->userManager->userExists($newOwnerId)) { + throw new BadRequestError('User does not exist'); + } + + $context->setOwnerId($newOwnerId); + $context->setOwnerType($newOwnerType); + + $context = $this->contextMapper->update($context); + + $auditEvent = new CriticalActionPerformedEvent( + sprintf('Tables application with ID %d was transferred to user %s', + $contextId, $newOwnerId, + ) + ); + + $this->eventDispatcher->dispatchTyped($auditEvent); + + return $context; + } + /** * @throws MultipleObjectsReturnedException * @throws DoesNotExistException From c12b8ffc24d06c8f6acca33f0be2b70d5feaf73f Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Tue, 5 Mar 2024 14:28:03 +0100 Subject: [PATCH 08/15] enh(Contexts): return full Contexts also for index endpoint Signed-off-by: Arthur Schiwon --- lib/Db/ContextMapper.php | 93 ++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 33 deletions(-) diff --git a/lib/Db/ContextMapper.php b/lib/Db/ContextMapper.php index f0048bcce..f83ab353e 100644 --- a/lib/Db/ContextMapper.php +++ b/lib/Db/ContextMapper.php @@ -21,27 +21,8 @@ public function __construct(IDBConnection $db, UserHelper $userHelper) { $this->userHelper = $userHelper; parent::__construct($db, $this->table, Context::class); } - /** - * @return Context[] - * @throws Exception - */ - public function findAll(?string $userId = null): array { - $qb = $this->db->getQueryBuilder(); - $qb->select('c.*') - ->from($this->table, 'c'); - if ($userId !== null) { - $this->applyOwnedOrSharedQuery($qb, $userId); - } - return $this->findEntities($qb); - } - - /** - * @throws DoesNotExistException - * @throws MultipleObjectsReturnedException - * @throws Exception - */ - public function findById(int $contextId, ?string $userId = null): Context { + protected function getFindContextBaseQuery(?string $userId): IQueryBuilder { $qb = $this->db->getQueryBuilder(); $qb->select( @@ -52,8 +33,7 @@ public function findById(int $contextId, ?string $userId = null): Context { 'n.display_mode as display_mode_default', 's.id as share_id', 's.receiver', 's.receiver_type' ) - ->from($this->table, 'c') - ->where($qb->expr()->eq('c.id', $qb->createNamedParameter($contextId, IQueryBuilder::PARAM_INT))); + ->from($this->table, 'c'); if ($userId !== null) { $this->applyOwnedOrSharedQuery($qb, $userId); @@ -84,19 +64,20 @@ public function findById(int $contextId, ?string $userId = null): Context { $qb->orderBy('pc.order', 'ASC'); - $result = $qb->executeQuery(); - $r = $result->fetchAll(); + return $qb; + } + protected function formatResultRows(array $rows, ?string $userId) { $formatted = [ - 'id' => $r[0]['id'], - 'name' => $r[0]['name'], - 'icon' => $r[0]['icon'], - 'description' => $r[0]['description'], - 'owner_id' => $r[0]['owner_id'], - 'owner_type' => $r[0]['owner_type'], + 'id' => $rows[0]['id'], + 'name' => $rows[0]['name'], + 'icon' => $rows[0]['icon'], + 'description' => $rows[0]['description'], + 'owner_id' => $rows[0]['owner_id'], + 'owner_type' => $rows[0]['owner_type'], ]; - $formatted['sharing'] = array_reduce($r, function (array $carry, array $item) use ($userId) { + $formatted['sharing'] = array_reduce($rows, function (array $carry, array $item) use ($userId) { if ($item['share_id'] === null) { // empty Context return $carry; @@ -113,7 +94,7 @@ public function findById(int $contextId, ?string $userId = null): Context { return $carry; }, []); - $formatted['nodes'] = array_reduce($r, function (array $carry, array $item) { + $formatted['nodes'] = array_reduce($rows, function (array $carry, array $item) { if ($item['node_rel_id'] === null) { // empty Context return $carry; @@ -127,7 +108,7 @@ public function findById(int $contextId, ?string $userId = null): Context { return $carry; }, []); - $formatted['pages'] = array_reduce($r, function (array $carry, array $item) { + $formatted['pages'] = array_reduce($rows, function (array $carry, array $item) { if ($item['page_id'] === null) { // empty Context return $carry; @@ -148,6 +129,52 @@ public function findById(int $contextId, ?string $userId = null): Context { return $this->mapRowToEntity($formatted); } + /** + * @return Context[] + * @throws Exception + */ + public function findAll(?string $userId = null): array { + $qb = $this->getFindContextBaseQuery($userId); + + $result = $qb->executeQuery(); + $r = $result->fetchAll(); + + $contextIds = []; + foreach ($r as $row) { + $contextIds[$row['id']] = 1; + } + $contextIds = array_keys($contextIds); + unset($row); + + $resultEntities = []; + foreach ($contextIds as $contextId) { + $workArray = []; + foreach ($r as $row) { + if ($row['id'] === $contextId) { + $workArray[] = $row; + } + } + $resultEntities[] = $this->formatResultRows($workArray, $userId); + } + + return $resultEntities; + } + + /** + * @throws DoesNotExistException + * @throws MultipleObjectsReturnedException + * @throws Exception + */ + public function findById(int $contextId, ?string $userId = null): Context { + $qb = $this->getFindContextBaseQuery($userId); + $qb->andWhere($qb->expr()->eq('c.id', $qb->createNamedParameter($contextId, IQueryBuilder::PARAM_INT))); + + $result = $qb->executeQuery(); + $r = $result->fetchAll(); + + return $this->formatResultRows($r, $userId); + } + protected function applyOwnedOrSharedQuery(IQueryBuilder $qb, string $userId): void { $sharedToConditions = $qb->expr()->orX(); From c591c20a86b061a580fa3b2123e1e205eae5e2c2 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 6 Mar 2024 22:53:58 +0100 Subject: [PATCH 09/15] fix(Contexts): fix return code when context not found Signed-off-by: Arthur Schiwon --- lib/Controller/ContextController.php | 2 ++ lib/Db/ContextMapper.php | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/lib/Controller/ContextController.php b/lib/Controller/ContextController.php index efd70cb40..8032c77da 100644 --- a/lib/Controller/ContextController.php +++ b/lib/Controller/ContextController.php @@ -72,6 +72,8 @@ public function show(int $contextId): DataResponse { try { $context = $this->contextService->findById($contextId, $this->userId); return new DataResponse($context->jsonSerialize()); + } catch (NotFoundError $e) { + return $this->handleNotFoundError($e); } catch (InternalError|Exception $e) { return $this->handleError($e); } diff --git a/lib/Db/ContextMapper.php b/lib/Db/ContextMapper.php index f83ab353e..fefe48968 100644 --- a/lib/Db/ContextMapper.php +++ b/lib/Db/ContextMapper.php @@ -4,6 +4,7 @@ namespace OCA\Tables\Db; +use OCA\Tables\Errors\NotFoundError; use OCA\Tables\Helper\UserHelper; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; @@ -172,6 +173,10 @@ public function findById(int $contextId, ?string $userId = null): Context { $result = $qb->executeQuery(); $r = $result->fetchAll(); + if (empty($r)) { + throw new NotFoundError('Context does not exist'); + } + return $this->formatResultRows($r, $userId); } From dc0eae0e8d7613d97390b9cf8e12a44b122e3af7 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 7 Mar 2024 19:27:02 +0100 Subject: [PATCH 10/15] feat(Contexts): accept nodes in context update endpoint - includes a fix to also show pages that have no content Signed-off-by: Arthur Schiwon --- lib/Controller/ContextController.php | 11 +++- lib/Db/ContextMapper.php | 14 ++-- lib/Service/ContextService.php | 96 +++++++++++++++++++++++++++- 3 files changed, 110 insertions(+), 11 deletions(-) diff --git a/lib/Controller/ContextController.php b/lib/Controller/ContextController.php index 8032c77da..bc7a31000 100644 --- a/lib/Controller/ContextController.php +++ b/lib/Controller/ContextController.php @@ -105,9 +105,16 @@ public function create(string $name, string $iconName, string $description = '', * @NoAdminRequired * @CanManageContext */ - public function update(int $contextId, ?string $name, ?string $iconName, ?string $description): DataResponse { + public function update(int $contextId, ?string $name, ?string $iconName, ?string $description, ?array $nodes): DataResponse { try { - return new DataResponse($this->contextService->update($contextId, $name, $iconName, $description)->jsonSerialize()); + return new DataResponse($this->contextService->update( + $contextId, + $this->userId, + $name, + $iconName, + $description, + $nodes, + )->jsonSerialize()); } catch (Exception|MultipleObjectsReturnedException $e) { return $this->handleError($e); } catch (DoesNotExistException $e) { diff --git a/lib/Db/ContextMapper.php b/lib/Db/ContextMapper.php index fefe48968..5b33ec10e 100644 --- a/lib/Db/ContextMapper.php +++ b/lib/Db/ContextMapper.php @@ -29,8 +29,8 @@ protected function getFindContextBaseQuery(?string $userId): IQueryBuilder { $qb->select( 'c.*', 'r.id as node_rel_id', 'r.node_id', 'r.node_type', 'r.permissions', - 'p.page_type', - 'pc.id as content_id', 'pc.page_id', 'pc.order', + 'p.id as page_id', 'p.page_type', + 'pc.id as content_id', 'pc.order', 'n.display_mode as display_mode_default', 's.id as share_id', 's.receiver', 's.receiver_type' ) @@ -119,10 +119,12 @@ protected function formatResultRows(array $rows, ?string $userId) { } $carry[$item['page_id']]['id'] = $item['page_id']; $carry[$item['page_id']]['page_type'] = $item['page_type']; - $carry[$item['page_id']]['content'][$item['content_id']] = [ - 'order' => $item['order'], - 'node_rel_id' => $item['node_rel_id'] - ]; + if ($item['node_rel_id'] !== null) { + $carry[$item['page_id']]['content'][$item['content_id']] = [ + 'order' => $item['order'], + 'node_rel_id' => $item['node_rel_id'] + ]; + } return $carry; }, []); diff --git a/lib/Service/ContextService.php b/lib/Service/ContextService.php index 2d4f7b358..7eccec9d5 100644 --- a/lib/Service/ContextService.php +++ b/lib/Service/ContextService.php @@ -120,8 +120,8 @@ public function create(string $name, string $iconName, string $description, arra * @throws DoesNotExistException * @throws MultipleObjectsReturnedException */ - public function update(int $contextId, ?string $name, ?string $iconName, ?string $description): Context { - $context = $this->contextMapper->findById($contextId); + public function update(int $contextId, string $userId, ?string $name, ?string $iconName, ?string $description, ?array $nodes): Context { + $context = $this->contextMapper->findById($contextId, $userId); if ($name !== null) { $context->setName(trim($name)); @@ -133,7 +133,75 @@ public function update(int $contextId, ?string $name, ?string $iconName, ?string $context->setDescription(trim($description)); } - return $this->contextMapper->update($context); + $hasUpdatedNodeInformation = false; + if ($nodes !== null) { + $currentNodes = $context->getNodes(); + $currentPages = $context->getPages(); + + $nodesBeingRemoved = []; + $nodesBeingAdded = []; + $nodesBeingKept = []; + + // new node relationships do not have an ID. We can recognize them + // through their nodeType and nodeIds. For this we need to transform + // the known relationships` keys to a compatible format. + $oldNodeResolvableIdMapper = []; + foreach ($currentNodes as $i => $oldNode) { + $key = sprintf('t%di%d', $oldNode['node_type'], $oldNode['node_id']); + $oldNodeResolvableIdMapper[$key] = $i; + } + + foreach ($nodes as $node) { + $key = sprintf('t%di%d', $node['type'], $node['id']); + if (isset($oldNodeResolvableIdMapper[$key])) { + unset($oldNodeResolvableIdMapper[$key]); + $nodesBeingKept[$key] = $node; + continue; + } + $nodesBeingAdded[$key] = $node; + } + + foreach (array_diff_key($oldNodeResolvableIdMapper, $nodesBeingAdded, $nodesBeingKept) as $toRemoveId) { + $nodesBeingRemoved[$toRemoveId] = $currentNodes[$toRemoveId]; + } + unset($nodesBeingKept); + + $hasUpdatedNodeInformation = !empty($nodesBeingAdded) || !empty($nodesBeingRemoved); + + foreach ($nodesBeingRemoved as $node) { + /** @var ContextNodeRelation $removedNode */ + /** @var PageContent[] $removedContents */ + [$removedNode, $removedContents] = $this->removeNodeFromContextAndPages($node['id']); + foreach ($removedContents as $removedContent) { + unset($currentPages[$removedContent->getPageId()]['content'][$removedContent->getId()]); + } + unset($currentNodes[$removedNode->getId()]); + } + unset($nodesBeingRemoved); + + foreach ($nodesBeingAdded as $node) { + /** @var ContextNodeRelation $addedNode */ + /** @var PageContent $updatedContent */ + [$addedNode, $updatedContent] = $this->addNodeToContextAndStartpage( + $contextId, + $node['id'], + $node['type'], + $node['permissions'], + $node['order'] ?? 100, + $userId + ); + $currentNodes[$addedNode->getId()] = $addedNode->jsonSerialize(); + $currentPages[$updatedContent->getPageId()]['content'][$updatedContent->getId()] = $updatedContent->jsonSerialize(); + } + unset($nodesBeingAdded); + } + + $context = $this->contextMapper->update($context); + if ($hasUpdatedNodeInformation && isset($currentNodes) && isset($currentPages)) { + $context->setNodes($currentNodes); + $context->setPages($currentPages); + } + return $context; } /** @@ -198,6 +266,28 @@ public function removeNodeFromContextById(int $nodeRelationId): ContextNodeRelat return $this->contextNodeRelMapper->delete($nodeRelation); } + /** + * @throws MultipleObjectsReturnedException + * @throws DoesNotExistException + * @throws Exception + */ + public function addNodeToContextAndStartpage(int $contextId, int $nodeId, int $nodeType, int $permissions, int $order, string $userId): array { + $relation = $this->addNodeToContextById($contextId, $nodeId, $nodeType, $permissions, $userId); + $pageContent = $this->addNodeRelToPage($relation, $order); + return [$relation, $pageContent]; + } + + /** + * @throws DoesNotExistException + * @throws MultipleObjectsReturnedException + * @throws Exception + */ + public function removeNodeFromContextAndPages(int $nodeRelationId): array { + $nodeRelation = $this->removeNodeFromContextById($nodeRelationId); + $contents = $this->removeNodeRelFromAllPages($nodeRelation); + return [$nodeRelation, $contents]; + } + /** * @throws Exception */ From 6de5ae583a20fc845bf8cc6d5e70640639195bf9 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Mon, 11 Mar 2024 17:41:07 +0100 Subject: [PATCH 11/15] feat(OpenAPI): add information on Contexts endpoints Signed-off-by: Arthur Schiwon --- lib/Controller/ContextController.php | 93 +++++++++++++++++++++++++--- lib/Db/ContextMapper.php | 3 +- lib/Service/ContextService.php | 4 +- 3 files changed, 88 insertions(+), 12 deletions(-) diff --git a/lib/Controller/ContextController.php b/lib/Controller/ContextController.php index bc7a31000..0a3978a86 100644 --- a/lib/Controller/ContextController.php +++ b/lib/Controller/ContextController.php @@ -59,8 +59,9 @@ public function index(): DataResponse { } /** - * [api v3] Get information about the requests context + * [api v2] Get information about the requests context * + * @param int $contextId ID of the context * @return DataResponse|DataResponse * * 200: returning the full context information @@ -87,11 +88,11 @@ public function show(int $contextId): DataResponse { * @param string $name Name of the context * @param string $iconName Material design icon name of the context * @param string $description Descriptive text of the context - * @param array $nodes optional nodes to be connected to this context + * @param array{id: int, type: int, permissions: int} $nodes optional nodes to be connected to this context * * @return DataResponse|DataResponse * - * 200: Tables returned + * 200: returning the full context information */ public function create(string $name, string $iconName, string $description = '', array $nodes = []): DataResponse { try { @@ -102,6 +103,20 @@ public function create(string $name, string $iconName, string $description = '', } /** + * [api v2] Update an existing context and return it + * + * @param int $contextId ID of the context + * @param ?string $name provide this parameter to set a new name + * @param ?string $iconName provide this parameter to set a new icon + * @param ?string $description provide this parameter to set a new description + * @param ?array{id: int, type: int, permissions: int, order: int} $nodes provide this parameter to set a new list of nodes. + * + * @return DataResponse|DataResponse + * + * 200: returning the full context information + * 403: No permissions + * 404: Not found + * * @NoAdminRequired * @CanManageContext */ @@ -123,6 +138,19 @@ public function update(int $contextId, ?string $name, ?string $iconName, ?string } /** + * [api v2] Transfer the ownership of a context and return it + * + * @param int $contextId ID of the context + * @param string $newOwnerId ID of the new owner + * @param int $newOwnerType any Application::OWNER_TYPE_* constant + * + * @return DataResponse|DataResponse + * + * 200: Ownership transferred + * 400: Invalid request + * 403: No permissions + * 404: Not found + * * @NoAdminRequired * @CanManageContext * @@ -142,6 +170,20 @@ public function transfer(int $contextId, string $newOwnerId, int $newOwnerType = } /** + * [api v2] Add a node to a Context + * + * @param int $contextId ID of the context + * @param int $nodeId ID of the node + * @param int $nodeType any Application::NODE_TYPE_* constant + * @param int $permissions bitmask of the permissions for context recipients + * @param ?int $order in which order the node should appear within the context + * + * @return DataResponse|DataResponse + * + * 200: Node added successfully + * 403: No permissions + * 404: Not found + * * @NoAdminRequired * @CanManageNode */ @@ -151,6 +193,8 @@ public function addNode(int $contextId, int $nodeId, int $nodeType, int $permiss $this->contextService->addNodeRelToPage($rel, $order); $context = $this->contextService->findById($rel->getContextId(), $this->userId); return new DataResponse($context->jsonSerialize()); + } catch (NotFoundError $e) { + return $this->handleNotFoundError($e); } catch (DoesNotExistException $e) { return $this->handleNotFoundError(new NotFoundError($e->getMessage(), $e->getCode(), $e)); } catch (MultipleObjectsReturnedException|Exception|InternalError $e) { @@ -159,6 +203,18 @@ public function addNode(int $contextId, int $nodeId, int $nodeType, int $permiss } /** + * [api v2] Remove a node from a Context + * + * @param int $contextId ID of the context + * @param int $nodeRelId ID of the node-in-context relation + * + * @return DataResponse|DataResponse + * + * 200: Node removed successfully + * 400: Invalid request + * 403: No permissions + * 404: Not found + * * @NoAdminRequired * @CanManageContext */ @@ -174,21 +230,40 @@ public function removeNode(int $contextId, int $nodeRelId): DataResponse { $this->contextService->removeNodeRelFromAllPages($nodeRelation); $context = $this->contextService->findById($contextId, $this->userId); return new DataResponse($context->jsonSerialize()); + } catch (NotFoundError $e) { + return $this->handleNotFoundError($e); } catch (DoesNotExistException $e) { - $this->handleNotFoundError(new NotFoundError($e->getMessage(), $e->getCode(), $e)); - } catch (MultipleObjectsReturnedException|Exception $e) { - $this->handleError($e); + return $this->handleNotFoundError(new NotFoundError($e->getMessage(), $e->getCode(), $e)); + } catch (MultipleObjectsReturnedException|Exception|InternalError $e) { + return $this->handleError($e); } - - return new DataResponse(); } /** + * [api v2] Update the order on a page of a context + * + * @param int $contextId ID of the context + * @param int $pageId ID of the page + * @param array{id: int, order: int} $content content items with it and order values + * + * @return DataResponse|DataResponse + * * @NoAdminRequired * @CanManageContext + * + * 200: content updated successfully + * 400: Invalid request + * 403: No permissions + * 404: Not found */ public function updateContentOrder(int $contextId, int $pageId, array $content): DataResponse { - $context = $this->contextService->findById($contextId, $this->userId); + try { + $context = $this->contextService->findById($contextId, $this->userId); + } catch (Exception|InternalError $e) { + return $this->handleError($e); + } catch (NotFoundError $e) { + return $this->handleNotFoundError($e); + } if (!isset($context->getPages()[$pageId])) { return $this->handleBadRequestError(new BadRequestError('Page not found in given Context')); } diff --git a/lib/Db/ContextMapper.php b/lib/Db/ContextMapper.php index 5b33ec10e..44fb57ae6 100644 --- a/lib/Db/ContextMapper.php +++ b/lib/Db/ContextMapper.php @@ -164,9 +164,8 @@ public function findAll(?string $userId = null): array { } /** - * @throws DoesNotExistException - * @throws MultipleObjectsReturnedException * @throws Exception + * @throws NotFoundError */ public function findById(int $contextId, ?string $userId = null): Context { $qb = $this->getFindContextBaseQuery($userId); diff --git a/lib/Service/ContextService.php b/lib/Service/ContextService.php index 7eccec9d5..ee31cc7ad 100644 --- a/lib/Service/ContextService.php +++ b/lib/Service/ContextService.php @@ -16,6 +16,7 @@ use OCA\Tables\Db\PageMapper; use OCA\Tables\Errors\BadRequestError; use OCA\Tables\Errors\InternalError; +use OCA\Tables\Errors\NotFoundError; use OCA\Tables\Errors\PermissionError; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; @@ -77,8 +78,9 @@ public function findAll(?string $userId): array { } /** - * @return Context + * @throws Exception * @throws InternalError + * @throws NotFoundError */ public function findById(int $id, ?string $userId): Context { if ($userId !== null && trim($userId) === '') { From 47778a9861d249621d00002d55264271a845062e Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Tue, 12 Mar 2024 12:06:45 +0100 Subject: [PATCH 12/15] fix(CI): cater to code style and static analysis Signed-off-by: Arthur Schiwon --- lib/Controller/ContextController.php | 14 +++++++------- lib/Db/ContextMapper.php | 2 -- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/Controller/ContextController.php b/lib/Controller/ContextController.php index 0a3978a86..bd71417a1 100644 --- a/lib/Controller/ContextController.php +++ b/lib/Controller/ContextController.php @@ -62,7 +62,7 @@ public function index(): DataResponse { * [api v2] Get information about the requests context * * @param int $contextId ID of the context - * @return DataResponse|DataResponse + * @return DataResponse|DataResponse * * 200: returning the full context information * 404: context not found or not available anymore @@ -88,7 +88,7 @@ public function show(int $contextId): DataResponse { * @param string $name Name of the context * @param string $iconName Material design icon name of the context * @param string $description Descriptive text of the context - * @param array{id: int, type: int, permissions: int} $nodes optional nodes to be connected to this context + * @param array{id: int, type: int, permissions: int}|array $nodes optional nodes to be connected to this context * * @return DataResponse|DataResponse * @@ -111,7 +111,7 @@ public function create(string $name, string $iconName, string $description = '', * @param ?string $description provide this parameter to set a new description * @param ?array{id: int, type: int, permissions: int, order: int} $nodes provide this parameter to set a new list of nodes. * - * @return DataResponse|DataResponse + * @return DataResponse|DataResponse * * 200: returning the full context information * 403: No permissions @@ -144,7 +144,7 @@ public function update(int $contextId, ?string $name, ?string $iconName, ?string * @param string $newOwnerId ID of the new owner * @param int $newOwnerType any Application::OWNER_TYPE_* constant * - * @return DataResponse|DataResponse + * @return DataResponse|DataResponse * * 200: Ownership transferred * 400: Invalid request @@ -178,7 +178,7 @@ public function transfer(int $contextId, string $newOwnerId, int $newOwnerType = * @param int $permissions bitmask of the permissions for context recipients * @param ?int $order in which order the node should appear within the context * - * @return DataResponse|DataResponse + * @return DataResponse|DataResponse * * 200: Node added successfully * 403: No permissions @@ -208,7 +208,7 @@ public function addNode(int $contextId, int $nodeId, int $nodeType, int $permiss * @param int $contextId ID of the context * @param int $nodeRelId ID of the node-in-context relation * - * @return DataResponse|DataResponse + * @return DataResponse|DataResponse * * 200: Node removed successfully * 400: Invalid request @@ -246,7 +246,7 @@ public function removeNode(int $contextId, int $nodeRelId): DataResponse { * @param int $pageId ID of the page * @param array{id: int, order: int} $content content items with it and order values * - * @return DataResponse|DataResponse + * @return DataResponse|DataResponse * * @NoAdminRequired * @CanManageContext diff --git a/lib/Db/ContextMapper.php b/lib/Db/ContextMapper.php index 44fb57ae6..702af3767 100644 --- a/lib/Db/ContextMapper.php +++ b/lib/Db/ContextMapper.php @@ -6,8 +6,6 @@ use OCA\Tables\Errors\NotFoundError; use OCA\Tables\Helper\UserHelper; -use OCP\AppFramework\Db\DoesNotExistException; -use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\AppFramework\Db\QBMapper; use OCP\DB\Exception; use OCP\DB\QueryBuilder\IQueryBuilder; From 82a212758b5a4d8ec46a77162f7dc1967884ec39 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Tue, 12 Mar 2024 16:41:58 +0100 Subject: [PATCH 13/15] fix(Middleware): NC26 compat Signed-off-by: Arthur Schiwon --- lib/Middleware/PermissionMiddleware.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Middleware/PermissionMiddleware.php b/lib/Middleware/PermissionMiddleware.php index 5b736791b..49b239936 100644 --- a/lib/Middleware/PermissionMiddleware.php +++ b/lib/Middleware/PermissionMiddleware.php @@ -5,7 +5,6 @@ use OCA\Tables\Errors\InternalError; use OCA\Tables\Errors\PermissionError; use OCA\Tables\Service\PermissionsService; -use OCP\AppFramework\Controller; use OCP\AppFramework\Middleware; use OCP\AppFramework\Utility\IControllerMethodReflector; use OCP\IRequest; @@ -33,7 +32,9 @@ public function __construct( * @throws PermissionError * @throws InternalError */ - public function beforeController(Controller $controller, string $methodName): void { + public function beforeController($controller, $methodName): void { + // we can have type hinting in the signature only after dropping NC26 – calling parent to enforce on newer releases + parent::beforeController($controller, $methodName); $this->assertCanManageNode(); $this->assertCanManageContext(); } From 3d74dbd1d69c9d15feade3660c042c52b55d3530 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Tue, 12 Mar 2024 16:46:22 +0100 Subject: [PATCH 14/15] test(phpunit): adjust PermissionService instantiation Signed-off-by: Arthur Schiwon --- tests/unit/Service/PermissionsServiceTest.php | 41 +++++++------------ 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/tests/unit/Service/PermissionsServiceTest.php b/tests/unit/Service/PermissionsServiceTest.php index f4dcd06a6..6ff0e2a89 100644 --- a/tests/unit/Service/PermissionsServiceTest.php +++ b/tests/unit/Service/PermissionsServiceTest.php @@ -26,6 +26,7 @@ namespace OCA\Tables\Service; +use OCA\Tables\Db\ContextMapper; use OCA\Tables\Db\ShareMapper; use OCA\Tables\Db\TableMapper; use OCA\Tables\Db\ViewMapper; @@ -35,51 +36,42 @@ use Test\TestCase; class PermissionsServiceTest extends TestCase { - public function testPreCheckUserIdGivenUser() { + protected function getPermissionServiceWithUserId(mixed $userId, bool $isCli = false): PermissionsService { $logger = $this->createMock(LoggerInterface::class); - $userId = "TestUser"; $tableMapper = $this->createMock(TableMapper::class); $shareMapper = $this->createMock(ShareMapper::class); $viewMapper = $this->createMock(ViewMapper::class); + $contextMapper = $this->createMock(ContextMapper::class); $userHelper = $this->createMock(UserHelper::class); - $permissionsService = new PermissionsService($logger, $userId, $tableMapper, $viewMapper, $shareMapper, $userHelper, false); + + return new PermissionsService($logger, $userId, $tableMapper, $viewMapper, $shareMapper, $contextMapper, $userHelper, $isCli); + } + + public function testPreCheckUserIdGivenUser() { + $userId = 'TestUser'; + $permissionsService = $this->getPermissionServiceWithUserId($userId); self::assertEquals($userId, $permissionsService->preCheckUserId($userId)); } public function testPreCheckUserIdNoUser() { - $logger = $this->createMock(LoggerInterface::class); $userId = null; - $tableMapper = $this->createMock(TableMapper::class); - $viewMapper = $this->createMock(ViewMapper::class); - $shareMapper = $this->createMock(ShareMapper::class); - $userHelper = $this->createMock(UserHelper::class); - $permissionsService = new PermissionsService($logger, $userId, $tableMapper, $viewMapper, $shareMapper, $userHelper, false); + $permissionsService = $this->getPermissionServiceWithUserId($userId); self::expectException(InternalError::class); $permissionsService->preCheckUserId($userId); } public function testPreCheckUserIdNoUserButContext() { - $logger = $this->createMock(LoggerInterface::class); $userId = 'john'; - $tableMapper = $this->createMock(TableMapper::class); - $viewMapper = $this->createMock(ViewMapper::class); - $shareMapper = $this->createMock(ShareMapper::class); - $userHelper = $this->createMock(UserHelper::class); - $permissionsService = new PermissionsService($logger, $userId, $tableMapper, $viewMapper, $shareMapper, $userHelper, false); + $permissionsService = $this->getPermissionServiceWithUserId($userId); self::assertEquals($userId, $permissionsService->preCheckUserId(null)); } public function testPreCheckUserIdNoUserNotAllowed() { - $logger = $this->createMock(LoggerInterface::class); $userId = ''; - $tableMapper = $this->createMock(TableMapper::class); - $viewMapper = $this->createMock(ViewMapper::class); - $shareMapper = $this->createMock(ShareMapper::class); - $userHelper = $this->createMock(UserHelper::class); - $permissionsService = new PermissionsService($logger, $userId, $tableMapper, $viewMapper, $shareMapper, $userHelper, false); + $permissionsService = $this->getPermissionServiceWithUserId($userId); self::expectException(InternalError::class); $permissionsService->preCheckUserId($userId, false); @@ -89,13 +81,8 @@ public function testPreCheckUserIdNoUserNotAllowed() { } public function testPreCheckUserIdNoUserAllowed() { - $logger = $this->createMock(LoggerInterface::class); $userId = ''; - $tableMapper = $this->createMock(TableMapper::class); - $viewMapper = $this->createMock(ViewMapper::class); - $shareMapper = $this->createMock(ShareMapper::class); - $userHelper = $this->createMock(UserHelper::class); - $permissionsService = new PermissionsService($logger, $userId, $tableMapper, $viewMapper, $shareMapper, $userHelper, true); + $permissionsService = $this->getPermissionServiceWithUserId($userId, true); self::assertEquals($userId, $permissionsService->preCheckUserId($userId)); } From dd896acc99f0250686c608b543b204bc39a18f8b Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Tue, 12 Mar 2024 17:38:42 +0100 Subject: [PATCH 15/15] build(openapi): regenerate openapi files Signed-off-by: Arthur Schiwon --- openapi.json | 9275 ++++++++++++++++++++++++++++++++++ src/types/openapi/openapi.ts | 508 ++ 2 files changed, 9783 insertions(+) create mode 100644 openapi.json diff --git a/openapi.json b/openapi.json new file mode 100644 index 000000000..b6af3bbf1 --- /dev/null +++ b/openapi.json @@ -0,0 +1,9275 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "tables", + "version": "0.0.1", + "description": "Manage data the way you need it.", + "license": { + "name": "agpl" + } + }, + "components": { + "securitySchemes": { + "basic_auth": { + "type": "http", + "scheme": "basic" + }, + "bearer_auth": { + "type": "http", + "scheme": "bearer" + } + }, + "schemas": { + "Capabilities": { + "type": "object", + "required": [ + "tables" + ], + "properties": { + "tables": { + "type": "object", + "required": [ + "enabled", + "version", + "apiVersions", + "features", + "column_types" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "version": { + "type": "string" + }, + "apiVersions": { + "type": "array", + "items": { + "type": "string" + } + }, + "features": { + "type": "array", + "items": { + "type": "string" + } + }, + "column_types": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "Column": { + "type": "object", + "required": [ + "id", + "title", + "tableId", + "createdBy", + "createdAt", + "lastEditBy", + "lastEditAt", + "type", + "subtype", + "mandatory", + "description", + "orderWeight", + "numberDefault", + "numberMin", + "numberMax", + "numberDecimals", + "numberPrefix", + "numberSuffix", + "textDefault", + "textAllowedPattern", + "textMaxLength", + "selectionOptions", + "selectionDefault", + "datetimeDefault" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "title": { + "type": "string" + }, + "tableId": { + "type": "integer", + "format": "int64" + }, + "createdBy": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastEditBy": { + "type": "string" + }, + "lastEditAt": { + "type": "string" + }, + "type": { + "type": "string" + }, + "subtype": { + "type": "string" + }, + "mandatory": { + "type": "boolean" + }, + "description": { + "type": "string" + }, + "orderWeight": { + "type": "integer", + "format": "int64" + }, + "numberDefault": { + "type": "number", + "format": "float" + }, + "numberMin": { + "type": "number", + "format": "float" + }, + "numberMax": { + "type": "number", + "format": "float" + }, + "numberDecimals": { + "type": "integer", + "format": "int64" + }, + "numberPrefix": { + "type": "string" + }, + "numberSuffix": { + "type": "string" + }, + "textDefault": { + "type": "string" + }, + "textAllowedPattern": { + "type": "string" + }, + "textMaxLength": { + "type": "integer", + "format": "int64" + }, + "selectionOptions": { + "type": "string" + }, + "selectionDefault": { + "type": "string" + }, + "datetimeDefault": { + "type": "string" + } + } + }, + "Context": { + "type": "object", + "required": [ + "id", + "name", + "iconName", + "description", + "owner", + "ownerType" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + }, + "iconName": { + "type": "string" + }, + "description": { + "type": "string" + }, + "owner": { + "type": "string" + }, + "ownerType": { + "type": "integer", + "format": "int64" + } + } + }, + "ImportState": { + "type": "object", + "required": [ + "found_columns_count", + "matching_columns_count", + "created_columns_count", + "inserted_rows_count", + "errors_parsing_count", + "errors_count" + ], + "properties": { + "found_columns_count": { + "type": "integer", + "format": "int64" + }, + "matching_columns_count": { + "type": "integer", + "format": "int64" + }, + "created_columns_count": { + "type": "integer", + "format": "int64" + }, + "inserted_rows_count": { + "type": "integer", + "format": "int64" + }, + "errors_parsing_count": { + "type": "integer", + "format": "int64" + }, + "errors_count": { + "type": "integer", + "format": "int64" + } + } + }, + "Index": { + "type": "object", + "required": [ + "tables", + "views" + ], + "properties": { + "tables": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Table" + } + }, + "views": { + "type": "array", + "items": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "OCSMeta": { + "type": "object", + "required": [ + "status", + "statuscode" + ], + "properties": { + "status": { + "type": "string" + }, + "statuscode": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "totalitems": { + "type": "string" + }, + "itemsperpage": { + "type": "string" + } + } + }, + "Row": { + "type": "object", + "required": [ + "id", + "tableId", + "createdBy", + "createdAt", + "lastEditBy", + "lastEditAt", + "data" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "tableId": { + "type": "integer", + "format": "int64" + }, + "createdBy": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastEditBy": { + "type": "string" + }, + "lastEditAt": { + "type": "string" + }, + "data": { + "type": "object", + "nullable": true, + "required": [ + "columnId", + "value" + ], + "properties": { + "columnId": { + "type": "integer", + "format": "int64" + }, + "value": { + "type": "object" + } + } + } + } + }, + "Share": { + "type": "object", + "required": [ + "id", + "sender", + "receiver", + "receiverDisplayName", + "receiverType", + "nodeId", + "nodeType", + "permissionRead", + "permissionCreate", + "permissionUpdate", + "permissionDelete", + "permissionManage", + "createdAt", + "createdBy" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "sender": { + "type": "string" + }, + "receiver": { + "type": "string" + }, + "receiverDisplayName": { + "type": "string" + }, + "receiverType": { + "type": "string" + }, + "nodeId": { + "type": "integer", + "format": "int64" + }, + "nodeType": { + "type": "string" + }, + "permissionRead": { + "type": "boolean" + }, + "permissionCreate": { + "type": "boolean" + }, + "permissionUpdate": { + "type": "boolean" + }, + "permissionDelete": { + "type": "boolean" + }, + "permissionManage": { + "type": "boolean" + }, + "createdAt": { + "type": "string" + }, + "createdBy": { + "type": "string" + } + } + }, + "Table": { + "type": "object", + "required": [ + "id", + "title", + "emoji", + "ownership", + "ownerDisplayName", + "createdBy", + "createdAt", + "lastEditBy", + "lastEditAt", + "archived", + "favorite", + "isShared", + "onSharePermissions", + "hasShares", + "rowsCount", + "views", + "columnsCount" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "title": { + "type": "string" + }, + "emoji": { + "type": "string", + "nullable": true + }, + "ownership": { + "type": "string" + }, + "ownerDisplayName": { + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastEditBy": { + "type": "string" + }, + "lastEditAt": { + "type": "string" + }, + "archived": { + "type": "boolean" + }, + "favorite": { + "type": "boolean" + }, + "isShared": { + "type": "boolean" + }, + "onSharePermissions": { + "type": "object", + "nullable": true, + "required": [ + "read", + "create", + "update", + "delete", + "manage" + ], + "properties": { + "read": { + "type": "boolean" + }, + "create": { + "type": "boolean" + }, + "update": { + "type": "boolean" + }, + "delete": { + "type": "boolean" + }, + "manage": { + "type": "boolean" + } + } + }, + "hasShares": { + "type": "boolean" + }, + "rowsCount": { + "type": "integer", + "format": "int64" + }, + "views": { + "type": "array", + "items": { + "$ref": "#/components/schemas/View" + } + }, + "columnsCount": { + "type": "integer", + "format": "int64" + } + } + }, + "View": { + "type": "object", + "required": [ + "id", + "title", + "emoji", + "tableId", + "ownership", + "ownerDisplayName", + "createdBy", + "createdAt", + "lastEditBy", + "lastEditAt", + "description", + "columns", + "sort", + "filter", + "isShared", + "favorite", + "onSharePermissions", + "hasShares", + "rowsCount" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "title": { + "type": "string" + }, + "emoji": { + "type": "string", + "nullable": true + }, + "tableId": { + "type": "integer", + "format": "int64" + }, + "ownership": { + "type": "string" + }, + "ownerDisplayName": { + "type": "string", + "nullable": true + }, + "createdBy": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastEditBy": { + "type": "string" + }, + "lastEditAt": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "columns": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + "sort": { + "type": "array", + "items": { + "type": "object", + "required": [ + "columnId", + "mode" + ], + "properties": { + "columnId": { + "type": "integer", + "format": "int64" + }, + "mode": { + "type": "string", + "enum": [ + "ASC", + "DESC" + ] + } + } + } + }, + "filter": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "object", + "required": [ + "columnId", + "operator", + "value" + ], + "properties": { + "columnId": { + "type": "integer", + "format": "int64" + }, + "operator": { + "type": "string", + "enum": [ + "begins-with", + "ends-with", + "contains", + "is-equal", + "is-greater-than", + "is-greater-than-or-equal", + "is-lower-than", + "is-lower-than-or-equal", + "is-empty" + ] + }, + "value": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer", + "format": "int64" + }, + { + "type": "number", + "format": "float" + } + ] + } + } + } + } + }, + "isShared": { + "type": "boolean" + }, + "favorite": { + "type": "boolean" + }, + "onSharePermissions": { + "type": "object", + "nullable": true, + "required": [ + "read", + "create", + "update", + "delete", + "manage" + ], + "properties": { + "read": { + "type": "boolean" + }, + "create": { + "type": "boolean" + }, + "update": { + "type": "boolean" + }, + "delete": { + "type": "boolean" + }, + "manage": { + "type": "boolean" + } + } + }, + "hasShares": { + "type": "boolean" + }, + "rowsCount": { + "type": "integer", + "format": "int64" + } + } + } + } + }, + "paths": { + "/index.php/apps/tables/api/1/tables": { + "get": { + "operationId": "api1-list", + "summary": "Returns all Tables", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "responses": { + "200": { + "description": "Tables returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Table" + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api1-create-table", + "summary": "Create a new table and return it", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "Title of the table", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "emoji", + "in": "query", + "description": "Emoji for the table", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "template", + "in": "query", + "description": "Template to use if wanted", + "schema": { + "type": "string", + "default": "custom" + } + } + ], + "responses": { + "200": { + "description": "Tables returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Table" + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/tables/{tableId}": { + "put": { + "operationId": "api1-update-table", + "summary": "Update tables properties", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "New table title", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "emoji", + "in": "query", + "description": "New table emoji", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "archived", + "in": "query", + "description": "Whether the table is archived", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Tables returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Table" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "get": { + "operationId": "api1-get-table", + "summary": "Get a table object", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Table returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Table" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "api1-delete-table", + "summary": "Delete a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Deleted table returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Table" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/tables/{tableId}/views": { + "get": { + "operationId": "api1-list-views", + "summary": "Get all views for a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Views returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/View" + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api1-create-view", + "summary": "Create a new view for a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "Title for the view", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "emoji", + "in": "query", + "description": "Emoji for the view", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID that will hold the view", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/views/{viewId}": { + "get": { + "operationId": "api1-get-view", + "summary": "Get a view object", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "put": { + "operationId": "api1-update-view", + "summary": "Update a view via key-value sets", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "data", + "in": "query", + "description": "key-value pairs", + "required": true, + "schema": { + "oneOf": [ + { + "type": "object", + "required": [ + "key", + "value" + ], + "properties": { + "key": { + "type": "string", + "enum": [ + "title", + "emoji", + "description" + ] + }, + "value": { + "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "key", + "value" + ], + "properties": { + "key": { + "type": "string", + "enum": [ + "columns" + ] + }, + "value": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + } + } + }, + { + "type": "object", + "required": [ + "key", + "value" + ], + "properties": { + "key": { + "type": "string", + "enum": [ + "sort" + ] + }, + "value": { + "type": "object", + "required": [ + "columnId", + "mode" + ], + "properties": { + "columnId": { + "type": "integer", + "format": "int64" + }, + "mode": { + "type": "string", + "enum": [ + "ASC", + "DESC" + ] + } + } + } + } + }, + { + "type": "object", + "required": [ + "key", + "value" + ], + "properties": { + "key": { + "type": "string", + "enum": [ + "filter" + ] + }, + "value": { + "type": "object", + "required": [ + "columnId", + "operator", + "value" + ], + "properties": { + "columnId": { + "type": "integer", + "format": "int64" + }, + "operator": { + "type": "string", + "enum": [ + "begins-with", + "ends-with", + "contains", + "is-equal", + "is-greater-than", + "is-greater-than-or-equal", + "is-lower-than", + "is-lower-than-or-equal", + "is-empty" + ] + }, + "value": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer", + "format": "int64" + }, + { + "type": "number", + "format": "float" + } + ] + } + } + } + } + } + ] + } + }, + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "api1-delete-view", + "summary": "Delete a view", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/shares/{shareId}": { + "get": { + "operationId": "api1-get-share", + "summary": "Get a share object", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "shareId", + "in": "path", + "description": "Share ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Share returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Share" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "api1-delete-share", + "summary": "Delete a share", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "shareId", + "in": "path", + "description": "Share ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Share" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "put": { + "operationId": "api1-update-share-permissions", + "summary": "Update a share permission", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "permissionType", + "in": "query", + "description": "Permission type that should be changed", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "permissionValue", + "in": "query", + "description": "New permission value", + "required": true, + "schema": { + "type": "integer", + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "shareId", + "in": "path", + "description": "Share ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Share" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/views/{viewId}/shares": { + "get": { + "operationId": "api1-list-view-shares", + "summary": "Get all shares for a view Will be empty if view does not exist", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Shares returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Share" + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/tables/{tableId}/shares": { + "get": { + "operationId": "api1-list-table-shares", + "summary": "Get all shares for a table Will be empty if table does not exist", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Shares returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Share" + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api1-create-table-share", + "summary": "Create a share for a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "receiver", + "in": "query", + "description": "Receiver ID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "receiverType", + "in": "query", + "description": "Receiver type", + "required": true, + "schema": { + "type": "string", + "enum": [ + "user", + "group" + ] + } + }, + { + "name": "permissionRead", + "in": "query", + "description": "Permission if receiver can read data", + "required": true, + "schema": { + "type": "integer", + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "permissionCreate", + "in": "query", + "description": "Permission if receiver can create data", + "required": true, + "schema": { + "type": "integer", + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "permissionUpdate", + "in": "query", + "description": "Permission if receiver can update data", + "required": true, + "schema": { + "type": "integer", + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "permissionDelete", + "in": "query", + "description": "Permission if receiver can delete data", + "required": true, + "schema": { + "type": "integer", + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "permissionManage", + "in": "query", + "description": "Permission if receiver can manage table", + "required": true, + "schema": { + "type": "integer", + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Share" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/shares": { + "post": { + "operationId": "api1-create-share", + "summary": "Create a new share", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "nodeId", + "in": "query", + "description": "Node ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "nodeType", + "in": "query", + "description": "Node type", + "required": true, + "schema": { + "type": "string", + "enum": [ + "table", + "view" + ] + } + }, + { + "name": "receiver", + "in": "query", + "description": "Receiver ID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "receiverType", + "in": "query", + "description": "Receiver type", + "required": true, + "schema": { + "type": "string", + "enum": [ + "user", + "group" + ] + } + }, + { + "name": "permissionRead", + "in": "query", + "description": "Permission if receiver can read data", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "permissionCreate", + "in": "query", + "description": "Permission if receiver can create data", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "permissionUpdate", + "in": "query", + "description": "Permission if receiver can update data", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "permissionDelete", + "in": "query", + "description": "Permission if receiver can delete data", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "permissionManage", + "in": "query", + "description": "Permission if receiver can manage node", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + } + ], + "responses": { + "200": { + "description": "Share returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Share" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/tables/{tableId}/columns": { + "get": { + "operationId": "api1-list-table-columns", + "summary": "Get all columns for a table or a underlying view Return an empty array if no columns were found", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "query", + "description": "View ID", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View deleted", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Column" + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api1-create-table-column", + "summary": "Create a new column for a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "Title", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "description": "Column main type", + "required": true, + "schema": { + "type": "string", + "enum": [ + "text", + "number", + "datetime", + "select" + ] + } + }, + { + "name": "subtype", + "in": "query", + "description": "Column sub type", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is the column mandatory", + "required": true, + "schema": { + "type": "integer", + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberPrefix", + "in": "query", + "description": "Prefix if the column is a number field", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberSuffix", + "in": "query", + "description": "Suffix if the column is a number field", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberDefault", + "in": "query", + "description": "Default number, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMin", + "in": "query", + "description": "Min value, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMax", + "in": "query", + "description": "Max number, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberDecimals", + "in": "query", + "description": "Number of decimals, if column is a number", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "textDefault", + "in": "query", + "description": "Default text, if column is a text", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textAllowedPattern", + "in": "query", + "description": "Allowed pattern (regex) for text columns (not yet implemented)", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textMaxLength", + "in": "query", + "description": "Max length, if column is a text", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "selectionOptions", + "in": "query", + "description": "Options for a selection (json array{id: int, label: string})", + "schema": { + "type": "string", + "nullable": true, + "default": "" + } + }, + { + "name": "selectionDefault", + "in": "query", + "description": "Default option IDs for a selection (json int[])", + "schema": { + "type": "string", + "nullable": true, + "default": "" + } + }, + { + "name": "datetimeDefault", + "in": "query", + "description": "Default value, if column is datetime", + "schema": { + "type": "string", + "nullable": true, + "default": "" + } + }, + { + "name": "selectedViewIds[]", + "in": "query", + "description": "View IDs where this column should be added to be presented", + "schema": { + "type": "array", + "nullable": true, + "default": [], + "items": { + "type": "integer", + "format": "int64" + } + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Column created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Column" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/views/{viewId}/columns": { + "get": { + "operationId": "api1-list-view-columns", + "summary": "Get all columns for a view Return an empty array if no columns were found", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View deleted", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Column" + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/columns": { + "post": { + "operationId": "api1-create-column", + "summary": "Create a column", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "tableId", + "in": "query", + "description": "Table ID", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "viewId", + "in": "query", + "description": "View ID", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "title", + "in": "query", + "description": "Title", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "description": "Column main type", + "required": true, + "schema": { + "type": "string", + "enum": [ + "text", + "number", + "datetime", + "select" + ] + } + }, + { + "name": "subtype", + "in": "query", + "description": "Column sub type", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is the column mandatory", + "required": true, + "schema": { + "type": "integer", + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberPrefix", + "in": "query", + "description": "Prefix if the column is a number field", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberSuffix", + "in": "query", + "description": "Suffix if the column is a number field", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberDefault", + "in": "query", + "description": "Default number, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMin", + "in": "query", + "description": "Min value, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMax", + "in": "query", + "description": "Max number, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberDecimals", + "in": "query", + "description": "Number of decimals, if column is a number", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "textDefault", + "in": "query", + "description": "Default text, if column is a text", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textAllowedPattern", + "in": "query", + "description": "Allowed pattern (regex) for text columns (not yet implemented)", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textMaxLength", + "in": "query", + "description": "Max length, if column is a text", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "selectionOptions", + "in": "query", + "description": "Options for a selection (json array{id: int, label: string})", + "schema": { + "type": "string", + "nullable": true, + "default": "" + } + }, + { + "name": "selectionDefault", + "in": "query", + "description": "Default option IDs for a selection (json int[])", + "schema": { + "type": "string", + "nullable": true, + "default": "" + } + }, + { + "name": "datetimeDefault", + "in": "query", + "description": "Default value, if column is datetime", + "schema": { + "type": "string", + "nullable": true, + "default": "" + } + }, + { + "name": "selectedViewIds[]", + "in": "query", + "description": "View IDs where this column should be added to be presented", + "schema": { + "type": "array", + "nullable": true, + "default": [], + "items": { + "type": "integer", + "format": "int64" + } + } + } + ], + "responses": { + "200": { + "description": "Column created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Column" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/columns/{columnId}": { + "put": { + "operationId": "api1-update-column", + "summary": "Update a column", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "Title", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "subtype", + "in": "query", + "description": "Column sub type", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is the column mandatory", + "required": true, + "schema": { + "type": "integer", + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberPrefix", + "in": "query", + "description": "Prefix if the column is a number field", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberSuffix", + "in": "query", + "description": "Suffix if the column is a number field", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberDefault", + "in": "query", + "description": "Default number, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMin", + "in": "query", + "description": "Min value, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMax", + "in": "query", + "description": "Max number, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberDecimals", + "in": "query", + "description": "Number of decimals, if column is a number", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "textDefault", + "in": "query", + "description": "Default text, if column is a text", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textAllowedPattern", + "in": "query", + "description": "Allowed pattern (regex) for text columns (not yet implemented)", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textMaxLength", + "in": "query", + "description": "Max length, if column is a text", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "selectionOptions", + "in": "query", + "description": "Options for a selection (json array{id: int, label: string})", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "selectionDefault", + "in": "query", + "description": "Default option IDs for a selection (json int[])", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "datetimeDefault", + "in": "query", + "description": "Default value, if column is datetime", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "columnId", + "in": "path", + "description": "Column ID that will be updated", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Updated column", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Column" + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "get": { + "operationId": "api1-get-column", + "summary": "Returns a column object", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "columnId", + "in": "path", + "description": "Wanted Column ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Column returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Column" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "api1-delete-column", + "summary": "Delete a column", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "columnId", + "in": "path", + "description": "Wanted Column ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Deleted column returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Column" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/tables/{tableId}/rows/simple": { + "get": { + "operationId": "api1-list-table-rows-simple", + "summary": "List all rows values for a table, first row are the column titles", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "Limit", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "offset", + "in": "query", + "description": "Offset", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Row values returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/tables/{tableId}/rows": { + "get": { + "operationId": "api1-list-table-rows", + "summary": "List all rows for a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "Limit", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "offset", + "in": "query", + "description": "Offset", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Rows returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Row" + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api1-create-row-in-table", + "summary": "Create a row within a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "data", + "in": "query", + "description": "Data as key - value store", + "required": true, + "schema": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "required": [ + "columnId", + "value" + ], + "properties": { + "columnId": { + "type": "integer", + "format": "int64" + }, + "value": { + "type": "object" + } + } + } + ] + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Row returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Row" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/views/{viewId}/rows": { + "get": { + "operationId": "api1-list-view-rows", + "summary": "List all rows for a view", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "Limit", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "offset", + "in": "query", + "description": "Offset", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Rows returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Row" + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api1-create-row-in-view", + "summary": "Create a row within a view", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "data", + "in": "query", + "description": "Data as key - value store", + "required": true, + "schema": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "required": [ + "columnId", + "value" + ], + "properties": { + "columnId": { + "type": "integer", + "format": "int64" + }, + "value": { + "type": "object" + } + } + } + ] + } + }, + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Row returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Row" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/rows/{rowId}": { + "get": { + "operationId": "api1-get-row", + "summary": "Get a row", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "rowId", + "in": "path", + "description": "Row ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Row returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Row" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "put": { + "operationId": "api1-update-row", + "summary": "Update a row", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "query", + "description": "View ID", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "data", + "in": "query", + "description": "Data as key - value store", + "required": true, + "schema": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "required": [ + "columnId", + "value" + ], + "properties": { + "columnId": { + "type": "integer", + "format": "int64" + }, + "value": { + "type": "object" + } + } + } + ] + } + }, + { + "name": "rowId", + "in": "path", + "description": "Row ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Updated row returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Row" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "api1-delete-row", + "summary": "Delete a row", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "rowId", + "in": "path", + "description": "Row ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Deleted row returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Row" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/views/{viewId}/rows/{rowId}": { + "delete": { + "operationId": "api1-delete-row-by-view", + "summary": "Delete a row within a view", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "rowId", + "in": "path", + "description": "Row ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Deleted row returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Row" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/import/table/{tableId}": { + "post": { + "operationId": "api1-import-in-table", + "summary": "Import from file in to a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "path", + "in": "query", + "description": "Path to file", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "createMissingColumns", + "in": "query", + "description": "Create missing columns", + "schema": { + "type": "integer", + "default": 1, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Import status returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ImportState" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/import/views/{viewId}": { + "post": { + "operationId": "api1-import-in-view", + "summary": "Import from file in to a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "path", + "in": "query", + "description": "Path to file", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "createMissingColumns", + "in": "query", + "description": "Create missing columns", + "schema": { + "type": "integer", + "default": 1, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Import status returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ImportState" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/init": { + "get": { + "operationId": "api_general-list", + "summary": "[api v2] Returns all main resources", + "description": "Tables and views incl. shares", + "tags": [ + "api_general" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "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": "Index returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Index" + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/tables": { + "get": { + "operationId": "api_tables-list", + "summary": "[api v2] Returns all Tables", + "tags": [ + "api_tables" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "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": "Tables returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Table" + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api_tables-create", + "summary": "[api v2] Create a new table and return it", + "tags": [ + "api_tables" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "Title of the table", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "emoji", + "in": "query", + "description": "Emoji for the table", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "template", + "in": "query", + "description": "Template to use if wanted", + "schema": { + "type": "string", + "default": "custom" + } + }, + { + "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": "Tables returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Table" + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/tables/{id}": { + "get": { + "operationId": "api_tables-show", + "summary": "[api v2] Get a table object", + "tags": [ + "api_tables" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "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": "Table returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Table" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permissions", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + }, + "put": { + "operationId": "api_tables-update", + "summary": "[api v2] Update tables properties", + "tags": [ + "api_tables" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "New table title", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "emoji", + "in": "query", + "description": "New table emoji", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "archived", + "in": "query", + "description": "whether the table is archived", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "id", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "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": "Tables returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Table" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permissions", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "api_tables-destroy", + "summary": "[api v2] Delete a table", + "tags": [ + "api_tables" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "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": "Deleted table returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Table" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permissions", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/tables/{id}/transfer": { + "put": { + "operationId": "api_tables-transfer", + "summary": "[api v2] Transfer table", + "description": "Transfer table from one user to another", + "tags": [ + "api_tables" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "newOwnerUserId", + "in": "query", + "description": "New user ID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "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": "Ownership changed", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Table" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permissions", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/columns/{nodeType}/{nodeId}": { + "get": { + "operationId": "api_columns-list", + "summary": "[api v2] Get all columns for a table or a view", + "description": "Return an empty array if no columns were found", + "tags": [ + "api_columns" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "nodeType", + "in": "path", + "description": "Node type", + "required": true, + "schema": { + "type": "string", + "enum": [ + "table", + "view" + ] + } + }, + { + "name": "nodeId", + "in": "path", + "description": "Node ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "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": "View deleted", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Column" + } + } + } + } + } + } + } + } + }, + "403": { + "description": "No permissions", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/columns/{id}": { + "get": { + "operationId": "api_columns-show", + "summary": "[api v2] Get a column object", + "tags": [ + "api_columns" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Column ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "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": "Column returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Column" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permissions", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/columns/number": { + "post": { + "operationId": "api_columns-create-number-column", + "summary": "[api v2] Create new numbered column", + "description": "Specify a subtype to use any special numbered column", + "tags": [ + "api_columns" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "baseNodeId", + "in": "query", + "description": "Context of the column creation", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "title", + "in": "query", + "description": "Title", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "numberDefault", + "in": "query", + "description": "Default value for new rows", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberDecimals", + "in": "query", + "description": "Decimals", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "numberPrefix", + "in": "query", + "description": "Prefix", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberSuffix", + "in": "query", + "description": "Suffix", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberMin", + "in": "query", + "description": "Min", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMax", + "in": "query", + "description": "Max", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "subtype", + "in": "query", + "description": "Subtype for the new column", + "schema": { + "type": "string", + "nullable": true, + "enum": [ + "progress", + "stars" + ] + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "selectedViewIds[]", + "in": "query", + "description": "View IDs where this columns should be added", + "schema": { + "type": "array", + "nullable": true, + "default": [], + "items": { + "type": "integer", + "format": "int64" + } + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is mandatory", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "baseNodeType", + "in": "query", + "description": "Context type of the column creation", + "schema": { + "type": "string", + "default": "table", + "enum": [ + "table", + "view" + ] + } + }, + { + "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": "Column created", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Column" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permission", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/columns/text": { + "post": { + "operationId": "api_columns-create-text-column", + "summary": "[api v2] Create new text column", + "description": "Specify a subtype to use any special text column", + "tags": [ + "api_columns" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "baseNodeId", + "in": "query", + "description": "Context of the column creation", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "title", + "in": "query", + "description": "Title", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "textDefault", + "in": "query", + "description": "Default", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textAllowedPattern", + "in": "query", + "description": "Allowed regex pattern", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textMaxLength", + "in": "query", + "description": "Max raw text length", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "subtype", + "in": "query", + "description": "Subtype for the new column", + "schema": { + "type": "string", + "nullable": true, + "enum": [ + "progress", + "stars" + ] + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "selectedViewIds[]", + "in": "query", + "description": "View IDs where this columns should be added", + "schema": { + "type": "array", + "nullable": true, + "default": [], + "items": { + "type": "integer", + "format": "int64" + } + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is mandatory", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "baseNodeType", + "in": "query", + "description": "Context type of the column creation", + "schema": { + "type": "string", + "default": "table", + "enum": [ + "table", + "view" + ] + } + }, + { + "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": "Column created", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Column" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permission", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/columns/selection": { + "post": { + "operationId": "api_columns-create-selection-column", + "summary": "[api v2] Create new selection column", + "description": "Specify a subtype to use any special selection column", + "tags": [ + "api_columns" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "baseNodeId", + "in": "query", + "description": "Context of the column creation", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "title", + "in": "query", + "description": "Title", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "selectionOptions", + "in": "query", + "description": "Json array{id: int, label: string} with options that can be selected, eg [{\"id\": 1, \"label\": \"first\"},{\"id\": 2, \"label\": \"second\"}]", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "selectionDefault", + "in": "query", + "description": "Json int|int[] for default selected option(s), eg 5 or [\"1\", \"8\"]", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "subtype", + "in": "query", + "description": "Subtype for the new column", + "schema": { + "type": "string", + "nullable": true, + "enum": [ + "progress", + "stars" + ] + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "selectedViewIds[]", + "in": "query", + "description": "View IDs where this columns should be added", + "schema": { + "type": "array", + "nullable": true, + "default": [], + "items": { + "type": "integer", + "format": "int64" + } + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is mandatory", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "baseNodeType", + "in": "query", + "description": "Context type of the column creation", + "schema": { + "type": "string", + "default": "table", + "enum": [ + "table", + "view" + ] + } + }, + { + "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": "Column created", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Column" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permission", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/columns/datetime": { + "post": { + "operationId": "api_columns-create-datetime-column", + "summary": "[api v2] Create new datetime column", + "description": "Specify a subtype to use any special datetime column", + "tags": [ + "api_columns" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "baseNodeId", + "in": "query", + "description": "Context of the column creation", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "title", + "in": "query", + "description": "Title", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "datetimeDefault", + "in": "query", + "description": "For a subtype 'date' you can set 'today'. For a main type or subtype 'time' you can set to 'now'.", + "schema": { + "type": "string", + "nullable": true, + "enum": [ + "today", + "now" + ] + } + }, + { + "name": "subtype", + "in": "query", + "description": "Subtype for the new column", + "schema": { + "type": "string", + "nullable": true, + "enum": [ + "progress", + "stars" + ] + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "selectedViewIds[]", + "in": "query", + "description": "View IDs where this columns should be added", + "schema": { + "type": "array", + "nullable": true, + "default": [], + "items": { + "type": "integer", + "format": "int64" + } + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is mandatory", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } + }, + { + "name": "baseNodeType", + "in": "query", + "description": "Context type of the column creation", + "schema": { + "type": "string", + "default": "table", + "enum": [ + "table", + "view" + ] + } + }, + { + "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": "Column created", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Column" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permission", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/favorites/{nodeType}/{nodeId}": { + "post": { + "operationId": "api_favorite-create", + "summary": "[api v2] Add a node (table or view) to user favorites", + "tags": [ + "api_favorite" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "nodeType", + "in": "path", + "description": "any Application::NODE_TYPE_* constant", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "nodeId", + "in": "path", + "description": "identifier of the node", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "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": "Tables 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" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permissions", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "api_favorite-destroy", + "summary": "[api v2] Remove a node (table or view) to from favorites", + "tags": [ + "api_favorite" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "nodeType", + "in": "path", + "description": "any Application::NODE_TYPE_* constant", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "nodeId", + "in": "path", + "description": "identifier of the node", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "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": "Deleted table 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" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permissions", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/contexts": { + "get": { + "operationId": "context-list", + "summary": "[api v3] Get all contexts available to the requesting person", + "description": "Return an empty array if no contexts were found", + "tags": [ + "context" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "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": "reporting in available contexts", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Context" + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "context-create", + "summary": "[api v2] Create a new context and return it", + "tags": [ + "context" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "name", + "in": "query", + "description": "Name of the context", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "iconName", + "in": "query", + "description": "Material design icon name of the context", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "description", + "in": "query", + "description": "Descriptive text of the context", + "schema": { + "type": "string", + "default": "" + } + }, + { + "name": "nodes", + "in": "query", + "description": "optional nodes to be connected to this context", + "schema": { + "default": [], + "oneOf": [ + { + "type": "object", + "required": [ + "id", + "type", + "permissions" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "type": { + "type": "integer", + "format": "int64" + }, + "permissions": { + "type": "integer", + "format": "int64" + } + } + }, + { + "type": "array", + "maxLength": 0 + } + ] + } + }, + { + "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": "returning the full context information", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Context" + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/contexts/{contextId}": { + "get": { + "operationId": "context-show", + "summary": "[api v2] Get information about the requests context", + "tags": [ + "context" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "contextId", + "in": "path", + "description": "ID of the context", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "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": "returning the full context information", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Context" + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "context not found or not available anymore", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + }, + "put": { + "operationId": "context-update", + "summary": "[api v2] Update an existing context and return it", + "tags": [ + "context" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "name", + "in": "query", + "description": "provide this parameter to set a new name", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "iconName", + "in": "query", + "description": "provide this parameter to set a new icon", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "description", + "in": "query", + "description": "provide this parameter to set a new description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "nodes", + "in": "query", + "description": "provide this parameter to set a new list of nodes.", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "contextId", + "in": "path", + "description": "ID of the context", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "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": "returning the full context information", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Context" + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/contexts/{contextId}/transfer": { + "put": { + "operationId": "context-transfer", + "summary": "[api v2] Transfer the ownership of a context and return it", + "tags": [ + "context" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "newOwnerId", + "in": "query", + "description": "ID of the new owner", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "newOwnerType", + "in": "query", + "description": "any Application::OWNER_TYPE_* constant", + "schema": { + "type": "integer", + "format": "int64", + "default": 0, + "minimum": 0, + "maximum": 0 + } + }, + { + "name": "contextId", + "in": "path", + "description": "ID of the context", + "required": true, + "schema": { + "type": "integer", + "format": "int64", + "minimum": 0 + } + }, + { + "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": "Ownership transferred", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Context" + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Invalid request", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/contexts/{contextId}/nodes": { + "post": { + "operationId": "context-add-node", + "summary": "[api v2] Add a node to a Context", + "tags": [ + "context" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "nodeId", + "in": "query", + "description": "ID of the node", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "nodeType", + "in": "query", + "description": "any Application::NODE_TYPE_* constant", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "permissions", + "in": "query", + "description": "bitmask of the permissions for context recipients", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "order", + "in": "query", + "description": "in which order the node should appear within the context", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "contextId", + "in": "path", + "description": "ID of the context", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "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": "Node added successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Context" + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/contexts/{contextId}/nodes/{nodeRelId}": { + "delete": { + "operationId": "context-remove-node", + "summary": "[api v2] Remove a node from a Context", + "tags": [ + "context" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "contextId", + "in": "path", + "description": "ID of the context", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "nodeRelId", + "in": "path", + "description": "ID of the node-in-context relation", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "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": "Node removed successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Context" + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Invalid request", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/contexts/{contextId}/pages/{pageId}": { + "put": { + "operationId": "context-update-content-order", + "summary": "[api v2] Update the order on a page of a context", + "tags": [ + "context" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "content", + "in": "query", + "description": "content items with it and order values", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "contextId", + "in": "path", + "description": "ID of the context", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "pageId", + "in": "path", + "description": "ID of the page", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "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": "content updated successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Context" + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Invalid request", + "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": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "tags": [] +} \ No newline at end of file diff --git a/src/types/openapi/openapi.ts b/src/types/openapi/openapi.ts index c7e693067..96936503a 100644 --- a/src/types/openapi/openapi.ts +++ b/src/types/openapi/openapi.ts @@ -191,6 +191,37 @@ export type paths = { /** [api v2] Remove a node (table or view) to from favorites */ delete: operations["api_favorite-destroy"]; }; + "/ocs/v2.php/apps/tables/api/2/contexts": { + /** + * [api v3] Get all contexts available to the requesting person + * @description Return an empty array if no contexts were found + */ + get: operations["context-list"]; + /** [api v2] Create a new context and return it */ + post: operations["context-create"]; + }; + "/ocs/v2.php/apps/tables/api/2/contexts/{contextId}": { + /** [api v2] Get information about the requests context */ + get: operations["context-show"]; + /** [api v2] Update an existing context and return it */ + put: operations["context-update"]; + }; + "/ocs/v2.php/apps/tables/api/2/contexts/{contextId}/transfer": { + /** [api v2] Transfer the ownership of a context and return it */ + put: operations["context-transfer"]; + }; + "/ocs/v2.php/apps/tables/api/2/contexts/{contextId}/nodes": { + /** [api v2] Add a node to a Context */ + post: operations["context-add-node"]; + }; + "/ocs/v2.php/apps/tables/api/2/contexts/{contextId}/nodes/{nodeRelId}": { + /** [api v2] Remove a node from a Context */ + delete: operations["context-remove-node"]; + }; + "/ocs/v2.php/apps/tables/api/2/contexts/{contextId}/pages/{pageId}": { + /** [api v2] Update the order on a page of a context */ + put: operations["context-update-content-order"]; + }; }; export type webhooks = Record; @@ -240,6 +271,16 @@ export type components = { selectionDefault: string; datetimeDefault: string; }; + Context: { + /** Format: int64 */ + id: number; + name: string; + iconName: string; + description: string; + owner: string; + /** Format: int64 */ + ownerType: number; + }; ImportState: { /** Format: int64 */ found_columns_count: number; @@ -2923,4 +2964,471 @@ export type operations = { }; }; }; + /** + * [api v3] Get all contexts available to the requesting person + * @description Return an empty array if no contexts were found + */ + "context-list": { + parameters: { + header: { + /** @description Required to be true for the API request to pass */ + "OCS-APIRequest": boolean; + }; + }; + responses: { + /** @description reporting in available contexts */ + 200: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: components["schemas"]["Context"][]; + }; + }; + }; + }; + 500: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + }; + }; + /** [api v2] Create a new context and return it */ + "context-create": { + parameters: { + query: { + /** @description Name of the context */ + name: string; + /** @description Material design icon name of the context */ + iconName: string; + /** @description Descriptive text of the context */ + description?: string; + /** @description optional nodes to be connected to this context */ + nodes?: OneOf<[{ + /** Format: int64 */ + id: number; + /** Format: int64 */ + type: number; + /** Format: int64 */ + permissions: number; + }, unknown[]]>; + }; + header: { + /** @description Required to be true for the API request to pass */ + "OCS-APIRequest": boolean; + }; + }; + responses: { + /** @description returning the full context information */ + 200: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: components["schemas"]["Context"]; + }; + }; + }; + }; + 500: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + }; + }; + /** [api v2] Get information about the requests context */ + "context-show": { + parameters: { + header: { + /** @description Required to be true for the API request to pass */ + "OCS-APIRequest": boolean; + }; + path: { + /** @description ID of the context */ + contextId: number; + }; + }; + responses: { + /** @description returning the full context information */ + 200: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: components["schemas"]["Context"]; + }; + }; + }; + }; + /** @description context not found or not available anymore */ + 404: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + 500: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + }; + }; + /** [api v2] Update an existing context and return it */ + "context-update": { + parameters: { + query?: { + /** @description provide this parameter to set a new name */ + name?: string | null; + /** @description provide this parameter to set a new icon */ + iconName?: string | null; + /** @description provide this parameter to set a new description */ + description?: string | null; + /** @description provide this parameter to set a new list of nodes. */ + nodes?: string | null; + }; + header: { + /** @description Required to be true for the API request to pass */ + "OCS-APIRequest": boolean; + }; + path: { + /** @description ID of the context */ + contextId: number; + }; + }; + responses: { + /** @description returning the full context information */ + 200: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: components["schemas"]["Context"]; + }; + }; + }; + }; + /** @description Not found */ + 404: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + 500: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + }; + }; + /** [api v2] Transfer the ownership of a context and return it */ + "context-transfer": { + parameters: { + query: { + /** @description ID of the new owner */ + newOwnerId: string; + /** @description any Application::OWNER_TYPE_* constant */ + newOwnerType?: number; + }; + header: { + /** @description Required to be true for the API request to pass */ + "OCS-APIRequest": boolean; + }; + path: { + /** @description ID of the context */ + contextId: number; + }; + }; + responses: { + /** @description Ownership transferred */ + 200: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: components["schemas"]["Context"]; + }; + }; + }; + }; + /** @description Invalid request */ + 400: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + /** @description Not found */ + 404: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + 500: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + }; + }; + /** [api v2] Add a node to a Context */ + "context-add-node": { + parameters: { + query: { + /** @description ID of the node */ + nodeId: number; + /** @description any Application::NODE_TYPE_* constant */ + nodeType: number; + /** @description bitmask of the permissions for context recipients */ + permissions: number; + /** @description in which order the node should appear within the context */ + order?: number | null; + }; + header: { + /** @description Required to be true for the API request to pass */ + "OCS-APIRequest": boolean; + }; + path: { + /** @description ID of the context */ + contextId: number; + }; + }; + responses: { + /** @description Node added successfully */ + 200: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: components["schemas"]["Context"]; + }; + }; + }; + }; + /** @description Not found */ + 404: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + 500: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + }; + }; + /** [api v2] Remove a node from a Context */ + "context-remove-node": { + parameters: { + header: { + /** @description Required to be true for the API request to pass */ + "OCS-APIRequest": boolean; + }; + path: { + /** @description ID of the context */ + contextId: number; + /** @description ID of the node-in-context relation */ + nodeRelId: number; + }; + }; + responses: { + /** @description Node removed successfully */ + 200: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: components["schemas"]["Context"]; + }; + }; + }; + }; + /** @description Invalid request */ + 400: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + /** @description Not found */ + 404: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + 500: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + }; + }; + /** [api v2] Update the order on a page of a context */ + "context-update-content-order": { + parameters: { + query: { + /** @description content items with it and order values */ + content: string; + }; + header: { + /** @description Required to be true for the API request to pass */ + "OCS-APIRequest": boolean; + }; + path: { + /** @description ID of the context */ + contextId: number; + /** @description ID of the page */ + pageId: number; + }; + }; + responses: { + /** @description content updated successfully */ + 200: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: components["schemas"]["Context"]; + }; + }; + }; + }; + /** @description Invalid request */ + 400: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + /** @description Not found */ + 404: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + 500: { + content: { + "application/json": { + ocs: { + meta: components["schemas"]["OCSMeta"]; + data: { + message: string; + }; + }; + }; + }; + }; + }; + }; };