From 57029441168f81e94a974affd8be610c732e8172 Mon Sep 17 00:00:00 2001 From: Philipp Date: Sat, 11 Sep 2021 14:33:26 +0200 Subject: [PATCH] Add the possibility to use a different configuration directory --- doc/Config.md | 3 + src/App.php | 2 +- src/Module/Admin/Summary.php | 2 +- src/Util/ConfigFileLoader.php | 17 +++++- static/dependencies.config.php | 1 + tests/Util/VFSTrait.php | 1 + tests/src/Core/Cache/DatabaseCacheTest.php | 2 +- .../src/Core/Lock/DatabaseLockDriverTest.php | 2 +- tests/src/Core/StorageManagerTest.php | 2 +- tests/src/Model/ProcessTest.php | 2 +- .../src/Model/Storage/DatabaseStorageTest.php | 2 +- .../src/Util/Config/ConfigFileLoaderTest.php | 58 ++++++++++++++++--- 12 files changed, 75 insertions(+), 19 deletions(-) diff --git a/doc/Config.md b/doc/Config.md index f2224f5de..885509939 100644 --- a/doc/Config.md +++ b/doc/Config.md @@ -42,6 +42,9 @@ Some examples of common known configuration files: Addons can define their own default configuration values in `addon/[addon]/config/[addon].config.php` which is loaded when the addon is activated. +If needed, an alternative `config` path can be used by using the `FRIENDICA_CONFIG_DIR` environment variable (full path required!). +This is useful in case of hardening the system by separating configuration from program binaries. + ### Static Configuration location The `static` directory holds the codebase default configurations files. diff --git a/src/App.php b/src/App.php index 6e9f7c318..67b2592bd 100644 --- a/src/App.php +++ b/src/App.php @@ -352,7 +352,7 @@ class App $this->profiler->update($this->config); Core\Hook::loadHooks(); - $loader = new ConfigFileLoader($this->getBasePath()); + $loader = new ConfigFileLoader($this->getBasePath(), $_SERVER); Core\Hook::callAll('load_config', $loader); } diff --git a/src/Module/Admin/Summary.php b/src/Module/Admin/Summary.php index 1c5785d1f..9bd902b35 100644 --- a/src/Module/Admin/Summary.php +++ b/src/Module/Admin/Summary.php @@ -151,7 +151,7 @@ class Summary extends BaseAdmin } // check legacy basepath settings - $configLoader = new ConfigFileLoader($a->getBasePath()); + $configLoader = new ConfigFileLoader($a->getBasePath(), $_SERVER); $configCache = new Cache(); $configLoader->setupCache($configCache); $confBasepath = $configCache->get('system', 'basepath'); diff --git a/src/Util/ConfigFileLoader.php b/src/Util/ConfigFileLoader.php index 0c416a189..f2aa9124f 100644 --- a/src/Util/ConfigFileLoader.php +++ b/src/Util/ConfigFileLoader.php @@ -35,6 +35,13 @@ use Friendica\Core\Config\Cache; */ class ConfigFileLoader { + /** + * The key of the $_SERVER variable to override the config directory + * + * @var string + */ + const CONFIG_DIR_ENV = 'FRIENDICA_CONFIG_DIR'; + /** * The Sub directory of the config-files * @@ -83,10 +90,14 @@ class ConfigFileLoader */ private $staticDir; - public function __construct(string $basePath) + public function __construct(string $basePath, array $server) { - $this->baseDir = $basePath; - $this->configDir = $this->baseDir . DIRECTORY_SEPARATOR . self::CONFIG_DIR; + $this->baseDir = $basePath; + if (!empty($server[self::CONFIG_DIR_ENV]) && is_dir($server[self::CONFIG_DIR_ENV])) { + $this->configDir = $server[self::CONFIG_DIR_ENV]; + } else { + $this->configDir = $this->baseDir . DIRECTORY_SEPARATOR . self::CONFIG_DIR; + } $this->staticDir = $this->baseDir . DIRECTORY_SEPARATOR . self::STATIC_DIR; } diff --git a/static/dependencies.config.php b/static/dependencies.config.php index 2068b6b1a..79b7f1364 100644 --- a/static/dependencies.config.php +++ b/static/dependencies.config.php @@ -77,6 +77,7 @@ return [ 'shared' => true, 'constructParams' => [ [Dice::INSTANCE => '$basepath'], + $_SERVER, ], ], Config\Cache::class => [ diff --git a/tests/Util/VFSTrait.php b/tests/Util/VFSTrait.php index 7040f1fc0..0b594814f 100644 --- a/tests/Util/VFSTrait.php +++ b/tests/Util/VFSTrait.php @@ -43,6 +43,7 @@ trait VFSTrait 'static' => [], 'test' => [], 'logs' => [], + 'config2' => [], ]; // create a virtual directory and copy all needed files and folders to it diff --git a/tests/src/Core/Cache/DatabaseCacheTest.php b/tests/src/Core/Cache/DatabaseCacheTest.php index 0d57f7128..a89714a85 100644 --- a/tests/src/Core/Cache/DatabaseCacheTest.php +++ b/tests/src/Core/Cache/DatabaseCacheTest.php @@ -55,7 +55,7 @@ class DatabaseCacheTest extends CacheTest // load real config to avoid mocking every config-entry which is related to the Database class $configFactory = new ConfigFactory(); - $loader = new ConfigFileLoader($this->root->url()); + $loader = new ConfigFileLoader($this->root->url(), []); $configCache = $configFactory->createCache($loader); $dba = new StaticDatabase($configCache, $profiler, $logger); diff --git a/tests/src/Core/Lock/DatabaseLockDriverTest.php b/tests/src/Core/Lock/DatabaseLockDriverTest.php index f7db9d8b4..9e995c123 100644 --- a/tests/src/Core/Lock/DatabaseLockDriverTest.php +++ b/tests/src/Core/Lock/DatabaseLockDriverTest.php @@ -57,7 +57,7 @@ class DatabaseLockDriverTest extends LockTest // load real config to avoid mocking every config-entry which is related to the Database class $configFactory = new ConfigFactory(); - $loader = new ConfigFileLoader($this->root->url()); + $loader = new ConfigFileLoader($this->root->url(), []); $configCache = $configFactory->createCache($loader); $dba = new StaticDatabase($configCache, $profiler, $logger); diff --git a/tests/src/Core/StorageManagerTest.php b/tests/src/Core/StorageManagerTest.php index 93fc0b664..f68bf027b 100644 --- a/tests/src/Core/StorageManagerTest.php +++ b/tests/src/Core/StorageManagerTest.php @@ -73,7 +73,7 @@ class StorageManagerTest extends DatabaseTest // load real config to avoid mocking every config-entry which is related to the Database class $configFactory = new ConfigFactory(); - $loader = new ConfigFileLoader($this->root->url()); + $loader = new ConfigFileLoader($this->root->url(), []); $configCache = $configFactory->createCache($loader); $this->dba = new StaticDatabase($configCache, $profiler, $this->logger); diff --git a/tests/src/Model/ProcessTest.php b/tests/src/Model/ProcessTest.php index 0410ff2de..66a02eced 100644 --- a/tests/src/Model/ProcessTest.php +++ b/tests/src/Model/ProcessTest.php @@ -33,7 +33,7 @@ class ProcessTest extends DatabaseTest // load real config to avoid mocking every config-entry which is related to the Database class $configFactory = new ConfigFactory(); - $loader = new ConfigFileLoader($this->root->url()); + $loader = new ConfigFileLoader($this->root->url(), []); $configCache = $configFactory->createCache($loader); $this->dba = new StaticDatabase($configCache, $profiler, $logger); diff --git a/tests/src/Model/Storage/DatabaseStorageTest.php b/tests/src/Model/Storage/DatabaseStorageTest.php index d7b810c1f..8fd8c8c42 100644 --- a/tests/src/Model/Storage/DatabaseStorageTest.php +++ b/tests/src/Model/Storage/DatabaseStorageTest.php @@ -55,7 +55,7 @@ class DatabaseStorageTest extends StorageTest // load real config to avoid mocking every config-entry which is related to the Database class $configFactory = new ConfigFactory(); - $loader = new ConfigFileLoader($this->root->url()); + $loader = new ConfigFileLoader($this->root->url(), []); $configCache = $configFactory->createCache($loader); $dba = new StaticDatabase($configCache, $profiler, $logger); diff --git a/tests/src/Util/Config/ConfigFileLoaderTest.php b/tests/src/Util/Config/ConfigFileLoaderTest.php index b54ae1ec2..c69d94679 100644 --- a/tests/src/Util/Config/ConfigFileLoaderTest.php +++ b/tests/src/Util/Config/ConfigFileLoaderTest.php @@ -45,7 +45,7 @@ class ConfigFileLoaderTest extends MockedTest { $this->delConfigFile('local.config.php'); - $configFileLoader = new ConfigFileLoader($this->root->url()); + $configFileLoader = new ConfigFileLoader($this->root->url(), []); $configCache = new Cache(); $configFileLoader->setupCache($configCache); @@ -67,7 +67,7 @@ class ConfigFileLoaderTest extends MockedTest ->at($this->root->getChild('config')) ->setContent('root->url()); + $configFileLoader = new ConfigFileLoader($this->root->url(), []); $configCache = new Cache(); $configFileLoader->setupCache($configCache); @@ -91,7 +91,7 @@ class ConfigFileLoaderTest extends MockedTest ->at($this->root->getChild('config')) ->setContent(file_get_contents($file)); - $configFileLoader = new ConfigFileLoader($this->root->url()); + $configFileLoader = new ConfigFileLoader($this->root->url(), []); $configCache = new Cache(); $configFileLoader->setupCache($configCache); @@ -123,7 +123,7 @@ class ConfigFileLoaderTest extends MockedTest ->at($this->root->getChild('config')) ->setContent(file_get_contents($file)); - $configFileLoader = new ConfigFileLoader($this->root->url()); + $configFileLoader = new ConfigFileLoader($this->root->url(), []); $configCache = new Cache(); $configFileLoader->setupCache($configCache); @@ -154,7 +154,7 @@ class ConfigFileLoaderTest extends MockedTest ->at($this->root) ->setContent(file_get_contents($file)); - $configFileLoader = new ConfigFileLoader($this->root->url()); + $configFileLoader = new ConfigFileLoader($this->root->url(), []); $configCache = new Cache(); $configFileLoader->setupCache($configCache); @@ -203,7 +203,7 @@ class ConfigFileLoaderTest extends MockedTest ->at($this->root->getChild('addon')->getChild('test')->getChild('config')) ->setContent(file_get_contents($file)); - $configFileLoader = new ConfigFileLoader($this->root->url()); + $configFileLoader = new ConfigFileLoader($this->root->url(), []); $conf = $configFileLoader->loadAddonConfig('test'); @@ -235,7 +235,7 @@ class ConfigFileLoaderTest extends MockedTest ->at($this->root->getChild('config')) ->setContent(file_get_contents($fileDir . 'B.config.php')); - $configFileLoader = new ConfigFileLoader($this->root->url()); + $configFileLoader = new ConfigFileLoader($this->root->url(), []); $configCache = new Cache(); $configFileLoader->setupCache($configCache); @@ -264,7 +264,7 @@ class ConfigFileLoaderTest extends MockedTest ->at($this->root->getChild('config')) ->setContent(file_get_contents($fileDir . 'B.ini.php')); - $configFileLoader = new ConfigFileLoader($this->root->url()); + $configFileLoader = new ConfigFileLoader($this->root->url(), []); $configCache = new Cache(); $configFileLoader->setupCache($configCache); @@ -293,7 +293,7 @@ class ConfigFileLoaderTest extends MockedTest ->at($this->root->getChild('config')) ->setContent(file_get_contents($fileDir . 'B.ini.php')); - $configFileLoader = new ConfigFileLoader($this->root->url()); + $configFileLoader = new ConfigFileLoader($this->root->url(), []); $configCache = new Cache(); $configFileLoader->setupCache($configCache); @@ -301,4 +301,44 @@ class ConfigFileLoaderTest extends MockedTest self::assertEquals('admin@test.it', $configCache->get('config', 'admin_email')); self::assertEmpty($configCache->get('system', 'NewKey')); } + + /** + * Test that using a wrong configuration directory leads to the "normal" config path + */ + public function testWrongEnvDir() + { + $this->delConfigFile('local.config.php'); + + $configFileLoader = new ConfigFileLoader($this->root->url(), ['FRIENDICA_CONFIG_DIR' => '/a/wrong/dir/']); + $configCache = new Cache(); + + $configFileLoader->setupCache($configCache); + + self::assertEquals($this->root->url(), $configCache->get('system', 'basepath')); + } + + /** + * Test that a different location of the configuration directory produces the expected output + */ + public function testRightEnvDir() + { + $this->delConfigFile('local.config.php'); + + $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + 'datasets' . DIRECTORY_SEPARATOR . + 'config' . DIRECTORY_SEPARATOR; + + vfsStream::newFile('B.config.php') + ->at($this->root->getChild('config2')) + ->setContent(file_get_contents($fileDir . 'B.config.php')); + + $configFileLoader = new ConfigFileLoader($this->root->url(), ['FRIENDICA_CONFIG_DIR' => $this->root->getChild('config2')->url()]); + $configCache = new Cache(); + + $configFileLoader->setupCache($configCache); + + self::assertEquals('newValue', $configCache->get('system', 'newKey')); + } }