mirror of
https://github.com/nextcloud/server.git
synced 2026-02-20 00:12:30 -05:00
Add option to disallow creation of local storages
Introduce a new config option to prevent web UI admins to create or edit external storages of type "local". Signed-off-by: Vincent Petry <vincent@nextcloud.com>
This commit is contained in:
parent
4ee10c85dd
commit
fd220bc771
10 changed files with 148 additions and 15 deletions
|
|
@ -659,6 +659,7 @@ MountConfigListView.prototype = _.extend({
|
|||
}
|
||||
|
||||
this._encryptionEnabled = options.encryptionEnabled;
|
||||
this._canCreateLocal = options.canCreateLocal;
|
||||
|
||||
// read the backend config that was carefully crammed
|
||||
// into the data-configurations attribute of the select
|
||||
|
|
@ -825,10 +826,13 @@ MountConfigListView.prototype = _.extend({
|
|||
$tr.addClass(backend.identifier);
|
||||
$tr.find('.backend').data('identifier', backend.identifier);
|
||||
|
||||
if (backend.invalid) {
|
||||
if (backend.invalid || (backend.identifier === 'local' && !this._canCreateLocal)) {
|
||||
$tr.find('[name=mountPoint]').prop('disabled', true);
|
||||
$tr.find('.applicable,.mountOptionsToggle').empty();
|
||||
this.updateStatus($tr, false, 'Unknown backend: ' + backend.name);
|
||||
$tr.find('.save').empty();
|
||||
if (backend.invalid) {
|
||||
this.updateStatus($tr, false, 'Unknown backend: ' + backend.name);
|
||||
}
|
||||
return $tr;
|
||||
}
|
||||
|
||||
|
|
@ -970,6 +974,7 @@ MountConfigListView.prototype = _.extend({
|
|||
var storageConfig = new self._storageConfigClass();
|
||||
_.extend(storageConfig, storageParams);
|
||||
var $tr = self.newStorage(storageConfig, onCompletion);
|
||||
|
||||
self.recheckStorageConfig($tr);
|
||||
});
|
||||
onCompletion.resolve();
|
||||
|
|
@ -1313,9 +1318,11 @@ MountConfigListView.prototype = _.extend({
|
|||
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
var enabled = $('#files_external').attr('data-encryption-enabled');
|
||||
var canCreateLocal = $('#files_external').attr('data-can-create-local');
|
||||
var encryptionEnabled = (enabled ==='true')? true: false;
|
||||
var mountConfigListView = new MountConfigListView($('#externalStorage'), {
|
||||
encryptionEnabled: encryptionEnabled
|
||||
encryptionEnabled: encryptionEnabled,
|
||||
canCreateLocal: (canCreateLocal === 'true') ? true: false,
|
||||
});
|
||||
mountConfigListView.loadStorages();
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ use OCA\Files_External\NotFoundException;
|
|||
use OCA\Files_External\Service\GlobalStoragesService;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IL10N;
|
||||
use OCP\ILogger;
|
||||
|
|
@ -51,6 +52,7 @@ class GlobalStoragesController extends StoragesController {
|
|||
* @param ILogger $logger
|
||||
* @param IUserSession $userSession
|
||||
* @param IGroupManager $groupManager
|
||||
* @param IConfig $config
|
||||
*/
|
||||
public function __construct(
|
||||
$AppName,
|
||||
|
|
@ -59,7 +61,8 @@ class GlobalStoragesController extends StoragesController {
|
|||
GlobalStoragesService $globalStoragesService,
|
||||
ILogger $logger,
|
||||
IUserSession $userSession,
|
||||
IGroupManager $groupManager
|
||||
IGroupManager $groupManager,
|
||||
IConfig $config
|
||||
) {
|
||||
parent::__construct(
|
||||
$AppName,
|
||||
|
|
@ -68,7 +71,8 @@ class GlobalStoragesController extends StoragesController {
|
|||
$globalStoragesService,
|
||||
$logger,
|
||||
$userSession,
|
||||
$groupManager
|
||||
$groupManager,
|
||||
$config
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -96,6 +100,16 @@ class GlobalStoragesController extends StoragesController {
|
|||
$applicableGroups,
|
||||
$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,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ use OCP\AppFramework\Controller;
|
|||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\Files\StorageNotAvailableException;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IL10N;
|
||||
use OCP\ILogger;
|
||||
|
|
@ -79,6 +80,11 @@ abstract class StoragesController extends Controller {
|
|||
*/
|
||||
protected $groupManager;
|
||||
|
||||
/**
|
||||
* @var IConfig
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Creates a new storages controller.
|
||||
*
|
||||
|
|
@ -95,7 +101,8 @@ abstract class StoragesController extends Controller {
|
|||
StoragesService $storagesService,
|
||||
ILogger $logger,
|
||||
IUserSession $userSession,
|
||||
IGroupManager $groupManager
|
||||
IGroupManager $groupManager,
|
||||
IConfig $config
|
||||
) {
|
||||
parent::__construct($AppName, $request);
|
||||
$this->l10n = $l10n;
|
||||
|
|
@ -103,6 +110,7 @@ abstract class StoragesController extends Controller {
|
|||
$this->logger = $logger;
|
||||
$this->userSession = $userSession;
|
||||
$this->groupManager = $groupManager;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -129,6 +137,16 @@ abstract class StoragesController extends Controller {
|
|||
$applicableGroups = 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,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ use OCA\Files_External\NotFoundException;
|
|||
use OCA\Files_External\Service\UserGlobalStoragesService;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IL10N;
|
||||
use OCP\ILogger;
|
||||
|
|
@ -64,7 +65,8 @@ class UserGlobalStoragesController extends StoragesController {
|
|||
UserGlobalStoragesService $userGlobalStoragesService,
|
||||
ILogger $logger,
|
||||
IUserSession $userSession,
|
||||
IGroupManager $groupManager
|
||||
IGroupManager $groupManager,
|
||||
IConfig $config
|
||||
) {
|
||||
parent::__construct(
|
||||
$AppName,
|
||||
|
|
@ -73,7 +75,8 @@ class UserGlobalStoragesController extends StoragesController {
|
|||
$userGlobalStoragesService,
|
||||
$logger,
|
||||
$userSession,
|
||||
$groupManager
|
||||
$groupManager,
|
||||
$config
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ use OCA\Files_External\NotFoundException;
|
|||
use OCA\Files_External\Service\UserStoragesService;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IL10N;
|
||||
use OCP\ILogger;
|
||||
|
|
@ -63,7 +64,8 @@ class UserStoragesController extends StoragesController {
|
|||
UserStoragesService $userStoragesService,
|
||||
ILogger $logger,
|
||||
IUserSession $userSession,
|
||||
IGroupManager $groupManager
|
||||
IGroupManager $groupManager,
|
||||
IConfig $config
|
||||
) {
|
||||
parent::__construct(
|
||||
$AppName,
|
||||
|
|
@ -72,7 +74,8 @@ class UserStoragesController extends StoragesController {
|
|||
$userStoragesService,
|
||||
$logger,
|
||||
$userSession,
|
||||
$groupManager
|
||||
$groupManager,
|
||||
$config
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +130,15 @@ class UserStoragesController extends StoragesController {
|
|||
$backendOptions,
|
||||
$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,
|
||||
|
|
|
|||
|
|
@ -100,7 +100,10 @@ $canCreateMounts = $_['visibilityType'] === BackendService::VISIBILITY_ADMIN ||
|
|||
<h2><?php p($l->t('No external storage configured or you don\'t have the permission to configure them')); ?></h2>
|
||||
</div>
|
||||
|
||||
<form data-can-create="<?php echo $canCreateMounts?'true':'false' ?>" id="files_external" class="section" data-encryption-enabled="<?php echo $_['encryptionEnabled']?'true': 'false'; ?>">
|
||||
<?php
|
||||
$canCreateNewLocalStorage = \OC::$server->getConfig()->getSystemValue('files_external_allow_create_new_local', true);
|
||||
?>
|
||||
<form data-can-create="<?php echo $canCreateMounts?'true':'false' ?>" data-can-create-local="<?php echo $canCreateNewLocalStorage?'true':'false' ?>" id="files_external" class="section" data-encryption-enabled="<?php echo $_['encryptionEnabled']?'true': 'false'; ?>">
|
||||
<h2 class="inlineblock" data-anchor-name="external-storage"><?php p($l->t('External storage')); ?></h2>
|
||||
<a target="_blank" rel="noreferrer" class="icon-info" title="<?php p($l->t('Open documentation'));?>" href="<?php p(link_to_docs('admin-external-storage')); ?>"></a>
|
||||
<p class="settings-hint"><?php p($l->t('External storage enables you to mount external storage services and devices as secondary Nextcloud storage devices. You may also allow users to mount their own external storage services.')); ?></p>
|
||||
|
|
@ -150,7 +153,7 @@ $canCreateMounts = $_['visibilityType'] === BackendService::VISIBILITY_ADMIN ||
|
|||
});
|
||||
?>
|
||||
<?php foreach ($sortedBackends as $backend): ?>
|
||||
<?php if ($backend->getDeprecateTo()) {
|
||||
<?php if ($backend->getDeprecateTo() || (!$canCreateNewLocalStorage && $backend->getIdentifier() == "local")) {
|
||||
continue;
|
||||
} // ignore deprecated backends?>
|
||||
<option value="<?php p($backend->getIdentifier()); ?>"><?php p($backend->getText()); ?></option>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ namespace OCA\Files_External\Tests\Controller;
|
|||
use OC\User\User;
|
||||
use OCA\Files_External\Controller\GlobalStoragesController;
|
||||
use OCA\Files_External\Service\BackendService;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IL10N;
|
||||
use OCP\ILogger;
|
||||
|
|
@ -38,6 +39,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
|||
class GlobalStoragesControllerTest extends StoragesControllerTest {
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->service = $this->getMockBuilder('\OCA\Files_External\Service\GlobalStoragesService')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
|
@ -45,11 +47,20 @@ class GlobalStoragesControllerTest extends StoragesControllerTest {
|
|||
$this->service->method('getVisibilityType')
|
||||
->willReturn(BackendService::VISIBILITY_ADMIN);
|
||||
|
||||
$this->controller = $this->createController(true);
|
||||
}
|
||||
|
||||
private function createController($allowCreateLocal = true) {
|
||||
$session = $this->createMock(IUserSession::class);
|
||||
$session->method('getUser')
|
||||
->willReturn(new User('test', null, $this->createMock(EventDispatcherInterface::class)));
|
||||
|
||||
$this->controller = new GlobalStoragesController(
|
||||
$config = $this->createMock(IConfig::class);
|
||||
$config->method('getSystemValue')
|
||||
->with('files_external_allow_create_new_local', true)
|
||||
->willReturn($allowCreateLocal);
|
||||
|
||||
return new GlobalStoragesController(
|
||||
'files_external',
|
||||
$this->createMock(IRequest::class),
|
||||
$this->createMock(IL10N::class),
|
||||
|
|
@ -57,6 +68,12 @@ class GlobalStoragesControllerTest extends StoragesControllerTest {
|
|||
$this->createMock(ILogger::class),
|
||||
$session,
|
||||
$this->createMock(IGroupManager::class),
|
||||
$config
|
||||
);
|
||||
}
|
||||
|
||||
public function testAddLocalStorageWhenDisabled() {
|
||||
$this->controller = $this->createController(false);
|
||||
parent::testAddLocalStorageWhenDisabled();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,6 +130,36 @@ abstract class StoragesControllerTest extends \Test\TestCase {
|
|||
$this->assertEquals($storageConfig, $data);
|
||||
}
|
||||
|
||||
public function testAddLocalStorageWhenDisabled() {
|
||||
$authMech = $this->getAuthMechMock();
|
||||
$backend = $this->getBackendMock();
|
||||
|
||||
$storageConfig = new StorageConfig(1);
|
||||
$storageConfig->setMountPoint('mount');
|
||||
$storageConfig->setBackend($backend);
|
||||
$storageConfig->setAuthMechanism($authMech);
|
||||
$storageConfig->setBackendOptions([]);
|
||||
|
||||
$this->service->expects($this->never())
|
||||
->method('createStorage');
|
||||
$this->service->expects($this->never())
|
||||
->method('addStorage');
|
||||
|
||||
$response = $this->controller->create(
|
||||
'mount',
|
||||
'local',
|
||||
'\OCA\Files_External\Lib\Auth\NullMechanism',
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
null
|
||||
);
|
||||
|
||||
$data = $response->getData();
|
||||
$this->assertEquals(Http::STATUS_FORBIDDEN, $response->getStatus());
|
||||
}
|
||||
|
||||
public function testUpdateStorage() {
|
||||
$authMech = $this->getAuthMechMock();
|
||||
$authMech->method('validateStorage')
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ use OCA\Files_External\Controller\UserStoragesController;
|
|||
use OCA\Files_External\Lib\StorageConfig;
|
||||
use OCA\Files_External\Service\BackendService;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IL10N;
|
||||
use OCP\ILogger;
|
||||
|
|
@ -54,21 +55,36 @@ class UserStoragesControllerTest extends StoragesControllerTest {
|
|||
$this->service->method('getVisibilityType')
|
||||
->willReturn(BackendService::VISIBILITY_PERSONAL);
|
||||
|
||||
$this->controller = $this->createController(true);
|
||||
}
|
||||
|
||||
private function createController($allowCreateLocal = true) {
|
||||
$session = $this->createMock(IUserSession::class);
|
||||
$session->method('getUser')
|
||||
->willReturn(new User('test', null, $this->createMock(EventDispatcherInterface::class)));
|
||||
|
||||
$this->controller = new UserStoragesController(
|
||||
$config = $this->createMock(IConfig::class);
|
||||
$config->method('getSystemValue')
|
||||
->with('files_external_allow_create_new_local', true)
|
||||
->willReturn($allowCreateLocal);
|
||||
|
||||
return new UserStoragesController(
|
||||
'files_external',
|
||||
$this->createMock(IRequest::class),
|
||||
$this->createMock(IL10N::class),
|
||||
$this->service,
|
||||
$this->createMock(ILogger::class),
|
||||
$session,
|
||||
$this->createMock(IGroupManager::class)
|
||||
$this->createMock(IGroupManager::class),
|
||||
$config
|
||||
);
|
||||
}
|
||||
|
||||
public function testAddLocalStorageWhenDisabled() {
|
||||
$this->controller = $this->createController(false);
|
||||
parent::testAddLocalStorageWhenDisabled();
|
||||
}
|
||||
|
||||
public function testAddOrUpdateStorageDisallowedBackend() {
|
||||
$backend = $this->getBackendMock();
|
||||
$backend->method('isVisibleFor')
|
||||
|
|
|
|||
|
|
@ -1768,6 +1768,19 @@ $CONFIG = [
|
|||
*/
|
||||
'external_storage.auth_availability_delay' => 1800,
|
||||
|
||||
/**
|
||||
* Allows to create external storages of type "Local" in the web interface and APIs.
|
||||
*
|
||||
* When disable, it is still possible to create local storages with occ using
|
||||
* the following command:
|
||||
*
|
||||
* % php occ files_external:create /mountpoint local null::null -c datadir=/path/to/data
|
||||
*
|
||||
* Defaults to ``true``
|
||||
*
|
||||
*/
|
||||
'files_external_allow_create_new_local' => true,
|
||||
|
||||
/**
|
||||
* Specifies how often the local filesystem (the Nextcloud data/ directory, and
|
||||
* NFS mounts in data/) is checked for changes made outside Nextcloud. This
|
||||
|
|
|
|||
Loading…
Reference in a new issue