Fix initialization of Relation and Tracker

Signed-off-by: Kamil Tekiela <tekiela246@gmail.com>
This commit is contained in:
Kamil Tekiela 2024-01-09 16:38:58 +01:00
parent 37d1b3ec33
commit 4e8c62f885
19 changed files with 47 additions and 209 deletions

View File

@ -15695,11 +15695,6 @@ parameters:
count: 2
path: src/Tracking/Tracker.php
-
message: "#^Only booleans are allowed in a negated boolean, mixed given\\.$#"
count: 2
path: src/Tracking/Tracker.php
-
message: "#^Only booleans are allowed in an if condition, string\\|false given\\.$#"
count: 1
@ -15825,11 +15820,6 @@ parameters:
count: 1
path: src/Tracking/Tracking.php
-
message: "#^Only booleans are allowed in a negated boolean, mixed given\\.$#"
count: 1
path: src/Tracking/TrackingChecker.php
-
message: "#^Method PhpMyAdmin\\\\Transformations\\:\\:getAvailableMimeTypes\\(\\) should return array but returns mixed\\.$#"
count: 1

View File

@ -5095,7 +5095,6 @@
<code>Config::getInstance()</code>
<code>Config::getInstance()</code>
<code>Config::getInstance()</code>
<code>Config::getInstance()</code>
</DeprecatedMethod>
<DeprecatedProperty>
<code>Routing::$route</code>
@ -6513,11 +6512,6 @@
<code><![CDATA[$_REQUEST['goto']]]></code>
</PossiblyInvalidCast>
</file>
<file src="src/Http/Middleware/ZeroConfPostConnection.php">
<DeprecatedMethod>
<code>DatabaseInterface::getInstance()</code>
</DeprecatedMethod>
</file>
<file src="src/Image/ImageWrapper.php">
<PossiblyUnusedReturnValue>
<code>bool</code>
@ -11857,8 +11851,6 @@
<MixedAssignment>
<code><![CDATA[$GLOBALS['export_type']]]></code>
<code><![CDATA[$result['tablename']]]></code>
<code>$trackingEnabled</code>
<code>$trackingEnabled</code>
<code>Current::$database</code>
</MixedAssignment>
<MixedInferredReturnType>
@ -11966,11 +11958,6 @@
<code>$versionNumber</code>
</PossiblyNullArgument>
</file>
<file src="src/Tracking/TrackingChecker.php">
<MixedAssignment>
<code>$trackingEnabled</code>
</MixedAssignment>
</file>
<file src="src/Transformations.php">
<DeprecatedMethod>
<code>DatabaseInterface::getInstance()</code>
@ -13809,8 +13796,6 @@
<code>Config::getInstance()</code>
<code>Config::getInstance()</code>
<code>Config::getInstance()</code>
<code>Config::getInstance()</code>
<code>Config::getInstance()</code>
<code>DatabaseInterface::getInstance()</code>
<code>DatabaseInterface::getInstance()</code>
</DeprecatedMethod>

View File

@ -40,12 +40,10 @@ use PhpMyAdmin\Http\Middleware\SqlQueryGlobalSetting;
use PhpMyAdmin\Http\Middleware\ThemeInitialization;
use PhpMyAdmin\Http\Middleware\TokenMismatchChecking;
use PhpMyAdmin\Http\Middleware\TokenRequestParamChecking;
use PhpMyAdmin\Http\Middleware\TrackerEnabling;
use PhpMyAdmin\Http\Middleware\UriSchemeUpdating;
use PhpMyAdmin\Http\Middleware\UrlParamsSetting;
use PhpMyAdmin\Http\Middleware\UrlRedirection;
use PhpMyAdmin\Http\Middleware\UserPreferencesLoading;
use PhpMyAdmin\Http\Middleware\ZeroConfPostConnection;
use PhpMyAdmin\Http\Response;
use PhpMyAdmin\Http\ServerRequest;
use PhpMyAdmin\Routing\Routing;
@ -116,8 +114,6 @@ class Application
$requestHandler->add(new TokenMismatchChecking());
$requestHandler->add(new ProfilingChecking());
$requestHandler->add(new UserPreferencesLoading($this->config));
$requestHandler->add(new TrackerEnabling());
$requestHandler->add(new ZeroConfPostConnection($this->config));
$runner = new RequestHandlerRunner(
$requestHandler,

View File

@ -5,7 +5,6 @@ declare(strict_types=1);
namespace PhpMyAdmin;
use PhpMyAdmin\Config\Settings\Server;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Dbal\Connection;
use PhpMyAdmin\Dbal\ConnectionException;
use PhpMyAdmin\Dbal\DbalInterface;
@ -1208,23 +1207,6 @@ class DatabaseInterface implements DbalInterface
}
}
/**
* Function called just after a connection to the MySQL database server has
* been established. It sets the connection collation, and determines the
* version of MySQL which is running.
*/
public function postConnectControl(Relation $relation): void
{
// If Zero configuration mode enabled, check PMA tables in current db.
if (! Config::getInstance()->settings['ZeroConf']) {
return;
}
$this->databaseList = null;
$relation->initRelationParamsCache();
}
/**
* returns a single value from the given result or query,
* if the query or the result has more than one row or field
@ -1665,14 +1647,6 @@ class DatabaseInterface implements DbalInterface
),
E_USER_WARNING,
);
return null;
}
if ($connectionType === Connection::TYPE_AUXILIARY) {
// Do not go back to main login if connection failed
// (currently used only in unit testing)
return null;
}
return null;

View File

@ -7,7 +7,6 @@ namespace PhpMyAdmin\Dbal;
use PhpMyAdmin\Column;
use PhpMyAdmin\ColumnFull;
use PhpMyAdmin\Config\Settings\Server;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Identifiers\DatabaseName;
@ -298,13 +297,6 @@ interface DbalInterface
*/
public function setCollation(string $collation): void;
/**
* Function called just after a connection to the MySQL database server has
* been established. It sets the connection collation, and determines the
* version of MySQL which is running.
*/
public function postConnectControl(Relation $relation): void;
/**
* returns a single value from the given result or query,
* if the query or the result has more than one row or field

View File

@ -7,6 +7,7 @@ namespace PhpMyAdmin\Http\Middleware;
use Fig\Http\Message\StatusCodeInterface;
use PhpMyAdmin\Config;
use PhpMyAdmin\Config\Settings\Server;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Container\ContainerBuilder;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Dbal\Connection;
@ -20,6 +21,7 @@ use PhpMyAdmin\Plugins\AuthenticationPlugin;
use PhpMyAdmin\Plugins\AuthenticationPluginFactory;
use PhpMyAdmin\ResponseRenderer;
use PhpMyAdmin\Template;
use PhpMyAdmin\Tracking\Tracker;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
@ -70,6 +72,15 @@ final class Authentication implements MiddlewareInterface
}
$this->connectToDatabaseServer(DatabaseInterface::getInstance(), $authPlugin, $currentServer);
// Relation should only be initialized after the connection is successful
/** @var Relation $relation */
$relation = ContainerBuilder::getContainer()->get('relation');
$relation->initRelationParamsCache();
// Tracker can only be activated after the relation has been initialized
Tracker::enable();
$authPlugin->rememberCredentials();
assert($request instanceof ServerRequest);
$authPlugin->checkTwoFactor($request);

View File

@ -12,7 +12,6 @@ use PhpMyAdmin\Http\ServerRequest;
use PhpMyAdmin\ResponseRenderer;
use PhpMyAdmin\Routing\Routing;
use PhpMyAdmin\Theme\ThemeManager;
use PhpMyAdmin\Tracking\Tracker;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
@ -36,7 +35,6 @@ final class MinimumCommonRedirection implements MiddlewareInterface
/** @var ThemeManager $themeManager */
$themeManager = $container->get(ThemeManager::class);
$this->config->loadUserPreferences($themeManager, true);
Tracker::enable();
assert($request instanceof ServerRequest);
try {

View File

@ -13,7 +13,6 @@ use PhpMyAdmin\Http\ServerRequest;
use PhpMyAdmin\ResponseRenderer;
use PhpMyAdmin\Routing\Routing;
use PhpMyAdmin\Theme\ThemeManager;
use PhpMyAdmin\Tracking\Tracker;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
@ -39,7 +38,6 @@ final class SetupPageRedirection implements MiddlewareInterface
/** @var ThemeManager $themeManager */
$themeManager = $container->get(ThemeManager::class);
$this->config->loadUserPreferences($themeManager, true);
Tracker::enable();
$this->setupPageBootstrap();
assert($request instanceof ServerRequest);

View File

@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Http\Middleware;
use PhpMyAdmin\Tracking\Tracker;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
final class TrackerEnabling implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
/* Tell tracker that it can actually work */
Tracker::enable();
return $handler->handle($request);
}
}

View File

@ -7,7 +7,6 @@ namespace PhpMyAdmin\Http\Middleware;
use PhpMyAdmin\Config;
use PhpMyAdmin\Container\ContainerBuilder;
use PhpMyAdmin\Theme\ThemeManager;
use PhpMyAdmin\Tracking\Tracker;
use PhpMyAdmin\UrlRedirector;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
@ -32,7 +31,6 @@ final class UrlRedirection implements MiddlewareInterface
/** @var ThemeManager $themeManager */
$themeManager = $container->get(ThemeManager::class);
$this->config->loadUserPreferences($themeManager, true);
Tracker::enable();
return UrlRedirector::redirect($this->getUrlParam($request->getQueryParams()['url'] ?? null));
}

View File

@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Http\Middleware;
use PhpMyAdmin\Config;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Container\ContainerBuilder;
use PhpMyAdmin\Current;
use PhpMyAdmin\DatabaseInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
final class ZeroConfPostConnection implements MiddlewareInterface
{
public function __construct(private readonly Config $config)
{
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$settings = $this->config->getSettings();
if (Current::$server > 0 && $settings->zeroConf) {
/** @var Relation $relation */
$relation = ContainerBuilder::getContainer()->get('relation');
DatabaseInterface::getInstance()->postConnectControl($relation);
}
return $handler->handle($request);
}
}

View File

@ -7,7 +7,6 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tracking;
use PhpMyAdmin\Cache;
use PhpMyAdmin\Config;
use PhpMyAdmin\ConfigStorage\Features\TrackingFeature;
use PhpMyAdmin\ConfigStorage\Relation;
@ -43,7 +42,7 @@ use function trim;
*/
class Tracker
{
public const TRACKER_ENABLED_CACHE_KEY = 'phpmyadmin.tracker.enabled';
private static bool $enabled = false;
/**
* Cache to avoid quering tracking status multiple times.
@ -58,7 +57,17 @@ class Tracker
*/
public static function enable(): void
{
Cache::set(self::TRACKER_ENABLED_CACHE_KEY, true);
self::$enabled = true;
}
public static function disable(): void
{
self::$enabled = false;
}
public static function isEnabled(): bool
{
return self::$enabled;
}
/**
@ -66,19 +75,12 @@ class Tracker
*/
public static function isActive(): bool
{
$trackingEnabled = Cache::get(self::TRACKER_ENABLED_CACHE_KEY, false);
if (! $trackingEnabled) {
if (! self::$enabled) {
return false;
}
/**
* We need to avoid attempt to track any queries from {@link Relation::getRelationParameters()}
*/
Cache::set(self::TRACKER_ENABLED_CACHE_KEY, false);
$relation = new Relation(DatabaseInterface::getInstance());
$relationParameters = $relation->getRelationParameters();
/* Restore original state */
Cache::set(self::TRACKER_ENABLED_CACHE_KEY, true);
return $relationParameters->trackingFeature !== null;
}
@ -91,8 +93,7 @@ class Tracker
*/
public static function isTracked(string $dbName, string $tableName): bool
{
$trackingEnabled = Cache::get(self::TRACKER_ENABLED_CACHE_KEY, false);
if (! $trackingEnabled) {
if (! self::$enabled) {
return false;
}
@ -100,15 +101,9 @@ class Tracker
return self::$trackingCache[$dbName][$tableName];
}
/**
* We need to avoid attempt to track any queries from {@link Relation::getRelationParameters()}
*/
Cache::set(self::TRACKER_ENABLED_CACHE_KEY, false);
$dbi = DatabaseInterface::getInstance();
$relation = new Relation($dbi);
$trackingFeature = $relation->getRelationParameters()->trackingFeature;
/* Restore original state */
Cache::set(self::TRACKER_ENABLED_CACHE_KEY, true);
if ($trackingFeature === null) {
return false;
}

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tracking;
use PhpMyAdmin\Cache;
use PhpMyAdmin\ConfigStorage\Features\TrackingFeature;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\DatabaseInterface;
@ -50,8 +49,7 @@ class TrackingChecker
/** @return TrackedTable[] */
public function getTrackedTables(string $dbName): array
{
$trackingEnabled = Cache::get(Tracker::TRACKER_ENABLED_CACHE_KEY, false);
if (! $trackingEnabled) {
if (! Tracker::isEnabled()) {
return [];
}

View File

@ -55,10 +55,8 @@ class TwoFactor
public function __construct(public string $user)
{
$dbi = DatabaseInterface::getInstance();
$relation = new Relation($dbi);
$relation->initRelationParamsCache();
$this->userPreferences = new UserPreferences($dbi, $relation, new Template());
$this->userPreferences = new UserPreferences($dbi, new Relation($dbi), new Template());
$this->available = $this->getAvailableBackends();
$this->config = $this->readConfig();
$this->writable = ($this->config['type'] === 'db');

View File

@ -15,6 +15,7 @@ use PhpMyAdmin\LanguageManager;
use PhpMyAdmin\SqlParser\Translator;
use PhpMyAdmin\Template;
use PhpMyAdmin\Tests\Stubs\DbiDummy;
use PhpMyAdmin\Tracking\Tracker;
use PhpMyAdmin\UserPrivileges;
use PhpMyAdmin\Utils\HttpRequest;
use PHPUnit\Framework\TestCase;
@ -91,6 +92,7 @@ abstract class AbstractTestCase extends TestCase
// Config before DBI
$this->setGlobalConfig();
Cache::purge();
Tracker::disable();
(new ReflectionProperty(Relation::class, 'cache'))->setValue(null, null);
ContainerBuilder::$container = null;

View File

@ -6,7 +6,6 @@ namespace PhpMyAdmin\Tests;
use PhpMyAdmin\Config;
use PhpMyAdmin\Config\Settings\Server;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Current;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Dbal\Connection;
@ -105,24 +104,6 @@ class DatabaseInterfaceTest extends AbstractTestCase
$this->assertInstanceOf(SystemDatabase::class, $sd);
}
public function testPostConnectControlWithZeroConf(): void
{
Config::getInstance()->settings['ZeroConf'] = true;
$dbi = $this->createDatabaseInterface();
$relationMock = $this->createMock(Relation::class);
$relationMock->expects($this->once())->method('initRelationParamsCache');
$dbi->postConnectControl($relationMock);
}
public function testPostConnectControlWithoutZeroConf(): void
{
Config::getInstance()->settings['ZeroConf'] = false;
$dbi = $this->createDatabaseInterface();
$relationMock = $this->createMock(Relation::class);
$relationMock->expects($this->never())->method('initRelationParamsCache');
$dbi->postConnectControl($relationMock);
}
/**
* Tests for DBI::postConnect() method.
* should not call setVersion method if cannot fetch version

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests\Tracking;
use PhpMyAdmin\Cache;
use PhpMyAdmin\ColumnFull;
use PhpMyAdmin\Config;
use PhpMyAdmin\ConfigStorage\Relation;
@ -58,13 +57,11 @@ class TrackerTest extends AbstractTestCase
*/
public function testEnabled(): void
{
$this->assertFalse(
Cache::has(Tracker::TRACKER_ENABLED_CACHE_KEY),
);
$this->assertFalse(Tracker::isEnabled());
Tracker::enable();
$this->assertTrue(
Cache::get(Tracker::TRACKER_ENABLED_CACHE_KEY),
);
$this->assertTrue(Tracker::isEnabled());
Tracker::disable();
$this->assertFalse(Tracker::isEnabled());
}
/**
@ -72,9 +69,7 @@ class TrackerTest extends AbstractTestCase
*/
public function testIsActive(): void
{
$this->assertFalse(
Cache::has(Tracker::TRACKER_ENABLED_CACHE_KEY),
);
$this->assertFalse(Tracker::isEnabled());
$this->assertFalse(
Tracker::isActive(),
@ -106,9 +101,7 @@ class TrackerTest extends AbstractTestCase
*/
public function testIsTracked(): void
{
$this->assertFalse(
Cache::has(Tracker::TRACKER_ENABLED_CACHE_KEY),
);
$this->assertFalse(Tracker::isEnabled());
$this->assertFalse(
Tracker::isTracked('', ''),

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests\Tracking;
use PhpMyAdmin\Cache;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\ConfigStorage\RelationParameters;
use PhpMyAdmin\DatabaseInterface;
@ -46,9 +45,7 @@ class TrackingCheckerTest extends AbstractTestCase
public function testGetTrackedTables(): void
{
$this->assertFalse(
Cache::has(Tracker::TRACKER_ENABLED_CACHE_KEY),
);
$this->assertFalse(Tracker::isEnabled());
$actual = $this->trackingChecker->getTrackedTables('dummyDb');
$this->assertEquals([], $actual);
@ -67,9 +64,7 @@ class TrackingCheckerTest extends AbstractTestCase
public function testGetUntrackedTableNames(): void
{
$this->assertFalse(
Cache::has(Tracker::TRACKER_ENABLED_CACHE_KEY),
);
$this->assertFalse(Tracker::isEnabled());
$expectation = ['0', 'actor', 'untrackedTable'];
$actual = $this->trackingChecker->getUntrackedTableNames('dummyDb');

View File

@ -7,6 +7,8 @@ namespace PhpMyAdmin\Tests;
use CodeLts\U2F\U2FServer\RegistrationRequest;
use CodeLts\U2F\U2FServer\SignRequest;
use PhpMyAdmin\Config;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\ConfigStorage\RelationParameters;
use PhpMyAdmin\Current;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Http\ServerRequest;
@ -17,6 +19,7 @@ use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
use Psr\Http\Message\ServerRequestInterface;
use ReflectionProperty;
use function count;
use function in_array;
@ -81,25 +84,13 @@ class TwoFactorTest extends AbstractTestCase
$this->dbi = $this->createDatabaseInterface($this->dummyDbi);
DatabaseInterface::$instance = $this->dbi;
$this->dummyDbi->removeDefaultResults();
$this->dummyDbi->addResult(
'SHOW TABLES FROM `phpmyadmin`;',
[
['pma__userconfig'],// Minimal working setup for 2FA
],
['Tables_in_phpmyadmin'],
);
$this->dummyDbi->addResult(
'SHOW TABLES FROM `phpmyadmin`',
[
['pma__userconfig'],// Minimal working setup for 2FA
],
['Tables_in_phpmyadmin'],
);
$this->dummyDbi->addResult('SELECT NULL FROM `pma__userconfig` LIMIT 0', [], ['NULL']);
$relationParameters = RelationParameters::fromArray([
'db' => 'phpmyadmin',
'user' => 'groot',
'userconfigwork' => true,
'userconfig' => 'pma__userconfig',
]);
(new ReflectionProperty(Relation::class, 'cache'))->setValue(null, $relationParameters);
}
/**
@ -118,7 +109,6 @@ class TwoFactorTest extends AbstractTestCase
$config['settings'] = [];
}
$this->dummyDbi->addSelectDb('phpmyadmin');
$this->loadResultForConfig($config);
return new TwoFactor($user);