aboutsummaryrefslogtreecommitdiffstats
path: root/core/Controller/ProfileApiController.php
diff options
context:
space:
mode:
Diffstat (limited to 'core/Controller/ProfileApiController.php')
-rw-r--r--core/Controller/ProfileApiController.php147
1 files changed, 97 insertions, 50 deletions
diff --git a/core/Controller/ProfileApiController.php b/core/Controller/ProfileApiController.php
index d9e20701eaa..02979cb1649 100644
--- a/core/Controller/ProfileApiController.php
+++ b/core/Controller/ProfileApiController.php
@@ -3,83 +3,79 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christopher Ng <chrng8@gmail.com>
- *
- * @author Christopher Ng <chrng8@gmail.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/>.
- *
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Core\Controller;
use OC\Core\Db\ProfileConfigMapper;
+use OC\Core\ResponseDefinitions;
+use OC\Profile\ProfileManager;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\ApiRoute;
+use OCP\AppFramework\Http\Attribute\BruteForceProtection;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
+use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired;
+use OCP\AppFramework\Http\Attribute\UserRateLimit;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSBadRequestException;
use OCP\AppFramework\OCS\OCSForbiddenException;
use OCP\AppFramework\OCS\OCSNotFoundException;
use OCP\AppFramework\OCSController;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\IConfig;
use OCP\IRequest;
+use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
-use OC\Profile\ProfileManager;
+use OCP\Share\IManager;
+/**
+ * @psalm-import-type CoreProfileData from ResponseDefinitions
+ */
class ProfileApiController extends OCSController {
-
- /** @var ProfileConfigMapper */
- private $configMapper;
-
- /** @var ProfileManager */
- private $profileManager;
-
- /** @var IUserManager */
- private $userManager;
-
- /** @var IUserSession */
- private $userSession;
-
public function __construct(
IRequest $request,
- ProfileConfigMapper $configMapper,
- ProfileManager $profileManager,
- IUserManager $userManager,
- IUserSession $userSession
+ private IConfig $config,
+ private ITimeFactory $timeFactory,
+ private ProfileConfigMapper $configMapper,
+ private ProfileManager $profileManager,
+ private IUserManager $userManager,
+ private IUserSession $userSession,
+ private IManager $shareManager,
) {
parent::__construct('core', $request);
- $this->configMapper = $configMapper;
- $this->profileManager = $profileManager;
- $this->userManager = $userManager;
- $this->userSession = $userSession;
}
/**
- * @NoAdminRequired
* @NoSubAdminRequired
- * @PasswordConfirmationRequired
+ *
+ * Update the visibility of a parameter
+ *
+ * @param string $targetUserId ID of the user
+ * @param string $paramId ID of the parameter
+ * @param string $visibility New visibility
+ * @return DataResponse<Http::STATUS_OK, list<empty>, array{}>
+ * @throws OCSBadRequestException Updating visibility is not possible
+ * @throws OCSForbiddenException Not allowed to edit other users visibility
+ * @throws OCSNotFoundException Account not found
+ *
+ * 200: Visibility updated successfully
*/
+ #[NoAdminRequired]
+ #[PasswordConfirmationRequired]
+ #[UserRateLimit(limit: 40, period: 600)]
+ #[ApiRoute(verb: 'PUT', url: '/{targetUserId}', root: '/profile')]
public function setVisibility(string $targetUserId, string $paramId, string $visibility): DataResponse {
$requestingUser = $this->userSession->getUser();
- $targetUser = $this->userManager->get($targetUserId);
-
- if (!$this->userManager->userExists($targetUserId)) {
- throw new OCSNotFoundException('User does not exist');
+ if ($requestingUser->getUID() !== $targetUserId) {
+ throw new OCSForbiddenException('People can only edit their own visibility settings');
}
- if ($requestingUser !== $targetUser) {
- throw new OCSForbiddenException('Users can only edit their own visibility settings');
+ $targetUser = $this->userManager->get($targetUserId);
+ if (!$targetUser instanceof IUser) {
+ throw new OCSNotFoundException('Account does not exist');
}
// Ensure that a profile config is created in the database
@@ -87,7 +83,7 @@ class ProfileApiController extends OCSController {
$config = $this->configMapper->get($targetUserId);
if (!in_array($paramId, array_keys($config->getVisibilityMap()), true)) {
- throw new OCSBadRequestException('User does not have a profile parameter with ID: ' . $paramId);
+ throw new OCSBadRequestException('Account does not have a profile parameter with ID: ' . $paramId);
}
$config->setVisibility($paramId, $visibility);
@@ -95,4 +91,55 @@ class ProfileApiController extends OCSController {
return new DataResponse();
}
+
+ /**
+ * Get profile fields for another user
+ *
+ * @param string $targetUserId ID of the user
+ * @return DataResponse<Http::STATUS_OK, CoreProfileData, array{}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_NOT_FOUND, null, array{}>
+ *
+ * 200: Profile data returned successfully
+ * 400: Profile is disabled
+ * 404: Account not found or disabled
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'GET', url: '/{targetUserId}', root: '/profile')]
+ #[BruteForceProtection(action: 'user')]
+ #[UserRateLimit(limit: 30, period: 120)]
+ public function getProfileFields(string $targetUserId): DataResponse {
+ $targetUser = $this->userManager->get($targetUserId);
+ if (!$targetUser instanceof IUser) {
+ $response = new DataResponse(null, Http::STATUS_NOT_FOUND);
+ $response->throttle();
+ return $response;
+ }
+ if (!$targetUser->isEnabled()) {
+ return new DataResponse(null, Http::STATUS_NOT_FOUND);
+ }
+
+ if (!$this->profileManager->isProfileEnabled($targetUser)) {
+ return new DataResponse(null, Http::STATUS_BAD_REQUEST);
+ }
+
+ $requestingUser = $this->userSession->getUser();
+ if ($targetUser !== $requestingUser) {
+ if (!$this->shareManager->currentUserCanEnumerateTargetUser($requestingUser, $targetUser)) {
+ return new DataResponse(null, Http::STATUS_NOT_FOUND);
+ }
+ }
+
+ $profileFields = $this->profileManager->getProfileFields($targetUser, $requestingUser);
+
+ // Extend the profile information with timezone of the user
+ $timezoneStringTarget = $this->config->getUserValue($targetUser->getUID(), 'core', 'timezone') ?: $this->config->getSystemValueString('default_timezone', 'UTC');
+ try {
+ $timezoneTarget = new \DateTimeZone($timezoneStringTarget);
+ } catch (\Throwable) {
+ $timezoneTarget = new \DateTimeZone('UTC');
+ }
+ $profileFields['timezone'] = $timezoneTarget->getName(); // E.g. Europe/Berlin
+ $profileFields['timezoneOffset'] = $timezoneTarget->getOffset($this->timeFactory->now()); // In seconds E.g. 7200
+
+ return new DataResponse($profileFields);
+ }
}