From 2b29189de057a398d2c184218905074010271130 Mon Sep 17 00:00:00 2001 From: jld3103 Date: Sat, 4 Feb 2023 22:33:32 +0100 Subject: [PATCH] provisioning_api: Add OpenAPI spec Signed-off-by: jld3103 --- .../lib/Controller/AUserData.php | 61 +- .../lib/Controller/AppConfigController.php | 56 +- .../lib/Controller/AppsController.php | 36 +- .../lib/Controller/GroupsController.php | 85 +- .../lib/Controller/PreferencesController.php | 39 +- .../lib/Controller/UsersController.php | 184 +- .../lib/ResponseDefinitions.php | 135 + apps/provisioning_api/openapi.json | 3402 +++++++++++++++++ 8 files changed, 3796 insertions(+), 202 deletions(-) create mode 100644 apps/provisioning_api/lib/ResponseDefinitions.php create mode 100644 apps/provisioning_api/openapi.json diff --git a/apps/provisioning_api/lib/Controller/AUserData.php b/apps/provisioning_api/lib/Controller/AUserData.php index bbb3abe3c24ac..14e4a3d3bd4ce 100644 --- a/apps/provisioning_api/lib/Controller/AUserData.php +++ b/apps/provisioning_api/lib/Controller/AUserData.php @@ -30,12 +30,17 @@ * along with this program. If not, see . * */ + namespace OCA\Provisioning_API\Controller; +use Exception; +use OC; use OC\Group\Manager; use OC\User\Backend; use OC\User\NoUserException; use OC_Helper; +use OC_Util; +use OCA\Provisioning_API\ResponseDefinitions; use OCP\Accounts\IAccountManager; use OCP\Accounts\PropertyDoesNotExistException; use OCP\AppFramework\Http; @@ -51,7 +56,11 @@ use OCP\L10N\IFactory; use OCP\User\Backend\ISetDisplayNameBackend; use OCP\User\Backend\ISetPasswordBackend; +use Psr\Log\LoggerInterface; +/** + * @psalm-import-type UserDetails from ResponseDefinitions + */ abstract class AUserData extends OCSController { public const SCOPE_SUFFIX = 'Scope'; @@ -76,13 +85,13 @@ abstract class AUserData extends OCSController { protected $l10nFactory; public function __construct(string $appName, - IRequest $request, - IUserManager $userManager, - IConfig $config, - IGroupManager $groupManager, - IUserSession $userSession, - IAccountManager $accountManager, - IFactory $l10nFactory) { + IRequest $request, + IUserManager $userManager, + IConfig $config, + IGroupManager $groupManager, + IUserSession $userSession, + IAccountManager $accountManager, + IFactory $l10nFactory) { parent::__construct($appName, $request); $this->userManager = $userManager; @@ -98,12 +107,12 @@ public function __construct(string $appName, * * @param string $userId * @param bool $includeScopes - * @return array + * @return UserDetails|null * @throws NotFoundException * @throws OCSException * @throws OCSNotFoundException */ - protected function getUserData(string $userId, bool $includeScopes = false): array { + protected function getUserData(string $userId, bool $includeScopes = false): ?array { $currentLoggedInUser = $this->userSession->getUser(); assert($currentLoggedInUser !== null, 'No user logged in'); @@ -122,7 +131,7 @@ protected function getUserData(string $userId, bool $includeScopes = false): arr } else { // Check they are looking up themselves if ($currentLoggedInUser->getUID() !== $targetUserObject->getUID()) { - return $data; + return null; } } @@ -182,17 +191,17 @@ protected function getUserData(string $userId, bool $includeScopes = false): arr } foreach ([ - IAccountManager::PROPERTY_PHONE, - IAccountManager::PROPERTY_ADDRESS, - IAccountManager::PROPERTY_WEBSITE, - IAccountManager::PROPERTY_TWITTER, - IAccountManager::PROPERTY_FEDIVERSE, - IAccountManager::PROPERTY_ORGANISATION, - IAccountManager::PROPERTY_ROLE, - IAccountManager::PROPERTY_HEADLINE, - IAccountManager::PROPERTY_BIOGRAPHY, - IAccountManager::PROPERTY_PROFILE_ENABLED, - ] as $propertyName) { + IAccountManager::PROPERTY_PHONE, + IAccountManager::PROPERTY_ADDRESS, + IAccountManager::PROPERTY_WEBSITE, + IAccountManager::PROPERTY_TWITTER, + IAccountManager::PROPERTY_FEDIVERSE, + IAccountManager::PROPERTY_ORGANISATION, + IAccountManager::PROPERTY_ROLE, + IAccountManager::PROPERTY_HEADLINE, + IAccountManager::PROPERTY_BIOGRAPHY, + IAccountManager::PROPERTY_PROFILE_ENABLED, + ] as $propertyName) { $property = $userAccount->getProperty($propertyName); $data[$propertyName] = $property->getValue(); if ($includeScopes) { @@ -249,8 +258,8 @@ protected function getUserSubAdminGroupsData(string $userId): array { */ protected function fillStorageInfo(string $userId): array { try { - \OC_Util::tearDownFS(); - \OC_Util::setupFS($userId); + OC_Util::tearDownFS(); + OC_Util::setupFS($userId); $storage = OC_Helper::getStorageInfo('/', null, true, false); $data = [ 'free' => $storage['free'], @@ -273,8 +282,8 @@ protected function fillStorageInfo(string $userId): array { self::USER_FIELD_QUOTA => $quota !== false ? $quota : 'none', 'used' => 0 ]; - } catch (\Exception $e) { - \OC::$server->get(\Psr\Log\LoggerInterface::class)->error( + } catch (Exception $e) { + OC::$server->get(LoggerInterface::class)->error( "Could not load storage info for {user}", [ 'app' => 'provisioning_api', @@ -283,7 +292,7 @@ protected function fillStorageInfo(string $userId): array { ] ); /* In case the Exception left things in a bad state */ - \OC_Util::tearDownFS(); + OC_Util::tearDownFS(); return []; } return $data; diff --git a/apps/provisioning_api/lib/Controller/AppConfigController.php b/apps/provisioning_api/lib/Controller/AppConfigController.php index 929676be16ec1..21f30c36eead9 100644 --- a/apps/provisioning_api/lib/Controller/AppConfigController.php +++ b/apps/provisioning_api/lib/Controller/AppConfigController.php @@ -7,6 +7,7 @@ * * @author Joas Schilling * @author Roeland Jago Douma + * @author Kate Döen * * @license GNU AGPL version 3 or any later version * @@ -24,11 +25,14 @@ * along with this program. If not, see . * */ + namespace OCA\Provisioning_API\Controller; use OC\AppFramework\Middleware\Security\Exceptions\NotAdminException; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\DataResponse200; +use OCP\AppFramework\Http\DataResponse403; use OCP\AppFramework\OCSController; use OCP\IAppConfig; use OCP\IConfig; @@ -67,13 +71,13 @@ class AppConfigController extends OCSController { * @param IAppConfig $appConfig */ public function __construct(string $appName, - IRequest $request, - IConfig $config, - IAppConfig $appConfig, - IUserSession $userSession, - IL10N $l10n, - IGroupManager $groupManager, - IManager $settingManager) { + IRequest $request, + IConfig $config, + IAppConfig $appConfig, + IUserSession $userSession, + IL10N $l10n, + IGroupManager $groupManager, + IManager $settingManager) { parent::__construct($appName, $request); $this->config = $config; $this->appConfig = $appConfig; @@ -84,25 +88,25 @@ public function __construct(string $appName, } /** - * @return DataResponse + * @return DataResponse200 */ - public function getApps(): DataResponse { - return new DataResponse([ + public function getApps(): DataResponse200 { + return new DataResponse200([ 'data' => $this->appConfig->getApps(), ]); } /** * @param string $app - * @return DataResponse + * @return DataResponse200|DataResponse403 */ - public function getKeys(string $app): DataResponse { + public function getKeys(string $app): DataResponse200|DataResponse403 { try { $this->verifyAppId($app); } catch (\InvalidArgumentException $e) { - return new DataResponse(['data' => ['message' => $e->getMessage()]], Http::STATUS_FORBIDDEN); + return new DataResponse403(['data' => ['message' => $e->getMessage()]]); } - return new DataResponse([ + return new DataResponse200([ 'data' => $this->config->getAppKeys($app), ]); } @@ -111,15 +115,15 @@ public function getKeys(string $app): DataResponse { * @param string $app * @param string $key * @param string $defaultValue - * @return DataResponse + * @return DataResponse200|DataResponse403 */ - public function getValue(string $app, string $key, string $defaultValue = ''): DataResponse { + public function getValue(string $app, string $key, string $defaultValue = ''): DataResponse200|DataResponse403 { try { $this->verifyAppId($app); } catch (\InvalidArgumentException $e) { - return new DataResponse(['data' => ['message' => $e->getMessage()]], Http::STATUS_FORBIDDEN); + return new DataResponse403(['data' => ['message' => $e->getMessage()]]); } - return new DataResponse([ + return new DataResponse200([ 'data' => $this->config->getAppValue($app, $key, $defaultValue), ]); } @@ -131,9 +135,9 @@ public function getValue(string $app, string $key, string $defaultValue = ''): D * @param string $app * @param string $key * @param string $value - * @return DataResponse + * @return DataResponse200|DataResponse403 */ - public function setValue(string $app, string $key, string $value): DataResponse { + public function setValue(string $app, string $key, string $value): DataResponse200|DataResponse403 { $user = $this->userSession->getUser(); if ($user === null) { throw new \Exception("User is not logged in."); // Should not happen, since method is guarded by middleware @@ -147,29 +151,29 @@ public function setValue(string $app, string $key, string $value): DataResponse $this->verifyAppId($app); $this->verifyConfigKey($app, $key, $value); } catch (\InvalidArgumentException $e) { - return new DataResponse(['data' => ['message' => $e->getMessage()]], Http::STATUS_FORBIDDEN); + return new DataResponse403(['data' => ['message' => $e->getMessage()]]); } $this->config->setAppValue($app, $key, $value); - return new DataResponse(); + return new DataResponse200(); } /** * @PasswordConfirmationRequired * @param string $app * @param string $key - * @return DataResponse + * @return DataResponse200|DataResponse403 */ - public function deleteKey(string $app, string $key): DataResponse { + public function deleteKey(string $app, string $key): DataResponse200|DataResponse403 { try { $this->verifyAppId($app); $this->verifyConfigKey($app, $key, ''); } catch (\InvalidArgumentException $e) { - return new DataResponse(['data' => ['message' => $e->getMessage()]], Http::STATUS_FORBIDDEN); + return new DataResponse403(['data' => ['message' => $e->getMessage()]]); } $this->config->deleteAppValue($app, $key); - return new DataResponse(); + return new DataResponse200(); } /** diff --git a/apps/provisioning_api/lib/Controller/AppsController.php b/apps/provisioning_api/lib/Controller/AppsController.php index fa0f2597e7fde..259c59310410d 100644 --- a/apps/provisioning_api/lib/Controller/AppsController.php +++ b/apps/provisioning_api/lib/Controller/AppsController.php @@ -10,6 +10,7 @@ * @author Lukas Reschke * @author Roeland Jago Douma * @author Tom Needham + * @author Kate Döen * * @license AGPL-3.0 * @@ -26,16 +27,22 @@ * along with this program. If not, see * */ + namespace OCA\Provisioning_API\Controller; use OC_App; +use OCA\Provisioning_API\ResponseDefinitions; use OCP\App\AppPathNotFoundException; use OCP\App\IAppManager; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\DataResponse200; use OCP\AppFramework\OCS\OCSException; use OCP\AppFramework\OCSController; use OCP\IRequest; +/** + * @psalm-import-type AppInfo from ResponseDefinitions + */ class AppsController extends OCSController { /** @var IAppManager */ private $appManager; @@ -52,11 +59,12 @@ public function __construct( /** * @param string|null $filter - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function getApps(string $filter = null): DataResponse { + public function getApps(string $filter = null): DataResponse200 { $apps = (new OC_App())->listAllApps(); + /** @var string[] $list */ $list = []; foreach ($apps as $app) { $list[] = $app['id']; @@ -64,30 +72,30 @@ public function getApps(string $filter = null): DataResponse { if ($filter) { switch ($filter) { case 'enabled': - return new DataResponse(['apps' => \OC_App::getEnabledApps()]); + return new DataResponse200(['apps' => OC_App::getEnabledApps()]); break; case 'disabled': $enabled = OC_App::getEnabledApps(); - return new DataResponse(['apps' => array_diff($list, $enabled)]); + return new DataResponse200(['apps' => array_diff($list, $enabled)]); break; default: // Invalid filter variable throw new OCSException('', 101); } } else { - return new DataResponse(['apps' => $list]); + return new DataResponse200(['apps' => $list]); } } /** * @param string $app - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function getAppInfo(string $app): DataResponse { + public function getAppInfo(string $app): DataResponse200 { $info = $this->appManager->getAppInfo($app); if (!is_null($info)) { - return new DataResponse($info); + return new DataResponse200($info); } throw new OCSException('The request app was not found', OCSController::RESPOND_NOT_FOUND); @@ -96,25 +104,25 @@ public function getAppInfo(string $app): DataResponse { /** * @PasswordConfirmationRequired * @param string $app - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function enable(string $app): DataResponse { + public function enable(string $app): DataResponse200 { try { $this->appManager->enableApp($app); } catch (AppPathNotFoundException $e) { throw new OCSException('The request app was not found', OCSController::RESPOND_NOT_FOUND); } - return new DataResponse(); + return new DataResponse200(); } /** * @PasswordConfirmationRequired * @param string $app - * @return DataResponse + * @return DataResponse200 */ - public function disable(string $app): DataResponse { + public function disable(string $app): DataResponse200 { $this->appManager->disableApp($app); - return new DataResponse(); + return new DataResponse200(); } } diff --git a/apps/provisioning_api/lib/Controller/GroupsController.php b/apps/provisioning_api/lib/Controller/GroupsController.php index e7e2a666b7bb4..8bfb870ecd0e0 100644 --- a/apps/provisioning_api/lib/Controller/GroupsController.php +++ b/apps/provisioning_api/lib/Controller/GroupsController.php @@ -14,6 +14,7 @@ * @author Robin Appelman * @author Roeland Jago Douma * @author Tom Needham + * @author Kate Döen * * @license AGPL-3.0 * @@ -30,10 +31,13 @@ * along with this program. If not, see * */ + namespace OCA\Provisioning_API\Controller; +use OCA\Provisioning_API\ResponseDefinitions; use OCP\Accounts\IAccountManager; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\DataResponse200; use OCP\AppFramework\OCS\OCSException; use OCP\AppFramework\OCS\OCSForbiddenException; use OCP\AppFramework\OCS\OCSNotFoundException; @@ -48,20 +52,24 @@ use OCP\L10N\IFactory; use Psr\Log\LoggerInterface; +/** + * @psalm-import-type GroupDetails from ResponseDefinitions + * @psalm-import-type UserDetails from ResponseDefinitions + */ class GroupsController extends AUserData { /** @var LoggerInterface */ private $logger; public function __construct(string $appName, - IRequest $request, - IUserManager $userManager, - IConfig $config, - IGroupManager $groupManager, - IUserSession $userSession, - IAccountManager $accountManager, - IFactory $l10nFactory, - LoggerInterface $logger) { + IRequest $request, + IUserManager $userManager, + IConfig $config, + IGroupManager $groupManager, + IUserSession $userSession, + IAccountManager $accountManager, + IFactory $l10nFactory, + LoggerInterface $logger) { parent::__construct($appName, $request, $userManager, @@ -83,16 +91,16 @@ public function __construct(string $appName, * @param string $search * @param int $limit * @param int $offset - * @return DataResponse + * @return DataResponse200 */ - public function getGroups(string $search = '', int $limit = null, int $offset = 0): DataResponse { + public function getGroups(string $search = '', int $limit = null, int $offset = 0): DataResponse200 { $groups = $this->groupManager->search($search, $limit, $offset); $groups = array_map(function ($group) { /** @var IGroup $group */ return $group->getGID(); }, $groups); - return new DataResponse(['groups' => $groups]); + return new DataResponse200(['groups' => $groups]); } /** @@ -104,9 +112,9 @@ public function getGroups(string $search = '', int $limit = null, int $offset = * @param string $search * @param int $limit * @param int $offset - * @return DataResponse + * @return DataResponse200 */ - public function getGroupsDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse { + public function getGroupsDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse200 { $groups = $this->groupManager->search($search, $limit, $offset); $groups = array_map(function ($group) { /** @var IGroup $group */ @@ -120,19 +128,19 @@ public function getGroupsDetails(string $search = '', int $limit = null, int $of ]; }, $groups); - return new DataResponse(['groups' => $groups]); + return new DataResponse200(['groups' => $groups]); } /** * @NoAdminRequired * * @param string $groupId - * @return DataResponse + * @return DataResponse200 * @throws OCSException * * @deprecated 14 Use getGroupUsers */ - public function getGroup(string $groupId): DataResponse { + public function getGroup(string $groupId): DataResponse200 { return $this->getGroupUsers($groupId); } @@ -142,10 +150,12 @@ public function getGroup(string $groupId): DataResponse { * @NoAdminRequired * * @param string $groupId - * @return DataResponse + * @return DataResponse200 * @throws OCSException + * @throws OCSNotFoundException + * @throws OCSForbiddenException */ - public function getGroupUsers(string $groupId): DataResponse { + public function getGroupUsers(string $groupId): DataResponse200 { $groupId = urldecode($groupId); $user = $this->userSession->getUser(); @@ -161,14 +171,15 @@ public function getGroupUsers(string $groupId): DataResponse { // Check subadmin has access to this group if ($this->groupManager->isAdmin($user->getUID()) - || $isSubadminOfGroup) { + || $isSubadminOfGroup) { $users = $this->groupManager->get($groupId)->getUsers(); $users = array_map(function ($user) { /** @var IUser $user */ return $user->getUID(); }, $users); + /** @var string[] $users */ $users = array_values($users); - return new DataResponse(['users' => $users]); + return new DataResponse200(['users' => $users]); } throw new OCSForbiddenException(); @@ -183,10 +194,11 @@ public function getGroupUsers(string $groupId): DataResponse { * @param string $search * @param int $limit * @param int $offset - * @return DataResponse + * + * @return DataResponse200}> * @throws OCSException */ - public function getGroupUsersDetails(string $groupId, string $search = '', int $limit = null, int $offset = 0): DataResponse { + public function getGroupUsersDetails(string $groupId, string $search = '', int $limit = null, int $offset = 0): DataResponse200 { $groupId = urldecode($groupId); $currentUser = $this->userSession->getUser(); @@ -210,7 +222,7 @@ public function getGroupUsersDetails(string $groupId, string $search = '', int $ $userId = (string)$user->getUID(); $userData = $this->getUserData($userId); // Do not insert empty entry - if (!empty($userData)) { + if ($userData != null) { $usersDetails[$userId] = $userData; } else { // Logged user does not have permissions to see this user @@ -221,7 +233,7 @@ public function getGroupUsersDetails(string $groupId, string $search = '', int $ // continue if a users ceased to exist. } } - return new DataResponse(['users' => $usersDetails]); + return new DataResponse200(['users' => $usersDetails]); } throw new OCSException('The requested group could not be found', OCSController::RESPOND_NOT_FOUND); @@ -234,10 +246,10 @@ public function getGroupUsersDetails(string $groupId, string $search = '', int $ * * @param string $groupid * @param string $displayname - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function addGroup(string $groupid, string $displayname = ''): DataResponse { + public function addGroup(string $groupid, string $displayname = ''): DataResponse200 { // Validate name if (empty($groupid)) { $this->logger->error('Group name not supplied', ['app' => 'provisioning_api']); @@ -254,7 +266,7 @@ public function addGroup(string $groupid, string $displayname = ''): DataRespons if ($displayname !== '') { $group->setDisplayName($displayname); } - return new DataResponse(); + return new DataResponse200(); } /** @@ -263,16 +275,16 @@ public function addGroup(string $groupid, string $displayname = ''): DataRespons * @param string $groupId * @param string $key * @param string $value - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function updateGroup(string $groupId, string $key, string $value): DataResponse { + public function updateGroup(string $groupId, string $key, string $value): DataResponse200 { $groupId = urldecode($groupId); if ($key === 'displayname') { $group = $this->groupManager->get($groupId); if ($group->setDisplayName($value)) { - return new DataResponse(); + return new DataResponse200(); } throw new OCSException('Not supported by backend', 101); @@ -285,10 +297,10 @@ public function updateGroup(string $groupId, string $key, string $value): DataRe * @PasswordConfirmationRequired * * @param string $groupId - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function deleteGroup(string $groupId): DataResponse { + public function deleteGroup(string $groupId): DataResponse200 { $groupId = urldecode($groupId); // Check it exists @@ -299,15 +311,15 @@ public function deleteGroup(string $groupId): DataResponse { throw new OCSException('', 102); } - return new DataResponse(); + return new DataResponse200(); } /** * @param string $groupId - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function getSubAdminsOfGroup(string $groupId): DataResponse { + public function getSubAdminsOfGroup(string $groupId): DataResponse200 { // Check group exists $targetGroup = $this->groupManager->get($groupId); if ($targetGroup === null) { @@ -317,11 +329,12 @@ public function getSubAdminsOfGroup(string $groupId): DataResponse { /** @var IUser[] $subadmins */ $subadmins = $this->groupManager->getSubAdmin()->getGroupsSubAdmins($targetGroup); // New class returns IUser[] so convert back + /** @var string[] $uids */ $uids = []; foreach ($subadmins as $user) { $uids[] = $user->getUID(); } - return new DataResponse($uids); + return new DataResponse200($uids); } } diff --git a/apps/provisioning_api/lib/Controller/PreferencesController.php b/apps/provisioning_api/lib/Controller/PreferencesController.php index 2dba8b86eb6fc..579451080fdce 100644 --- a/apps/provisioning_api/lib/Controller/PreferencesController.php +++ b/apps/provisioning_api/lib/Controller/PreferencesController.php @@ -6,6 +6,7 @@ * @copyright Copyright (c) 2022 Joas Schilling * * @author Joas Schilling + * @author Kate Döen * * @license GNU AGPL version 3 or any later version * @@ -28,6 +29,8 @@ use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\DataResponse200; +use OCP\AppFramework\Http\DataResponse400; use OCP\AppFramework\OCSController; use OCP\Config\BeforePreferenceDeletedEvent; use OCP\Config\BeforePreferenceSetEvent; @@ -58,8 +61,12 @@ public function __construct( /** * @NoAdminRequired * @NoSubAdminRequired + * + * @param array $configs + * + * @return DataResponse200|DataResponse400 */ - public function setMultiplePreferences(string $appId, array $configs): DataResponse { + public function setMultiplePreferences(string $appId, array $configs): DataResponse200|DataResponse400 { $userId = $this->userSession->getUser()->getUID(); foreach ($configs as $configKey => $configValue) { @@ -74,7 +81,7 @@ public function setMultiplePreferences(string $appId, array $configs): DataRespo if (!$event->isValid()) { // No listener validated that the preference can be set (to this value) - return new DataResponse([], Http::STATUS_BAD_REQUEST); + return new DataResponse400(); } } @@ -87,14 +94,16 @@ public function setMultiplePreferences(string $appId, array $configs): DataRespo ); } - return new DataResponse(); + return new DataResponse200(); } /** * @NoAdminRequired * @NoSubAdminRequired + * + * @return DataResponse200|DataResponse400 */ - public function setPreference(string $appId, string $configKey, string $configValue): DataResponse { + public function setPreference(string $appId, string $configKey, string $configValue): DataResponse200|DataResponse400 { $userId = $this->userSession->getUser()->getUID(); $event = new BeforePreferenceSetEvent( @@ -108,7 +117,7 @@ public function setPreference(string $appId, string $configKey, string $configVa if (!$event->isValid()) { // No listener validated that the preference can be set (to this value) - return new DataResponse([], Http::STATUS_BAD_REQUEST); + return new DataResponse400(); } $this->config->setUserValue( @@ -118,14 +127,18 @@ public function setPreference(string $appId, string $configKey, string $configVa $configValue ); - return new DataResponse(); + return new DataResponse200(); } /** * @NoAdminRequired * @NoSubAdminRequired + * + * @param string[] $configKeys + * + * @return DataResponse200|DataResponse400 */ - public function deleteMultiplePreference(string $appId, array $configKeys): DataResponse { + public function deleteMultiplePreference(string $appId, array $configKeys): DataResponse200|DataResponse400 { $userId = $this->userSession->getUser()->getUID(); foreach ($configKeys as $configKey) { @@ -139,7 +152,7 @@ public function deleteMultiplePreference(string $appId, array $configKeys): Data if (!$event->isValid()) { // No listener validated that the preference can be deleted - return new DataResponse([], Http::STATUS_BAD_REQUEST); + return new DataResponse400(); } } @@ -151,14 +164,16 @@ public function deleteMultiplePreference(string $appId, array $configKeys): Data ); } - return new DataResponse(); + return new DataResponse200(); } /** * @NoAdminRequired * @NoSubAdminRequired + * + * @return DataResponse200|DataResponse400 */ - public function deletePreference(string $appId, string $configKey): DataResponse { + public function deletePreference(string $appId, string $configKey): DataResponse200|DataResponse400 { $userId = $this->userSession->getUser()->getUID(); $event = new BeforePreferenceDeletedEvent( @@ -171,7 +186,7 @@ public function deletePreference(string $appId, string $configKey): DataResponse if (!$event->isValid()) { // No listener validated that the preference can be deleted - return new DataResponse([], Http::STATUS_BAD_REQUEST); + return new DataResponse400(); } $this->config->deleteUserValue( @@ -180,6 +195,6 @@ public function deletePreference(string $appId, string $configKey): DataResponse $configKey ); - return new DataResponse(); + return new DataResponse200(); } } diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php index f5bbf4899a4d1..5453ad5bd8f2d 100644 --- a/apps/provisioning_api/lib/Controller/UsersController.php +++ b/apps/provisioning_api/lib/Controller/UsersController.php @@ -44,6 +44,7 @@ namespace OCA\Provisioning_API\Controller; +use Exception; use InvalidArgumentException; use libphonenumber\NumberParseException; use libphonenumber\PhoneNumber; @@ -52,12 +53,13 @@ use OC\Authentication\Token\RemoteWipe; use OC\KnownUser\KnownUserService; use OC\User\Backend; +use OCA\Provisioning_API\ResponseDefinitions; use OCA\Settings\Mailer\NewUserMailHelper; use OCP\Accounts\IAccountManager; use OCP\Accounts\IAccountProperty; use OCP\Accounts\PropertyDoesNotExistException; -use OCP\AppFramework\Http; -use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\DataResponse200; +use OCP\AppFramework\Http\DataResponse400; use OCP\AppFramework\OCS\OCSException; use OCP\AppFramework\OCS\OCSForbiddenException; use OCP\AppFramework\OCSController; @@ -75,8 +77,12 @@ use OCP\Security\Events\GenerateSecurePasswordEvent; use OCP\Security\ISecureRandom; use OCP\User\Backend\ISetDisplayNameBackend; +use OCP\Util; use Psr\Log\LoggerInterface; +/** + * @psalm-import-type UserDetails from ResponseDefinitions + */ class UsersController extends AUserData { /** @var IURLGenerator */ @@ -142,9 +148,9 @@ public function __construct( * @param string $search * @param int $limit * @param int $offset - * @return DataResponse + * @return DataResponse200 */ - public function getUsers(string $search = '', int $limit = null, int $offset = 0): DataResponse { + public function getUsers(string $search = '', int $limit = null, int $offset = 0): DataResponse200 { $user = $this->userSession->getUser(); $users = []; @@ -165,9 +171,10 @@ public function getUsers(string $search = '', int $limit = null, int $offset = 0 } } + /** @var string[] $users */ $users = array_keys($users); - return new DataResponse([ + return new DataResponse200([ 'users' => $users ]); } @@ -176,8 +183,9 @@ public function getUsers(string $search = '', int $limit = null, int $offset = 0 * @NoAdminRequired * * returns a list of users and their data + * @return DataResponse200}> */ - public function getUsersDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse { + public function getUsersDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse200 { $currentUser = $this->userSession->getUser(); $users = []; @@ -200,12 +208,13 @@ public function getUsersDetails(string $search = '', int $limit = null, int $off $users = array_merge(...$users); } + /** @var array $usersDetails */ $usersDetails = []; foreach ($users as $userId) { - $userId = (string) $userId; + $userId = (string)$userId; $userData = $this->getUserData($userId); // Do not insert empty entry - if (!empty($userData)) { + if ($userData != null) { $usersDetails[$userId] = $userData; } else { // Logged user does not have permissions to see this user @@ -214,7 +223,7 @@ public function getUsersDetails(string $search = '', int $limit = null, int $off } } - return new DataResponse([ + return new DataResponse200([ 'users' => $usersDetails ]); } @@ -225,15 +234,15 @@ public function getUsersDetails(string $search = '', int $limit = null, int $off * @NoSubAdminRequired * * @param string $location - * @param array $search - * @return DataResponse + * @param array $search + * @return DataResponse200>|DataResponse400 */ - public function searchByPhoneNumbers(string $location, array $search): DataResponse { + public function searchByPhoneNumbers(string $location, array $search): DataResponse200|DataResponse400 { $phoneUtil = PhoneNumberUtil::getInstance(); if ($phoneUtil->getCountryCodeForRegion($location) === 0) { // Not a valid region code - return new DataResponse([], Http::STATUS_BAD_REQUEST); + return new DataResponse400(); } /** @var IUser $user */ @@ -248,7 +257,7 @@ public function searchByPhoneNumbers(string $location, array $search): DataRespo $phoneNumber = $phoneUtil->parse($phone, $location); if ($phoneNumber instanceof PhoneNumber && $phoneUtil->isValidNumber($phoneNumber)) { $normalizedNumber = $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164); - $normalizedNumberToKey[$normalizedNumber] = (string) $key; + $normalizedNumberToKey[$normalizedNumber] = (string)$key; } } catch (NumberParseException $e) { } @@ -261,7 +270,7 @@ public function searchByPhoneNumbers(string $location, array $search): DataRespo $phoneNumber = $phoneUtil->parse($phone, $defaultPhoneRegion); if ($phoneNumber instanceof PhoneNumber && $phoneUtil->isValidNumber($phoneNumber)) { $normalizedNumber = $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164); - $normalizedNumberToKey[$normalizedNumber] = (string) $key; + $normalizedNumberToKey[$normalizedNumber] = (string)$key; } } catch (NumberParseException $e) { } @@ -272,7 +281,7 @@ public function searchByPhoneNumbers(string $location, array $search): DataRespo $phoneNumbers = array_keys($normalizedNumberToKey); if (empty($phoneNumbers)) { - return new DataResponse(); + return new DataResponse200(); } // Cleanup all previous entries and only allow new matches @@ -280,10 +289,6 @@ public function searchByPhoneNumbers(string $location, array $search): DataRespo $userMatches = $this->accountManager->searchUsers(IAccountManager::PROPERTY_PHONE, $phoneNumbers); - if (empty($userMatches)) { - return new DataResponse(); - } - $cloudUrl = rtrim($this->urlGenerator->getAbsoluteURL('/'), '/'); if (strpos($cloudUrl, 'http://') === 0) { $cloudUrl = substr($cloudUrl, strlen('http://')); @@ -298,7 +303,7 @@ public function searchByPhoneNumbers(string $location, array $search): DataRespo $this->knownUserService->storeIsKnownToUser($knownTo, $userId); } - return new DataResponse($matches); + return new DataResponse200($matches); } /** @@ -324,12 +329,13 @@ private function createNewUserId(): string { * @param string $password * @param string $displayName * @param string $email - * @param array $groups - * @param array $subadmin + * @param string[] $groups + * @param string[] $subadmin * @param string $quota * @param string $language - * @return DataResponse + * @return DataResponse200 * @throws OCSException + * @throws OCSForbiddenException */ public function addUser( string $userid, @@ -340,7 +346,7 @@ public function addUser( array $subadmin = [], string $quota = '', string $language = '' - ): DataResponse { + ): DataResponse200 { $user = $this->userSession->getUser(); $isAdmin = $this->groupManager->isAdmin($user->getUID()); $subAdminManager = $this->groupManager->getSubAdmin(); @@ -375,7 +381,7 @@ public function addUser( $group = $this->groupManager->get($groupid); // Check if group exists if ($group === null) { - throw new OCSException('Subadmin group does not exist', 102); + throw new OCSException('Subadmin group does not exist', 102); } // Check if trying to make subadmin of admin group if ($group->getGID() === 'admin') { @@ -455,7 +461,7 @@ public function addUser( try { $emailTemplate = $this->newUserMailHelper->generateTemplate($newUser, $generatePasswordResetToken); $this->newUserMailHelper->sendMail($newUser, $emailTemplate); - } catch (\Exception $e) { + } catch (Exception $e) { // Mail could be failing hard or just be plain not configured // Logging error as it is the hardest of the two $this->logger->error( @@ -469,7 +475,7 @@ public function addUser( } } - return new DataResponse(['id' => $userid]); + return new DataResponse200(['id' => $userid]); } catch (HintException $e) { $this->logger->warning( 'Failed addUser attempt with hint exception.', @@ -497,7 +503,7 @@ public function addUser( ] ); throw new OCSException($e->getMessage(), 101); - } catch (\Exception $e) { + } catch (Exception $e) { $this->logger->error( 'Failed addUser attempt with exception.', [ @@ -516,10 +522,10 @@ public function addUser( * gets user info * * @param string $userId - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function getUser(string $userId): DataResponse { + public function getUser(string $userId): DataResponse200 { $includeScopes = false; $currentUser = $this->userSession->getUser(); if ($currentUser && $currentUser->getUID() === $userId) { @@ -528,10 +534,10 @@ public function getUser(string $userId): DataResponse { $data = $this->getUserData($userId, $includeScopes); // getUserData returns empty array if not enough permissions - if (empty($data)) { + if ($data == null) { throw new OCSException('', OCSController::RESPOND_NOT_FOUND); } - return new DataResponse($data); + return new DataResponse200($data); } /** @@ -540,14 +546,15 @@ public function getUser(string $userId): DataResponse { * * gets user info from the currently logged in user * - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function getCurrentUser(): DataResponse { + public function getCurrentUser(): DataResponse200 { $user = $this->userSession->getUser(); if ($user) { + /** @var UserDetails $data */ $data = $this->getUserData($user->getUID(), true); - return new DataResponse($data); + return new DataResponse200($data); } throw new OCSException('', OCSController::RESPOND_UNAUTHORISED); @@ -557,10 +564,10 @@ public function getCurrentUser(): DataResponse { * @NoAdminRequired * @NoSubAdminRequired * - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function getEditableFields(): DataResponse { + public function getEditableFields(): DataResponse200 { $currentLoggedInUser = $this->userSession->getUser(); if (!$currentLoggedInUser instanceof IUser) { throw new OCSException('', OCSController::RESPOND_NOT_FOUND); @@ -574,10 +581,10 @@ public function getEditableFields(): DataResponse { * @NoSubAdminRequired * * @param string $userId - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function getEditableFieldsForUser(string $userId): DataResponse { + public function getEditableFieldsForUser(string $userId): DataResponse200 { $currentLoggedInUser = $this->userSession->getUser(); if (!$currentLoggedInUser instanceof IUser) { throw new OCSException('', OCSController::RESPOND_NOT_FOUND); @@ -625,7 +632,7 @@ public function getEditableFieldsForUser(string $userId): DataResponse { $permittedFields[] = IAccountManager::PROPERTY_BIOGRAPHY; $permittedFields[] = IAccountManager::PROPERTY_PROFILE_ENABLED; - return new DataResponse($permittedFields); + return new DataResponse200($permittedFields); } /** @@ -633,6 +640,7 @@ public function getEditableFieldsForUser(string $userId): DataResponse { * @NoSubAdminRequired * @PasswordConfirmationRequired * + * @return DataResponse200 * @throws OCSException */ public function editUserMultiValue( @@ -640,7 +648,7 @@ public function editUserMultiValue( string $collectionName, string $key, string $value - ): DataResponse { + ): DataResponse200 { $currentLoggedInUser = $this->userSession->getUser(); if ($currentLoggedInUser === null) { throw new OCSException('', OCSController::RESPOND_UNAUTHORISED); @@ -717,7 +725,7 @@ public function editUserMultiValue( default: throw new OCSException('', 103); } - return new DataResponse(); + return new DataResponse200(); } /** @@ -730,10 +738,10 @@ public function editUserMultiValue( * @param string $userId * @param string $key * @param string $value - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function editUser(string $userId, string $key, string $value): DataResponse { + public function editUser(string $userId, string $key, string $value): DataResponse200 { $currentLoggedInUser = $this->userSession->getUser(); $targetUser = $this->userManager->get($userId); @@ -858,9 +866,9 @@ public function editUser(string $userId, string $key, string $value): DataRespon $quota = $value; if ($quota !== 'none' && $quota !== 'default') { if (is_numeric($quota)) { - $quota = (float) $quota; + $quota = (float)$quota; } else { - $quota = \OCP\Util::computerFileSize($quota); + $quota = Util::computerFileSize($quota); } if ($quota === false) { throw new OCSException('Invalid quota value ' . $value, 102); @@ -868,11 +876,11 @@ public function editUser(string $userId, string $key, string $value): DataRespon if ($quota === -1) { $quota = 'none'; } else { - $maxQuota = (int) $this->config->getAppValue('files', 'max_quota', '-1'); + $maxQuota = (int)$this->config->getAppValue('files', 'max_quota', '-1'); if ($maxQuota !== -1 && $quota > $maxQuota) { throw new OCSException('Invalid quota value. ' . $value . ' is exceeding the maximum quota', 102); } - $quota = \OCP\Util::humanFileSize($quota); + $quota = Util::humanFileSize($quota); } } // no else block because quota can be set to 'none' in previous if @@ -1023,7 +1031,7 @@ public function editUser(string $userId, string $key, string $value): DataRespon default: throw new OCSException('', 103); } - return new DataResponse(); + return new DataResponse200(); } /** @@ -1032,11 +1040,11 @@ public function editUser(string $userId, string $key, string $value): DataRespon * * @param string $userId * - * @return DataResponse + * @return DataResponse200 * * @throws OCSException */ - public function wipeUserDevices(string $userId): DataResponse { + public function wipeUserDevices(string $userId): DataResponse200 { /** @var IUser $currentLoggedInUser */ $currentLoggedInUser = $this->userSession->getUser(); @@ -1058,7 +1066,7 @@ public function wipeUserDevices(string $userId): DataResponse { $this->remoteWipe->markAllTokensForWipe($targetUser); - return new DataResponse(); + return new DataResponse200(); } /** @@ -1066,10 +1074,10 @@ public function wipeUserDevices(string $userId): DataResponse { * @NoAdminRequired * * @param string $userId - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function deleteUser(string $userId): DataResponse { + public function deleteUser(string $userId): DataResponse200 { $currentLoggedInUser = $this->userSession->getUser(); $targetUser = $this->userManager->get($userId); @@ -1090,7 +1098,7 @@ public function deleteUser(string $userId): DataResponse { // Go ahead with the delete if ($targetUser->delete()) { - return new DataResponse(); + return new DataResponse200(); } else { throw new OCSException('', 101); } @@ -1101,11 +1109,11 @@ public function deleteUser(string $userId): DataResponse { * @NoAdminRequired * * @param string $userId - * @return DataResponse + * @return DataResponse200 * @throws OCSException * @throws OCSForbiddenException */ - public function disableUser(string $userId): DataResponse { + public function disableUser(string $userId): DataResponse200 { return $this->setEnabled($userId, false); } @@ -1114,21 +1122,21 @@ public function disableUser(string $userId): DataResponse { * @NoAdminRequired * * @param string $userId - * @return DataResponse + * @return DataResponse200 * @throws OCSException * @throws OCSForbiddenException */ - public function enableUser(string $userId): DataResponse { + public function enableUser(string $userId): DataResponse200 { return $this->setEnabled($userId, true); } /** * @param string $userId * @param bool $value - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - private function setEnabled(string $userId, bool $value): DataResponse { + private function setEnabled(string $userId, bool $value): DataResponse200 { $currentLoggedInUser = $this->userSession->getUser(); $targetUser = $this->userManager->get($userId); @@ -1144,7 +1152,7 @@ private function setEnabled(string $userId, bool $value): DataResponse { // enable/disable the user now $targetUser->setEnabled($value); - return new DataResponse(); + return new DataResponse200(); } /** @@ -1152,10 +1160,10 @@ private function setEnabled(string $userId, bool $value): DataResponse { * @NoSubAdminRequired * * @param string $userId - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function getUsersGroups(string $userId): DataResponse { + public function getUsersGroups(string $userId): DataResponse200 { $loggedInUser = $this->userSession->getUser(); $targetUser = $this->userManager->get($userId); @@ -1165,7 +1173,7 @@ public function getUsersGroups(string $userId): DataResponse { if ($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) { // Self lookup or admin lookup - return new DataResponse([ + return new DataResponse200([ 'groups' => $this->groupManager->getUserGroupIds($targetUser) ]); } else { @@ -1183,7 +1191,7 @@ public function getUsersGroups(string $userId): DataResponse { $getSubAdminsGroups, $this->groupManager->getUserGroupIds($targetUser) ); - return new DataResponse(['groups' => $groups]); + return new DataResponse200(['groups' => $groups]); } else { // Not permitted throw new OCSException('', OCSController::RESPOND_NOT_FOUND); @@ -1197,10 +1205,10 @@ public function getUsersGroups(string $userId): DataResponse { * * @param string $userId * @param string $groupid - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function addToGroup(string $userId, string $groupid = ''): DataResponse { + public function addToGroup(string $userId, string $groupid = ''): DataResponse200 { if ($groupid === '') { throw new OCSException('', 101); } @@ -1223,7 +1231,7 @@ public function addToGroup(string $userId, string $groupid = ''): DataResponse { // Add user to group $group->addUser($targetUser); - return new DataResponse(); + return new DataResponse200(); } /** @@ -1232,10 +1240,10 @@ public function addToGroup(string $userId, string $groupid = ''): DataResponse { * * @param string $userId * @param string $groupid - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function removeFromGroup(string $userId, string $groupid): DataResponse { + public function removeFromGroup(string $userId, string $groupid): DataResponse200 { $loggedInUser = $this->userSession->getUser(); if ($groupid === null || trim($groupid) === '') { @@ -1285,7 +1293,7 @@ public function removeFromGroup(string $userId, string $groupid): DataResponse { // Remove user from group $group->removeUser($targetUser); - return new DataResponse(); + return new DataResponse200(); } /** @@ -1295,10 +1303,10 @@ public function removeFromGroup(string $userId, string $groupid): DataResponse { * * @param string $userId * @param string $groupid - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function addSubAdmin(string $userId, string $groupid): DataResponse { + public function addSubAdmin(string $userId, string $groupid): DataResponse200 { $group = $this->groupManager->get($groupid); $user = $this->userManager->get($userId); @@ -1308,7 +1316,7 @@ public function addSubAdmin(string $userId, string $groupid): DataResponse { } // Check if group exists if ($group === null) { - throw new OCSException('Group does not exist', 102); + throw new OCSException('Group does not exist', 102); } // Check if trying to make subadmin of admin group if ($group->getGID() === 'admin') { @@ -1319,11 +1327,11 @@ public function addSubAdmin(string $userId, string $groupid): DataResponse { // We cannot be subadmin twice if ($subAdminManager->isSubAdminOfGroup($user, $group)) { - return new DataResponse(); + return new DataResponse200(); } // Go $subAdminManager->createSubAdmin($user, $group); - return new DataResponse(); + return new DataResponse200(); } /** @@ -1333,10 +1341,10 @@ public function addSubAdmin(string $userId, string $groupid): DataResponse { * * @param string $userId * @param string $groupid - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function removeSubAdmin(string $userId, string $groupid): DataResponse { + public function removeSubAdmin(string $userId, string $groupid): DataResponse200 { $group = $this->groupManager->get($groupid); $user = $this->userManager->get($userId); $subAdminManager = $this->groupManager->getSubAdmin(); @@ -1356,19 +1364,19 @@ public function removeSubAdmin(string $userId, string $groupid): DataResponse { // Go $subAdminManager->deleteSubAdmin($user, $group); - return new DataResponse(); + return new DataResponse200(); } /** * Get the groups a user is a subadmin of * * @param string $userId - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function getUserSubAdminGroups(string $userId): DataResponse { + public function getUserSubAdminGroups(string $userId): DataResponse200 { $groups = $this->getUserSubAdminGroupsData($userId); - return new DataResponse($groups); + return new DataResponse200($groups); } /** @@ -1378,10 +1386,10 @@ public function getUserSubAdminGroups(string $userId): DataResponse { * resend welcome message * * @param string $userId - * @return DataResponse + * @return DataResponse200 * @throws OCSException */ - public function resendWelcomeMessage(string $userId): DataResponse { + public function resendWelcomeMessage(string $userId): DataResponse200 { $currentLoggedInUser = $this->userSession->getUser(); $targetUser = $this->userManager->get($userId); @@ -1407,7 +1415,7 @@ public function resendWelcomeMessage(string $userId): DataResponse { try { $emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false); $this->newUserMailHelper->sendMail($targetUser, $emailTemplate); - } catch (\Exception $e) { + } catch (Exception $e) { $this->logger->error( "Can't send new user mail to $email", [ @@ -1418,6 +1426,6 @@ public function resendWelcomeMessage(string $userId): DataResponse { throw new OCSException('Sending email failed', 102); } - return new DataResponse(); + return new DataResponse200(); } } diff --git a/apps/provisioning_api/lib/ResponseDefinitions.php b/apps/provisioning_api/lib/ResponseDefinitions.php new file mode 100644 index 0000000000000..75870e04cdde7 --- /dev/null +++ b/apps/provisioning_api/lib/ResponseDefinitions.php @@ -0,0 +1,135 @@ + + * + * @author Kate Döen + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Provisioning_API; + +/** + * @psalm-type UserDetails = array{ + * additional_mail: string[], + * additional_mailScope: string[]|null, + * address: string, + * addressScope: string|null, + * avatarScope: string|null, + * backend: string, + * backendCapabilities: array{ + * setDisplayName: bool, + * setPassword: bool + * }, + * biography: string, + * biographyScope: string|null, + * displayname: string, + * display-name: string, + * displaynameScope: string|null, + * email: string|null, + * emailScope: string|null, + * enabled: bool|null, + * fediverse: string|null, + * fediverseScope: string|null, + * groups: string[], + * headline: string, + * headlineScope: string|null, + * id: string, + * language: string, + * lastLogin: int, + * locale: string, + * notify_email: string|null, + * organisation: string, + * organisationScope: string|null, + * phone: string, + * phoneScope: string|null, + * profile_enabled: string, + * profile_enabledScope: string|null, + * quota: array{ + * free: int|null, + * quota: string|int|bool, + * relative: float|null, + * total: int|null, + * used: int, + * }, + * role: string, + * roleScope: string|null, + * storageLocation: string|null, + * subadmin: string[], + * twitter: string, + * twitterScope: string|null, + * website: string, + * websiteScope: string|null, + * } + * + * @psalm-type AppInfoValue = string|string[]|array + * + * @psalm-type AppInfo = array{ + * active: bool|null, + * activity: AppInfoValue|null, + * author: AppInfoValue|null, + * background-jobs: AppInfoValue|null, + * bugs: AppInfoValue|null, + * category: AppInfoValue|null, + * collaboration: AppInfoValue|null, + * commands: AppInfoValue|null, + * default_enable: AppInfoValue|null, + * dependencies: AppInfoValue|null, + * description: string, + * discussion: AppInfoValue|null, + * documentation: AppInfoValue|null, + * groups: AppInfoValue|null, + * id: string, + * info: AppInfoValue|null, + * internal: bool|null, + * level: int|null, + * licence: AppInfoValue|null, + * name: string, + * namespace: AppInfoValue|null, + * navigations: AppInfoValue|null, + * preview: AppInfoValue|null, + * previewAsIcon: bool|null, + * public: AppInfoValue|null, + * remote: AppInfoValue|null, + * removable: bool|null, + * repair-steps: AppInfoValue|null, + * repository: AppInfoValue|null, + * sabre: AppInfoValue|null, + * screenshot: AppInfoValue|null, + * settings: AppInfoValue|null, + * summary: string, + * trash: AppInfoValue|null, + * two-factor-providers: AppInfoValue|null, + * types: AppInfoValue|null, + * version: string, + * versions: AppInfoValue|null, + * website: AppInfoValue|null, + * } + * + * @psalm-type GroupDetails = array{ + * id: string, + * displayname: string, + * usercount: bool|int, + * disabled: bool|int, + * canAdd: bool, + * canRemove: bool, + * } + */ +class ResponseDefinitions { +} diff --git a/apps/provisioning_api/openapi.json b/apps/provisioning_api/openapi.json new file mode 100644 index 0000000000000..bcae45c510928 --- /dev/null +++ b/apps/provisioning_api/openapi.json @@ -0,0 +1,3402 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Provisioning API", + "description": "This application enables a set of APIs that external systems can use to manage users, groups and apps.", + "license": { + "name": "agpl" + }, + "version": "1.16.0" + }, + "paths": { + "/ocs/v2.php/cloud/apps": { + "get": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "get-apps", + "parameters": [ + { + "name": "filter", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "apps" + ], + "type": "object", + "properties": { + "apps": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/apps/{app}": { + "parameters": [ + { + "name": "app", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "apps-get-app-info", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/AppInfo" + } + } + } + } + } + } + } + } + } + }, + "post": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "enable-apps", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + }, + "delete": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "disable-apps", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/groups": { + "get": { + "tags": [ + "provisioning_api" + ], + "description": "returns a list of groups", + "operationId": "get-groups", + "parameters": [ + { + "name": "search", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "offset", + "in": "query", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "groups" + ], + "type": "object", + "properties": { + "groups": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "post": { + "tags": [ + "provisioning_api" + ], + "description": "creates a new group", + "operationId": "groups-add-group", + "parameters": [ + { + "name": "groupid", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "displayname", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/groups/details": { + "get": { + "tags": [ + "provisioning_api" + ], + "description": "Returns a list of groups details with ids and displaynames", + "operationId": "get-groups-details", + "parameters": [ + { + "name": "search", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "offset", + "in": "query", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "groups" + ], + "type": "object", + "properties": { + "groups": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GroupDetails" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/groups/{groupId}/users": { + "parameters": [ + { + "name": "groupId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "tags": [ + "provisioning_api" + ], + "description": "returns an array of users in the specified group", + "operationId": "groups-get-group-users", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "users" + ], + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "", + "content": { + "text/plain": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "string" + } + } + } + } + } + } + } + }, + "403": { + "description": "", + "content": { + "text/plain": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/groups/{groupId}/users/details": { + "parameters": [ + { + "name": "groupId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "tags": [ + "provisioning_api" + ], + "description": "returns an array of users details in the specified group", + "operationId": "groups-get-group-users-details", + "parameters": [ + { + "name": "search", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "offset", + "in": "query", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "users" + ], + "type": "object", + "properties": { + "users": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/components/schemas/UserDetails" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + } + ] + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/groups/{groupId}/subadmins": { + "parameters": [ + { + "name": "groupId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "groups-get-sub-admins-of-group", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/groups/{groupId}": { + "parameters": [ + { + "name": "groupId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "groups-get-group", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "users" + ], + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "put": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "groups-update-group", + "parameters": [ + { + "name": "key", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "value", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + }, + "delete": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "groups-delete-group", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/users": { + "get": { + "tags": [ + "provisioning_api" + ], + "description": "returns a list of users", + "operationId": "get-users", + "parameters": [ + { + "name": "search", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "offset", + "in": "query", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "users" + ], + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "post": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "users-add-user", + "parameters": [ + { + "name": "userid", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "password", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "displayName", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "email", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "groups", + "in": "query", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "subadmin", + "in": "query", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "quota", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "language", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "403": { + "description": "", + "content": { + "text/plain": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/users/details": { + "get": { + "tags": [ + "provisioning_api" + ], + "description": "returns a list of users and their data", + "operationId": "get-users-details", + "parameters": [ + { + "name": "search", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "offset", + "in": "query", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "users" + ], + "type": "object", + "properties": { + "users": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/components/schemas/UserDetails" + }, + { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + } + ] + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/users/search/by-phone": { + "post": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "users-search-by-phone-numbers", + "parameters": [ + { + "name": "location", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "search", + "in": "query", + "required": true, + "schema": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/users/{userId}": { + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "tags": [ + "provisioning_api" + ], + "description": "gets user info", + "operationId": "users-get-user", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/UserDetails" + } + } + } + } + } + } + } + } + } + }, + "put": { + "tags": [ + "provisioning_api" + ], + "description": "edit users", + "operationId": "users-edit-user", + "parameters": [ + { + "name": "key", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "value", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + }, + "delete": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "users-delete-user", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/user": { + "get": { + "tags": [ + "provisioning_api" + ], + "description": "gets user info from the currently logged in user", + "operationId": "users-get-current-user", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/UserDetails" + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/user/fields": { + "get": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "users-get-editable-fields", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/user/fields/{userId}": { + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "users-get-editable-fields-for-user", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/users/{userId}/{collectionName}": { + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "collectionName", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "put": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "users-edit-user-multi-value", + "parameters": [ + { + "name": "key", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "value", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/users/{userId}/wipe": { + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "post": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "users-wipe-user-devices", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/users/{userId}/enable": { + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "put": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "users-enable-user", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "403": { + "description": "", + "content": { + "text/plain": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/users/{userId}/disable": { + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "put": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "users-disable-user", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "403": { + "description": "", + "content": { + "text/plain": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/users/{userId}/groups": { + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "get-users-groups", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "groups" + ], + "type": "object", + "properties": { + "groups": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "post": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "users-add-to-group", + "parameters": [ + { + "name": "groupid", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + }, + "delete": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "users-remove-from-group", + "parameters": [ + { + "name": "groupid", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/users/{userId}/subadmins": { + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "tags": [ + "provisioning_api" + ], + "description": "Get the groups a user is a subadmin of", + "operationId": "users-get-user-sub-admin-groups", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "post": { + "tags": [ + "provisioning_api" + ], + "description": "Creates a subadmin", + "operationId": "users-add-sub-admin", + "parameters": [ + { + "name": "groupid", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + }, + "delete": { + "tags": [ + "provisioning_api" + ], + "description": "Removes a subadmin from a group", + "operationId": "users-remove-sub-admin", + "parameters": [ + { + "name": "groupid", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/cloud/users/{userId}/welcome": { + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "post": { + "tags": [ + "provisioning_api" + ], + "description": "resend welcome message", + "operationId": "users-resend-welcome-message", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/provisioning_api/api/v1/config/apps": { + "get": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "app-config-get-apps", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/provisioning_api/api/v1/config/apps/{app}": { + "parameters": [ + { + "name": "app", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "app-config-get-keys", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "403": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/provisioning_api/api/v1/config/apps/{app}/{key}": { + "parameters": [ + { + "name": "app", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "key", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "app-config-get-value", + "parameters": [ + { + "name": "defaultValue", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "403": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "post": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "app-config-set-value", + "parameters": [ + { + "name": "value", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "403": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "delete": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "app-config-delete-key", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "403": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/provisioning_api/api/v1/config/users/{appId}/{configKey}": { + "parameters": [ + { + "name": "appId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "configKey", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "post": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "preferences-set-preference", + "parameters": [ + { + "name": "configValue", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + }, + "delete": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "preferences-delete-preference", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/provisioning_api/api/v1/config/users/{appId}": { + "parameters": [ + { + "name": "appId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "post": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "set-multiple-preferences", + "parameters": [ + { + "name": "configs", + "in": "query", + "required": true, + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + }, + "delete": { + "tags": [ + "provisioning_api" + ], + "description": "", + "operationId": "preferences-delete-multiple-preference", + "parameters": [ + { + "name": "configKeys", + "in": "query", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "required": [ + "ocs" + ], + "type": "object", + "properties": { + "ocs": { + "required": [ + "meta", + "data" + ], + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "AppInfo": { + "required": [ + "description", + "id", + "name", + "summary", + "version" + ], + "type": "object", + "properties": { + "active": { + "type": "boolean" + }, + "activity": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "author": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "background-jobs": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "bugs": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "category": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "collaboration": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "commands": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "default_enable": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "dependencies": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "description": { + "type": "string" + }, + "discussion": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "documentation": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "groups": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "id": { + "type": "string" + }, + "info": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "internal": { + "type": "boolean" + }, + "level": { + "type": "integer" + }, + "licence": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "name": { + "type": "string" + }, + "namespace": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "navigations": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "preview": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "previewAsIcon": { + "type": "boolean" + }, + "public": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "remote": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "removable": { + "type": "boolean" + }, + "repair-steps": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "repository": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "sabre": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "screenshot": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "settings": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "summary": { + "type": "string" + }, + "trash": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "two-factor-providers": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "types": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "version": { + "type": "string" + }, + "versions": { + "$ref": "#/components/schemas/AppInfoValue" + }, + "website": { + "$ref": "#/components/schemas/AppInfoValue" + } + } + }, + "AppInfoValue": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "object", + "additionalProperties": true + } + ] + }, + "GroupDetails": { + "required": [ + "id", + "displayname", + "usercount", + "disabled", + "canAdd", + "canRemove" + ], + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "displayname": { + "type": "string" + }, + "usercount": { + "oneOf": [ + { + "type": "boolean" + }, + { + "type": "integer" + } + ] + }, + "disabled": { + "oneOf": [ + { + "type": "boolean" + }, + { + "type": "integer" + } + ] + }, + "canAdd": { + "type": "boolean" + }, + "canRemove": { + "type": "boolean" + } + } + }, + "OCSMeta": { + "type": "object", + "required": [ + "status", + "statuscode" + ], + "properties": { + "status": { + "type": "string" + }, + "statuscode": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "totalitems": { + "type": "string" + }, + "itemsperpage": { + "type": "string" + } + } + }, + "UserDetails": { + "required": [ + "additional_mail", + "address", + "backend", + "backendCapabilities", + "biography", + "displayname", + "display-name", + "groups", + "headline", + "id", + "language", + "lastLogin", + "locale", + "organisation", + "phone", + "profile_enabled", + "quota", + "role", + "subadmin", + "twitter", + "website" + ], + "type": "object", + "properties": { + "additional_mail": { + "type": "array", + "items": { + "type": "string" + } + }, + "additional_mailScope": { + "type": "array", + "items": { + "type": "string" + } + }, + "address": { + "type": "string" + }, + "addressScope": { + "type": "string" + }, + "avatarScope": { + "type": "string" + }, + "backend": { + "type": "string" + }, + "backendCapabilities": { + "required": [ + "setDisplayName", + "setPassword" + ], + "type": "object", + "properties": { + "setDisplayName": { + "type": "boolean" + }, + "setPassword": { + "type": "boolean" + } + } + }, + "biography": { + "type": "string" + }, + "biographyScope": { + "type": "string" + }, + "displayname": { + "type": "string" + }, + "display-name": { + "type": "string" + }, + "displaynameScope": { + "type": "string" + }, + "email": { + "type": "string" + }, + "emailScope": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "fediverse": { + "type": "string" + }, + "fediverseScope": { + "type": "string" + }, + "groups": { + "type": "array", + "items": { + "type": "string" + } + }, + "headline": { + "type": "string" + }, + "headlineScope": { + "type": "string" + }, + "id": { + "type": "string" + }, + "language": { + "type": "string" + }, + "lastLogin": { + "type": "integer" + }, + "locale": { + "type": "string" + }, + "notify_email": { + "type": "string" + }, + "organisation": { + "type": "string" + }, + "organisationScope": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "phoneScope": { + "type": "string" + }, + "profile_enabled": { + "type": "string" + }, + "profile_enabledScope": { + "type": "string" + }, + "quota": { + "required": [ + "quota", + "used" + ], + "type": "object", + "properties": { + "free": { + "type": "integer" + }, + "quota": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "boolean" + } + ] + }, + "relative": { + "type": "number", + "format": "float" + }, + "total": { + "type": "integer" + }, + "used": { + "type": "integer" + } + } + }, + "role": { + "type": "string" + }, + "roleScope": { + "type": "string" + }, + "storageLocation": { + "type": "string" + }, + "subadmin": { + "type": "array", + "items": { + "type": "string" + } + }, + "twitter": { + "type": "string" + }, + "twitterScope": { + "type": "string" + }, + "website": { + "type": "string" + }, + "websiteScope": { + "type": "string" + } + } + } + }, + "securitySchemes": { + "basic_auth": { + "type": "http", + "scheme": "basic" + } + } + }, + "security": [ + { + "basic_auth": [] + } + ], + "tags": [ + { + "name": "provisioning_api" + } + ] +} \ No newline at end of file