aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_external/lib/Controller
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_external/lib/Controller')
-rw-r--r--apps/files_external/lib/Controller/AjaxController.php109
-rw-r--r--apps/files_external/lib/Controller/ApiController.php109
-rw-r--r--apps/files_external/lib/Controller/GlobalStoragesController.php88
-rw-r--r--apps/files_external/lib/Controller/StoragesController.php195
-rw-r--r--apps/files_external/lib/Controller/UserGlobalStoragesController.php112
-rw-r--r--apps/files_external/lib/Controller/UserStoragesController.php119
6 files changed, 327 insertions, 405 deletions
diff --git a/apps/files_external/lib/Controller/AjaxController.php b/apps/files_external/lib/Controller/AjaxController.php
index 9c2953851f5..5cee6422530 100644
--- a/apps/files_external/lib/Controller/AjaxController.php
+++ b/apps/files_external/lib/Controller/AjaxController.php
@@ -1,53 +1,25 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Martin Mattel <martin.mattel@diemattels.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Ross Nicoll <jrn@jrn.me.uk>
- *
- * @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: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OCA\Files_External\Controller;
use OCA\Files_External\Lib\Auth\Password\GlobalAuth;
+use OCA\Files_External\Lib\Auth\PublicKey\RSA;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
-use OCP\AppFramework\Http\Response;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
+use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired;
+use OCP\AppFramework\Http\JSONResponse;
use OCP\IGroupManager;
+use OCP\IL10N;
use OCP\IRequest;
-use OCP\AppFramework\Http\JSONResponse;
-use OCA\Files_External\Lib\Auth\PublicKey\RSA;
use OCP\IUserSession;
class AjaxController extends Controller {
- /** @var RSA */
- private $rsaMechanism;
- /** @var GlobalAuth */
- private $globalAuth;
- /** @var IUserSession */
- private $userSession;
- /** @var IGroupManager */
- private $groupManager;
-
/**
* @param string $appName
* @param IRequest $request
@@ -56,17 +28,16 @@ class AjaxController extends Controller {
* @param IUserSession $userSession
* @param IGroupManager $groupManager
*/
- public function __construct($appName,
- IRequest $request,
- RSA $rsaMechanism,
- GlobalAuth $globalAuth,
- IUserSession $userSession,
- IGroupManager $groupManager) {
+ public function __construct(
+ $appName,
+ IRequest $request,
+ private RSA $rsaMechanism,
+ private GlobalAuth $globalAuth,
+ private IUserSession $userSession,
+ private IGroupManager $groupManager,
+ private IL10N $l10n,
+ ) {
parent::__construct($appName, $request);
- $this->rsaMechanism = $rsaMechanism;
- $this->globalAuth = $globalAuth;
- $this->userSession = $userSession;
- $this->groupManager = $groupManager;
}
/**
@@ -84,41 +55,53 @@ class AjaxController extends Controller {
/**
* Generates an SSH public/private key pair.
*
- * @NoAdminRequired
* @param int $keyLength
*/
+ #[NoAdminRequired]
public function getSshKeys($keyLength = 1024) {
$key = $this->generateSshKeys($keyLength);
- return new JSONResponse(
- array('data' => array(
+ return new JSONResponse([
+ 'data' => [
'private_key' => $key['privatekey'],
'public_key' => $key['publickey']
- ),
- 'status' => 'success'
- ));
+ ],
+ 'status' => 'success',
+ ]);
}
/**
- * @NoAdminRequired
- *
* @param string $uid
* @param string $user
* @param string $password
- * @return bool
+ * @return JSONResponse
*/
- public function saveGlobalCredentials($uid, $user, $password) {
+ #[NoAdminRequired]
+ #[PasswordConfirmationRequired(strict: true)]
+ public function saveGlobalCredentials($uid, $user, $password): JSONResponse {
$currentUser = $this->userSession->getUser();
+ if ($currentUser === null) {
+ return new JSONResponse([
+ 'status' => 'error',
+ 'message' => $this->l10n->t('You are not logged in'),
+ ], Http::STATUS_UNAUTHORIZED);
+ }
// Non-admins can only edit their own credentials
- $allowedToEdit = (
- $this->groupManager->isAdmin($currentUser->getUID()) || $currentUser->getUID() === $uid
- ) ? true : false;
+ // Admin can edit global credentials
+ $allowedToEdit = $uid === ''
+ ? $this->groupManager->isAdmin($currentUser->getUID())
+ : $currentUser->getUID() === $uid;
if ($allowedToEdit) {
$this->globalAuth->saveAuth($uid, $user, $password);
- return true;
- } else {
- return false;
+ return new JSONResponse([
+ 'status' => 'success',
+ ]);
}
+
+ return new JSONResponse([
+ 'status' => 'success',
+ 'message' => $this->l10n->t('Permission denied'),
+ ], Http::STATUS_FORBIDDEN);
}
}
diff --git a/apps/files_external/lib/Controller/ApiController.php b/apps/files_external/lib/Controller/ApiController.php
index 8be623c5eee..49547357e6b 100644
--- a/apps/files_external/lib/Controller/ApiController.php
+++ b/apps/files_external/lib/Controller/ApiController.php
@@ -1,105 +1,98 @@
<?php
+
declare(strict_types=1);
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Jesús Macias <jmacias@solidgear.es>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <pvince81@owncloud.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: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OCA\Files_External\Controller;
+use OCA\Files_External\Lib\StorageConfig;
+use OCA\Files_External\ResponseDefinitions;
+use OCA\Files_External\Service\UserGlobalStoragesService;
+use OCA\Files_External\Service\UserStoragesService;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
+use OCP\Constants;
use OCP\IRequest;
-use OCP\IUserSession;
+/**
+ * @psalm-import-type Files_ExternalMount from ResponseDefinitions
+ */
class ApiController extends OCSController {
- /** @var IUserSession */
- private $userSession;
-
- public function __construct(string $appName,
- IRequest $request,
- IUserSession $userSession) {
+ public function __construct(
+ string $appName,
+ IRequest $request,
+ private UserGlobalStoragesService $userGlobalStoragesService,
+ private UserStoragesService $userStoragesService,
+ ) {
parent::__construct($appName, $request);
-
- $this->userSession = $userSession;
}
/**
* Formats the given mount config to a mount entry.
*
* @param string $mountPoint mount point name, relative to the data dir
- * @param array $mountConfig mount config to format
+ * @param StorageConfig $mountConfig mount config to format
*
- * @return array entry
+ * @return Files_ExternalMount
*/
- private function formatMount(string $mountPoint, array $mountConfig): array {
- // strip "/$user/files" from mount point
- $mountPoint = explode('/', trim($mountPoint, '/'), 3);
- $mountPoint = $mountPoint[2] ?? '';
-
+ private function formatMount(string $mountPoint, StorageConfig $mountConfig): array {
// split path from mount point
$path = \dirname($mountPoint);
- if ($path === '.') {
+ if ($path === '.' || $path === '/') {
$path = '';
}
- $isSystemMount = !$mountConfig['personal'];
+ $isSystemMount = $mountConfig->getType() === StorageConfig::MOUNT_TYPE_ADMIN;
- $permissions = \OCP\Constants::PERMISSION_READ;
+ $permissions = Constants::PERMISSION_READ;
// personal mounts can be deleted
if (!$isSystemMount) {
- $permissions |= \OCP\Constants::PERMISSION_DELETE;
+ $permissions |= Constants::PERMISSION_DELETE;
}
- $entry = array(
+ $entry = [
+ 'id' => $mountConfig->getId(),
+ 'type' => 'dir',
'name' => basename($mountPoint),
'path' => $path,
- 'type' => 'dir',
- 'backend' => $mountConfig['backend'],
- 'scope' => $isSystemMount ? 'system' : 'personal',
'permissions' => $permissions,
- 'id' => $mountConfig['id'],
- 'class' => $mountConfig['class']
- );
+ 'scope' => $isSystemMount ? 'system' : 'personal',
+ 'backend' => $mountConfig->getBackend()->getText(),
+ 'class' => $mountConfig->getBackend()->getIdentifier(),
+ 'config' => $mountConfig->jsonSerialize(true),
+ ];
return $entry;
}
/**
- * @NoAdminRequired
+ * Get the mount points visible for this user
*
- * Returns the mount points visible for this user.
+ * @return DataResponse<Http::STATUS_OK, list<Files_ExternalMount>, array{}>
*
- * @return DataResponse share information
+ * 200: User mounts returned
*/
+ #[NoAdminRequired]
public function getUserMounts(): DataResponse {
$entries = [];
- $user = $this->userSession->getUser()->getUID();
+ $mountPoints = [];
- $mounts = \OC_Mount_Config::getAbsoluteMountPoints($user);
- foreach($mounts as $mountPoint => $mount) {
+ foreach ($this->userGlobalStoragesService->getStorages() as $storage) {
+ $mountPoint = $storage->getMountPoint();
+ $mountPoints[$mountPoint] = $storage;
+ }
+
+ foreach ($this->userStoragesService->getStorages() as $storage) {
+ $mountPoint = $storage->getMountPoint();
+ $mountPoints[$mountPoint] = $storage;
+ }
+ foreach ($mountPoints as $mountPoint => $mount) {
$entries[] = $this->formatMount($mountPoint, $mount);
}
diff --git a/apps/files_external/lib/Controller/GlobalStoragesController.php b/apps/files_external/lib/Controller/GlobalStoragesController.php
index 69056225f8a..e7274c9cfb6 100644
--- a/apps/files_external/lib/Controller/GlobalStoragesController.php
+++ b/apps/files_external/lib/Controller/GlobalStoragesController.php
@@ -1,39 +1,23 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Juan Pablo Villafáñez <jvillafanez@solidgear.es>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Vincent Petry <pvince81@owncloud.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: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OCA\Files_External\Controller;
-
-use OCP\ILogger;
-use \OCP\IRequest;
-use \OCP\IL10N;
-use \OCP\AppFramework\Http\DataResponse;
-use \OCP\AppFramework\Http;
-use OCA\Files_External\Service\GlobalStoragesService;
use OCA\Files_External\NotFoundException;
+use OCA\Files_External\Service\GlobalStoragesService;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IL10N;
+use OCP\IRequest;
+use OCP\IUserSession;
+use Psr\Log\LoggerInterface;
/**
* Global storages controller
@@ -46,21 +30,30 @@ class GlobalStoragesController extends StoragesController {
* @param IRequest $request request object
* @param IL10N $l10n l10n service
* @param GlobalStoragesService $globalStoragesService storage service
- * @param ILogger $logger
+ * @param LoggerInterface $logger
+ * @param IUserSession $userSession
+ * @param IGroupManager $groupManager
+ * @param IConfig $config
*/
public function __construct(
$AppName,
IRequest $request,
IL10N $l10n,
GlobalStoragesService $globalStoragesService,
- ILogger $logger
+ LoggerInterface $logger,
+ IUserSession $userSession,
+ IGroupManager $groupManager,
+ IConfig $config,
) {
parent::__construct(
$AppName,
$request,
$l10n,
$globalStoragesService,
- $logger
+ $logger,
+ $userSession,
+ $groupManager,
+ $config
);
}
@@ -78,6 +71,7 @@ class GlobalStoragesController extends StoragesController {
*
* @return DataResponse
*/
+ #[PasswordConfirmationRequired(strict: true)]
public function create(
$mountPoint,
$backend,
@@ -86,8 +80,18 @@ class GlobalStoragesController extends StoragesController {
$mountOptions,
$applicableUsers,
$applicableGroups,
- $priority
+ $priority,
) {
+ $canCreateNewLocalStorage = $this->config->getSystemValue('files_external_allow_create_new_local', true);
+ if (!$canCreateNewLocalStorage && $backend === 'local') {
+ return new DataResponse(
+ [
+ 'message' => $this->l10n->t('Forbidden to manage local mounts')
+ ],
+ Http::STATUS_FORBIDDEN
+ );
+ }
+
$newStorage = $this->createStorage(
$mountPoint,
$backend,
@@ -112,7 +116,7 @@ class GlobalStoragesController extends StoragesController {
$this->updateStorageStatus($newStorage);
return new DataResponse(
- $newStorage,
+ $newStorage->jsonSerialize(true),
Http::STATUS_CREATED
);
}
@@ -123,16 +127,16 @@ class GlobalStoragesController extends StoragesController {
* @param int $id storage id
* @param string $mountPoint storage mount point
* @param string $backend backend identifier
- * @param string $authMechanism authentication mechansim identifier
+ * @param string $authMechanism authentication mechanism identifier
* @param array $backendOptions backend-specific options
* @param array $mountOptions mount-specific options
* @param array $applicableUsers users for which to mount the storage
* @param array $applicableGroups groups for which to mount the storage
* @param int $priority priority
- * @param bool $testOnly whether to storage should only test the connection or do more things
*
* @return DataResponse
*/
+ #[PasswordConfirmationRequired(strict: true)]
public function update(
$id,
$mountPoint,
@@ -143,7 +147,6 @@ class GlobalStoragesController extends StoragesController {
$applicableUsers,
$applicableGroups,
$priority,
- $testOnly = true
) {
$storage = $this->createStorage(
$mountPoint,
@@ -170,20 +173,17 @@ class GlobalStoragesController extends StoragesController {
} catch (NotFoundException $e) {
return new DataResponse(
[
- 'message' => (string)$this->l10n->t('Storage with ID "%d" not found', array($id))
+ 'message' => $this->l10n->t('Storage with ID "%d" not found', [$id])
],
Http::STATUS_NOT_FOUND
);
}
- $this->updateStorageStatus($storage, $testOnly);
+ $this->updateStorageStatus($storage);
return new DataResponse(
- $storage,
+ $storage->jsonSerialize(true),
Http::STATUS_OK
);
-
}
-
-
}
diff --git a/apps/files_external/lib/Controller/StoragesController.php b/apps/files_external/lib/Controller/StoragesController.php
index dd2bf69a0a6..df3a4528054 100644
--- a/apps/files_external/lib/Controller/StoragesController.php
+++ b/apps/files_external/lib/Controller/StoragesController.php
@@ -1,71 +1,35 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Jesús Macias <jmacias@solidgear.es>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Juan Pablo Villafáñez <jvillafanez@solidgear.es>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Vincent Petry <pvince81@owncloud.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: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OCA\Files_External\Controller;
-
-use OCP\ILogger;
-use \OCP\IRequest;
-use \OCP\IL10N;
-use \OCP\AppFramework\Http\DataResponse;
-use \OCP\AppFramework\Controller;
-use \OCP\AppFramework\Http;
-use OCA\Files_External\Service\StoragesService;
-use OCA\Files_External\NotFoundException;
+use OCA\Files_External\Lib\Auth\AuthMechanism;
+use OCA\Files_External\Lib\Backend\Backend;
+use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException;
use OCA\Files_External\Lib\StorageConfig;
-use \OCA\Files_External\Lib\Backend\Backend;
-use \OCA\Files_External\Lib\Auth\AuthMechanism;
-use \OCP\Files\StorageNotAvailableException;
-use \OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException;
+use OCA\Files_External\MountConfig;
+use OCA\Files_External\NotFoundException;
+use OCA\Files_External\Service\StoragesService;
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\Files\StorageNotAvailableException;
+use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IL10N;
+use OCP\IRequest;
+use OCP\IUserSession;
+use Psr\Log\LoggerInterface;
/**
* Base class for storages controllers
*/
abstract class StoragesController extends Controller {
-
- /**
- * L10N service
- *
- * @var IL10N
- */
- protected $l10n;
-
- /**
- * Storages service
- *
- * @var StoragesService
- */
- protected $service;
-
- /**
- * @var ILogger
- */
- protected $logger;
-
/**
* Creates a new storages controller.
*
@@ -73,19 +37,19 @@ abstract class StoragesController extends Controller {
* @param IRequest $request request object
* @param IL10N $l10n l10n service
* @param StoragesService $storagesService storage service
- * @param ILogger $logger
+ * @param LoggerInterface $logger
*/
public function __construct(
$AppName,
IRequest $request,
- IL10N $l10n,
- StoragesService $storagesService,
- ILogger $logger
+ protected IL10N $l10n,
+ protected StoragesService $service,
+ protected LoggerInterface $logger,
+ protected IUserSession $userSession,
+ protected IGroupManager $groupManager,
+ protected IConfig $config,
) {
parent::__construct($AppName, $request);
- $this->l10n = $l10n;
- $this->service = $storagesService;
- $this->logger = $logger;
}
/**
@@ -110,8 +74,18 @@ abstract class StoragesController extends Controller {
$mountOptions = null,
$applicableUsers = null,
$applicableGroups = null,
- $priority = null
+ $priority = null,
) {
+ $canCreateNewLocalStorage = $this->config->getSystemValue('files_external_allow_create_new_local', true);
+ if (!$canCreateNewLocalStorage && $backend === 'local') {
+ return new DataResponse(
+ [
+ 'message' => $this->l10n->t('Forbidden to manage local mounts')
+ ],
+ Http::STATUS_FORBIDDEN
+ );
+ }
+
try {
return $this->service->createStorage(
$mountPoint,
@@ -124,10 +98,10 @@ abstract class StoragesController extends Controller {
$priority
);
} catch (\InvalidArgumentException $e) {
- $this->logger->logException($e);
+ $this->logger->error($e->getMessage(), ['exception' => $e]);
return new DataResponse(
[
- 'message' => (string)$this->l10n->t('Invalid backend or authentication mechanism class')
+ 'message' => $this->l10n->t('Invalid backend or authentication mechanism class')
],
Http::STATUS_UNPROCESSABLE_ENTITY
);
@@ -145,9 +119,9 @@ abstract class StoragesController extends Controller {
$mountPoint = $storage->getMountPoint();
if ($mountPoint === '') {
return new DataResponse(
- array(
- 'message' => (string)$this->l10n->t('Invalid mount point')
- ),
+ [
+ 'message' => $this->l10n->t('Invalid mount point'),
+ ],
Http::STATUS_UNPROCESSABLE_ENTITY
);
}
@@ -155,9 +129,9 @@ abstract class StoragesController extends Controller {
if ($storage->getBackendOption('objectstore')) {
// objectstore must not be sent from client side
return new DataResponse(
- array(
- 'message' => (string)$this->l10n->t('Objectstore forbidden')
- ),
+ [
+ 'message' => $this->l10n->t('Objectstore forbidden'),
+ ],
Http::STATUS_UNPROCESSABLE_ENTITY
);
}
@@ -169,11 +143,11 @@ abstract class StoragesController extends Controller {
if ($backend->checkDependencies()) {
// invalid backend
return new DataResponse(
- array(
- 'message' => (string)$this->l10n->t('Invalid storage backend "%s"', [
- $backend->getIdentifier()
- ])
- ),
+ [
+ 'message' => $this->l10n->t('Invalid storage backend "%s"', [
+ $backend->getIdentifier(),
+ ]),
+ ],
Http::STATUS_UNPROCESSABLE_ENTITY
);
}
@@ -181,22 +155,22 @@ abstract class StoragesController extends Controller {
if (!$backend->isVisibleFor($this->service->getVisibilityType())) {
// not permitted to use backend
return new DataResponse(
- array(
- 'message' => (string)$this->l10n->t('Not permitted to use backend "%s"', [
- $backend->getIdentifier()
- ])
- ),
+ [
+ 'message' => $this->l10n->t('Not permitted to use backend "%s"', [
+ $backend->getIdentifier(),
+ ]),
+ ],
Http::STATUS_UNPROCESSABLE_ENTITY
);
}
if (!$authMechanism->isVisibleFor($this->service->getVisibilityType())) {
// not permitted to use auth mechanism
return new DataResponse(
- array(
- 'message' => (string)$this->l10n->t('Not permitted to use authentication mechanism "%s"', [
- $authMechanism->getIdentifier()
- ])
- ),
+ [
+ 'message' => $this->l10n->t('Not permitted to use authentication mechanism "%s"', [
+ $authMechanism->getIdentifier(),
+ ]),
+ ],
Http::STATUS_UNPROCESSABLE_ENTITY
);
}
@@ -204,9 +178,9 @@ abstract class StoragesController extends Controller {
if (!$backend->validateStorage($storage)) {
// unsatisfied parameters
return new DataResponse(
- array(
- 'message' => (string)$this->l10n->t('Unsatisfied backend parameters')
- ),
+ [
+ 'message' => $this->l10n->t('Unsatisfied backend parameters'),
+ ],
Http::STATUS_UNPROCESSABLE_ENTITY
);
}
@@ -214,7 +188,7 @@ abstract class StoragesController extends Controller {
// unsatisfied parameters
return new DataResponse(
[
- 'message' => (string)$this->l10n->t('Unsatisfied authentication mechanism parameters')
+ 'message' => $this->l10n->t('Unsatisfied authentication mechanism parameters'),
],
Http::STATUS_UNPROCESSABLE_ENTITY
);
@@ -239,9 +213,8 @@ abstract class StoragesController extends Controller {
* on whether the remote storage is available or not.
*
* @param StorageConfig $storage storage configuration
- * @param bool $testOnly whether to storage should only test the connection or do more things
*/
- protected function updateStorageStatus(StorageConfig &$storage, $testOnly = true) {
+ protected function updateStorageStatus(StorageConfig &$storage) {
try {
$this->manipulateStorageConfig($storage);
@@ -249,29 +222,27 @@ abstract class StoragesController extends Controller {
$backend = $storage->getBackend();
// update status (can be time-consuming)
$storage->setStatus(
- \OC_Mount_Config::getBackendStatus(
+ MountConfig::getBackendStatus(
$backend->getStorageClass(),
$storage->getBackendOptions(),
- false,
- $testOnly
)
);
} catch (InsufficientDataForMeaningfulAnswerException $e) {
- $status = $e->getCode() ? $e->getCode() : StorageNotAvailableException::STATUS_INDETERMINATE;
+ $status = $e->getCode() ?: StorageNotAvailableException::STATUS_INDETERMINATE;
$storage->setStatus(
- $status,
+ (int)$status,
$this->l10n->t('Insufficient data: %s', [$e->getMessage()])
);
} catch (StorageNotAvailableException $e) {
$storage->setStatus(
- $e->getCode(),
+ (int)$e->getCode(),
$this->l10n->t('%s', [$e->getMessage()])
);
} catch (\Exception $e) {
// FIXME: convert storage exceptions to StorageNotAvailableException
$storage->setStatus(
StorageNotAvailableException::STATUS_ERROR,
- get_class($e).': '.$e->getMessage()
+ get_class($e) . ': ' . $e->getMessage()
);
}
}
@@ -282,7 +253,7 @@ abstract class StoragesController extends Controller {
* @return DataResponse
*/
public function index() {
- $storages = $this->service->getStorages();
+ $storages = array_map(static fn ($storage) => $storage->jsonSerialize(true), $this->service->getStorages());
return new DataResponse(
$storages,
@@ -294,26 +265,29 @@ abstract class StoragesController extends Controller {
* Get an external storage entry.
*
* @param int $id storage id
- * @param bool $testOnly whether to storage should only test the connection or do more things
*
* @return DataResponse
*/
- public function show($id, $testOnly = true) {
+ public function show(int $id) {
try {
$storage = $this->service->getStorage($id);
- $this->updateStorageStatus($storage, $testOnly);
+ $this->updateStorageStatus($storage);
} catch (NotFoundException $e) {
return new DataResponse(
[
- 'message' => (string)$this->l10n->t('Storage with ID "%d" not found', array($id))
+ 'message' => $this->l10n->t('Storage with ID "%d" not found', [$id]),
],
Http::STATUS_NOT_FOUND
);
}
+ $data = $storage->jsonSerialize(true);
+ $isAdmin = $this->groupManager->isAdmin($this->userSession->getUser()->getUID());
+ $data['can_edit'] = $storage->getType() === StorageConfig::MOUNT_TYPE_PERSONAL || $isAdmin;
+
return new DataResponse(
- $storage,
+ $data,
Http::STATUS_OK
);
}
@@ -325,13 +299,14 @@ abstract class StoragesController extends Controller {
*
* @return DataResponse
*/
- public function destroy($id) {
+ #[PasswordConfirmationRequired(strict: true)]
+ public function destroy(int $id) {
try {
$this->service->removeStorage($id);
} catch (NotFoundException $e) {
return new DataResponse(
[
- 'message' => (string)$this->l10n->t('Storage with ID "%d" not found', array($id))
+ 'message' => $this->l10n->t('Storage with ID "%d" not found', [$id]),
],
Http::STATUS_NOT_FOUND
);
@@ -339,6 +314,4 @@ abstract class StoragesController extends Controller {
return new DataResponse([], Http::STATUS_NO_CONTENT);
}
-
}
-
diff --git a/apps/files_external/lib/Controller/UserGlobalStoragesController.php b/apps/files_external/lib/Controller/UserGlobalStoragesController.php
index 22c9c867855..88a9f936401 100644
--- a/apps/files_external/lib/Controller/UserGlobalStoragesController.php
+++ b/apps/files_external/lib/Controller/UserGlobalStoragesController.php
@@ -1,94 +1,82 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Juan Pablo Villafáñez <jvillafanez@solidgear.es>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- *
- * @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: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OCA\Files_External\Controller;
use OCA\Files_External\Lib\Auth\AuthMechanism;
use OCA\Files_External\Lib\Auth\IUserProvided;
+use OCA\Files_External\Lib\Auth\Password\UserGlobalAuth;
+use OCA\Files_External\Lib\Backend\Backend;
use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException;
-use OCP\ILogger;
-use \OCP\IRequest;
-use \OCP\IL10N;
-use \OCP\AppFramework\Http\DataResponse;
-use \OCP\AppFramework\Http;
-use OCA\Files_External\Service\UserGlobalStoragesService;
-use OCA\Files_External\NotFoundException;
use OCA\Files_External\Lib\StorageConfig;
-use \OCA\Files_External\Lib\Backend\Backend;
+use OCA\Files_External\NotFoundException;
+use OCA\Files_External\Service\UserGlobalStoragesService;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
+use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IL10N;
+use OCP\IRequest;
use OCP\IUserSession;
+use Psr\Log\LoggerInterface;
/**
* User global storages controller
*/
class UserGlobalStoragesController extends StoragesController {
/**
- * @var IUserSession
- */
- private $userSession;
-
- /**
* Creates a new user global storages controller.
*
* @param string $AppName application name
* @param IRequest $request request object
* @param IL10N $l10n l10n service
* @param UserGlobalStoragesService $userGlobalStoragesService storage service
+ * @param LoggerInterface $logger
* @param IUserSession $userSession
+ * @param IGroupManager $groupManager
*/
public function __construct(
$AppName,
IRequest $request,
IL10N $l10n,
UserGlobalStoragesService $userGlobalStoragesService,
+ LoggerInterface $logger,
IUserSession $userSession,
- ILogger $logger
+ IGroupManager $groupManager,
+ IConfig $config,
) {
parent::__construct(
$AppName,
$request,
$l10n,
$userGlobalStoragesService,
- $logger
+ $logger,
+ $userSession,
+ $groupManager,
+ $config
);
- $this->userSession = $userSession;
}
/**
* Get all storage entries
*
* @return DataResponse
- *
- * @NoAdminRequired
*/
+ #[NoAdminRequired]
public function index() {
- $storages = $this->service->getUniqueStorages();
-
- // remove configuration data, this must be kept private
- foreach ($storages as $storage) {
+ /** @var UserGlobalStoragesService */
+ $service = $this->service;
+ $storages = array_map(function ($storage) {
+ // remove configuration data, this must be kept private
$this->sanitizeStorage($storage);
- }
+ return $storage->jsonSerialize(true);
+ }, $service->getUniqueStorages());
return new DataResponse(
$storages,
@@ -109,20 +97,18 @@ class UserGlobalStoragesController extends StoragesController {
* Get an external storage entry.
*
* @param int $id storage id
- * @param bool $testOnly whether to storage should only test the connection or do more things
* @return DataResponse
- *
- * @NoAdminRequired
*/
- public function show($id, $testOnly = true) {
+ #[NoAdminRequired]
+ public function show($id) {
try {
$storage = $this->service->getStorage($id);
- $this->updateStorageStatus($storage, $testOnly);
+ $this->updateStorageStatus($storage);
} catch (NotFoundException $e) {
return new DataResponse(
[
- 'message' => (string)$this->l10n->t('Storage with ID "%d" not found', array($id))
+ 'message' => $this->l10n->t('Storage with ID "%d" not found', [$id])
],
Http::STATUS_NOT_FOUND
);
@@ -130,8 +116,12 @@ class UserGlobalStoragesController extends StoragesController {
$this->sanitizeStorage($storage);
+ $data = $storage->jsonSerialize(true);
+ $isAdmin = $this->groupManager->isAdmin($this->userSession->getUser()->getUID());
+ $data['can_edit'] = $storage->getType() === StorageConfig::MOUNT_TYPE_PERSONAL || $isAdmin;
+
return new DataResponse(
- $storage,
+ $data,
Http::STATUS_OK
);
}
@@ -142,27 +132,25 @@ class UserGlobalStoragesController extends StoragesController {
*
* @param int $id storage id
* @param array $backendOptions backend-specific options
- * @param bool $testOnly whether to storage should only test the connection or do more things
*
* @return DataResponse
- *
- * @NoAdminRequired
*/
+ #[NoAdminRequired]
+ #[PasswordConfirmationRequired(strict: true)]
public function update(
$id,
$backendOptions,
- $testOnly = true
) {
try {
$storage = $this->service->getStorage($id);
$authMechanism = $storage->getAuthMechanism();
- if ($authMechanism instanceof IUserProvided) {
+ if ($authMechanism instanceof IUserProvided || $authMechanism instanceof UserGlobalAuth) {
$authMechanism->saveBackendOptions($this->userSession->getUser(), $id, $backendOptions);
$authMechanism->manipulateStorageConfig($storage, $this->userSession->getUser());
} else {
return new DataResponse(
[
- 'message' => (string)$this->l10n->t('Storage with ID "%d" is not user editable', array($id))
+ 'message' => $this->l10n->t('Storage with ID "%d" is not editable by non-admins', [$id])
],
Http::STATUS_FORBIDDEN
);
@@ -170,20 +158,19 @@ class UserGlobalStoragesController extends StoragesController {
} catch (NotFoundException $e) {
return new DataResponse(
[
- 'message' => (string)$this->l10n->t('Storage with ID "%d" not found', array($id))
+ 'message' => $this->l10n->t('Storage with ID "%d" not found', [$id])
],
Http::STATUS_NOT_FOUND
);
}
- $this->updateStorageStatus($storage, $testOnly);
+ $this->updateStorageStatus($storage);
$this->sanitizeStorage($storage);
return new DataResponse(
- $storage,
+ $storage->jsonSerialize(true),
Http::STATUS_OK
);
-
}
/**
@@ -203,5 +190,4 @@ class UserGlobalStoragesController extends StoragesController {
}
}
}
-
}
diff --git a/apps/files_external/lib/Controller/UserStoragesController.php b/apps/files_external/lib/Controller/UserStoragesController.php
index 724bdd01463..7b564d57f7e 100644
--- a/apps/files_external/lib/Controller/UserStoragesController.php
+++ b/apps/files_external/lib/Controller/UserStoragesController.php
@@ -1,79 +1,63 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Juan Pablo Villafáñez <jvillafanez@solidgear.es>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @author Vincent Petry <pvince81@owncloud.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: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OCA\Files_External\Controller;
-
use OCA\Files_External\Lib\Auth\AuthMechanism;
-use OCP\ILogger;
-use \OCP\IUserSession;
-use \OCP\IRequest;
-use \OCP\IL10N;
-use \OCP\AppFramework\Http\DataResponse;
-use \OCP\AppFramework\Http;
-use OCA\Files_External\Service\UserStoragesService;
-use OCA\Files_External\NotFoundException;
+use OCA\Files_External\Lib\Backend\Backend;
use OCA\Files_External\Lib\StorageConfig;
-use \OCA\Files_External\Lib\Backend\Backend;
+use OCA\Files_External\NotFoundException;
+use OCA\Files_External\Service\UserStoragesService;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
+use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IL10N;
+use OCP\IRequest;
+use OCP\IUserSession;
+use Psr\Log\LoggerInterface;
/**
* User storages controller
*/
class UserStoragesController extends StoragesController {
/**
- * @var IUserSession
- */
- private $userSession;
-
- /**
* Creates a new user storages controller.
*
* @param string $AppName application name
* @param IRequest $request request object
* @param IL10N $l10n l10n service
* @param UserStoragesService $userStoragesService storage service
+ * @param LoggerInterface $logger
* @param IUserSession $userSession
- * @param ILogger $logger
+ * @param IGroupManager $groupManager
*/
public function __construct(
$AppName,
IRequest $request,
IL10N $l10n,
UserStoragesService $userStoragesService,
+ LoggerInterface $logger,
IUserSession $userSession,
- ILogger $logger
+ IGroupManager $groupManager,
+ IConfig $config,
) {
parent::__construct(
$AppName,
$request,
$l10n,
$userStoragesService,
- $logger
+ $logger,
+ $userSession,
+ $groupManager,
+ $config
);
- $this->userSession = $userSession;
}
protected function manipulateStorageConfig(StorageConfig $storage) {
@@ -88,10 +72,9 @@ class UserStoragesController extends StoragesController {
/**
* Get all storage entries
*
- * @NoAdminRequired
- *
* @return DataResponse
*/
+ #[NoAdminRequired]
public function index() {
return parent::index();
}
@@ -99,12 +82,11 @@ class UserStoragesController extends StoragesController {
/**
* Return storage
*
- * @NoAdminRequired
- *
* {@inheritdoc}
*/
- public function show($id, $testOnly = true) {
- return parent::show($id, $testOnly);
+ #[NoAdminRequired]
+ public function show(int $id) {
+ return parent::show($id);
}
/**
@@ -117,16 +99,25 @@ class UserStoragesController extends StoragesController {
* @param array $mountOptions backend-specific mount options
*
* @return DataResponse
- *
- * @NoAdminRequired
*/
+ #[NoAdminRequired]
+ #[PasswordConfirmationRequired(strict: true)]
public function create(
$mountPoint,
$backend,
$authMechanism,
$backendOptions,
- $mountOptions
+ $mountOptions,
) {
+ $canCreateNewLocalStorage = $this->config->getSystemValue('files_external_allow_create_new_local', true);
+ if (!$canCreateNewLocalStorage && $backend === 'local') {
+ return new DataResponse(
+ [
+ 'message' => $this->l10n->t('Forbidden to manage local mounts')
+ ],
+ Http::STATUS_FORBIDDEN
+ );
+ }
$newStorage = $this->createStorage(
$mountPoint,
$backend,
@@ -134,7 +125,7 @@ class UserStoragesController extends StoragesController {
$backendOptions,
$mountOptions
);
- if ($newStorage instanceOf DataResponse) {
+ if ($newStorage instanceof DataResponse) {
return $newStorage;
}
@@ -147,7 +138,7 @@ class UserStoragesController extends StoragesController {
$this->updateStorageStatus($newStorage);
return new DataResponse(
- $newStorage,
+ $newStorage->jsonSerialize(true),
Http::STATUS_CREATED
);
}
@@ -161,12 +152,11 @@ class UserStoragesController extends StoragesController {
* @param string $authMechanism authentication mechanism identifier
* @param array $backendOptions backend-specific options
* @param array $mountOptions backend-specific mount options
- * @param bool $testOnly whether to storage should only test the connection or do more things
*
* @return DataResponse
- *
- * @NoAdminRequired
*/
+ #[NoAdminRequired]
+ #[PasswordConfirmationRequired(strict: true)]
public function update(
$id,
$mountPoint,
@@ -174,7 +164,6 @@ class UserStoragesController extends StoragesController {
$authMechanism,
$backendOptions,
$mountOptions,
- $testOnly = true
) {
$storage = $this->createStorage(
$mountPoint,
@@ -183,7 +172,7 @@ class UserStoragesController extends StoragesController {
$backendOptions,
$mountOptions
);
- if ($storage instanceOf DataResponse) {
+ if ($storage instanceof DataResponse) {
return $storage;
}
$storage->setId($id);
@@ -198,30 +187,28 @@ class UserStoragesController extends StoragesController {
} catch (NotFoundException $e) {
return new DataResponse(
[
- 'message' => (string)$this->l10n->t('Storage with ID "%d" not found', array($id))
+ 'message' => $this->l10n->t('Storage with ID "%d" not found', [$id])
],
Http::STATUS_NOT_FOUND
);
}
- $this->updateStorageStatus($storage, $testOnly);
+ $this->updateStorageStatus($storage);
return new DataResponse(
- $storage,
+ $storage->jsonSerialize(true),
Http::STATUS_OK
);
-
}
/**
* Delete storage
*
- * @NoAdminRequired
- *
* {@inheritdoc}
*/
- public function destroy($id) {
+ #[NoAdminRequired]
+ #[PasswordConfirmationRequired(strict: true)]
+ public function destroy(int $id) {
return parent::destroy($id);
}
-
}