Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions core/Command/Config/Preset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Core\Command\Config;

use NCU\Config\Lexicon\Preset as ConfigLexiconPreset;
use OC\Config\ConfigManager;
use OC\Core\Command\Base;
use OCP\IConfig;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class Preset extends Base {
public function __construct(
private readonly IConfig $config,
private readonly ConfigManager $configManager,
) {
parent::__construct();
}

protected function configure() {
parent::configure();
$this->setName('config:preset')
->setDescription('Select a config preset')
->addArgument('preset', InputArgument::OPTIONAL, 'Preset to use for all unset config values', '')
->addOption('list', '', InputOption::VALUE_NONE, 'display available preset');
}

protected function execute(InputInterface $input, OutputInterface $output): int {
if ($input->getOption('list')) {
$this->getEnum('', $list);
$this->writeArrayInOutputFormat($input, $output, $list);
return self::SUCCESS;
}

$presetArg = $input->getArgument('preset');
if ($presetArg !== '') {
$preset = $this->getEnum($presetArg, $list);
if ($preset === null) {
$output->writeln('<error>Invalid preset: ' . $presetArg . '</error>');
$output->writeln('Available presets: ' . implode(', ', $list));
return self::INVALID;
}

$this->configManager->setLexiconPreset($preset);
}

$current = ConfigLexiconPreset::tryFrom($this->config->getSystemValueInt(ConfigManager::PRESET_CONFIGKEY, 0)) ?? ConfigLexiconPreset::NONE;
$this->writeArrayInOutputFormat($input, $output, [$current->name], 'current preset: ');
return self::SUCCESS;
}

private function getEnum(string $name, ?array &$list = null): ?ConfigLexiconPreset {
$list = [];
foreach (ConfigLexiconPreset::cases() as $case) {
$list[] = $case->name;
if (strtolower($case->name) === strtolower($name)) {
return $case;
}
}

return null;
}
}
2 changes: 2 additions & 0 deletions core/register_command.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use OC\Core\Command\Config\App\SetConfig;
use OC\Core\Command\Config\Import;
use OC\Core\Command\Config\ListConfigs;
use OC\Core\Command\Config\Preset;
use OC\Core\Command\Db\AddMissingColumns;
use OC\Core\Command\Db\AddMissingIndices;
use OC\Core\Command\Db\AddMissingPrimaryKeys;
Expand Down Expand Up @@ -149,6 +150,7 @@
$application->add(Server::get(SetConfig::class));
$application->add(Server::get(Import::class));
$application->add(Server::get(ListConfigs::class));
$application->add(Server::get(Preset::class));
$application->add(Server::get(Command\Config\System\DeleteConfig::class));
$application->add(Server::get(Command\Config\System\GetConfig::class));
$application->add(Server::get(Command\Config\System\SetConfig::class));
Expand Down
2 changes: 2 additions & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
'NCU\\Config\\Lexicon\\ConfigLexiconEntry' => $baseDir . '/lib/unstable/Config/Lexicon/ConfigLexiconEntry.php',
'NCU\\Config\\Lexicon\\ConfigLexiconStrictness' => $baseDir . '/lib/unstable/Config/Lexicon/ConfigLexiconStrictness.php',
'NCU\\Config\\Lexicon\\IConfigLexicon' => $baseDir . '/lib/unstable/Config/Lexicon/IConfigLexicon.php',
'NCU\\Config\\Lexicon\\Preset' => $baseDir . '/lib/unstable/Config/Lexicon/Preset.php',
'NCU\\Config\\ValueType' => $baseDir . '/lib/unstable/Config/ValueType.php',
'NCU\\Federation\\ISignedCloudFederationProvider' => $baseDir . '/lib/unstable/Federation/ISignedCloudFederationProvider.php',
'NCU\\Security\\Signature\\Enum\\DigestAlgorithm' => $baseDir . '/lib/unstable/Security/Signature/Enum/DigestAlgorithm.php',
Expand Down Expand Up @@ -1244,6 +1245,7 @@
'OC\\Core\\Command\\Config\\App\\SetConfig' => $baseDir . '/core/Command/Config/App/SetConfig.php',
'OC\\Core\\Command\\Config\\Import' => $baseDir . '/core/Command/Config/Import.php',
'OC\\Core\\Command\\Config\\ListConfigs' => $baseDir . '/core/Command/Config/ListConfigs.php',
'OC\\Core\\Command\\Config\\Preset' => $baseDir . '/core/Command/Config/Preset.php',
'OC\\Core\\Command\\Config\\System\\Base' => $baseDir . '/core/Command/Config/System/Base.php',
'OC\\Core\\Command\\Config\\System\\CastHelper' => $baseDir . '/core/Command/Config/System/CastHelper.php',
'OC\\Core\\Command\\Config\\System\\DeleteConfig' => $baseDir . '/core/Command/Config/System/DeleteConfig.php',
Expand Down
2 changes: 2 additions & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'NCU\\Config\\Lexicon\\ConfigLexiconEntry' => __DIR__ . '/../../..' . '/lib/unstable/Config/Lexicon/ConfigLexiconEntry.php',
'NCU\\Config\\Lexicon\\ConfigLexiconStrictness' => __DIR__ . '/../../..' . '/lib/unstable/Config/Lexicon/ConfigLexiconStrictness.php',
'NCU\\Config\\Lexicon\\IConfigLexicon' => __DIR__ . '/../../..' . '/lib/unstable/Config/Lexicon/IConfigLexicon.php',
'NCU\\Config\\Lexicon\\Preset' => __DIR__ . '/../../..' . '/lib/unstable/Config/Lexicon/Preset.php',
'NCU\\Config\\ValueType' => __DIR__ . '/../../..' . '/lib/unstable/Config/ValueType.php',
'NCU\\Federation\\ISignedCloudFederationProvider' => __DIR__ . '/../../..' . '/lib/unstable/Federation/ISignedCloudFederationProvider.php',
'NCU\\Security\\Signature\\Enum\\DigestAlgorithm' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Enum/DigestAlgorithm.php',
Expand Down Expand Up @@ -1285,6 +1286,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Core\\Command\\Config\\App\\SetConfig' => __DIR__ . '/../../..' . '/core/Command/Config/App/SetConfig.php',
'OC\\Core\\Command\\Config\\Import' => __DIR__ . '/../../..' . '/core/Command/Config/Import.php',
'OC\\Core\\Command\\Config\\ListConfigs' => __DIR__ . '/../../..' . '/core/Command/Config/ListConfigs.php',
'OC\\Core\\Command\\Config\\Preset' => __DIR__ . '/../../..' . '/core/Command/Config/Preset.php',
'OC\\Core\\Command\\Config\\System\\Base' => __DIR__ . '/../../..' . '/core/Command/Config/System/Base.php',
'OC\\Core\\Command\\Config\\System\\CastHelper' => __DIR__ . '/../../..' . '/core/Command/Config/System/CastHelper.php',
'OC\\Core\\Command\\Config\\System\\DeleteConfig' => __DIR__ . '/../../..' . '/core/Command/Config/System/DeleteConfig.php',
Expand Down
35 changes: 29 additions & 6 deletions lib/private/AppConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use NCU\Config\Lexicon\ConfigLexiconEntry;
use NCU\Config\Lexicon\ConfigLexiconStrictness;
use NCU\Config\Lexicon\IConfigLexicon;
use NCU\Config\Lexicon\Preset;
use OC\AppFramework\Bootstrap\Coordinator;
use OC\Config\ConfigManager;
use OCP\DB\Exception as DBException;
Expand Down Expand Up @@ -64,12 +65,13 @@ class AppConfig implements IAppConfig {
/** @var array<string, array{entries: array<string, ConfigLexiconEntry>, aliases: array<string, string>, strictness: ConfigLexiconStrictness}> ['app_id' => ['strictness' => ConfigLexiconStrictness, 'entries' => ['config_key' => ConfigLexiconEntry[]]] */
private array $configLexiconDetails = [];
private bool $ignoreLexiconAliases = false;

private ?Preset $configLexiconPreset = null;
/** @var ?array<string, string> */
private ?array $appVersionsCache = null;

public function __construct(
protected IDBConnection $connection,
protected IConfig $config,
protected LoggerInterface $logger,
protected ICrypto $crypto,
) {
Expand Down Expand Up @@ -438,9 +440,17 @@ private function getTypedValue(
): string {
$this->assertParams($app, $key, valueType: $type);
$origKey = $key;
if (!$this->matchAndApplyLexiconDefinition($app, $key, $lazy, $type, $default)) {
return $default; // returns default if strictness of lexicon is set to WARNING (block and report)
$matched = $this->matchAndApplyLexiconDefinition($app, $key, $lazy, $type, $default);
if ($default === null) {
// there is no logical reason for it to be null
throw new \Exception('default cannot be null');
}

// returns default if strictness of lexicon is set to WARNING (block and report)
if (!$matched) {
return $default;
}

$this->loadConfig($app, $lazy);

/**
Expand Down Expand Up @@ -1146,7 +1156,8 @@ public function deleteApp(string $app): void {
*/
public function clearCache(bool $reload = false): void {
$this->lazyLoaded = $this->fastLoaded = false;
$this->lazyCache = $this->fastCache = $this->valueTypes = [];
$this->lazyCache = $this->fastCache = $this->valueTypes = $this->configLexiconDetails = [];
$this->configLexiconPreset = null;

if (!$reload) {
return;
Expand Down Expand Up @@ -1592,7 +1603,7 @@ private function matchAndApplyLexiconDefinition(
string &$key,
?bool &$lazy = null,
int &$type = self::VALUE_MIXED,
string &$default = '',
?string &$default = null,
): bool {
if (in_array($key,
[
Expand Down Expand Up @@ -1629,7 +1640,11 @@ private function matchAndApplyLexiconDefinition(
}

$lazy = $configValue->isLazy();
$default = $configValue->getDefault() ?? $default; // default from Lexicon got priority
// only look for default if needed, default from Lexicon got priority
if ($default !== null) {
$default = $configValue->getDefault($this->getLexiconPreset()) ?? $default;
}

if ($configValue->isFlagged(self::FLAG_SENSITIVE)) {
$type |= self::VALUE_SENSITIVE;
}
Expand Down Expand Up @@ -1715,6 +1730,14 @@ public function ignoreLexiconAliases(bool $ignore): void {
$this->ignoreLexiconAliases = $ignore;
}

private function getLexiconPreset(): Preset {
if ($this->configLexiconPreset === null) {
$this->configLexiconPreset = Preset::tryFrom($this->config->getSystemValueInt(ConfigManager::PRESET_CONFIGKEY, 0)) ?? Preset::NONE;
}

return $this->configLexiconPreset;
}

/**
* Returns the installed versions of all apps
*
Expand Down
17 changes: 17 additions & 0 deletions lib/private/Config/ConfigManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
use NCU\Config\Exceptions\TypeConflictException;
use NCU\Config\IUserConfig;
use NCU\Config\Lexicon\ConfigLexiconEntry;
use NCU\Config\Lexicon\Preset;
use NCU\Config\ValueType;
use OC\AppConfig;
use OCP\App\IAppManager;
use OCP\IAppConfig;
use OCP\IConfig;
use OCP\Server;
use Psr\Log\LoggerInterface;

Expand All @@ -25,12 +27,16 @@
* @since 32.0.0
*/
class ConfigManager {
/** @since 32.0.0 */
public const PRESET_CONFIGKEY = 'config_preset';

/** @var AppConfig|null $appConfig */
private ?IAppConfig $appConfig = null;
/** @var UserConfig|null $userConfig */
private ?IUserConfig $userConfig = null;

public function __construct(
private readonly IConfig $config,
private readonly LoggerInterface $logger,
) {
}
Expand Down Expand Up @@ -74,6 +80,17 @@ public function migrateConfigLexiconKeys(?string $appId = null): void {
$this->userConfig->ignoreLexiconAliases(false);
}

/**
* store in config.php the new preset
* refresh cached preset
*/
public function setLexiconPreset(Preset $preset): void {
$this->config->setSystemValue(self::PRESET_CONFIGKEY, $preset->value);
$this->loadConfigServices();
$this->appConfig->clearCache();
$this->userConfig->clearCacheAll();
}

/**
* config services cannot be load at __construct() or install will fail
*/
Expand Down
32 changes: 26 additions & 6 deletions lib/private/Config/UserConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use NCU\Config\IUserConfig;
use NCU\Config\Lexicon\ConfigLexiconEntry;
use NCU\Config\Lexicon\ConfigLexiconStrictness;
use NCU\Config\Lexicon\Preset;
use NCU\Config\ValueType;
use OC\AppFramework\Bootstrap\Coordinator;
use OCP\DB\Exception as DBException;
Expand Down Expand Up @@ -66,6 +67,7 @@ class UserConfig implements IUserConfig {
/** @var array<string, array{entries: array<string, ConfigLexiconEntry>, aliases: array<string, string>, strictness: ConfigLexiconStrictness}> ['app_id' => ['strictness' => ConfigLexiconStrictness, 'entries' => ['config_key' => ConfigLexiconEntry[]]] */
private array $configLexiconDetails = [];
private bool $ignoreLexiconAliases = false;
private ?Preset $configLexiconPreset = null;

public function __construct(
protected IDBConnection $connection,
Expand Down Expand Up @@ -721,10 +723,17 @@ private function getTypedValue(
): string {
$this->assertParams($userId, $app, $key);
$origKey = $key;
if (!$this->matchAndApplyLexiconDefinition($userId, $app, $key, $lazy, $type, default: $default)) {
// returns default if strictness of lexicon is set to WARNING (block and report)
$matched = $this->matchAndApplyLexiconDefinition($userId, $app, $key, $lazy, $type, default: $default);
if ($default === null) {
// there is no logical reason for it to be null
throw new \Exception('default cannot be null');
}

// returns default if strictness of lexicon is set to WARNING (block and report)
if (!$matched) {
return $default;
}

$this->loadConfig($userId, $lazy);

/**
Expand Down Expand Up @@ -1625,7 +1634,8 @@ public function clearCache(string $userId, bool $reload = false): void {
*/
public function clearCacheAll(): void {
$this->lazyLoaded = $this->fastLoaded = [];
$this->lazyCache = $this->fastCache = $this->valueDetails = [];
$this->lazyCache = $this->fastCache = $this->valueDetails = $this->configLexiconDetails = [];
$this->configLexiconPreset = null;
}

/**
Expand Down Expand Up @@ -1886,7 +1896,7 @@ private function matchAndApplyLexiconDefinition(
?bool &$lazy = null,
ValueType &$type = ValueType::MIXED,
int &$flags = 0,
string &$default = '',
?string &$default = null,
): bool {
$configDetails = $this->getConfigDetailsFromLexicon($app);
if (array_key_exists($key, $configDetails['aliases']) && !$this->ignoreLexiconAliases) {
Expand Down Expand Up @@ -1924,8 +1934,10 @@ private function matchAndApplyLexiconDefinition(
return true;
}

// default from Lexicon got priority but it can still be overwritten by admin
$default = $this->getSystemDefault($app, $configValue) ?? $configValue->getDefault() ?? $default;
// only look for default if needed, default from Lexicon got priority if not overwritten by admin
if ($default !== null) {
$default = $this->getSystemDefault($app, $configValue) ?? $configValue->getDefault($this->getLexiconPreset()) ?? $default;
}

// returning false will make get() returning $default and set() not changing value in database
return !$enforcedValue;
Expand Down Expand Up @@ -2025,4 +2037,12 @@ private function getLexiconEntry(string $appId, string $key): ?ConfigLexiconEntr
public function ignoreLexiconAliases(bool $ignore): void {
$this->ignoreLexiconAliases = $ignore;
}

private function getLexiconPreset(): Preset {
if ($this->configLexiconPreset === null) {
$this->configLexiconPreset = Preset::tryFrom($this->config->getSystemValueInt(ConfigManager::PRESET_CONFIGKEY, 0)) ?? Preset::NONE;
}

return $this->configLexiconPreset;
}
}
Loading
Loading