Skip to content

Commit

Permalink
feat(config): frame config keys/values
Browse files Browse the repository at this point in the history
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
  • Loading branch information
ArtificialOwl committed Mar 22, 2024
1 parent 4121b84 commit eee62ee
Show file tree
Hide file tree
Showing 9 changed files with 316 additions and 0 deletions.
4 changes: 4 additions & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
'OCP\\AppFramework\\Bootstrap\\IBootContext' => $baseDir . '/lib/public/AppFramework/Bootstrap/IBootContext.php',
'OCP\\AppFramework\\Bootstrap\\IBootstrap' => $baseDir . '/lib/public/AppFramework/Bootstrap/IBootstrap.php',
'OCP\\AppFramework\\Bootstrap\\IRegistrationContext' => $baseDir . '/lib/public/AppFramework/Bootstrap/IRegistrationContext.php',
'OCP\\AppFramework\\ConfigValues\\IConfigValue' => $baseDir . '/lib/public/AppFramework/ConfigValues/IConfigValue.php',
'OCP\\AppFramework\\Controller' => $baseDir . '/lib/public/AppFramework/Controller.php',
'OCP\\AppFramework\\Db\\DoesNotExistException' => $baseDir . '/lib/public/AppFramework/Db/DoesNotExistException.php',
'OCP\\AppFramework\\Db\\Entity' => $baseDir . '/lib/public/AppFramework/Db/Entity.php',
Expand Down Expand Up @@ -830,6 +831,9 @@
'OC\\AppFramework\\Bootstrap\\ServiceAliasRegistration' => $baseDir . '/lib/private/AppFramework/Bootstrap/ServiceAliasRegistration.php',
'OC\\AppFramework\\Bootstrap\\ServiceFactoryRegistration' => $baseDir . '/lib/private/AppFramework/Bootstrap/ServiceFactoryRegistration.php',
'OC\\AppFramework\\Bootstrap\\ServiceRegistration' => $baseDir . '/lib/private/AppFramework/Bootstrap/ServiceRegistration.php',
'OC\\AppFramework\\ConfigValues\\AConfigValue' => $baseDir . '/lib/private/AppFramework/ConfigValues/AConfigValue.php',
'OC\\AppFramework\\ConfigValues\\AppConfigValue' => $baseDir . '/lib/private/AppFramework/ConfigValues/AppConfigValue.php',
'OC\\AppFramework\\ConfigValues\\UserPreferenceValue' => $baseDir . '/lib/private/AppFramework/ConfigValues/UserPreferenceValue.php',
'OC\\AppFramework\\DependencyInjection\\DIContainer' => $baseDir . '/lib/private/AppFramework/DependencyInjection/DIContainer.php',
'OC\\AppFramework\\Http' => $baseDir . '/lib/private/AppFramework/Http.php',
'OC\\AppFramework\\Http\\Dispatcher' => $baseDir . '/lib/private/AppFramework/Http/Dispatcher.php',
Expand Down
4 changes: 4 additions & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\AppFramework\\Bootstrap\\IBootContext' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Bootstrap/IBootContext.php',
'OCP\\AppFramework\\Bootstrap\\IBootstrap' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Bootstrap/IBootstrap.php',
'OCP\\AppFramework\\Bootstrap\\IRegistrationContext' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Bootstrap/IRegistrationContext.php',
'OCP\\AppFramework\\ConfigValues\\IConfigValue' => __DIR__ . '/../../..' . '/lib/public/AppFramework/ConfigValues/IConfigValue.php',
'OCP\\AppFramework\\Controller' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Controller.php',
'OCP\\AppFramework\\Db\\DoesNotExistException' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Db/DoesNotExistException.php',
'OCP\\AppFramework\\Db\\Entity' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Db/Entity.php',
Expand Down Expand Up @@ -863,6 +864,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\AppFramework\\Bootstrap\\ServiceAliasRegistration' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Bootstrap/ServiceAliasRegistration.php',
'OC\\AppFramework\\Bootstrap\\ServiceFactoryRegistration' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Bootstrap/ServiceFactoryRegistration.php',
'OC\\AppFramework\\Bootstrap\\ServiceRegistration' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Bootstrap/ServiceRegistration.php',
'OC\\AppFramework\\ConfigValues\\AConfigValue' => __DIR__ . '/../../..' . '/lib/private/AppFramework/ConfigValues/AConfigValue.php',
'OC\\AppFramework\\ConfigValues\\AppConfigValue' => __DIR__ . '/../../..' . '/lib/private/AppFramework/ConfigValues/AppConfigValue.php',
'OC\\AppFramework\\ConfigValues\\UserPreferenceValue' => __DIR__ . '/../../..' . '/lib/private/AppFramework/ConfigValues/UserPreferenceValue.php',
'OC\\AppFramework\\DependencyInjection\\DIContainer' => __DIR__ . '/../../..' . '/lib/private/AppFramework/DependencyInjection/DIContainer.php',
'OC\\AppFramework\\Http' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http.php',
'OC\\AppFramework\\Http\\Dispatcher' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http/Dispatcher.php',
Expand Down
47 changes: 47 additions & 0 deletions lib/private/AppConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@

use InvalidArgumentException;
use JsonException;
use OC\AppFramework\Bootstrap\Coordinator;
use OC\AppFramework\ConfigValues\AppConfigValue;
use OCP\AppFramework\ConfigValues\IConfigValue;
use OCP\DB\Exception as DBException;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Exceptions\AppConfigIncorrectTypeException;
Expand Down Expand Up @@ -97,6 +100,7 @@ public function __construct(
protected IDBConnection $connection,
protected LoggerInterface $logger,
protected ICrypto $crypto,
private Coordinator $coordinator,
) {
}

Expand Down Expand Up @@ -455,6 +459,7 @@ private function getTypedValue(
int $type
): string {
$this->assertParams($app, $key, valueType: $type);
$this->compareRegisteredConfigValues($app, $key, $lazy, $type, $default);
$this->loadConfig($lazy);

/**
Expand Down Expand Up @@ -746,6 +751,7 @@ private function setTypedValue(
int $type
): bool {
$this->assertParams($app, $key);
$this->compareRegisteredConfigValues($app, $key, $lazy, $type);
$this->loadConfig($lazy);

$sensitive = $this->isTyped(self::VALUE_SENSITIVE, $type);
Expand Down Expand Up @@ -1506,4 +1512,45 @@ private function getSensitiveKeys(string $app): array {
public function clearCachedConfig(): void {
$this->clearCache();
}



private function compareRegisteredConfigValues(
string $app,
string $key,
bool &$lazy,
int &$type,
string &$default = '',
): void {
$context = $this->coordinator->getRegistrationContext();
$configValues = $context->getConfigValues($app, AppConfigValue::TYPE);

if (!array_key_exists($key, $configValues)) {
if ($context->strictConfigValues($app)) {
throw new AppConfigUnknownKeyException('This key is not defined in the list of available AppConfig keys for this app');
}
return;
}

$configValue = $configValues[$key];

if ($configValue->getValueType() !== match($type) {
self::VALUE_STRING => IConfigValue::TYPE_STRING,
self::VALUE_INT => IConfigValue::TYPE_INT,
self::VALUE_FLOAT => IConfigValue::TYPE_FLOAT,
self::VALUE_BOOL => IConfigValue::TYPE_BOOL,
self::VALUE_ARRAY => IConfigValue::TYPE_ARRAY,
}) {
throw new AppConfigTypeConflictException('This key is mistyped compare to the list of available AppConfig keys for this app');
}

$lazy = $configValue->isLazy();
$default = $configValue->getDefault() ?? $default;
if ($configValue->isSensitive()) {
$type |= self::VALUE_SENSITIVE;
}
if ($configValue->isDeprecated()) {
$this->logger->notice('config value ' . $key . ' from ' . $app . ' is set as deprecated');
}
}
}
34 changes: 34 additions & 0 deletions lib/private/AppFramework/Bootstrap/RegistrationContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
use OC\Support\CrashReport\Registry;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\AppFramework\ConfigValues\IConfigValue;
use OCP\AppFramework\Middleware;
use OCP\AppFramework\Services\InitialStateProvider;
use OCP\Authentication\IAlternativeLogin;
Expand Down Expand Up @@ -160,6 +161,7 @@ class RegistrationContext {
/** @var ServiceRegistration<IDeclarativeSettingsForm>[] */
private array $declarativeSettings = [];

private array $configValues = [];
/** @var ServiceRegistration<ITeamResourceProvider>[] */
private array $teamResourceProviders = [];

Expand Down Expand Up @@ -411,6 +413,14 @@ public function registerDeclarativeSettings(string $declarativeSettingsClass): v
$declarativeSettingsClass
);
}

public function registerConfigValues(bool $strict, IConfigValue ...$configValues): void {
$this->context->registerConfigValues(
$this->appId,
$strict,
...$configValues
);
}
};
}

Expand Down Expand Up @@ -590,6 +600,16 @@ public function registerDeclarativeSettings(string $appId, string $declarativeSe
$this->declarativeSettings[] = new ServiceRegistration($appId, $declarativeSettingsClass);
}

public function registerConfigValues(string $appId, bool $strict, IConfigValue ...$configValues): void {
$values = ['_strict' => $strict];
foreach ($configValues as $configValue) {
$values[$configValue->getConfigType()][$configValue->getKey()] = $configValue;
}

$this->configValues[$appId] = $values;
}


/**
* @param App[] $apps
*/
Expand Down Expand Up @@ -920,4 +940,18 @@ public function getTeamResourceProviders(): array {
public function getDeclarativeSettings(): array {
return $this->declarativeSettings;
}

/**
* @param string $app
* @param string $configType
*
* @return array<string, IConfigValue>
*/
public function getConfigValues(string $app, string $configType): array {
return $this->configValues[$app][$configType] ?? [];
}

public function strictConfigValues(string $app): bool {
return $this->configValues[$app]['_strict'] ?? false;
}
}
106 changes: 106 additions & 0 deletions lib/private/AppFramework/ConfigValues/AConfigValue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

declare(strict_types=1);
/**
* @copyright Copyright (c) 2024 Maxence Lange <maxence@artificial-owl.com>
*
* @author Maxence Lange <maxence@artificial-owl.com>
*
* @license AGPL-3.0 or later
*
* 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/>
*
*/

namespace OC\AppFramework\ConfigValues;

use OCP\AppFramework\ConfigValues\IConfigValue;

abstract class AConfigValue implements IConfigValue {
private ?string $default = null;
private bool $lazy = false;
private bool $sensitive = false;
private bool $deprecated = false;

public function __construct(
private string $key,
private int $valueType
) {
}

abstract public function getConfigType(): string;

public function getKey(): string {
return $this->key;
}

public function getValueType(): int {
return $this->valueType;
}

public function withDefaultString(string $default): self {
$this->default = $default;
return $this;
}

public function withDefaultInt(int $default): self {
$this->default = (string) $default;
return $this;
}

public function withDefaultFloat(float $default): self {
$this->default = (string) $default;
return $this;
}

public function withDefaultBool(bool $default): self {
$this->default = ($default) ? '1' : '0';
return $this;
}

public function withDefaultArray(array $default): self {
$this->default = json_encode($default);
return $this;
}

public function getDefault(): ?string {
return $this->default;
}

public function asLazy(bool $lazy = true): self {
$this->lazy = $lazy;
return $this;
}

public function isLazy(): bool {
return $this->lazy;
}

public function asSensitive(bool $sensitive = true): self {
$this->sensitive = $sensitive;
return $this;
}

public function isSensitive(): bool {
return $this->sensitive;
}

public function asDeprecated(bool $deprecated = true): self {
$this->deprecated = $deprecated;
return $this;
}

public function isDeprecated(): bool {
return $this->deprecated;
}
}
33 changes: 33 additions & 0 deletions lib/private/AppFramework/ConfigValues/AppConfigValue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);
/**
* @copyright Copyright (c) 2024 Maxence Lange <maxence@artificial-owl.com>
*
* @author Maxence Lange <maxence@artificial-owl.com>
*
* @license AGPL-3.0 or later
*
* 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/>
*
*/

namespace OC\AppFramework\ConfigValues;

class AppConfigValue extends AConfigValue {
public const TYPE = 'AppConfig';

public function getConfigType(): string {
return self::TYPE;
}
}
33 changes: 33 additions & 0 deletions lib/private/AppFramework/ConfigValues/UserPreferenceValue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);
/**
* @copyright Copyright (c) 2024 Maxence Lange <maxence@artificial-owl.com>
*
* @author Maxence Lange <maxence@artificial-owl.com>
*
* @license AGPL-3.0 or later
*
* 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/>
*
*/

namespace OC\AppFramework\ConfigValues;

class UserPreferenceValue extends AConfigValue {
public const TYPE = 'UserPreference';

public function getConfigType(): string {
return self::TYPE;
}
}
3 changes: 3 additions & 0 deletions lib/public/AppFramework/Bootstrap/IRegistrationContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

namespace OCP\AppFramework\Bootstrap;

use OCP\AppFramework\ConfigValues\IConfigValue;
use OCP\AppFramework\IAppContainer;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\Calendar\ICalendarProvider;
Expand Down Expand Up @@ -410,4 +411,6 @@ public function registerSetupCheck(string $setupCheckClass): void;
* @since 29.0.0
*/
public function registerDeclarativeSettings(string $declarativeSettingsClass): void;

public function registerConfigValues(bool $strict, IConfigValue ...$configValues): void;

Check failure on line 415 in lib/public/AppFramework/Bootstrap/IRegistrationContext.php

View workflow job for this annotation

GitHub Actions / static-code-analysis-ocp

InvalidDocblock

lib/public/AppFramework/Bootstrap/IRegistrationContext.php:415:2: InvalidDocblock: PHPDoc is required for methods in OCP. (see https://psalm.dev/008)
}
Loading

0 comments on commit eee62ee

Please sign in to comment.