diff options
Diffstat (limited to 'apps/provisioning_api')
12 files changed, 530 insertions, 344 deletions
diff --git a/apps/provisioning_api/composer/composer/autoload_classmap.php b/apps/provisioning_api/composer/composer/autoload_classmap.php index 12c2daf7a14..d702db318db 100644 --- a/apps/provisioning_api/composer/composer/autoload_classmap.php +++ b/apps/provisioning_api/composer/composer/autoload_classmap.php @@ -20,4 +20,5 @@ return array( 'OCA\\Provisioning_API\\Listener\\UserDeletedListener' => $baseDir . '/../lib/Listener/UserDeletedListener.php', 'OCA\\Provisioning_API\\Middleware\\Exceptions\\NotSubAdminException' => $baseDir . '/../lib/Middleware/Exceptions/NotSubAdminException.php', 'OCA\\Provisioning_API\\Middleware\\ProvisioningApiMiddleware' => $baseDir . '/../lib/Middleware/ProvisioningApiMiddleware.php', + 'OCA\\Provisioning_API\\ResponseDefinitions' => $baseDir . '/../lib/ResponseDefinitions.php', ); diff --git a/apps/provisioning_api/composer/composer/autoload_static.php b/apps/provisioning_api/composer/composer/autoload_static.php index 5aadb1574b3..4c987e24fc9 100644 --- a/apps/provisioning_api/composer/composer/autoload_static.php +++ b/apps/provisioning_api/composer/composer/autoload_static.php @@ -35,6 +35,7 @@ class ComposerStaticInitProvisioning_API 'OCA\\Provisioning_API\\Listener\\UserDeletedListener' => __DIR__ . '/..' . '/../lib/Listener/UserDeletedListener.php', 'OCA\\Provisioning_API\\Middleware\\Exceptions\\NotSubAdminException' => __DIR__ . '/..' . '/../lib/Middleware/Exceptions/NotSubAdminException.php', 'OCA\\Provisioning_API\\Middleware\\ProvisioningApiMiddleware' => __DIR__ . '/..' . '/../lib/Middleware/ProvisioningApiMiddleware.php', + 'OCA\\Provisioning_API\\ResponseDefinitions' => __DIR__ . '/..' . '/../lib/ResponseDefinitions.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/apps/provisioning_api/lib/Capabilities.php b/apps/provisioning_api/lib/Capabilities.php index 614c20e66a8..3504868fcf3 100644 --- a/apps/provisioning_api/lib/Capabilities.php +++ b/apps/provisioning_api/lib/Capabilities.php @@ -3,6 +3,7 @@ * @copyright Copyright (c) 2021 Vincent Petry <vincent@nextcloud.com> * * @author Vincent Petry <vincent@nextcloud.com> + * @author Kate Döen <kate.doeen@nextcloud.com> * * @license GNU AGPL version 3 or any later version * @@ -37,6 +38,15 @@ class Capabilities implements ICapability { /** * Function an app uses to return the capabilities + * + * @return array{ + * provisioning_api: array{ + * version: string, + * AccountPropertyScopesVersion: int, + * AccountPropertyScopesFederatedEnabled: bool, + * AccountPropertyScopesPublishedEnabled: bool, + * }, + * } */ public function getCapabilities() { $federatedScopeEnabled = $this->appManager->isEnabledForUser('federation'); diff --git a/apps/provisioning_api/lib/Controller/AUserData.php b/apps/provisioning_api/lib/Controller/AUserData.php index 128fda588e2..7ce1484cf71 100644 --- a/apps/provisioning_api/lib/Controller/AUserData.php +++ b/apps/provisioning_api/lib/Controller/AUserData.php @@ -36,6 +36,7 @@ use OC\Group\Manager; use OC\User\Backend; use OC\User\NoUserException; use OC_Helper; +use OCA\Provisioning_API\ResponseDefinitions; use OCP\Accounts\IAccountManager; use OCP\Accounts\PropertyDoesNotExistException; use OCP\AppFramework\Http; @@ -52,6 +53,10 @@ use OCP\L10N\IFactory; use OCP\User\Backend\ISetDisplayNameBackend; use OCP\User\Backend\ISetPasswordBackend; +/** + * @psalm-import-type ProvisioningApiUserDetails from ResponseDefinitions + * @psalm-import-type ProvisioningApiUserDetailsQuota from ResponseDefinitions + */ abstract class AUserData extends OCSController { public const SCOPE_SUFFIX = 'Scope'; @@ -99,12 +104,12 @@ abstract class AUserData extends OCSController { * * @param string $userId * @param bool $includeScopes - * @return array + * @return ProvisioningApiUserDetails|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'); @@ -123,7 +128,7 @@ abstract class AUserData extends OCSController { } else { // Check they are looking up themselves if ($currentLoggedInUser->getUID() !== $targetUserObject->getUID()) { - return $data; + return null; } } @@ -225,7 +230,7 @@ abstract class AUserData extends OCSController { * Get the groups a user is a subadmin of * * @param string $userId - * @return array + * @return string[] * @throws OCSException */ protected function getUserSubAdminGroupsData(string $userId): array { @@ -247,7 +252,7 @@ abstract class AUserData extends OCSController { /** * @param string $userId - * @return array + * @return ProvisioningApiUserDetailsQuota * @throws OCSException */ protected function fillStorageInfo(string $userId): array { diff --git a/apps/provisioning_api/lib/Controller/AppConfigController.php b/apps/provisioning_api/lib/Controller/AppConfigController.php index 929676be16e..b6e2bec0ccd 100644 --- a/apps/provisioning_api/lib/Controller/AppConfigController.php +++ b/apps/provisioning_api/lib/Controller/AppConfigController.php @@ -7,6 +7,7 @@ declare(strict_types=1); * * @author Joas Schilling <coding@schilljs.com> * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Kate Döen <kate.doeen@nextcloud.com> * * @license GNU AGPL version 3 or any later version * @@ -84,7 +85,9 @@ class AppConfigController extends OCSController { } /** - * @return DataResponse + * Get a list of apps + * + * @return DataResponse<Http::STATUS_OK, array{data: string[]}, array{}> */ public function getApps(): DataResponse { return new DataResponse([ @@ -93,8 +96,13 @@ class AppConfigController extends OCSController { } /** - * @param string $app - * @return DataResponse + * Get the config keys of an app + * + * @param string $app ID of the app + * @return DataResponse<Http::STATUS_OK, array{data: string[]}, array{}>|DataResponse<Http::STATUS_FORBIDDEN, array{data: array{message: string}}, array{}> + * + * 200: Keys returned + * 403: App is not allowed */ public function getKeys(string $app): DataResponse { try { @@ -108,10 +116,15 @@ class AppConfigController extends OCSController { } /** - * @param string $app - * @param string $key - * @param string $defaultValue - * @return DataResponse + * Get a the config value of an app + * + * @param string $app ID of the app + * @param string $key Key + * @param string $defaultValue Default returned value if the value is empty + * @return DataResponse<Http::STATUS_OK, array{data: string}, array{}>|DataResponse<Http::STATUS_FORBIDDEN, array{data: array{message: string}}, array{}> + * + * 200: Value returned + * 403: App is not allowed */ public function getValue(string $app, string $key, string $defaultValue = ''): DataResponse { try { @@ -128,10 +141,16 @@ class AppConfigController extends OCSController { * @PasswordConfirmationRequired * @NoSubAdminRequired * @NoAdminRequired - * @param string $app - * @param string $key - * @param string $value - * @return DataResponse + * + * Update the config value of an app + * + * @param string $app ID of the app + * @param string $key Key to update + * @param string $value New value for the key + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}>|DataResponse<Http::STATUS_FORBIDDEN, array{data: array{message: string}}, array{}> + * + * 200: Value updated successfully + * 403: App or key is not allowed */ public function setValue(string $app, string $key, string $value): DataResponse { $user = $this->userSession->getUser(); @@ -156,9 +175,15 @@ class AppConfigController extends OCSController { /** * @PasswordConfirmationRequired - * @param string $app - * @param string $key - * @return DataResponse + * + * Delete a config key of an app + * + * @param string $app ID of the app + * @param string $key Key to delete + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}>|DataResponse<Http::STATUS_FORBIDDEN, array{data: array{message: string}}, array{}> + * + * 200: Key deleted successfully + * 403: App or key is not allowed */ public function deleteKey(string $app, string $key): DataResponse { try { diff --git a/apps/provisioning_api/lib/Controller/AppsController.php b/apps/provisioning_api/lib/Controller/AppsController.php index fa0f2597e7f..7f84bdeb9db 100644 --- a/apps/provisioning_api/lib/Controller/AppsController.php +++ b/apps/provisioning_api/lib/Controller/AppsController.php @@ -10,6 +10,7 @@ declare(strict_types=1); * @author Lukas Reschke <lukas@statuscode.ch> * @author Roeland Jago Douma <roeland@famdouma.nl> * @author Tom Needham <tom@owncloud.com> + * @author Kate Döen <kate.doeen@nextcloud.com> * * @license AGPL-3.0 * @@ -29,13 +30,18 @@ declare(strict_types=1); 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; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSException; use OCP\AppFramework\OCSController; use OCP\IRequest; +/** + * @psalm-import-type ProvisioningApiAppInfo from ResponseDefinitions + */ class AppsController extends OCSController { /** @var IAppManager */ private $appManager; @@ -51,16 +57,19 @@ class AppsController extends OCSController { } /** - * @param string|null $filter - * @return DataResponse + * Get a list of installed apps + * + * @param ?string $filter Filter for enabled or disabled apps + * @return DataResponse<Http::STATUS_OK, array{apps: string[]}, array{}> * @throws OCSException */ - public function getApps(string $filter = null): DataResponse { + public function getApps(?string $filter = null): DataResponse { $apps = (new OC_App())->listAllApps(); $list = []; foreach ($apps as $app) { $list[] = $app['id']; } + /** @var string[] $list */ if ($filter) { switch ($filter) { case 'enabled': @@ -80,8 +89,10 @@ class AppsController extends OCSController { } /** - * @param string $app - * @return DataResponse + * Get the app info for an app + * + * @param string $app ID of the app + * @return DataResponse<Http::STATUS_OK, ProvisioningApiAppInfo, array{}> * @throws OCSException */ public function getAppInfo(string $app): DataResponse { @@ -95,8 +106,11 @@ class AppsController extends OCSController { /** * @PasswordConfirmationRequired - * @param string $app - * @return DataResponse + * + * Enable an app + * + * @param string $app ID of the app + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException */ public function enable(string $app): DataResponse { @@ -110,8 +124,11 @@ class AppsController extends OCSController { /** * @PasswordConfirmationRequired - * @param string $app - * @return DataResponse + * + * Disable an app + * + * @param string $app ID of the app + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> */ public function disable(string $app): DataResponse { $this->appManager->disableApp($app); diff --git a/apps/provisioning_api/lib/Controller/GroupsController.php b/apps/provisioning_api/lib/Controller/GroupsController.php index 46de5395a65..5404f47efc2 100644 --- a/apps/provisioning_api/lib/Controller/GroupsController.php +++ b/apps/provisioning_api/lib/Controller/GroupsController.php @@ -14,6 +14,7 @@ declare(strict_types=1); * @author Robin Appelman <robin@icewind.nl> * @author Roeland Jago Douma <roeland@famdouma.nl> * @author Tom Needham <tom@owncloud.com> + * @author Kate Döen <kate.doeen@nextcloud.com> * * @license AGPL-3.0 * @@ -32,7 +33,9 @@ declare(strict_types=1); */ namespace OCA\Provisioning_API\Controller; +use OCA\Provisioning_API\ResponseDefinitions; use OCP\Accounts\IAccountManager; +use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSException; use OCP\AppFramework\OCS\OCSForbiddenException; @@ -48,6 +51,10 @@ use OCP\IUserSession; use OCP\L10N\IFactory; use Psr\Log\LoggerInterface; +/** + * @psalm-import-type ProvisioningApiGroupDetails from ResponseDefinitions + * @psalm-import-type ProvisioningApiUserDetails from ResponseDefinitions + */ class GroupsController extends AUserData { /** @var LoggerInterface */ @@ -76,16 +83,16 @@ class GroupsController extends AUserData { } /** - * returns a list of groups - * * @NoAdminRequired * - * @param string $search - * @param int $limit - * @param int $offset - * @return DataResponse + * Get a list of groups + * + * @param string $search Text to search for + * @param ?int $limit Limit the amount of groups returned + * @param int $offset Offset for searching for groups + * @return DataResponse<Http::STATUS_OK, array{groups: string[]}, array{}> */ - public function getGroups(string $search = '', int $limit = null, int $offset = 0): DataResponse { + public function getGroups(string $search = '', ?int $limit = null, int $offset = 0): DataResponse { $groups = $this->groupManager->search($search, $limit, $offset); $groups = array_map(function ($group) { /** @var IGroup $group */ @@ -96,15 +103,15 @@ class GroupsController extends AUserData { } /** - * Returns a list of groups details with ids and displaynames - * * @NoAdminRequired * @AuthorizedAdminSetting(settings=OCA\Settings\Settings\Admin\Sharing) * - * @param string $search - * @param int $limit - * @param int $offset - * @return DataResponse + * Get a list of groups details + * + * @param string $search Text to search for + * @param ?int $limit Limit the amount of groups returned + * @param int $offset Offset for searching for groups + * @return DataResponse<Http::STATUS_OK, array{groups: ProvisioningApiGroupDetails[]}, array{}> */ public function getGroupsDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse { $groups = $this->groupManager->search($search, $limit, $offset); @@ -126,8 +133,10 @@ class GroupsController extends AUserData { /** * @NoAdminRequired * - * @param string $groupId - * @return DataResponse + * Get a list of users in the specified group + * + * @param string $groupId ID of the group + * @return DataResponse<Http::STATUS_OK, array{users: string[]}, array{}> * @throws OCSException * * @deprecated 14 Use getGroupUsers @@ -137,13 +146,17 @@ class GroupsController extends AUserData { } /** - * returns an array of users in the specified group - * * @NoAdminRequired * - * @param string $groupId - * @return DataResponse + * Get a list of users in the specified group + * + * @param string $groupId ID of the group + * @return DataResponse<Http::STATUS_OK, array{users: string[]}, array{}> * @throws OCSException + * @throws OCSNotFoundException Group not found + * @throws OCSForbiddenException Missing permissions to get users in the group + * + * 200: User IDs returned */ public function getGroupUsers(string $groupId): DataResponse { $groupId = urldecode($groupId); @@ -167,6 +180,7 @@ class GroupsController extends AUserData { /** @var IUser $user */ return $user->getUID(); }, $users); + /** @var string[] $users */ $users = array_values($users); return new DataResponse(['users' => $users]); } @@ -175,15 +189,16 @@ class GroupsController extends AUserData { } /** - * returns an array of users details in the specified group - * * @NoAdminRequired * - * @param string $groupId - * @param string $search - * @param int $limit - * @param int $offset - * @return DataResponse + * Get a list of users details in the specified group + * + * @param string $groupId ID of the group + * @param string $search Text to search for + * @param int|null $limit Limit the amount of groups returned + * @param int $offset Offset for searching for groups + * + * @return DataResponse<Http::STATUS_OK, array{users: array<string, ProvisioningApiUserDetails|array{id: string}>}, array{}> * @throws OCSException */ public function getGroupUsersDetails(string $groupId, string $search = '', int $limit = null, int $offset = 0): DataResponse { @@ -210,7 +225,7 @@ class GroupsController extends AUserData { $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 @@ -228,13 +243,13 @@ class GroupsController extends AUserData { } /** - * creates a new group - * * @PasswordConfirmationRequired * - * @param string $groupid - * @param string $displayname - * @return DataResponse + * Create a new group + * + * @param string $groupid ID of the group + * @param string $displayname Display name of the group + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException */ public function addGroup(string $groupid, string $displayname = ''): DataResponse { @@ -260,10 +275,12 @@ class GroupsController extends AUserData { /** * @PasswordConfirmationRequired * - * @param string $groupId - * @param string $key - * @param string $value - * @return DataResponse + * Update a group + * + * @param string $groupId ID of the group + * @param string $key Key to update, only 'displayname' + * @param string $value New value for the key + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException */ public function updateGroup(string $groupId, string $key, string $value): DataResponse { @@ -287,8 +304,10 @@ class GroupsController extends AUserData { /** * @PasswordConfirmationRequired * - * @param string $groupId - * @return DataResponse + * Delete a group + * + * @param string $groupId ID of the group + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException */ public function deleteGroup(string $groupId): DataResponse { @@ -306,8 +325,10 @@ class GroupsController extends AUserData { } /** - * @param string $groupId - * @return DataResponse + * Get the list of user IDs that are a subadmin of the group + * + * @param string $groupId ID of the group + * @return DataResponse<Http::STATUS_OK, string[], array{}> * @throws OCSException */ public function getSubAdminsOfGroup(string $groupId): DataResponse { @@ -320,6 +341,7 @@ class GroupsController extends AUserData { /** @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(); diff --git a/apps/provisioning_api/lib/Controller/PreferencesController.php b/apps/provisioning_api/lib/Controller/PreferencesController.php index 2dba8b86eb6..cc7a9efd764 100644 --- a/apps/provisioning_api/lib/Controller/PreferencesController.php +++ b/apps/provisioning_api/lib/Controller/PreferencesController.php @@ -6,6 +6,7 @@ declare(strict_types=1); * @copyright Copyright (c) 2022 Joas Schilling <coding@schilljs.com> * * @author Joas Schilling <coding@schilljs.com> + * @author Kate Döen <kate.doeen@nextcloud.com> * * @license GNU AGPL version 3 or any later version * @@ -58,6 +59,16 @@ class PreferencesController extends OCSController { /** * @NoAdminRequired * @NoSubAdminRequired + * + * Update multiple preference values of an app + * + * @param string $appId ID of the app + * @param array<string, string> $configs Key-value pairs of the preferences + * + * @return DataResponse<Http::STATUS_OK|Http::STATUS_BAD_REQUEST, array<empty>, array{}> + * + * 200: Preferences updated successfully + * 400: Preference invalid */ public function setMultiplePreferences(string $appId, array $configs): DataResponse { $userId = $this->userSession->getUser()->getUID(); @@ -93,6 +104,16 @@ class PreferencesController extends OCSController { /** * @NoAdminRequired * @NoSubAdminRequired + * + * Update a preference value of an app + * + * @param string $appId ID of the app + * @param string $configKey Key of the preference + * @param string $configValue New value + * @return DataResponse<Http::STATUS_OK|Http::STATUS_BAD_REQUEST, array<empty>, array{}> + * + * 200: Preference updated successfully + * 400: Preference invalid */ public function setPreference(string $appId, string $configKey, string $configValue): DataResponse { $userId = $this->userSession->getUser()->getUID(); @@ -124,6 +145,15 @@ class PreferencesController extends OCSController { /** * @NoAdminRequired * @NoSubAdminRequired + * + * Delete multiple preferences for an app + * + * @param string $appId ID of the app + * @param string[] $configKeys Keys to delete + * + * @return DataResponse<Http::STATUS_OK|Http::STATUS_BAD_REQUEST, array<empty>, array{}> + * 200: Preferences deleted successfully + * 400: Preference invalid */ public function deleteMultiplePreference(string $appId, array $configKeys): DataResponse { $userId = $this->userSession->getUser()->getUID(); @@ -157,6 +187,15 @@ class PreferencesController extends OCSController { /** * @NoAdminRequired * @NoSubAdminRequired + * + * Delete a preference for an app + * + * @param string $appId ID of the app + * @param string $configKey Key to delete + * @return DataResponse<Http::STATUS_OK|Http::STATUS_BAD_REQUEST, array<empty>, array{}> + * + * 200: Preference deleted successfully + * 400: Preference invalid */ public function deletePreference(string $appId, string $configKey): DataResponse { $userId = $this->userSession->getUser()->getUID(); diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php index 6ce46087d80..07f651c74fa 100644 --- a/apps/provisioning_api/lib/Controller/UsersController.php +++ b/apps/provisioning_api/lib/Controller/UsersController.php @@ -51,6 +51,7 @@ use libphonenumber\PhoneNumberUtil; 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; @@ -76,6 +77,9 @@ use OCP\Security\ISecureRandom; use OCP\User\Backend\ISetDisplayNameBackend; use Psr\Log\LoggerInterface; +/** + * @psalm-import-type ProvisioningApiUserDetails from ResponseDefinitions + */ class UsersController extends AUserData { /** @var IURLGenerator */ protected $urlGenerator; @@ -135,12 +139,12 @@ class UsersController extends AUserData { /** * @NoAdminRequired * - * returns a list of users + * Get a list of users * - * @param string $search - * @param int $limit - * @param int $offset - * @return DataResponse + * @param string $search Text to search for + * @param int|null $limit Limit the amount of groups returned + * @param int $offset Offset for searching for groups + * @return DataResponse<Http::STATUS_OK, array{users: string[]}, array{}> */ public function getUsers(string $search = '', int $limit = null, int $offset = 0): DataResponse { $user = $this->userSession->getUser(); @@ -163,6 +167,7 @@ class UsersController extends AUserData { } } + /** @var string[] $users */ $users = array_keys($users); return new DataResponse([ @@ -173,7 +178,12 @@ class UsersController extends AUserData { /** * @NoAdminRequired * - * returns a list of users and their data + * Get a list of users and their details + * + * @param string $search Text to search for + * @param int|null $limit Limit the amount of groups returned + * @param int $offset Offset for searching for groups + * @return DataResponse<Http::STATUS_OK, array{users: array<string, ProvisioningApiUserDetails|array{id: string}>}, array{}> */ public function getUsersDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse { $currentUser = $this->userSession->getUser(); @@ -198,12 +208,13 @@ class UsersController extends AUserData { $users = array_merge(...$users); } + /** @var array<string, ProvisioningApiUserDetails|array{id: string}> $usersDetails */ $usersDetails = []; foreach ($users as $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 @@ -222,9 +233,14 @@ class UsersController extends AUserData { * @NoAdminRequired * @NoSubAdminRequired * - * @param string $location - * @param array $search - * @return DataResponse + * Search users by their phone numbers + * + * @param string $location Location of the phone number (for country code) + * @param array<string, string[]> $search Phone numbers to search for + * @return DataResponse<Http::STATUS_OK, array<string, string>, array{}>|DataResponse<Http::STATUS_BAD_REQUEST, array<empty>, array{}> + * + * 200: Users returned + * 400: Invalid location */ public function searchByPhoneNumbers(string $location, array $search): DataResponse { $phoneUtil = PhoneNumberUtil::getInstance(); @@ -318,16 +334,22 @@ class UsersController extends AUserData { * @PasswordConfirmationRequired * @NoAdminRequired * - * @param string $userid - * @param string $password - * @param string $displayName - * @param string $email - * @param array $groups - * @param array $subadmin - * @param string $quota - * @param string $language - * @return DataResponse + * Create a new user + * + * @param string $userid ID of the user + * @param string $password Password of the user + * @param string $displayName Display name of the user + * @param string $email Email of the user + * @param string[] $groups Groups of the user + * @param string[] $subadmin Groups where the user is subadmin + * @param string $quota Quota of the user + * @param string $language Language of the user + * @param ?string $manager Manager of the user + * @return DataResponse<Http::STATUS_OK, array{id: string}, array{}> * @throws OCSException + * @throws OCSForbiddenException Missing permissions to make user subadmin + * + * 200: User added successfully */ public function addUser( string $userid, @@ -521,10 +543,10 @@ class UsersController extends AUserData { * @NoAdminRequired * @NoSubAdminRequired * - * gets user info + * Get the details of a user * - * @param string $userId - * @return DataResponse + * @param string $userId ID of the user + * @return DataResponse<Http::STATUS_OK, ProvisioningApiUserDetails, array{}> * @throws OCSException */ public function getUser(string $userId): DataResponse { @@ -535,8 +557,8 @@ class UsersController extends AUserData { } $data = $this->getUserData($userId, $includeScopes); - // getUserData returns empty array if not enough permissions - if (empty($data)) { + // getUserData returns null if not enough permissions + if ($data === null) { throw new OCSException('', OCSController::RESPOND_NOT_FOUND); } return new DataResponse($data); @@ -546,14 +568,15 @@ class UsersController extends AUserData { * @NoAdminRequired * @NoSubAdminRequired * - * gets user info from the currently logged in user + * Get the details of the current user * - * @return DataResponse + * @return DataResponse<Http::STATUS_OK, ProvisioningApiUserDetails, array{}> * @throws OCSException */ public function getCurrentUser(): DataResponse { $user = $this->userSession->getUser(); if ($user) { + /** @var ProvisioningApiUserDetails $data */ $data = $this->getUserData($user->getUID(), true); return new DataResponse($data); } @@ -565,7 +588,9 @@ class UsersController extends AUserData { * @NoAdminRequired * @NoSubAdminRequired * - * @return DataResponse + * Get a list of fields that are editable for the current user + * + * @return DataResponse<Http::STATUS_OK, string[], array{}> * @throws OCSException */ public function getEditableFields(): DataResponse { @@ -581,8 +606,10 @@ class UsersController extends AUserData { * @NoAdminRequired * @NoSubAdminRequired * - * @param string $userId - * @return DataResponse + * Get a list of fields that are editable for a user + * + * @param string $userId ID of the user + * @return DataResponse<Http::STATUS_OK, string[], array{}> * @throws OCSException */ public function getEditableFieldsForUser(string $userId): DataResponse { @@ -642,6 +669,13 @@ class UsersController extends AUserData { * @PasswordConfirmationRequired * @UserRateThrottle(limit=5, period=60) * + * Update multiple values of the user's details + * + * @param string $userId ID of the user + * @param string $collectionName Collection to update + * @param string $key Key that will be updated + * @param string $value New value for the key + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException */ public function editUserMultiValue( @@ -735,12 +769,12 @@ class UsersController extends AUserData { * @PasswordConfirmationRequired * @UserRateThrottle(limit=50, period=600) * - * edit users + * Update a value of the user's details * - * @param string $userId - * @param string $key - * @param string $value - * @return DataResponse + * @param string $userId ID of the user + * @param string $key Key that will be updated + * @param string $value New value for the key + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException */ public function editUser(string $userId, string $key, string $value): DataResponse { @@ -1046,9 +1080,11 @@ class UsersController extends AUserData { * @PasswordConfirmationRequired * @NoAdminRequired * - * @param string $userId + * Wipe all devices of a user * - * @return DataResponse + * @param string $userId ID of the user + * + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * * @throws OCSException */ @@ -1081,8 +1117,10 @@ class UsersController extends AUserData { * @PasswordConfirmationRequired * @NoAdminRequired * - * @param string $userId - * @return DataResponse + * Delete a user + * + * @param string $userId ID of the user + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException */ public function deleteUser(string $userId): DataResponse { @@ -1116,10 +1154,11 @@ class UsersController extends AUserData { * @PasswordConfirmationRequired * @NoAdminRequired * - * @param string $userId - * @return DataResponse + * Disable a user + * + * @param string $userId ID of the user + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException - * @throws OCSForbiddenException */ public function disableUser(string $userId): DataResponse { return $this->setEnabled($userId, false); @@ -1129,10 +1168,11 @@ class UsersController extends AUserData { * @PasswordConfirmationRequired * @NoAdminRequired * - * @param string $userId - * @return DataResponse + * Enable a user + * + * @param string $userId ID of the user + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException - * @throws OCSForbiddenException */ public function enableUser(string $userId): DataResponse { return $this->setEnabled($userId, true); @@ -1141,7 +1181,7 @@ class UsersController extends AUserData { /** * @param string $userId * @param bool $value - * @return DataResponse + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException */ private function setEnabled(string $userId, bool $value): DataResponse { @@ -1167,8 +1207,10 @@ class UsersController extends AUserData { * @NoAdminRequired * @NoSubAdminRequired * - * @param string $userId - * @return DataResponse + * Get a list of groups the user belongs to + * + * @param string $userId ID of the user + * @return DataResponse<Http::STATUS_OK, array{groups: string[]}, array{}> * @throws OCSException */ public function getUsersGroups(string $userId): DataResponse { @@ -1195,6 +1237,7 @@ class UsersController extends AUserData { foreach ($getSubAdminsGroups as $key => $group) { $getSubAdminsGroups[$key] = $group->getGID(); } + /** @var string[] $groups */ $groups = array_intersect( $getSubAdminsGroups, $this->groupManager->getUserGroupIds($targetUser) @@ -1211,9 +1254,11 @@ class UsersController extends AUserData { * @PasswordConfirmationRequired * @NoAdminRequired * - * @param string $userId - * @param string $groupid - * @return DataResponse + * Add a user to a group + * + * @param string $userId ID of the user + * @param string $groupid ID of the group + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException */ public function addToGroup(string $userId, string $groupid = ''): DataResponse { @@ -1246,9 +1291,11 @@ class UsersController extends AUserData { * @PasswordConfirmationRequired * @NoAdminRequired * - * @param string $userId - * @param string $groupid - * @return DataResponse + * Remove a user from a group + * + * @param string $userId ID of the user + * @param string $groupid ID of the group + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException */ public function removeFromGroup(string $userId, string $groupid): DataResponse { @@ -1305,13 +1352,13 @@ class UsersController extends AUserData { } /** - * Creates a subadmin - * * @PasswordConfirmationRequired * - * @param string $userId - * @param string $groupid - * @return DataResponse + * Make a user a subadmin of a group + * + * @param string $userId ID of the user + * @param string $groupid ID of the group + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException */ public function addSubAdmin(string $userId, string $groupid): DataResponse { @@ -1343,13 +1390,13 @@ class UsersController extends AUserData { } /** - * Removes a subadmin from a group - * * @PasswordConfirmationRequired * - * @param string $userId - * @param string $groupid - * @return DataResponse + * Remove a user from the subadmins of a group + * + * @param string $userId ID of the user + * @param string $groupid ID of the group + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException */ public function removeSubAdmin(string $userId, string $groupid): DataResponse { @@ -1378,8 +1425,8 @@ class UsersController extends AUserData { /** * Get the groups a user is a subadmin of * - * @param string $userId - * @return DataResponse + * @param string $userId ID if the user + * @return DataResponse<Http::STATUS_OK, string[], array{}> * @throws OCSException */ public function getUserSubAdminGroups(string $userId): DataResponse { @@ -1391,10 +1438,10 @@ class UsersController extends AUserData { * @NoAdminRequired * @PasswordConfirmationRequired * - * resend welcome message + * Resend the welcome message * - * @param string $userId - * @return DataResponse + * @param string $userId ID if the user + * @return DataResponse<Http::STATUS_OK, array<empty>, array{}> * @throws OCSException */ public function resendWelcomeMessage(string $userId): DataResponse { diff --git a/apps/provisioning_api/lib/Controller/VerificationController.php b/apps/provisioning_api/lib/Controller/VerificationController.php index f16f50385e7..0b04a0d7218 100644 --- a/apps/provisioning_api/lib/Controller/VerificationController.php +++ b/apps/provisioning_api/lib/Controller/VerificationController.php @@ -6,6 +6,7 @@ declare(strict_types=1); * @copyright Copyright (c) 2021 Arthur Schiwon <blizzz@arthur-schiwon.de> * * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * @author Kate Döen <kate.doeen@nextcloud.com> * * @license GNU AGPL version 3 or any later version * @@ -30,6 +31,7 @@ use InvalidArgumentException; use OC\Security\Crypto; use OCP\Accounts\IAccountManager; use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\Attribute\IgnoreOpenAPI; use OCP\AppFramework\Http\TemplateResponse; use OCP\IL10N; use OCP\IRequest; @@ -38,6 +40,7 @@ use OCP\IUserSession; use OCP\Security\VerificationToken\InvalidTokenException; use OCP\Security\VerificationToken\IVerificationToken; +#[IgnoreOpenAPI] class VerificationController extends Controller { /** @var IVerificationToken */ diff --git a/apps/provisioning_api/lib/ResponseDefinitions.php b/apps/provisioning_api/lib/ResponseDefinitions.php new file mode 100644 index 00000000000..4e562ec648f --- /dev/null +++ b/apps/provisioning_api/lib/ResponseDefinitions.php @@ -0,0 +1,136 @@ +<?php +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2023 Kate Döen <kate.doeen@nextcloud.com> + * + * @author Kate Döen <kate.doeen@nextcloud.com> + * + * @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 <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Provisioning_API; + +/** + * @psalm-type ProvisioningApiUserDetailsQuota = array{ + * free?: float, + * quota?: float|string, + * relative?: float, + * total?: float, + * used?: float, + * } + * + * @psalm-type ProvisioningApiUserDetails = array{ + * additional_mail: string[], + * additional_mailScope?: string[], + * address: string, + * addressScope?: string, + * avatarScope?: string, + * backend: string, + * backendCapabilities: array{ + * setDisplayName: bool, + * setPassword: bool + * }, + * biography: string, + * biographyScope?: string, + * display-name: string, + * displayname: string, + * displaynameScope?: string, + * email: ?string, + * emailScope?: string, + * enabled?: bool, + * fediverse: string, + * fediverseScope?: string, + * groups: string[], + * headline: string, + * headlineScope?: string, + * id: string, + * language: string, + * lastLogin: int, + * locale: string, + * manager: string, + * notify_email: ?string, + * organisation: string, + * organisationScope?: string, + * phone: string, + * phoneScope?: string, + * profile_enabled: string, + * profile_enabledScope?: string, + * quota: ProvisioningApiUserDetailsQuota, + * role: string, + * roleScope?: string, + * storageLocation?: string, + * subadmin: string[], + * twitter: string, + * twitterScope?: string, + * website: string, + * websiteScope?: string, + * } + * + * @psalm-type ProvisioningApiAppInfo = array{ + * active: bool|null, + * activity: ?mixed, + * author: ?mixed, + * background-jobs: ?mixed, + * bugs: ?mixed, + * category: ?mixed, + * collaboration: ?mixed, + * commands: ?mixed, + * default_enable: ?mixed, + * dependencies: ?mixed, + * description: string, + * discussion: ?mixed, + * documentation: ?mixed, + * groups: ?mixed, + * id: string, + * info: ?mixed, + * internal: bool|null, + * level: int|null, + * licence: ?mixed, + * name: string, + * namespace: ?mixed, + * navigations: ?mixed, + * preview: ?mixed, + * previewAsIcon: bool|null, + * public: ?mixed, + * remote: ?mixed, + * removable: bool|null, + * repair-steps: ?mixed, + * repository: ?mixed, + * sabre: ?mixed, + * screenshot: ?mixed, + * settings: ?mixed, + * summary: string, + * trash: ?mixed, + * two-factor-providers: ?mixed, + * types: ?mixed, + * version: string, + * versions: ?mixed, + * website: ?mixed, + * } + * + * @psalm-type ProvisioningApiGroupDetails = 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 index 82ee9b16e31..6eb16aa6ad1 100644 --- a/apps/provisioning_api/openapi.json +++ b/apps/provisioning_api/openapi.json @@ -325,45 +325,30 @@ "type": "object", "required": [ "additional_mail", - "additional_mailScope", "address", - "addressScope", - "avatarScope", "backend", "backendCapabilities", "biography", - "biographyScope", - "displayname", "display-name", - "displaynameScope", + "displayname", "email", - "emailScope", - "enabled", "fediverse", - "fediverseScope", "groups", "headline", - "headlineScope", "id", "language", "lastLogin", "locale", + "manager", "notify_email", "organisation", - "organisationScope", "phone", - "phoneScope", "profile_enabled", - "profile_enabledScope", "quota", "role", - "roleScope", - "storageLocation", "subadmin", "twitter", - "twitterScope", - "website", - "websiteScope" + "website" ], "properties": { "additional_mail": { @@ -374,7 +359,6 @@ }, "additional_mailScope": { "type": "array", - "nullable": true, "items": { "type": "string" } @@ -383,12 +367,10 @@ "type": "string" }, "addressScope": { - "type": "string", - "nullable": true + "type": "string" }, "avatarScope": { - "type": "string", - "nullable": true + "type": "string" }, "backend": { "type": "string" @@ -412,38 +394,32 @@ "type": "string" }, "biographyScope": { - "type": "string", - "nullable": true - }, - "displayname": { "type": "string" }, "display-name": { "type": "string" }, + "displayname": { + "type": "string" + }, "displaynameScope": { - "type": "string", - "nullable": true + "type": "string" }, "email": { "type": "string", "nullable": true }, "emailScope": { - "type": "string", - "nullable": true + "type": "string" }, "enabled": { - "type": "boolean", - "nullable": true + "type": "boolean" }, "fediverse": { - "type": "string", - "nullable": true + "type": "string" }, "fediverseScope": { - "type": "string", - "nullable": true + "type": "string" }, "groups": { "type": "array", @@ -455,8 +431,7 @@ "type": "string" }, "headlineScope": { - "type": "string", - "nullable": true + "type": "string" }, "id": { "type": "string" @@ -471,6 +446,9 @@ "locale": { "type": "string" }, + "manager": { + "type": "string" + }, "notify_email": { "type": "string", "nullable": true @@ -479,78 +457,31 @@ "type": "string" }, "organisationScope": { - "type": "string", - "nullable": true + "type": "string" }, "phone": { "type": "string" }, "phoneScope": { - "type": "string", - "nullable": true + "type": "string" }, "profile_enabled": { "type": "string" }, "profile_enabledScope": { - "type": "string", - "nullable": true + "type": "string" }, "quota": { - "type": "object", - "required": [ - "free", - "quota", - "relative", - "total", - "used" - ], - "properties": { - "free": { - "type": "integer", - "format": "int64", - "nullable": true - }, - "quota": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer", - "format": "int64" - }, - { - "type": "boolean" - } - ] - }, - "relative": { - "type": "number", - "format": "float", - "nullable": true - }, - "total": { - "type": "integer", - "format": "int64", - "nullable": true - }, - "used": { - "type": "integer", - "format": "int64" - } - } + "$ref": "#/components/schemas/UserDetailsQuota" }, "role": { "type": "string" }, "roleScope": { - "type": "string", - "nullable": true + "type": "string" }, "storageLocation": { - "type": "string", - "nullable": true + "type": "string" }, "subadmin": { "type": "array", @@ -562,15 +493,45 @@ "type": "string" }, "twitterScope": { - "type": "string", - "nullable": true + "type": "string" }, "website": { "type": "string" }, "websiteScope": { - "type": "string", - "nullable": true + "type": "string" + } + } + }, + "UserDetailsQuota": { + "type": "object", + "properties": { + "free": { + "type": "number", + "format": "float" + }, + "quota": { + "oneOf": [ + { + "type": "number", + "format": "float" + }, + { + "type": "string" + } + ] + }, + "relative": { + "type": "number", + "format": "float" + }, + "total": { + "type": "number", + "format": "float" + }, + "used": { + "type": "number", + "format": "float" } } } @@ -783,10 +744,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -852,10 +810,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -1030,10 +985,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -1600,10 +1552,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -1670,10 +1619,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -2152,10 +2098,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -2307,10 +2250,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -2375,10 +2315,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -2668,10 +2605,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -2738,10 +2672,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -2808,10 +2739,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -2878,10 +2806,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -3035,10 +2960,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -3112,10 +3034,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -3263,10 +3182,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -3341,10 +3257,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -3411,10 +3324,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -3576,7 +3486,7 @@ } }, "403": { - "description": "App not allowed", + "description": "App is not allowed", "content": { "application/json": { "schema": { @@ -3718,7 +3628,7 @@ } }, "403": { - "description": "App not allowed", + "description": "App is not allowed", "content": { "application/json": { "schema": { @@ -3838,10 +3748,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -3850,7 +3757,7 @@ } }, "403": { - "description": "App or key not allowed", + "description": "App or key is not allowed", "content": { "application/json": { "schema": { @@ -3962,10 +3869,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -3974,7 +3878,7 @@ } }, "403": { - "description": "App or key not allowed", + "description": "App or key is not allowed", "content": { "application/json": { "schema": { @@ -4096,10 +4000,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -4127,10 +4028,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -4204,10 +4102,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -4235,10 +4130,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -4314,10 +4206,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -4345,10 +4234,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -4422,10 +4308,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } @@ -4453,10 +4336,7 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": { - "type": "object", - "additionalProperties": true - } + "data": {} } } } |