diff options
Diffstat (limited to 'apps/settings/lib/Controller/AuthSettingsController.php')
-rw-r--r-- | apps/settings/lib/Controller/AuthSettingsController.php | 157 |
1 files changed, 70 insertions, 87 deletions
diff --git a/apps/settings/lib/Controller/AuthSettingsController.php b/apps/settings/lib/Controller/AuthSettingsController.php index 13815f95c50..8652a49fb1d 100644 --- a/apps/settings/lib/Controller/AuthSettingsController.php +++ b/apps/settings/lib/Controller/AuthSettingsController.php @@ -1,84 +1,43 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Kesselberg <mail@danielkesselberg.de> - * @author Fabrizio Steiner <fabrizio.steiner@gmail.com> - * @author Greta Doci <gretadoci@gmail.com> - * @author Joas Schilling <coding@schilljs.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Marcel Waldvogel <marcel.waldvogel@uni-konstanz.de> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Sergej Nikolaev <kinolaev@gmail.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OCA\Settings\Controller; use BadMethodCallException; -use OC\Authentication\Exceptions\ExpiredTokenException; -use OC\Authentication\Exceptions\InvalidTokenException; +use OC\Authentication\Exceptions\InvalidTokenException as OcInvalidTokenException; use OC\Authentication\Exceptions\PasswordlessTokenException; -use OC\Authentication\Exceptions\WipeTokenException; use OC\Authentication\Token\INamedToken; use OC\Authentication\Token\IProvider; -use OC\Authentication\Token\IToken; use OC\Authentication\Token\RemoteWipe; use OCA\Settings\Activity\Provider; use OCP\Activity\IManager; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired; use OCP\AppFramework\Http\JSONResponse; -use OCP\ILogger; +use OCP\Authentication\Exceptions\ExpiredTokenException; +use OCP\Authentication\Exceptions\InvalidTokenException; +use OCP\Authentication\Exceptions\WipeTokenException; +use OCP\Authentication\Token\IToken; use OCP\IRequest; use OCP\ISession; use OCP\IUserSession; use OCP\Security\ISecureRandom; use OCP\Session\Exceptions\SessionNotAvailableException; +use Psr\Log\LoggerInterface; class AuthSettingsController extends Controller { - /** @var IProvider */ private $tokenProvider; - /** @var ISession */ - private $session; - - /** IUserSession */ - private $userSession; - - /** @var string */ - private $uid; - - /** @var ISecureRandom */ - private $random; - - /** @var IManager */ - private $activityManager; - /** @var RemoteWipe */ private $remoteWipe; - /** @var ILogger */ - private $logger; - /** * @param string $appName * @param IRequest $request @@ -89,38 +48,38 @@ class AuthSettingsController extends Controller { * @param IUserSession $userSession * @param IManager $activityManager * @param RemoteWipe $remoteWipe - * @param ILogger $logger + * @param LoggerInterface $logger */ - public function __construct(string $appName, - IRequest $request, - IProvider $tokenProvider, - ISession $session, - ISecureRandom $random, - ?string $userId, - IUserSession $userSession, - IManager $activityManager, - RemoteWipe $remoteWipe, - ILogger $logger) { + public function __construct( + string $appName, + IRequest $request, + IProvider $tokenProvider, + private ISession $session, + private ISecureRandom $random, + private ?string $userId, + private IUserSession $userSession, + private IManager $activityManager, + RemoteWipe $remoteWipe, + private LoggerInterface $logger, + ) { parent::__construct($appName, $request); $this->tokenProvider = $tokenProvider; - $this->uid = $userId; - $this->userSession = $userSession; - $this->session = $session; - $this->random = $random; - $this->activityManager = $activityManager; $this->remoteWipe = $remoteWipe; - $this->logger = $logger; } /** - * @NoAdminRequired * @NoSubAdminRequired - * @PasswordConfirmationRequired * * @param string $name * @return JSONResponse */ + #[NoAdminRequired] + #[PasswordConfirmationRequired] public function create($name) { + if ($this->checkAppToken()) { + return $this->getServiceNotAvailableResponse(); + } + try { $sessionId = $this->session->getId(); } catch (SessionNotAvailableException $ex) { @@ -142,8 +101,12 @@ class AuthSettingsController extends Controller { return $this->getServiceNotAvailableResponse(); } + if (mb_strlen($name) > 128) { + $name = mb_substr($name, 0, 120) . '…'; + } + $token = $this->generateRandomDeviceToken(); - $deviceToken = $this->tokenProvider->generateToken($token, $this->uid, $loginName, $password, $name, IToken::PERMANENT_TOKEN); + $deviceToken = $this->tokenProvider->generateToken($token, $this->userId, $loginName, $password, $name, IToken::PERMANENT_TOKEN); $tokenData = $deviceToken->jsonSerialize(); $tokenData['canDelete'] = true; $tokenData['canRename'] = true; @@ -181,14 +144,22 @@ class AuthSettingsController extends Controller { return implode('-', $groups); } + private function checkAppToken(): bool { + return $this->session->exists('app_password'); + } + /** - * @NoAdminRequired * @NoSubAdminRequired * * @param int $id * @return array|JSONResponse */ + #[NoAdminRequired] public function destroy($id) { + if ($this->checkAppToken()) { + return new JSONResponse([], Http::STATUS_BAD_REQUEST); + } + try { $token = $this->findTokenByIdAndUser($id); } catch (WipeTokenException $e) { @@ -198,13 +169,12 @@ class AuthSettingsController extends Controller { return new JSONResponse([], Http::STATUS_NOT_FOUND); } - $this->tokenProvider->invalidateTokenById($this->uid, $token->getId()); + $this->tokenProvider->invalidateTokenById($this->userId, $token->getId()); $this->publishActivity(Provider::APP_TOKEN_DELETED, $token->getId(), ['name' => $token->getName()]); return []; } /** - * @NoAdminRequired * @NoSubAdminRequired * * @param int $id @@ -212,7 +182,12 @@ class AuthSettingsController extends Controller { * @param string $name * @return array|JSONResponse */ + #[NoAdminRequired] public function update($id, array $scope, string $name) { + if ($this->checkAppToken()) { + return new JSONResponse([], Http::STATUS_BAD_REQUEST); + } + try { $token = $this->findTokenByIdAndUser($id); } catch (InvalidTokenException $e) { @@ -222,8 +197,12 @@ class AuthSettingsController extends Controller { $currentName = $token->getName(); if ($scope !== $token->getScopeAsArray()) { - $token->setScope(['filesystem' => $scope['filesystem']]); - $this->publishActivity($scope['filesystem'] ? Provider::APP_TOKEN_FILESYSTEM_GRANTED : Provider::APP_TOKEN_FILESYSTEM_REVOKED, $token->getId(), ['name' => $currentName]); + $token->setScope([IToken::SCOPE_FILESYSTEM => $scope[IToken::SCOPE_FILESYSTEM]]); + $this->publishActivity($scope[IToken::SCOPE_FILESYSTEM] ? Provider::APP_TOKEN_FILESYSTEM_GRANTED : Provider::APP_TOKEN_FILESYSTEM_REVOKED, $token->getId(), ['name' => $currentName]); + } + + if (mb_strlen($name) > 128) { + $name = mb_substr($name, 0, 120) . '…'; } if ($token instanceof INamedToken && $name !== $currentName) { @@ -244,16 +223,15 @@ class AuthSettingsController extends Controller { $event = $this->activityManager->generateEvent(); $event->setApp('settings') ->setType('security') - ->setAffectedUser($this->uid) - ->setAuthor($this->uid) + ->setAffectedUser($this->userId) + ->setAuthor($this->userId) ->setSubject($subject, $parameters) ->setObject('app_token', $id, 'App Password'); try { $this->activityManager->publish($event); } catch (BadMethodCallException $e) { - $this->logger->warning('could not publish activity'); - $this->logger->logException($e); + $this->logger->warning('could not publish activity', ['exception' => $e]); } } @@ -270,23 +248,28 @@ class AuthSettingsController extends Controller { } catch (ExpiredTokenException $e) { $token = $e->getToken(); } - if ($token->getUID() !== $this->uid) { - throw new InvalidTokenException('This token does not belong to you!'); + if ($token->getUID() !== $this->userId) { + /** @psalm-suppress DeprecatedClass We have to throw the OC version so both OC and OCP catches catch it */ + throw new OcInvalidTokenException('This token does not belong to you!'); } return $token; } /** - * @NoAdminRequired * @NoSubAdminRequired - * @PasswordConfirmationRequired * * @param int $id * @return JSONResponse * @throws InvalidTokenException - * @throws \OC\Authentication\Exceptions\ExpiredTokenException + * @throws ExpiredTokenException */ + #[NoAdminRequired] + #[PasswordConfirmationRequired] public function wipe(int $id): JSONResponse { + if ($this->checkAppToken()) { + return new JSONResponse([], Http::STATUS_BAD_REQUEST); + } + try { $token = $this->findTokenByIdAndUser($id); } catch (InvalidTokenException $e) { |