diff --git a/.github/workflows/openapi.yml b/.github/workflows/openapi.yml new file mode 100644 index 0000000000..03ed80d553 --- /dev/null +++ b/.github/workflows/openapi.yml @@ -0,0 +1,83 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization +# +# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2024 Arthur Schiwon +# SPDX-License-Identifier: MIT + +name: OpenAPI + +on: pull_request + +permissions: + contents: read + +concurrency: + group: openapi-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + openapi: + runs-on: ubuntu-latest + + if: ${{ github.repository_owner != 'nextcloud-gmbh' }} + + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Get php version + id: php_versions + uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1 + + - name: Set up php + uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b # v2.31.0 + with: + php-version: ${{ steps.php_versions.outputs.php-available }} + extensions: xml + coverage: none + ini-file: development + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check Typescript OpenApi types + id: check_typescript_openapi + uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0 + with: + files: "src/types/openapi/openapi*.ts" + + - name: Read package.json node and npm engines version + if: steps.check_typescript_openapi.outputs.files_exists == 'true' + uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 + id: node_versions + # Continue if no package.json + continue-on-error: true + with: + fallbackNode: '^20' + fallbackNpm: '^10' + + - name: Set up node ${{ steps.node_versions.outputs.nodeVersion }} + if: ${{ steps.node_versions.outputs.nodeVersion }} + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: ${{ steps.node_versions.outputs.nodeVersion }} + + - name: Set up npm ${{ steps.node_versions.outputs.npmVersion }} + if: ${{ steps.node_versions.outputs.nodeVersion }} + run: npm i -g 'npm@${{ steps.node_versions.outputs.npmVersion }}' + + - name: Install dependencies & build + if: ${{ steps.node_versions.outputs.nodeVersion }} + env: + CYPRESS_INSTALL_BINARY: 0 + PUPPETEER_SKIP_DOWNLOAD: true + run: | + npm ci + + - name: Set up dependencies + run: composer i + + - name: Regenerate OpenAPI + run: composer run openapi diff --git a/REUSE.toml b/REUSE.toml index c978d23ca6..01a10b282a 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -78,7 +78,7 @@ SPDX-FileCopyrightText = "2021 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" [[annotations]] -path = ["vendor-bin/cs-fixer/composer.json", "vendor-bin/cs-fixer/composer.lock", "vendor-bin/mozart/composer.json", "vendor-bin/mozart/composer.lock", "vendor-bin/phpunit/composer.json", "vendor-bin/phpunit/composer.lock", "vendor-bin/rector/composer.json", "vendor-bin/rector/composer.lock"] +path = ["vendor-bin/cs-fixer/composer.json", "vendor-bin/cs-fixer/composer.lock", "vendor-bin/mozart/composer.json", "vendor-bin/mozart/composer.lock", "vendor-bin/openapi/composer.*", "vendor-bin/phpunit/composer.json", "vendor-bin/phpunit/composer.lock", "vendor-bin/rector/composer.json", "vendor-bin/rector/composer.lock"] precedence = "aggregate" SPDX-FileCopyrightText = "2021-2024 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" diff --git a/composer.json b/composer.json index b3a6310d88..7b5d080f2f 100644 --- a/composer.json +++ b/composer.json @@ -75,7 +75,8 @@ "test:integration": "phpunit -c tests/phpunit.integration.xml --fail-on-warning", "test:integration:dev": "phpunit -c tests/phpunit.integration.xml --no-coverage --order-by=defects --stop-on-defect --fail-on-warning --stop-on-error --stop-on-failure", "test:unit": "phpunit -c tests/phpunit.unit.xml --fail-on-warning", - "test:unit:dev": "phpunit -c tests/phpunit.unit.xml --no-coverage --order-by=defects --stop-on-defect --fail-on-warning --stop-on-error --stop-on-failure" + "test:unit:dev": "phpunit -c tests/phpunit.unit.xml --no-coverage --order-by=defects --stop-on-defect --fail-on-warning --stop-on-error --stop-on-failure", + "openapi": "generate-spec" }, "extra": { "mozart": { diff --git a/composer.lock b/composer.lock index 702f908a56..ef46bd4bcf 100644 --- a/composer.lock +++ b/composer.lock @@ -3507,6 +3507,76 @@ } ], "packages-dev": [ + { + "name": "adhocore/cli", + "version": "v1.7.1", + "source": { + "type": "git", + "url": "https://github.com/adhocore/php-cli.git", + "reference": "3fde60a838912e71c82ed0f48048685dc32dbc77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/adhocore/php-cli/zipball/3fde60a838912e71c82ed0f48048685dc32dbc77", + "reference": "3fde60a838912e71c82ed0f48048685dc32dbc77", + "shasum": "" + }, + "require": { + "php": ">=8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ahc\\Cli\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jitendra Adhikari", + "email": "jiten.adhikary@gmail.com" + } + ], + "description": "Command line interface library for PHP", + "keywords": [ + "argument-parser", + "argv-parser", + "cli", + "cli-action", + "cli-app", + "cli-color", + "cli-option", + "cli-writer", + "command", + "console", + "console-app", + "php-cli", + "php8", + "stream-input", + "stream-output" + ], + "support": { + "issues": "https://github.com/adhocore/php-cli/issues", + "source": "https://github.com/adhocore/php-cli/tree/v1.7.1" + }, + "funding": [ + { + "url": "https://paypal.me/ji10", + "type": "custom" + }, + { + "url": "https://github.com/adhocore", + "type": "github" + } + ], + "time": "2024-03-28T08:30:12+00:00" + }, { "name": "nextcloud/ocp", "version": "dev-stable26", diff --git a/krankerl.toml b/krankerl.toml index 5e5f5c5001..f079fbe7ca 100644 --- a/krankerl.toml +++ b/krankerl.toml @@ -5,4 +5,5 @@ before_cmds = [ "composer install --no-dev -o", "npm install --deps", "npm run build", + "composer openapi" ] diff --git a/lib/Controller/MessageApiController.php b/lib/Controller/MessageApiController.php index 0422a8787a..71e6879756 100644 --- a/lib/Controller/MessageApiController.php +++ b/lib/Controller/MessageApiController.php @@ -43,8 +43,8 @@ use function array_merge; /** - * @psalm-import-type MessageApiResponse from ResponseDefinitions - * @psalm-import-type MessageApiAttachment from ResponseDefinitions + * @psalm-import-type MailMessageApiResponse from ResponseDefinitions + * @psalm-import-type MailMessageApiAttachment from ResponseDefinitions */ class MessageApiController extends OCSController { @@ -72,15 +72,17 @@ public function __construct( } /** + * Send an email though a mail account that has been configured with Nextcloud Mail + * * @param int $accountId The mail account to use for SMTP * @param string $fromEmail The "From" email address or alias email address * @param string $subject The subject * @param string $body The message body * @param bool $isHtml If the message body contains HTML - * @param array $to An array of "To" recipients in the format ['label' => 'Name', 'email' => 'Email Address'] or ['email' => 'Email Address'] - * @param array $cc An optional array of 'CC' recipients in the format ['label' => 'Name', 'email' => 'Email Address'] or ['email' => 'Email Address'] - * @param array $bcc An optional array of 'BCC' recipients in the format ['label' => 'Name', 'email' => 'Email Address'] or ['email' => 'Email Address'] - * @param ?string $references An optional string of an RFC2392 to set the "Reply-To" and "References" header on sending + * @param list $to An array of "To" recipients in the format ['label' => 'Name', 'email' => 'Email Address'] or ['email' => 'Email Address'] + * @param array|list $cc An optional array of 'CC' recipients in the format ['label' => 'Name', 'email' => 'Email Address'] or ['email' => 'Email Address'] + * @param array|list $bcc An optional array of 'BCC' recipients in the format ['label' => 'Name', 'email' => 'Email Address'] or ['email' => 'Email Address'] + * @param ?string $references An optional string of an RFC2392 "message-id" to set the "Reply-To" and "References" header on sending * @return DataResponse * * 200: The email was sent @@ -207,8 +209,10 @@ public function send( } /** - * @param int $id - * @return DataResponse|DataResponse + * Get a mail message with its metadata + * + * @param int $id the message id + * @return DataResponse|DataResponse * * 200: Message found * 206: Message could not be decrypted, no "body" data returned @@ -296,8 +300,10 @@ public function get(int $id): DataResponse { } /** + * Get the raw rfc2822 email + * * @param int $id the id of the message - * @return DataResponse|DataResponse + * @return DataResponse|DataResponse * * 200: Message found * 404: User was not logged in @@ -356,9 +362,11 @@ private function enrichDownloadUrl(int $id, array $attachment): array { } /** - * @param int $id - * @param string $attachmentId - * @return DataResponse|DataResponse + * Get a mail message's attachments + * + * @param int $id the mail id + * @param string $attachmentId the attachment id + * @return DataResponse|DataResponse * * 200: Message found * 404: User was not logged in diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php index ce11414bbe..1e5a301a09 100644 --- a/lib/ResponseDefinitions.php +++ b/lib/ResponseDefinitions.php @@ -15,9 +15,9 @@ * messageId: string, * from: list, * to: list, - * replyTo: array|list, - * cc: array|list, - * bcc: array|list, + * replyTo: list, + * cc: list, + * bcc: list, * subject: string, * dateInt: int<0, max>, * flags: array{seen: bool, flagged: bool, answered: bool, deleted: bool, draft: bool, forwarded: bool, hasAttachments: bool, mdnsent: bool, important: bool}, @@ -25,17 +25,17 @@ * body?: string, * dispositionNotificationTo: string, * hasDkimSignature: bool, - * phishingDetails: array{checks: list, warning: bool}, + * phishingDetails: array{checks: list}>, warning: bool}, * unsubscribeUrl: ?string, * isOneClickUnsubscribe: bool, * unsubscribeMailTo: ?string, - * scheduling: array|list, - * attachments: array|list, messageId: int<1, max>, filename: string, mime: string, size: int<0, max>, cid: ?string, disposition: string, downloadUrl?: string}> + * scheduling: list, + * attachments: list, messageId: int<1, max>, filename: string, mime: string, size: int<0, max>, cid: ?string, disposition: string, downloadUrl?: string}> * } * - * @psalm-type MessageApiResponse = MailIMAPFullMessage&array{ + * @psalm-type MailMessageApiResponse = MailIMAPFullMessage&array{ * signature: ?string, - * itineraries?: array{}, + * itineraries?: array, * id: int<1, max>, * isSenderTrusted: bool, * smime: array{ isSigned: bool, signatureIsValid: ?bool, isEncrypted: bool}, @@ -43,7 +43,7 @@ * rawUrl: string * } * - * @psalm-type MessageApiAttachment = array{ name: string, mime: string, size: int<0, max>, content: string} + * @psalm-type MailMessageApiAttachment = array{ name: string, mime: string, size: int<0, max>, content: string} */ class ResponseDefinitions { } diff --git a/vendor-bin/openapi/composer.json b/vendor-bin/openapi/composer.json new file mode 100644 index 0000000000..5bea58ef2c --- /dev/null +++ b/vendor-bin/openapi/composer.json @@ -0,0 +1,17 @@ +{ + "config": { + "platform": { + "php": "8.1" + }, + "sort-packages": true + }, + "require": { + "nextcloud/openapi-extractor": "dev-main" + }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/nextcloud/openapi-extractor" + } + ] +} diff --git a/vendor-bin/openapi/composer.lock b/vendor-bin/openapi/composer.lock new file mode 100644 index 0000000000..5d52863911 --- /dev/null +++ b/vendor-bin/openapi/composer.lock @@ -0,0 +1,255 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "143725e36726d6a8e8fc092c8b44a4ee", + "packages": [ + { + "name": "adhocore/cli", + "version": "v1.7.1", + "source": { + "type": "git", + "url": "https://github.com/adhocore/php-cli.git", + "reference": "3fde60a838912e71c82ed0f48048685dc32dbc77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/adhocore/php-cli/zipball/3fde60a838912e71c82ed0f48048685dc32dbc77", + "reference": "3fde60a838912e71c82ed0f48048685dc32dbc77", + "shasum": "" + }, + "require": { + "php": ">=8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ahc\\Cli\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jitendra Adhikari", + "email": "jiten.adhikary@gmail.com" + } + ], + "description": "Command line interface library for PHP", + "keywords": [ + "argument-parser", + "argv-parser", + "cli", + "cli-action", + "cli-app", + "cli-color", + "cli-option", + "cli-writer", + "command", + "console", + "console-app", + "php-cli", + "php8", + "stream-input", + "stream-output" + ], + "support": { + "issues": "https://github.com/adhocore/php-cli/issues", + "source": "https://github.com/adhocore/php-cli/tree/v1.7.1" + }, + "funding": [ + { + "url": "https://paypal.me/ji10", + "type": "custom" + }, + { + "url": "https://github.com/adhocore", + "type": "github" + } + ], + "time": "2024-03-28T08:30:12+00:00" + }, + { + "name": "nextcloud/openapi-extractor", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/nextcloud/openapi-extractor.git", + "reference": "cdfedf4382b4f9d2a90f6bb1578f6a590017944b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nextcloud/openapi-extractor/zipball/cdfedf4382b4f9d2a90f6bb1578f6a590017944b", + "reference": "cdfedf4382b4f9d2a90f6bb1578f6a590017944b", + "shasum": "" + }, + "require": { + "adhocore/cli": "^1.7", + "ext-simplexml": "*", + "nikic/php-parser": "^5.0", + "php": "^8.1", + "phpstan/phpdoc-parser": "^1.28" + }, + "require-dev": { + "nextcloud/coding-standard": "^1.2", + "nextcloud/ocp": "dev-master" + }, + "default-branch": true, + "bin": [ + "generate-spec", + "merge-specs" + ], + "type": "library", + "autoload": { + "psr-4": { + "OpenAPIExtractor\\": "src" + } + }, + "scripts": { + "lint": [ + "find . -name \\*.php -not -path './tests/*' -not -path './vendor/*' -not -path './build/*' -print0 | xargs -0 -n1 php -l && php -l generate-spec && php -l merge-specs" + ], + "cs:check": [ + "php-cs-fixer fix --dry-run --diff" + ], + "cs:fix": [ + "php-cs-fixer fix" + ], + "test:unit": [ + "cd tests && ../generate-spec" + ] + }, + "support": { + "source": "https://github.com/nextcloud/openapi-extractor/tree/main", + "issues": "https://github.com/nextcloud/openapi-extractor/issues" + }, + "time": "2024-08-05T15:03:39+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.1.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" + }, + "time": "2024-07-01T20:03:41+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.29.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fcaefacf2d5c417e928405b71b400d4ce10daaf4", + "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.29.1" + }, + "time": "2024-05-31T08:52:43+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "nextcloud/openapi-extractor": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "platform-overrides": { + "php": "8.1" + }, + "plugin-api-version": "2.3.0" +}