diff --git a/core/AppInfo/ConfigLexicon.php b/core/AppInfo/ConfigLexicon.php
index 5dad229267d01..865a0a4728fa7 100644
--- a/core/AppInfo/ConfigLexicon.php
+++ b/core/AppInfo/ConfigLexicon.php
@@ -10,6 +10,7 @@
use OCP\Config\Lexicon\Entry;
use OCP\Config\Lexicon\ILexicon;
+use OCP\Config\Lexicon\Preset;
use OCP\Config\Lexicon\Strictness;
use OCP\Config\ValueType;
@@ -20,6 +21,7 @@
*/
class ConfigLexicon implements ILexicon {
public const SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES = 'shareapi_allow_federation_on_public_shares';
+ public const SHARE_CUSTOM_TOKEN = 'shareapi_allow_custom_tokens';
public function getStrictness(): Strictness {
return Strictness::IGNORE;
@@ -34,6 +36,17 @@ public function getAppConfigs(): array {
definition: 'adds share permission to public shares to allow adding them to your Nextcloud (federation)',
lazy: true,
),
+ new Entry(
+ key: self::SHARE_CUSTOM_TOKEN,
+ type: ValueType::BOOL,
+ defaultRaw: fn (Preset $p): bool => match ($p) {
+ Preset::FAMILY, Preset::PRIVATE => true,
+ default => false,
+ },
+ definition: 'Allow users to set custom share link tokens',
+ lazy: true,
+ note: 'Shares with guessable tokens may be accessed easily. Shares with custom tokens will continue to be accessible after this setting has been disabled.',
+ ),
];
}
diff --git a/core/Command/Base.php b/core/Command/Base.php
index c9b6337b64a9a..6ab2765b0f93e 100644
--- a/core/Command/Base.php
+++ b/core/Command/Base.php
@@ -170,6 +170,8 @@ protected function valueToString($value, bool $returnNull = true): ?string {
return 'true';
} elseif ($value === null) {
return $returnNull ? null : 'null';
+ } if ($value instanceof \UnitEnum) {
+ return $value->value;
} else {
return $value;
}
diff --git a/core/Command/Config/App/GetConfig.php b/core/Command/Config/App/GetConfig.php
index b68476a2e91b9..af0c564823275 100644
--- a/core/Command/Config/App/GetConfig.php
+++ b/core/Command/Config/App/GetConfig.php
@@ -37,6 +37,12 @@ protected function configure() {
InputOption::VALUE_NONE,
'returns complete details about the app config value'
)
+ ->addOption(
+ '--key-details',
+ null,
+ InputOption::VALUE_NONE,
+ 'returns complete details about the app config key'
+ )
->addOption(
'default-value',
null,
@@ -66,6 +72,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return 0;
}
+ if ($input->getOption('key-details')) {
+ $details = $this->appConfig->getKeyDetails($appName, $configName);
+ $this->writeArrayInOutputFormat($input, $output, $details);
+ return 0;
+ }
+
try {
$configValue = $this->appConfig->getDetails($appName, $configName)['value'];
} catch (AppConfigUnknownKeyException $e) {
diff --git a/core/Command/Config/App/SetConfig.php b/core/Command/Config/App/SetConfig.php
index 1f4ab81bf051e..c818404fc0eab 100644
--- a/core/Command/Config/App/SetConfig.php
+++ b/core/Command/Config/App/SetConfig.php
@@ -199,6 +199,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$current['lazy'] ? 'lazy cache' : 'fast cache'
)
);
+ $keyDetails = $this->appConfig->getKeyDetails($appName, $configName);
+ if (($keyDetails['note'] ?? '') !== '') {
+ $output->writeln('Note: ' . $keyDetails['note']);
+ }
+
} else {
$output->writeln('Config value were not updated');
}
diff --git a/lib/private/AppConfig.php b/lib/private/AppConfig.php
index 0a46109c9f965..2280ac1a79fb7 100644
--- a/lib/private/AppConfig.php
+++ b/lib/private/AppConfig.php
@@ -17,6 +17,7 @@
use OCP\Config\Lexicon\ILexicon;
use OCP\Config\Lexicon\Preset;
use OCP\Config\Lexicon\Strictness;
+use OCP\Config\ValueType;
use OCP\DB\Exception as DBException;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Exceptions\AppConfigIncorrectTypeException;
@@ -1094,6 +1095,49 @@ public function getDetails(string $app, string $key): array {
];
}
+ /**
+ * @inheritDoc
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ *
+ * @return array{app: string, key: string, lazy?: bool, valueType?: ValueType, valueTypeName?: string, sensitive?: bool, default?: string, definition?: string, note?: string}
+ * @since 32.0.0
+ */
+ public function getKeyDetails(string $app, string $key): array {
+ $this->assertParams($app, $key);
+ try {
+ $details = $this->getDetails($app, $key);
+ } catch (AppConfigUnknownKeyException $e) {
+ $details = [
+ 'app' => $app,
+ 'key' => $key
+ ];
+ }
+
+ /** @var Entry $lexiconEntry */
+ try {
+ $lazy = false;
+ $this->matchAndApplyLexiconDefinition($app, $key, $lazy, lexiconEntry: $lexiconEntry);
+ } catch (AppConfigTypeConflictException|AppConfigUnknownKeyException) {
+ // can be ignored
+ }
+
+ if ($lexiconEntry !== null) {
+ $details = array_merge($details, [
+ 'lazy' => $lexiconEntry->isLazy(),
+ 'valueType' => $lexiconEntry->getValueType(),
+ 'valueTypeName' => $lexiconEntry->getValueType()->name,
+ 'sensitive' => $lexiconEntry->isFlagged(self::FLAG_SENSITIVE),
+ 'default' => $lexiconEntry->getDefault($this->getLexiconPreset()),
+ 'definition' => $lexiconEntry->getDefinition(),
+ 'note' => $lexiconEntry->getNote(),
+ ]);
+ }
+
+ return array_filter($details);
+ }
+
/**
* @param string $type
*
@@ -1631,6 +1675,7 @@ private function matchAndApplyLexiconDefinition(
?bool &$lazy = null,
int &$type = self::VALUE_MIXED,
?string &$default = null,
+ ?Entry &$lexiconEntry = null,
): bool {
if (in_array($key,
[
@@ -1655,27 +1700,27 @@ private function matchAndApplyLexiconDefinition(
return true;
}
- /** @var Entry $configValue */
- $configValue = $configDetails['entries'][$key];
+ /** @var Entry $lexiconEntry */
+ $lexiconEntry = $configDetails['entries'][$key];
$type &= ~self::VALUE_SENSITIVE;
- $appConfigValueType = $configValue->getValueType()->toAppConfigFlag();
+ $appConfigValueType = $lexiconEntry->getValueType()->toAppConfigFlag();
if ($type === self::VALUE_MIXED) {
$type = $appConfigValueType; // we overwrite if value was requested as mixed
} elseif ($appConfigValueType !== $type) {
throw new AppConfigTypeConflictException('The app config key ' . $app . '/' . $key . ' is typed incorrectly in relation to the config lexicon');
}
- $lazy = $configValue->isLazy();
+ $lazy = $lexiconEntry->isLazy();
// only look for default if needed, default from Lexicon got priority
if ($default !== null) {
- $default = $configValue->getDefault($this->getLexiconPreset()) ?? $default;
+ $default = $lexiconEntry->getDefault($this->getLexiconPreset()) ?? $default;
}
- if ($configValue->isFlagged(self::FLAG_SENSITIVE)) {
+ if ($lexiconEntry->isFlagged(self::FLAG_SENSITIVE)) {
$type |= self::VALUE_SENSITIVE;
}
- if ($configValue->isDeprecated()) {
+ if ($lexiconEntry->isDeprecated()) {
$this->logger->notice('App config key ' . $app . '/' . $key . ' is set as deprecated.');
}
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index 9bfa810b10839..2e538b6c33a43 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -7,6 +7,7 @@
*/
namespace OC\Share20;
+use OC\Core\AppInfo\ConfigLexicon;
use OC\Files\Mount\MoveableMount;
use OC\KnownUser\KnownUserService;
use OC\Share20\Exception\ProviderException;
@@ -1939,7 +1940,7 @@ public function ignoreSecondDisplayName(): bool {
}
public function allowCustomTokens(): bool {
- return $this->appConfig->getValueBool('core', 'shareapi_allow_custom_tokens', false);
+ return $this->appConfig->getValueBool('core', ConfigLexicon::SHARE_CUSTOM_TOKEN);
}
public function allowViewWithoutDownload(): bool {
diff --git a/lib/public/Config/Lexicon/Entry.php b/lib/public/Config/Lexicon/Entry.php
index 0e6e664db36a0..c810522dde5bb 100644
--- a/lib/public/Config/Lexicon/Entry.php
+++ b/lib/public/Config/Lexicon/Entry.php
@@ -23,16 +23,20 @@ class Entry {
public const RENAME_INVERT_BOOLEAN = 1;
private string $definition = '';
+ private string $note = '';
private ?string $default = null;
/**
- * @param string $key config key, can only contain alphanumerical chars and -._
+ * @param string $key config key; can only contain alphanumerical chars and underscore "_"
* @param ValueType $type type of config value
+ * @param string|int|float|bool|array|Closure|null $defaultRaw default value to be used in case none known
* @param string $definition optional description of config key available when using occ command
* @param bool $lazy set config value as lazy
* @param int $flags set flags
- * @param string|null $rename previous config key to migrate config value from
* @param bool $deprecated set config key as deprecated
+ * @param string|null $rename source in case of a rename of a config key.
+ * @param int $options additional bitflag options {@see self::RENAME_INVERT_BOOLEAN}
+ * @param string $note additional note and warning related to the use of the config key.
*
* @since 32.0.0
* @psalm-suppress PossiblyInvalidCast
@@ -48,6 +52,7 @@ public function __construct(
private readonly bool $deprecated = false,
private readonly ?string $rename = null,
private readonly int $options = 0,
+ string $note = '',
) {
// key can only contain alphanumeric chars and underscore "_"
if (preg_match('/[^[:alnum:]_]/', $key)) {
@@ -57,6 +62,7 @@ public function __construct(
/** @psalm-suppress UndefinedClass */
if (\OC::$CLI) { // only store definition if ran from CLI
$this->definition = $definition;
+ $this->note = $note;
}
}
@@ -187,6 +193,16 @@ public function getDefinition(): string {
return $this->definition;
}
+ /**
+ * returns eventual note
+ *
+ * @return string
+ * @since 32.0.0
+ */
+ public function getNote(): string {
+ return $this->note;
+ }
+
/**
* returns if config key is set as lazy
*
diff --git a/lib/public/IAppConfig.php b/lib/public/IAppConfig.php
index 68d4332146e5f..d9e3e0d95a784 100644
--- a/lib/public/IAppConfig.php
+++ b/lib/public/IAppConfig.php
@@ -8,6 +8,7 @@
*/
namespace OCP;
+use OCP\Config\ValueType;
use OCP\Exceptions\AppConfigUnknownKeyException;
/**
@@ -449,6 +450,33 @@ public function updateLazy(string $app, string $key, bool $lazy): bool;
*/
public function getDetails(string $app, string $key): array;
+ /**
+ * returns an array containing details about a config key.
+ * key/value pair are available only if it exists.
+ *
+ * ```
+ * [
+ * "app" => "myapp",
+ * "key" => "mykey",
+ * "value" => "current_value",
+ * "default" => "default_if_available",
+ * "definition" => "this is what it does",
+ * "note" => "enabling this is not compatible with that",
+ * "lazy" => false,
+ * "type" => 4,
+ * "typeString" => "string",
+ * 'sensitive' => false
+ * ]
+ * ```
+ *
+ * @param string $app id of the app
+ * @param string $key config key
+ *
+ * @return array{app: string, key: string, lazy?: bool, valueType?: ValueType, valueTypeName?: string, sensitive?: bool, default?: string, definition?: string, note?: string}
+ * @since 32.0.0
+ */
+ public function getKeyDetails(string $app, string $key): array;
+
/**
* Convert string like 'string', 'integer', 'float', 'bool' or 'array' to
* to bitflag {@see VALUE_STRING}, {@see VALUE_INT}, {@see VALUE_FLOAT},