Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add OpenAPI #3324

Merged
merged 1 commit into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,15 @@ module.exports = {
extends: [
'@nextcloud/eslint-config/typescript',
],
overrides: [
{
files: ['src/types/openapi/*.ts'],
rules: {
'@typescript-eslint/no-explicit-any': 'off',
quotes: 'off',
'no-multiple-empty-lines': 'off',
'no-use-before-define': 'off',
},
},
],
}
94 changes: 94 additions & 0 deletions .github/workflows/openapi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# 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 <[email protected]>
# 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@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
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@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
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

- name: Check openapi*.json and typescript changes
run: |
bash -c "[[ ! \"`git status --porcelain `\" ]] || (echo 'Please run \"composer run openapi\" and commit the openapi*.json files and (if applicable) src/types/openapi/openapi*.ts, see the section \"Show changes on failure\" for details' && exit 1)"

- name: Show changes on failure
if: failure()
run: |
git status
git --no-pager diff
exit 1 # make it red to grab attention
30 changes: 1 addition & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,35 +126,7 @@ To disable the advanced permissions feature for a group folder, use `occ groupfo

### REST API

Group folders can be configured externally through REST APIs.

The following REST API's are supported:

- `GET apps/groupfolders/folders`: Returns a list of all configured folders and their settings
- `POST apps/groupfolders/folders`: Create a new group folder
- `mountpoint`: The name for the new folder
- `GET apps/groupfolders/folders/$folderId`: Return a specific configured folder and its settings
- `DELETE apps/groupfolders/folders/$folderId`: Delete a group folder
- `POST apps/groupfolders/folders/$folderId/groups`: Give a group access to a folder
- `group`: The id of the group to be given access to the folder
- `DELETE apps/groupfolders/folders/$folderId/groups/$groupId`: Remove access from a group to a folder
- `POST apps/groupfolders/folders/$folderId/acl`: Enable/Disable folder advanced permissions
- `acl` 1 for enable, 0 for disable.
- `POST apps/groupfolders/folders/$folderId/manageACL`: Grants/Removes a group or user the ability to manage a groupfolders' advanced permissions
- `$mappingId`: the id of the group/user to be granted/removed access to/from the folder
- `$mappingType`: 'group' or 'user'
- `$manageAcl`: true to grants ability to manage a groupfolders' advanced permissions, false to remove
- `POST apps/groupfolders/folders/$folderId/groups/$groupId`: Set the permissions a group has in a folder
- `permissions` The new permissions for the group as bitmask of [permissions constants](https://github.com/nextcloud/server/blob/b4f36d44c43aac0efdc6c70ff8e46473341a9bfe/lib/public/Constants.php#L65)
- `POST apps/groupfolders/folders/$folderId/quota`: Set the quota for a folder
- `quota`: The new quota for the folder in bytes, user `-3` for unlimited
- `POST apps/groupfolders/folders/$folderId/mountpoint`: Change the name of a folder
- `mountpoint`: The new name for the folder

For all `POST` calls the required parameters are listed.

Non-admins can access the `GET` requests to retrieve info about group folders they have access to.
Admins can add `applicable=1` as a parameter to the group folder list request to get the same filtered results of only folders they have direct access to.
See the [OpenAPI specification](openapi.json) to learn about all available API endpoints: https://petstore.swagger.io/?url=https://raw.githubusercontent.com/nextcloud/groupfolders/master/openapi.json

### WebDAV API

Expand Down
6 changes: 6 additions & 0 deletions REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,9 @@ path = ["tests/stubs/icewind_streams_**"]
precedence = "aggregate"
SPDX-FileCopyrightText = "none"
SPDX-License-Identifier = "MIT"

[[annotations]]
path = ["openapi.json", "src/types/openapi/openapi.ts"]
precedence = "aggregate"
SPDX-FileCopyrightText = "2024 Nextcloud GmbH and Nextcloud contributors"
SPDX-License-Identifier = "AGPL-3.0-or-later"
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"psalm:fix": "psalm --no-cache --alter --issues=InvalidReturnType,InvalidNullableReturnType,MissingParamType,InvalidFalsableReturnType",
"test:unit": "phpunit -c tests/phpunit.xml",
"test:unit:coverage": "XDEBUG_MODE=coverage phpunit -c tests/phpunit.xml",
"rector": "rector && composer cs:fix"
"rector": "rector && composer cs:fix",
"openapi": "generate-spec && npm run typescript:generate"
},
"config": {
"allow-plugins": {
Expand Down
8 changes: 8 additions & 0 deletions lib/AppInfo/Capabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ public function __construct(
) {
}

/**
* @return array{
* groupfolders?: array{
* appVersion: string,
* hasGroupFolders: bool,
* },
* }
*/
public function getCapabilities(): array {
$user = $this->userSession->getUser();
if (!$user) {
Expand Down
4 changes: 3 additions & 1 deletion lib/Command/FolderCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

/**
* Base command for commands asking the user for a folder id.
*
* @psalm-import-type InternalFolderOut from FolderManager
*/
abstract class FolderCommand extends Base {

Expand All @@ -29,7 +31,7 @@ public function __construct(
}

/**
* @psalm-return ?array{id: mixed, mount_point: string, groups: array<empty, empty>|mixed, quota: int, size: int|mixed, acl: bool}
* @return ?InternalFolderOut
*/
protected function getFolder(InputInterface $input, OutputInterface $output): ?array {
$folderId = (int)$input->getArgument('folder_id');
Expand Down
26 changes: 22 additions & 4 deletions lib/Controller/DelegationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@

use OCA\Circles\CirclesManager;
use OCA\GroupFolders\Attribute\RequireGroupFolderAdmin;
use OCA\GroupFolders\ResponseDefinitions;
use OCA\GroupFolders\Service\DelegationService;
use OCA\Settings\Service\AuthorizedGroupService;
use OCP\App\IAppManager;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\FrontpageRoute;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\DataResponse;
Expand All @@ -23,6 +25,10 @@
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;

/**
* @psalm-import-type GroupFoldersDelegationGroup from ResponseDefinitions
* @psalm-import-type GroupFoldersDelegationCircle from ResponseDefinitions
*/
class DelegationController extends OCSController {
public function __construct(
string $appName,
Expand All @@ -39,6 +45,10 @@ public function __construct(

/**
* Returns the list of all groups
*
* @return DataResponse<Http::STATUS_OK, list<GroupFoldersDelegationGroup>, array{}>
*
* 200: All groups returned
*/
#[RequireGroupFolderAdmin]
#[NoAdminRequired]
Expand All @@ -61,6 +71,10 @@ public function getAllGroups(): DataResponse {

/**
* Returns the list of all visible circles
*
* @return DataResponse<Http::STATUS_OK, list<GroupFoldersDelegationCircle>, array{}>
*
* 200: All circles returned
*/
#[RequireGroupFolderAdmin]
#[NoAdminRequired]
Expand Down Expand Up @@ -97,10 +111,14 @@ public function getAllCircles(): DataResponse {

/**
* Get the list Groups related to classname.
* If the classname is
* - OCA\GroupFolders\Settings\Admin : It's reference to fields in Admin Priveleges.
* - OCA\GroupFolders\Controller\DelegationController : It's just to specific the subadmins.
* They can only manage groupfolders in which they are added in the Advanced Permissions (groups only)
* @param string $classname If the classname is
* - OCA\GroupFolders\Settings\Admin : It's reference to fields in Admin Privileges.
* - OCA\GroupFolders\Controller\DelegationController : It's just to specific the subadmins.
* They can only manage groupfolders in which they are added in the Advanced Permissions (groups only)
*
* @return DataResponse<Http::STATUS_OK, list<GroupFoldersDelegationGroup>, array{}>
*
* 200: Authorized groups returned
*/
#[RequireGroupFolderAdmin]
#[NoAdminRequired]
Expand Down
Loading
Loading