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

Fix for issue #39530 to avoid regenerating admin grid flat table #39540

Open
wants to merge 20 commits into
base: 2.4-develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e881f57
Fix for issue #39530 to avoid regenerating admin grid flat table
senthilengg Jan 14, 2025
18c5a10
Merge branch '2.4-develop' into senthilengg-patch-for-github-issue-39530
senthilengg Jan 14, 2025
ebbfbb1
Adding Dependency to the module.xml
senthilengg Jan 15, 2025
be0ea8f
Fixing CodeSniff violation
senthilengg Jan 15, 2025
b3090e5
Updating dependency in composer.json
senthilengg Jan 15, 2025
f51a23a
Fixing Unit test setup and removed indexer from module sequence
Jan 15, 2025
8cc9bb4
Merge branch 'magento:2.4-develop' into senthilengg-patch-for-github-…
senthilengg Jan 15, 2025
52b508a
Adding unit test and coding standard fixes
Jan 16, 2025
d501636
Adding Adobe copyright instead of magento
Jan 16, 2025
bb59e6f
Merge branch '2.4-develop' into senthilengg-patch-for-github-issue-39530
senthilengg Jan 16, 2025
195ba0b
Adding backward compatibility
Jan 17, 2025
6afb87d
Unit test fixes and adopting PSR CS for newly introduced functions
Jan 17, 2025
0027a89
Merge branch '2.4-develop' into senthilengg-patch-for-github-issue-39530
senthilengg Jan 17, 2025
ab3b6c8
Merge branch '2.4-develop' into senthilengg-patch-for-github-issue-39530
senthilengg Jan 22, 2025
beb8c6f
Merge branch '2.4-develop' into senthilengg-patch-for-github-issue-39530
senthilengg Jan 25, 2025
17ad25d
Merge branch '2.4-develop' into senthilengg-patch-for-github-issue-39530
senthilengg Jan 28, 2025
1077bcf
Merge branch '2.4-develop' into senthilengg-patch-for-github-issue-39530
senthilengg Feb 2, 2025
f96ffd9
Merge branch '2.4-develop' into senthilengg-patch-for-github-issue-39530
senthilengg Feb 9, 2025
f9d2e87
Merge branch '2.4-develop' into senthilengg-patch-for-github-issue-39530
senthilengg Feb 28, 2025
9362276
Merge branch '2.4-develop' into senthilengg-patch-for-github-issue-39530
senthilengg Mar 8, 2025
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
107 changes: 88 additions & 19 deletions app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@
use Magento\Framework\Config\Data\ConfigData;
use Magento\Framework\Config\File\ConfigFilePool;
use Magento\Framework\Encryption\EncryptorInterface;
use Magento\Framework\Encryption\Encryptor;
use Magento\Framework\Exception\FileSystemException;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Filesystem;
use Magento\Framework\Filesystem\Directory\WriteInterface;
use Magento\Framework\Math\Random;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
use Magento\Framework\Model\ResourceModel\Db\Context;
use Magento\Framework\Indexer\ConfigInterface;
use Magento\Framework\Json\EncoderInterface;
use Magento\Indexer\Model\ResourceModel\Indexer\State\CollectionFactory;

/**
* Encryption key changer resource model
Expand All @@ -29,9 +33,9 @@
* @api
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @since 100.0.2
* @since 100.0.2
* @deprecated
* @see Extensible Reencryption Mechanism
* @see Extensible Reencryption Mechanism
*/
class Change extends AbstractDb
{
Expand Down Expand Up @@ -66,19 +70,45 @@ class Change extends AbstractDb
/**
* Random string generator
*
* @var Random
* @var Random
* @since 100.0.4
*/
protected $random;

/**
* @param Context $context
* @param Filesystem $filesystem
* @param Structure $structure
* @param EncryptorInterface $encryptor
* @param Writer $writer
* @param Random $random
* @param string $connectionName
* Indexer Configuration
*
* @var IndexerConfig
*/
protected $indexerConfig;

/**
* Json Encoder
*
* @var Encoder
*/
protected $encoder;

/**
* Indexer State Collection Factory
*
* @var IndexerStateCollection
*/
protected $indexerStateCollection;

/**
* @param Context $context
* @param Filesystem $filesystem
* @param Structure $structure
* @param EncryptorInterface $encryptor
* @param Writer $writer
* @param Random $random
* @param ConfigInterface $indexerConfig
* @param EncoderInterface $encoder
* @param CollectionFactory $indexerStateCollection
* @param string $connectionName
*
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
Context $context,
Expand All @@ -87,6 +117,9 @@ public function __construct(
EncryptorInterface $encryptor,
Writer $writer,
Random $random,
ConfigInterface $indexerConfig,
EncoderInterface $encoder,
CollectionFactory $indexerStateCollection,
$connectionName = null
) {
$this->encryptor = clone $encryptor;
Expand All @@ -95,6 +128,9 @@ public function __construct(
$this->structure = $structure;
$this->writer = $writer;
$this->random = $random;
$this->indexerConfig = $indexerConfig;
$this->encoder = $encoder;
$this->indexerStateCollection = $indexerStateCollection;
}

/**
Expand All @@ -110,11 +146,11 @@ protected function _construct()
/**
* Change encryption key
*
* @param string|null $key
* @return null|string
* @throws FileSystemException|LocalizedException|Exception
* @param string|null $key
* @return null|string
* @throws FileSystemException|LocalizedException|Exception
* @deprecated
* @see Extensible Reencryption Mechanism
* @see Extensible Reencryption Mechanism
*/
public function changeEncryptionKey($key = null)
{
Expand All @@ -139,6 +175,7 @@ public function changeEncryptionKey($key = null)
try {
$this->_reEncryptSystemConfigurationValues();
$this->_reEncryptCreditCardNumbers();
$this->updateIndexersHash();
$this->writer->saveConfig($configData);
$this->commit();
return $key;
Expand All @@ -151,14 +188,16 @@ public function changeEncryptionKey($key = null)
/**
* Gather all encrypted system config values and re-encrypt them
*
* @return void
* @return void
* @deprecated
* @see Extensible Reencryption Mechanism
* @see Extensible Reencryption Mechanism
*/
protected function _reEncryptSystemConfigurationValues()
{
// look for encrypted node entries in all system.xml files
/** @var Structure $configStructure */
/**
* @var Structure $configStructure
*/
$configStructure = $this->structure;
$paths = $configStructure->getFieldPathsByAttribute(
'backend_model',
Expand Down Expand Up @@ -188,9 +227,9 @@ protected function _reEncryptSystemConfigurationValues()
/**
* Gather saved credit card numbers from sales order payments and re-encrypt them
*
* @return void
* @return void
* @deprecated
* @see Extensible Reencryption Mechanism
* @see Extensible Reencryption Mechanism
*/
protected function _reEncryptCreditCardNumbers()
{
Expand All @@ -207,4 +246,34 @@ protected function _reEncryptCreditCardNumbers()
);
}
}

/**
* Refresh the indexer hash to avoid grid data regeneration
*
* @return void
*/
protected function updateIndexersHash()
{

$stateIndexers = [];
$stateCollection = $this->indexerStateCollection->create();
foreach ($stateCollection->getItems() as $state) {
/**
* @var \Magento\Indexer\Model\Indexer\State $state
*/
$stateIndexers[$state->getIndexerId()] = $state;
}

foreach ($this->indexerConfig->getIndexers() as $indexerId => $indexerConfig) {
$newHashConfig = $this->encryptor->hash(
$this->encoder->encode($indexerConfig),
Encryptor::HASH_VERSION_MD5
);

if (isset($stateIndexers[$indexerId])) {
$stateIndexers[$indexerId]->setHashConfig($newHashConfig);
$stateIndexers[$indexerId]->save();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<?php

/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2015 Adobe
* All Rights Reserved.
*/

declare(strict_types=1);

namespace Magento\EncryptionKey\Test\Unit\Model\ResourceModel\Key;
Expand All @@ -22,6 +24,11 @@
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Magento\Framework\Indexer\ConfigInterface;
use Magento\Framework\Json\EncoderInterface;
use Magento\Indexer\Model\ResourceModel\Indexer\State\Collection as StateCollection;
use Magento\Indexer\Model\ResourceModel\Indexer\State\CollectionFactory;
use Magento\Indexer\Model\Indexer\State;

/**
* Test Class For Magento\EncryptionKey\Model\ResourceModel\Key\Change
Expand Down Expand Up @@ -63,6 +70,15 @@ class ChangeTest extends TestCase
/** @var Change */
protected $model;

/** @var ConfigInterface|MockObject */
protected $indexerConfigMock;

/** @var EncoderInterface|MockObject */
protected $encoderMock;

/** @var CollectionFactory|MockObject */
protected $indexerStateCollectionMock;

protected function setUp(): void
{
$this->encryptMock = $this->getMockBuilder(EncryptorInterface::class)
Expand Down Expand Up @@ -98,6 +114,17 @@ protected function setUp(): void
->disableOriginalConstructor()
->getMock();
$this->randomMock = $this->createMock(Random::class);
$this->indexerConfigMock = $this->getMockBuilder(ConfigInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
$this->encoderMock = $this->getMockBuilder(EncoderInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
$this->indexerStateCollectionMock = $this->getMockBuilder(CollectionFactory::class)
->disableOriginalConstructor()
->onlyMethods(['create'])
->addMethods(['getItems'])
->getMock();

$helper = new ObjectManager($this);

Expand All @@ -112,12 +139,19 @@ protected function setUp(): void
'resource' => $this->resourceMock,
'transactionManager' => $this->transactionMock,
'relationProcessor' => $this->objRelationMock,
'random' => $this->randomMock
'random' => $this->randomMock,
'indexerConfig' => $this->indexerConfigMock,
'encoder' => $this->encoderMock,
'indexerStateCollection' => $this->indexerStateCollectionMock
]
);
}

private function setUpChangeEncryptionKey()
/**
* @param array $indexersData
* @param array $states
*/
private function setUpChangeEncryptionKey(array $indexersData, array $states)
{
$paths = ['path1', 'path2'];
$table = ['item1', 'item2'];
Expand All @@ -138,19 +172,50 @@ private function setUpChangeEncryptionKey()
$this->selectMock->expects($this->any())->method('update')->willReturnSelf();
$this->writerMock->expects($this->once())->method('saveConfig');
$this->adapterMock->expects($this->once())->method('getTransactionLevel')->willReturn(1);

$indexerStateCollection = $this->getMockBuilder(StateCollection::class)
->disableOriginalConstructor()
->getMock();

$this->indexerStateCollectionMock->expects($this->once())
->method('create')->willReturn($indexerStateCollection);

$finalStates = [];

foreach ($states as $key => $state) {
if (is_callable($state)) {
$finalStates[$key] = $state($this);
}
}

$indexerStateCollection->method('getItems')
->willReturn($finalStates);

$this->indexerConfigMock->expects($this->any())->method('getIndexers')->willReturn($indexersData);
}

public function testChangeEncryptionKey()
/**
* @param array $indexersData
* @param array $states
* @dataProvider loadDataDataProvider
*/
public function testChangeEncryptionKey(array $indexersData, array $states)
{
$this->setUpChangeEncryptionKey();

$this->setUpChangeEncryptionKey($indexersData, $states);
$this->randomMock->expects($this->never())->method('getRandomBytes');
$key = 'key';
$this->assertEquals($key, $this->model->changeEncryptionKey($key));
}

public function testChangeEncryptionKeyAutogenerate()
/**
* @param array $indexersData
* @param array $states
* @dataProvider loadDataDataProvider
*/
public function testChangeEncryptionKeyAutogenerate(array $indexersData, array $states)
{
$this->setUpChangeEncryptionKey();
$this->setUpChangeEncryptionKey($indexersData, $states);
$this->randomMock->expects($this->once())->method('getRandomBytes')->willReturn('abc');
$this->assertEquals(
ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . 'abc',
Expand All @@ -171,4 +236,48 @@ public function testChangeEncryptionKeyThrowsException()

$this->fail('An expected exception was not signaled.');
}

/**
* @param array $data
* @return MockObject|State
*/
private function getStateMock(array $data = [])
{
/** @var MockObject|State $state */
$state = $this->getMockBuilder(State::class)
->disableOriginalConstructor()
->getMock();
if (isset($data['indexer_id'])) {
$state->method('getIndexerId')
->willReturn($data['indexer_id']);
}

return $state;
}

/**
* @return array
*/
public static function loadDataDataProvider()
{
return [
[
'indexersData' => [
'indexer_2' => [
'indexer_id' => 'indexer_2',
],
'indexer_3' => [
'indexer_id' => 'indexer_3',
],
'indexer_1' => [
'indexer_id' => 'indexer_1',
],
],
'states' => [
'indexer_2' => static fn (self $testCase) => $testCase->getStateMock(['indexer_id' => 'indexer_2']),
'indexer_3' => static fn (self $testCase) => $testCase->getStateMock(['indexer_id' => 'indexer_3']),
],
]
];
}
}
3 changes: 2 additions & 1 deletion app/code/Magento/EncryptionKey/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"php": "~8.2.0||~8.3.0||~8.4.0",
"magento/framework": "*",
"magento/module-backend": "*",
"magento/module-config": "*"
"magento/module-config": "*",
"magento/module-indexer": "*"
},
"type": "magento2-module",
"license": [
Expand Down