Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor ConfigGenerator to replace/set crypt key instead of append #11155

Merged
merged 29 commits into from
Oct 11, 2017
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
13daa74
Refactor ConfigGenerator to replace crypt key instead of append
renttek Sep 30, 2017
f50ad05
Change visibility of configDataFactory-member to private
renttek Sep 30, 2017
4f3e981
Remove unnecessary/old comments
renttek Sep 30, 2017
2718be3
Make ConfigDataFactory-parameter optional
renttek Sep 30, 2017
b517623
Refactoring of createCryptConfig
renttek Sep 30, 2017
345a7f3
Introduce CryptKeyGgeneratorInterface
renttek Sep 30, 2017
ae06955
Remove/refactor chained null coalescing operator
renttek Sep 30, 2017
43e9751
Make 'Random' optional
renttek Sep 30, 2017
4b748cf
Fix Unit/Module/ConfigGeneratorTest for Setup
renttek Sep 30, 2017
010097d
Refactor createCacheHostsConfig
renttek Sep 30, 2017
2316cd8
Reformat some code to make it consistent
renttek Sep 30, 2017
c7ca261
Reformat the big array on the top
renttek Sep 30, 2017
eb33d60
Shorten some function calls in createDbConfig
renttek Sep 30, 2017
61d9767
Remove list() to fix some tests
renttek Sep 30, 2017
aec956f
Put "random" parameter back in ConfigGenerator
renttek Sep 30, 2017
e440946
Make "random" required CryptKeyGenerator
renttek Sep 30, 2017
885ecf8
Add random as constructor param in test
renttek Sep 30, 2017
91ee875
Assign deprecated random parameter to property
renttek Sep 30, 2017
3faf8b5
Add type hints for new interface and impementation
renttek Sep 30, 2017
1fd5b0e
Add type hint for ConfigDataFactory->create()
renttek Sep 30, 2017
a2ae382
Add some type hints
renttek Sep 30, 2017
c868fa2
Add a empty string return to satisfy return hints
renttek Sep 30, 2017
d78ae56
Add ObjectManager to ConfigDataFactory
renttek Sep 30, 2017
b2146db
Refactor test after modifying factory
renttek Sep 30, 2017
bab5e31
Fix issues of static code checks
renttek Oct 1, 2017
c638fd7
Suppress warnings of long var names in testcases
renttek Oct 1, 2017
62eff1d
Remove type hints and @api annotation
renttek Oct 1, 2017
58aab5e
Some more fixes for static analysis
renttek Oct 1, 2017
e8fe7ed
Remove @SuppressWarning annotations form tests
Oct 4, 2017
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
25 changes: 25 additions & 0 deletions lib/internal/Magento/Framework/Config/Data/ConfigDataFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Framework\Config\Data;

/**
* Factory for ConfigData
* @api
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So since it is a patch release we cannot add these tag currently. @renttek Can you check all the classes and remove the @api tag if you added it in.

*/
class ConfigDataFactory
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I missed this before but this factory should either be updated to match the standard defined in http://devdocs.magento.com/guides/v2.2/extension-dev-guide/factories.html or actually it might be possible to use the autogenerated factory here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Autogenerated factories are not allowed in Magento\Framework as far as I know. But, the best option is to commit autogenerated factory here.

{
/**
* Returns a new instance of ConfigData on every call.
*
* @param string $fileKey
* @return ConfigData
*/
public function create(string $fileKey)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can update this to use PHP 7's return type declaration if you would like. http://php.net/manual/en/migration70.new-features.php#migration70.new-features.return-type-declarations

{
return new ConfigData($fileKey);
}
}
149 changes: 86 additions & 63 deletions setup/src/Magento/Setup/Model/ConfigGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@

namespace Magento\Setup\Model;

use Magento\Framework\App\ObjectManager;
use Magento\Framework\Config\Data\ConfigData;
use Magento\Framework\Config\Data\ConfigDataFactory;
use Magento\Framework\Config\File\ConfigFilePool;
use Magento\Framework\Math\Random;
use Magento\Framework\App\DeploymentConfig;
use Magento\Framework\Config\ConfigOptionsListConstants;
use Magento\Framework\App\State;
use Magento\Framework\App\ObjectManagerFactory;
use Magento\Framework\Math\Random;

/**
* Creates deployment config data based on user input array
Expand All @@ -26,39 +27,57 @@ class ConfigGenerator
* @var array
*/
private static $paramMap = [
ConfigOptionsListConstants::INPUT_KEY_DB_HOST => ConfigOptionsListConstants::KEY_HOST,
ConfigOptionsListConstants::INPUT_KEY_DB_NAME => ConfigOptionsListConstants::KEY_NAME,
ConfigOptionsListConstants::INPUT_KEY_DB_USER => ConfigOptionsListConstants::KEY_USER,
ConfigOptionsListConstants::INPUT_KEY_DB_PASSWORD => ConfigOptionsListConstants::KEY_PASSWORD,
ConfigOptionsListConstants::INPUT_KEY_DB_PREFIX => ConfigOptionsListConstants::KEY_PREFIX,
ConfigOptionsListConstants::INPUT_KEY_DB_MODEL => ConfigOptionsListConstants::KEY_MODEL,
ConfigOptionsListConstants::INPUT_KEY_DB_ENGINE => ConfigOptionsListConstants::KEY_ENGINE,
ConfigOptionsListConstants::INPUT_KEY_DB_HOST => ConfigOptionsListConstants::KEY_HOST,
ConfigOptionsListConstants::INPUT_KEY_DB_NAME => ConfigOptionsListConstants::KEY_NAME,
ConfigOptionsListConstants::INPUT_KEY_DB_USER => ConfigOptionsListConstants::KEY_USER,
ConfigOptionsListConstants::INPUT_KEY_DB_PASSWORD => ConfigOptionsListConstants::KEY_PASSWORD,
ConfigOptionsListConstants::INPUT_KEY_DB_PREFIX => ConfigOptionsListConstants::KEY_PREFIX,
ConfigOptionsListConstants::INPUT_KEY_DB_MODEL => ConfigOptionsListConstants::KEY_MODEL,
ConfigOptionsListConstants::INPUT_KEY_DB_ENGINE => ConfigOptionsListConstants::KEY_ENGINE,
ConfigOptionsListConstants::INPUT_KEY_DB_INIT_STATEMENTS => ConfigOptionsListConstants::KEY_INIT_STATEMENTS,
ConfigOptionsListConstants::INPUT_KEY_ENCRYPTION_KEY => ConfigOptionsListConstants::KEY_ENCRYPTION_KEY,
ConfigOptionsListConstants::INPUT_KEY_SESSION_SAVE => ConfigOptionsListConstants::KEY_SAVE,
ConfigOptionsListConstants::INPUT_KEY_RESOURCE => ConfigOptionsListConstants::KEY_RESOURCE,
ConfigOptionsListConstants::INPUT_KEY_ENCRYPTION_KEY => ConfigOptionsListConstants::KEY_ENCRYPTION_KEY,
ConfigOptionsListConstants::INPUT_KEY_SESSION_SAVE => ConfigOptionsListConstants::KEY_SAVE,
ConfigOptionsListConstants::INPUT_KEY_RESOURCE => ConfigOptionsListConstants::KEY_RESOURCE,
];

/**
* @var DeploymentConfig
*/
protected $deploymentConfig;

/**
* @var Random
* @deprecated since 100.2.0
*/
protected $random;

/**
* @var DeploymentConfig
* @var ConfigDataFactory
*/
protected $deploymentConfig;
private $configDataFactory;

/**
* @var CryptKeyGeneratorInterface
*/
private $cryptKeyGenerator;

/**
* Constructor
*
* @param Random $random
* @param Random $random Deprecated since 100.2.0
* @param DeploymentConfig $deploymentConfig
* @param ConfigDataFactory|null $configDataFactory
* @param CryptKeyGeneratorInterface|null $cryptKeyGenerator
*/
public function __construct(Random $random, DeploymentConfig $deploymentConfig)
{
$this->random = $random;
public function __construct(
Random $random,
DeploymentConfig $deploymentConfig,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned we need to keep the random parameter here but can mark the property as deprecated.

ConfigDataFactory $configDataFactory = null,
CryptKeyGeneratorInterface $cryptKeyGenerator = null
) {
$this->deploymentConfig = $deploymentConfig;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we still need to assign $this->random = $random here in-case someone is using it in an extension to this class.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aah, I thought I added id back.

$this->configDataFactory = $configDataFactory ?? ObjectManager::getInstance()->get(ConfigDataFactory::class);
$this->cryptKeyGenerator = $cryptKeyGenerator ?? ObjectManager::getInstance()->get(CryptKeyGenerator::class);
}

/**
Expand All @@ -70,23 +89,17 @@ public function createCryptConfig(array $data)
{
$currentKey = $this->deploymentConfig->get(ConfigOptionsListConstants::CONFIG_PATH_CRYPT_KEY);

$configData = new ConfigData(ConfigFilePool::APP_ENV);
if (isset($data[ConfigOptionsListConstants::INPUT_KEY_ENCRYPTION_KEY])) {
if ($currentKey !== null) {
$key = $currentKey . "\n" . $data[ConfigOptionsListConstants::INPUT_KEY_ENCRYPTION_KEY];
} else {
$key = $data[ConfigOptionsListConstants::INPUT_KEY_ENCRYPTION_KEY];
}
$configData = $this->configDataFactory->create(ConfigFilePool::APP_ENV);

$configData->set(ConfigOptionsListConstants::CONFIG_PATH_CRYPT_KEY, $key);
} else {
if ($currentKey === null) {
$configData->set(
ConfigOptionsListConstants::CONFIG_PATH_CRYPT_KEY,
md5($this->random->getRandomString(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE))
);
}
}
// Use given key if set, else use current
$key = $data[ConfigOptionsListConstants::INPUT_KEY_ENCRYPTION_KEY] ?? $currentKey;

// If there is no key given or currently set, generate a new one
$key = $key ?? $this->cryptKeyGenerator->generate();

// Chaining of ".. ?? .." is not used to keep it simpler to understand

$configData->set(ConfigOptionsListConstants::CONFIG_PATH_CRYPT_KEY, $key);

return $configData;
}
Expand All @@ -99,7 +112,7 @@ public function createCryptConfig(array $data)
*/
public function createSessionConfig(array $data)
{
$configData = new ConfigData(ConfigFilePool::APP_ENV);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice work, good to see this being moved out to a factory.

$configData = $this->configDataFactory->create(ConfigFilePool::APP_ENV);

if (isset($data[ConfigOptionsListConstants::INPUT_KEY_SESSION_SAVE])) {
$configData->set(
Expand Down Expand Up @@ -132,7 +145,7 @@ public function createDefinitionsConfig(array $data)
*/
public function createDbConfig(array $data)
{
$configData = new ConfigData(ConfigFilePool::APP_ENV);
$configData = $this->configDataFactory->create(ConfigFilePool::APP_ENV);

$optional = [
ConfigOptionsListConstants::INPUT_KEY_DB_HOST,
Expand All @@ -151,25 +164,18 @@ public function createDbConfig(array $data)
);
}

$dbConnectionPrefix = ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT . '/';

foreach ($optional as $key) {
if (isset($data[$key])) {
$configData->set(
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT . '/' . self::$paramMap[$key],
$data[$key]
);
$configData->set($dbConnectionPrefix . self::$paramMap[$key], $data[$key]);
}
}

$currentStatus = $this->deploymentConfig->get(
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT . '/' . ConfigOptionsListConstants::KEY_ACTIVE
);
$currentStatus = $this->deploymentConfig->get($dbConnectionPrefix . ConfigOptionsListConstants::KEY_ACTIVE);

if ($currentStatus === null) {
$configData->set(
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT
. '/' . ConfigOptionsListConstants::KEY_ACTIVE,
'1'
);
$configData->set($dbConnectionPrefix . ConfigOptionsListConstants::KEY_ACTIVE, '1');
}

return $configData;
Expand All @@ -182,7 +188,7 @@ public function createDbConfig(array $data)
*/
public function createResourceConfig()
{
$configData = new ConfigData(ConfigFilePool::APP_ENV);
$configData = $this->configDataFactory->create(ConfigFilePool::APP_ENV);

if ($this->deploymentConfig->get(ConfigOptionsListConstants::CONFIG_PATH_RESOURCE_DEFAULT_SETUP) === null) {
$configData->set(ConfigOptionsListConstants::CONFIG_PATH_RESOURCE_DEFAULT_SETUP, 'default');
Expand All @@ -198,10 +204,12 @@ public function createResourceConfig()
*/
public function createXFrameConfig()
{
$configData = new ConfigData(ConfigFilePool::APP_ENV);
$configData = $this->configDataFactory->create(ConfigFilePool::APP_ENV);

if ($this->deploymentConfig->get(ConfigOptionsListConstants::CONFIG_PATH_X_FRAME_OPT) === null) {
$configData->set(ConfigOptionsListConstants::CONFIG_PATH_X_FRAME_OPT, 'SAMEORIGIN');
}

return $configData;
}

Expand All @@ -212,10 +220,12 @@ public function createXFrameConfig()
*/
public function createModeConfig()
{
$configData = new ConfigData(ConfigFilePool::APP_ENV);
$configData = $this->configDataFactory->create(ConfigFilePool::APP_ENV);

if ($this->deploymentConfig->get(State::PARAM_MODE) === null) {
$configData->set(State::PARAM_MODE, State::MODE_DEFAULT);
}

return $configData;
}

Expand All @@ -227,22 +237,35 @@ public function createModeConfig()
*/
public function createCacheHostsConfig(array $data)
{
$configData = new ConfigData(ConfigFilePool::APP_ENV);
$configData = $this->configDataFactory->create(ConfigFilePool::APP_ENV);

if (isset($data[ConfigOptionsListConstants::INPUT_KEY_CACHE_HOSTS])) {
$hostData = explode(',', $data[ConfigOptionsListConstants::INPUT_KEY_CACHE_HOSTS]);
$hosts = [];
foreach ($hostData as $data) {
$dataArray = explode(':', trim($data));
$host = [];
$host['host'] = $dataArray[0];
if (isset($dataArray[1])) {
$host['port'] = $dataArray[1];
}
$hosts[] = $host;
}
$hosts = explode(',', $data[ConfigOptionsListConstants::INPUT_KEY_CACHE_HOSTS]);
$hosts = array_map([$this, 'mapHostData'], $hosts);
$configData->set(ConfigOptionsListConstants::CONFIG_PATH_CACHE_HOSTS, $hosts);
}

$configData->setOverrideWhenSave(true);
return $configData;
}

/**
* Splits host data to host and port and returns them as an assoc. array.
*
* @param string $hostData
*
* @return array
*/
private function mapHostData($hostData)
{
$hostDataParts = explode(':', trim($hostData));

$tmp = ['host' => $hostDataParts[0]];

if (isset($hostDataParts[1])) {
$tmp['port'] = $hostDataParts[1];
}

return $tmp;
}
}
51 changes: 51 additions & 0 deletions setup/src/Magento/Setup/Model/CryptKeyGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Setup\Model;

use Magento\Framework\Config\ConfigOptionsListConstants;
use Magento\Framework\Math\Random;

/**
* Generates a crypt
* @api
*/
class CryptKeyGenerator implements CryptKeyGeneratorInterface
{
/**
* @var Random
*/
private $random;

public function __construct(Random $random)
{
$this->random = $random;
}

/**
* Generates & returns a string to be used as crypt key.
*
* The key length is not a parameter, but an implementation detail.
*
* @return string
*
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function generate()
{
return md5($this->getRandomString());
}

/**
* Returns a random string.
*
* @return string
*/
private function getRandomString()
{
return $this->random->getRandomString(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE);
}
}
23 changes: 23 additions & 0 deletions setup/src/Magento/Setup/Model/CryptKeyGeneratorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Setup\Model;

/**
* Interface for crypt key generators.
* @api
*/
interface CryptKeyGeneratorInterface
{
/**
* Generates & returns a string to be used as crypt key.
*
* The key length is not a parameter, but an implementation detail.
*
* @return string
*/
public function generate();
}
Loading