Skip to content

Commit

Permalink
refs #21045 add app config to disable unlimited quota and to set max …
Browse files Browse the repository at this point in the history
…quota

avoid unlimited quota as default_quota fallback value if unlimited quota is not allowed
avoid getting/setting/displaying unlimited default quota if not allowed
implement tests for unlimited quota restrictions

Signed-off-by: Julien Veyssier <eneiluj@posteo.net>
  • Loading branch information
Julien Veyssier committed Jul 29, 2021
1 parent 6f1c2ed commit ea77ada
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 3 deletions.
7 changes: 7 additions & 0 deletions apps/provisioning_api/lib/Controller/AppConfigController.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,12 @@ protected function verifyConfigKey(string $app, string $key, string $value) {
if ($app === 'core' && (strpos($key, 'public_') === 0 || strpos($key, 'remote_') === 0)) {
throw new \InvalidArgumentException('The given key can not be set');
}

if ($app === 'files'
&& $key === 'default_quota'
&& $value === 'none'
&& $this->config->getAppValue('files', 'allow_unlimited_quota', '1') === '0') {
throw new \InvalidArgumentException('The given key can not be set, unlimited quota is forbidden on this instance');
}
}
}
11 changes: 11 additions & 0 deletions apps/provisioning_api/lib/Controller/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -798,9 +798,20 @@ public function editUser(string $userId, string $key, string $value): DataRespon
if ($quota === -1) {
$quota = 'none';
} else {
$maxQuota = (int) $this->config->getAppValue('files', 'max_quota', '-1');
if ($maxQuota !== -1 && $quota > $maxQuota) {
throw new OCSException('Invalid quota value. ' . $value . ' is exceeding the maximum quota', 102);
}
$quota = \OCP\Util::humanFileSize($quota);
}
}
// no else block because quota can be set to 'none' in previous if
if ($quota === 'none') {
$allowUnlimitedQuota = $this->config->getAppValue('files', 'allow_unlimited_quota', '1') === '1';
if (!$allowUnlimitedQuota) {
throw new OCSException('Unlimited quota is forbidden on this instance', 102);
}
}
$targetUser->setQuota($quota);
break;
case 'password':
Expand Down
8 changes: 7 additions & 1 deletion apps/settings/lib/Controller/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,12 @@ public function usersList(): TemplateResponse {

/* QUOTAS PRESETS */
$quotaPreset = $this->parseQuotaPreset($this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB'));
$defaultQuota = $this->config->getAppValue('files', 'default_quota', 'none');
$allowUnlimitedQuota = $this->config->getAppValue('files', 'allow_unlimited_quota', '1') === '1';
if (!$allowUnlimitedQuota && count($quotaPreset) > 0) {
$defaultQuota = $this->config->getAppValue('files', 'default_quota', $quotaPreset[0]);
} else {
$defaultQuota = $this->config->getAppValue('files', 'default_quota', 'none');
}

$event = new BeforeTemplateRenderedEvent();
$this->dispatcher->dispatch('OC\Settings\Users::loadAdditionalScripts', $event);
Expand All @@ -260,6 +265,7 @@ public function usersList(): TemplateResponse {
$serverData['isAdmin'] = $this->isAdmin;
$serverData['sortGroups'] = $sortGroupsBy;
$serverData['quotaPreset'] = $quotaPreset;
$serverData['allowUnlimitedQuota'] = $allowUnlimitedQuota;
$serverData['userCount'] = $userCount;
$serverData['languages'] = $languages;
$serverData['defaultLanguage'] = $this->config->getSystemValue('default_language', 'en');
Expand Down
4 changes: 3 additions & 1 deletion apps/settings/src/components/UserList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,9 @@ export default {
label: cur,
}), [])
// add default presets
quotaPreset.unshift(this.unlimitedQuota)
if (this.settings.allowUnlimitedQuota) {
quotaPreset.unshift(this.unlimitedQuota)
}
quotaPreset.unshift(this.defaultQuota)
return quotaPreset
},
Expand Down
4 changes: 3 additions & 1 deletion apps/settings/src/views/Users.vue
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,9 @@ export default {
// convert the preset array into objects
const quotaPreset = this.settings.quotaPreset.reduce((acc, cur) => acc.concat({ id: cur, label: cur }), [])
// add default presets
quotaPreset.unshift(this.unlimitedQuota)
if (this.settings.allowUnlimitedQuota) {
quotaPreset.unshift(this.unlimitedQuota)
}
return quotaPreset
},
// mapping saved values to objects
Expand Down
12 changes: 12 additions & 0 deletions lib/private/User/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,18 @@ public function getQuota() {
}
if ($quota === 'default') {
$quota = $this->config->getAppValue('files', 'default_quota', 'none');

// if unlimited quota is not allowed => avoid getting 'unlimited' as default_quota fallback value
// use the first preset instead
$allowUnlimitedQuota = $this->config->getAppValue('files', 'allow_unlimited_quota', '1') === '1';
if (!$allowUnlimitedQuota) {
$presets = $this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB');
$presets = array_filter(array_map('trim', explode(',', $presets)));
$quotaPreset = array_values(array_diff($presets, ['default', 'none']));
if (count($quotaPreset) > 0) {
$quota = $this->config->getAppValue('files', 'default_quota', $quotaPreset[0]);
}
}
}
return $quota;
}
Expand Down
65 changes: 65 additions & 0 deletions tests/lib/User/UserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,71 @@ public function testSetQuota() {
$user->setQuota('23 TB');
}

public function testGetDefaultUnlimitedQuota() {
/**
* @var UserInterface | \PHPUnit\Framework\MockObject\MockObject $backend
*/
$backend = $this->createMock(\Test\Util\User\Dummy::class);

/** @var PublicEmitter|\PHPUnit\Framework\MockObject\MockObject $emitter */
$emitter = $this->createMock(PublicEmitter::class);
$emitter->expects($this->never())
->method('emit');

$config = $this->createMock(IConfig::class);
$user = new User('foo', $backend, $this->dispatcher, $emitter, $config);

$userValueMap = [
['foo', 'files', 'quota', 'default', 'default'],
];
$appValueMap = [
['files', 'default_quota', 'none', 'none'],
// allow unlimited quota
['files', 'allow_unlimited_quota', '1', '1'],
];
$config->method('getUserValue')
->will($this->returnValueMap($userValueMap));
$config->method('getAppValue')
->will($this->returnValueMap($appValueMap));

$quota = $user->getQuota();
$this->assertEquals('none', $quota);
}

public function testGetDefaultUnlimitedQuotaForbidden() {
/**
* @var UserInterface | \PHPUnit\Framework\MockObject\MockObject $backend
*/
$backend = $this->createMock(\Test\Util\User\Dummy::class);

/** @var PublicEmitter|\PHPUnit\Framework\MockObject\MockObject $emitter */
$emitter = $this->createMock(PublicEmitter::class);
$emitter->expects($this->never())
->method('emit');

$config = $this->createMock(IConfig::class);
$user = new User('foo', $backend, $this->dispatcher, $emitter, $config);

$userValueMap = [
['foo', 'files', 'quota', 'default', 'default'],
];
$appValueMap = [
['files', 'default_quota', 'none', 'none'],
// do not allow unlimited quota
['files', 'allow_unlimited_quota', '1', '0'],
['files', 'quota_preset', '1 GB, 5 GB, 10 GB', '1 GB, 5 GB, 10 GB'],
// expect seeing 1 GB used as fallback value
['files', 'default_quota', '1 GB', '1 GB'],
];
$config->method('getUserValue')
->will($this->returnValueMap($userValueMap));
$config->method('getAppValue')
->will($this->returnValueMap($appValueMap));

$quota = $user->getQuota();
$this->assertEquals('1 GB', $quota);
}

public function testSetQuotaAddressNoChange() {
/**
* @var UserInterface | \PHPUnit\Framework\MockObject\MockObject $backend
Expand Down

0 comments on commit ea77ada

Please sign in to comment.