add migrations
This commit is contained in:
parent
028fc05d54
commit
462bb34447
|
@ -63,12 +63,14 @@ and its requirements.
|
||||||
|
|
||||||
The Flow and Wave themes are supported by default. Other themes may require customisation.
|
The Flow and Wave themes are supported by default. Other themes may require customisation.
|
||||||
|
|
||||||
## Module installation
|
## Module installation / update
|
||||||
|
|
||||||
Open a command line interface and navigate to the shop root directory (parent of source and vendor). Execute the following command. Adapt the paths to your environment.
|
Open a command line interface and navigate to the shop root directory (parent of source and vendor). Execute the following commands. Adapt the paths to your environment.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
php composer require d3/oxid-twofactor-passwordless:^1.0
|
composer require d3/oxid-twofactor-passwordless:^1.0
|
||||||
|
|
||||||
|
./vendor/bin/oe-eshop-db_migrate migrations:migrate d3webauthn
|
||||||
```
|
```
|
||||||
|
|
||||||
If a reference to an unsuitable package `symfony/process` is shown, this must be changed. To do this, please add the switch `-W` to the above command (`... require -W ...`).
|
If a reference to an unsuitable package `symfony/process` is shown, this must be changed. To do this, please add the switch `-W` to the above command (`... require -W ...`).
|
||||||
|
|
|
@ -63,12 +63,14 @@ und dessen Anforderungen.
|
||||||
|
|
||||||
Im Standard wird das Flow- und Wave-Theme unterstützt. Andere Themes können Anpassungen erfordern.
|
Im Standard wird das Flow- und Wave-Theme unterstützt. Andere Themes können Anpassungen erfordern.
|
||||||
|
|
||||||
## Modulinstallation
|
## Modulinstallation / -update
|
||||||
|
|
||||||
Öffnen Sie eine Kommandozeile und navigieren Sie zum Stammverzeichnis des Shops (Elternverzeichnis von source und vendor). Führen Sie den folgenden Befehl aus. Passen Sie die Pfadangaben an Ihre Installationsumgebung an.
|
Öffnen Sie eine Kommandozeile und navigieren Sie zum Stammverzeichnis des Shops (Elternverzeichnis von source und vendor). Führen Sie die folgenden Befehle aus. Passen Sie die Pfadangaben an Ihre Installationsumgebung an.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
php composer require d3/oxid-twofactor-passwordless:^1.0
|
composer require d3/oxid-twofactor-passwordless:^1.0
|
||||||
|
|
||||||
|
./vendor/bin/oe-eshop-db_migrate migrations:migrate d3webauthn
|
||||||
```
|
```
|
||||||
|
|
||||||
Wird ein Hinweis auf ein unpassendes Paket "symfony/process" gezeigt, muss dieses geändert werden. Fügen Sie dazu in den oben genannten Befehl bitte den Schalter `-W` ein (`... require -W ...`).
|
Wird ein Hinweis auf ein unpassendes Paket "symfony/process" gezeigt, muss dieses geändert werden. Fügen Sie dazu in den oben genannten Befehl bitte den Schalter `-W` ein (`... require -W ...`).
|
||||||
|
|
|
@ -55,7 +55,8 @@
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"D3\\Webauthn\\": "../../../source/modules/d3/oxwebauthn"
|
"D3\\Webauthn\\": "../../../source/modules/d3/oxwebauthn",
|
||||||
|
"D3\\Webauthn\\Migrations\\": "../../../source/modules/d3/oxwebauthn/migration/data"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
|
|
|
@ -19,7 +19,7 @@ use Assert\Assert;
|
||||||
use Assert\AssertionFailedException;
|
use Assert\AssertionFailedException;
|
||||||
use Assert\InvalidArgumentException;
|
use Assert\InvalidArgumentException;
|
||||||
use D3\TestingTools\Production\IsMockable;
|
use D3\TestingTools\Production\IsMockable;
|
||||||
use D3\Webauthn\Setup\Actions;
|
use D3\Webauthn\Migrations\Version20230209212939;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
|
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
|
||||||
use Doctrine\DBAL\Exception as DoctrineException;
|
use Doctrine\DBAL\Exception as DoctrineException;
|
||||||
|
@ -76,7 +76,7 @@ class PublicKeyCredential extends BaseModel
|
||||||
|
|
||||||
Assert::that($encodedCID)
|
Assert::that($encodedCID)
|
||||||
->maxLength(
|
->maxLength(
|
||||||
Actions::FIELDLENGTH_CREDID,
|
Version20230209212939::FIELDLENGTH_CREDID,
|
||||||
'the credentialId (%3$d) does not fit into the database field (%2$d)'
|
'the credentialId (%3$d) does not fit into the database field (%2$d)'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ class PublicKeyCredential extends BaseModel
|
||||||
|
|
||||||
Assert::that($encodedCredential)
|
Assert::that($encodedCredential)
|
||||||
->maxLength(
|
->maxLength(
|
||||||
Actions::FIELDLENGTH_CREDENTIAL,
|
Version20230209212939::FIELDLENGTH_CREDENTIAL,
|
||||||
'the credential source (%3$d) does not fit into the database field (%2$d)',
|
'the credential source (%3$d) does not fit into the database field (%2$d)',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -110,10 +110,10 @@ class WebauthnLogin
|
||||||
{
|
{
|
||||||
/** @var UtilsView $myUtilsView */
|
/** @var UtilsView $myUtilsView */
|
||||||
$myUtilsView = d3GetOxidDIC()->get('d3ox.webauthn.'.UtilsView::class);
|
$myUtilsView = d3GetOxidDIC()->get('d3ox.webauthn.'.UtilsView::class);
|
||||||
|
|
||||||
try {
|
|
||||||
/** @var d3_User_Webauthn $user */
|
/** @var d3_User_Webauthn $user */
|
||||||
$user = d3GetOxidDIC()->get('d3ox.webauthn.'.User::class);
|
$user = d3GetOxidDIC()->get('d3ox.webauthn.'.User::class);
|
||||||
|
|
||||||
|
try {
|
||||||
$userId = $this->getUserId();
|
$userId = $this->getUserId();
|
||||||
|
|
||||||
$this->handleErrorMessage();
|
$this->handleErrorMessage();
|
||||||
|
@ -158,10 +158,10 @@ class WebauthnLogin
|
||||||
{
|
{
|
||||||
/** @var UtilsView $myUtilsView */
|
/** @var UtilsView $myUtilsView */
|
||||||
$myUtilsView = d3GetOxidDIC()->get('d3ox.webauthn.'.UtilsView::class);
|
$myUtilsView = d3GetOxidDIC()->get('d3ox.webauthn.'.UtilsView::class);
|
||||||
|
|
||||||
try {
|
|
||||||
/** @var d3_User_Webauthn $user */
|
/** @var d3_User_Webauthn $user */
|
||||||
$user = d3GetOxidDIC()->get('d3ox.webauthn.'.User::class);
|
$user = d3GetOxidDIC()->get('d3ox.webauthn.'.User::class);
|
||||||
|
|
||||||
|
try {
|
||||||
$userId = $this->getUserId();
|
$userId = $this->getUserId();
|
||||||
|
|
||||||
$this->handleErrorMessage();
|
$this->handleErrorMessage();
|
||||||
|
@ -195,8 +195,6 @@ class WebauthnLogin
|
||||||
|
|
||||||
$user->logout();
|
$user->logout();
|
||||||
$oStr = Str::getStr();
|
$oStr = Str::getStr();
|
||||||
d3GetOxidDIC()->get('d3ox.webauthn.'.Config::class)->getActiveView()
|
|
||||||
->addTplParam('user', $oStr->htmlspecialchars($userId));
|
|
||||||
d3GetOxidDIC()->get('d3ox.webauthn.'.Config::class)->getActiveView()
|
d3GetOxidDIC()->get('d3ox.webauthn.'.Config::class)->getActiveView()
|
||||||
->addTplParam('profile', $oStr->htmlspecialchars($selectedProfile));
|
->addTplParam('profile', $oStr->htmlspecialchars($selectedProfile));
|
||||||
|
|
||||||
|
|
|
@ -136,3 +136,10 @@ services:
|
||||||
arguments:
|
arguments:
|
||||||
- 2
|
- 2
|
||||||
shared: true
|
shared: true
|
||||||
|
|
||||||
|
d3ox.webauthn.OxidEsales\DoctrineMigrationWrapper\MigrationsBuilder:
|
||||||
|
class: 'OxidEsales\DoctrineMigrationWrapper\MigrationsBuilder'
|
||||||
|
factory: 'oxNew'
|
||||||
|
arguments:
|
||||||
|
- 'OxidEsales\DoctrineMigrationWrapper\MigrationsBuilder'
|
||||||
|
shared: false
|
|
@ -18,12 +18,10 @@ namespace D3\Webauthn\Setup;
|
||||||
use D3\TestingTools\Production\IsMockable;
|
use D3\TestingTools\Production\IsMockable;
|
||||||
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
|
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use OxidEsales\DoctrineMigrationWrapper\MigrationsBuilder;
|
||||||
use OxidEsales\Eshop\Application\Controller\FrontendController;
|
use OxidEsales\Eshop\Application\Controller\FrontendController;
|
||||||
use OxidEsales\Eshop\Core\Config;
|
use OxidEsales\Eshop\Core\Config;
|
||||||
use OxidEsales\Eshop\Core\Database\Adapter\DatabaseInterface;
|
|
||||||
use OxidEsales\Eshop\Core\DbMetaDataHandler;
|
use OxidEsales\Eshop\Core\DbMetaDataHandler;
|
||||||
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
|
|
||||||
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
|
|
||||||
use OxidEsales\Eshop\Core\SeoEncoder;
|
use OxidEsales\Eshop\Core\SeoEncoder;
|
||||||
use OxidEsales\Eshop\Core\Utils;
|
use OxidEsales\Eshop\Core\Utils;
|
||||||
use OxidEsales\Eshop\Core\UtilsView;
|
use OxidEsales\Eshop\Core\UtilsView;
|
||||||
|
@ -39,93 +37,17 @@ use Psr\Log\LoggerInterface;
|
||||||
class Actions
|
class Actions
|
||||||
{
|
{
|
||||||
use IsMockable;
|
use IsMockable;
|
||||||
public const FIELDLENGTH_CREDID = 512;
|
|
||||||
public const FIELDLENGTH_CREDENTIAL = 2000;
|
|
||||||
|
|
||||||
public $seo_de = 'sicherheitsschluessel';
|
public $seo_de = 'sicherheitsschluessel';
|
||||||
public $seo_en = 'en/key-authentication';
|
public $seo_en = 'en/key-authentication';
|
||||||
public $stdClassName = 'd3_account_webauthn';
|
public $stdClassName = 'd3_account_webauthn';
|
||||||
|
|
||||||
/**
|
public function runModuleMigrations()
|
||||||
* SQL statement, that will be executed only at the first time of module installation.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $createCredentialSql =
|
|
||||||
"CREATE TABLE `d3wa_usercredentials` (
|
|
||||||
`OXID` char(32) NOT NULL,
|
|
||||||
`OXUSERID` char(32) NOT NULL,
|
|
||||||
`OXSHOPID` int(11) NOT NULL,
|
|
||||||
`NAME` varchar(100) NOT NULL,
|
|
||||||
`CREDENTIALID` varchar(".self::FIELDLENGTH_CREDID.") NOT NULL,
|
|
||||||
`CREDENTIAL` varchar(".self::FIELDLENGTH_CREDENTIAL.") NOT NULL,
|
|
||||||
`OXTIMESTAMP` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
|
||||||
PRIMARY KEY (`OXID`),
|
|
||||||
KEY `CREDENTIALID_IDX` (`CREDENTIALID`),
|
|
||||||
KEY `SHOPUSER_IDX` (`OXUSERID`,`OXSHOPID`) USING BTREE
|
|
||||||
) ENGINE=InnoDB COMMENT='WebAuthn Credentials';";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute the sql at the first time of the module installation.
|
|
||||||
* @return void
|
|
||||||
* @throws DatabaseConnectionException
|
|
||||||
* @throws DatabaseErrorException
|
|
||||||
*/
|
|
||||||
public function setupModule()
|
|
||||||
{
|
{
|
||||||
if (!$this->tableExists('d3wa_usercredentials')) {
|
/** @var MigrationsBuilder $migrationsBuilder */
|
||||||
$this->executeSQL($this->createCredentialSql);
|
$migrationsBuilder = d3GetOxidDIC()->get('d3ox.webauthn.'.MigrationsBuilder::class);
|
||||||
}
|
$migrations = $migrationsBuilder->build();
|
||||||
}
|
$migrations->execute('migrations:migrate', 'd3webauthn');
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if table exists
|
|
||||||
*
|
|
||||||
* @param string $sTableName table name
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function tableExists(string $sTableName): bool
|
|
||||||
{
|
|
||||||
$oDbMetaDataHandler = d3GetOxidDIC()->get('d3ox.webauthn.'.DbMetaDataHandler::class);
|
|
||||||
return $oDbMetaDataHandler->tableExists($sTableName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return DatabaseInterface|null
|
|
||||||
* @throws DatabaseConnectionException
|
|
||||||
*/
|
|
||||||
protected function d3GetDb(): ?DatabaseInterface
|
|
||||||
{
|
|
||||||
/** @var DatabaseInterface $db */
|
|
||||||
$db = d3GetOxidDIC()->get('d3ox.webauthn.'.DatabaseInterface::class.'.assoc');
|
|
||||||
return $db;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes given sql statement.
|
|
||||||
*
|
|
||||||
* @param string $sSQL Sql to execute.
|
|
||||||
* @throws DatabaseConnectionException
|
|
||||||
* @throws DatabaseErrorException
|
|
||||||
*/
|
|
||||||
public function executeSQL(string $sSQL)
|
|
||||||
{
|
|
||||||
$this->d3GetDb()->execute($sSQL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if field exists in table
|
|
||||||
*
|
|
||||||
* @param string $sFieldName field name
|
|
||||||
* @param string $sTableName table name
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function fieldExists(string $sFieldName, string $sTableName): bool
|
|
||||||
{
|
|
||||||
$oDbMetaDataHandler = d3GetOxidDIC()->get('d3ox.webauthn.'.DbMetaDataHandler::class);
|
|
||||||
return $oDbMetaDataHandler->fieldExists($sFieldName, $sTableName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -34,7 +34,7 @@ class Events
|
||||||
}
|
}
|
||||||
|
|
||||||
$actions = oxNew(Actions::class);
|
$actions = oxNew(Actions::class);
|
||||||
$actions->setupModule();
|
$actions->runModuleMigrations();
|
||||||
$actions->regenerateViews();
|
$actions->regenerateViews();
|
||||||
$actions->clearCache();
|
$actions->clearCache();
|
||||||
$actions->seoUrl();
|
$actions->seoUrl();
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* https://www.d3data.de
|
||||||
|
*
|
||||||
|
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||||
|
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
|
||||||
|
* @link https://www.oxidmodule.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace D3\Webauthn\Migrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\DBAL\Types\DateTimeType;
|
||||||
|
use Doctrine\DBAL\Types\IntegerType;
|
||||||
|
use Doctrine\DBAL\Types\StringType;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
final class Version20230209212939 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public const FIELDLENGTH_CREDID = 512;
|
||||||
|
public const FIELDLENGTH_CREDENTIAL = 2000;
|
||||||
|
|
||||||
|
public function getDescription() : string
|
||||||
|
{
|
||||||
|
return 'create credential database table';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema) : void
|
||||||
|
{
|
||||||
|
$this->connection->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
|
||||||
|
|
||||||
|
$table = !$schema->hasTable('d3wa_usercredentials') ?
|
||||||
|
$schema->createTable('d3wa_usercredentials') :
|
||||||
|
$schema->getTable('d3wa_usercredentials');
|
||||||
|
|
||||||
|
if (!$table->hasColumn('OXID')) {
|
||||||
|
$table->addColumn('OXID', (new StringType())->getName())
|
||||||
|
->setLength(32)
|
||||||
|
->setFixed(true)
|
||||||
|
->setNotnull(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$table->hasColumn('OXUSERID')) {
|
||||||
|
$table->addColumn('OXUSERID', (new StringType())->getName())
|
||||||
|
->setLength(32)
|
||||||
|
->setFixed(true)
|
||||||
|
->setNotnull(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$table->hasColumn('OXSHOPID')) {
|
||||||
|
$table->addColumn('OXSHOPID', (new IntegerType())->getName())
|
||||||
|
->setLength(11)
|
||||||
|
->setNotnull(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$table->hasColumn('NAME')) {
|
||||||
|
$table->addColumn('NAME', (new StringType())->getName())
|
||||||
|
->setLength(100)
|
||||||
|
->setFixed(false)
|
||||||
|
->setNotnull(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$table->hasColumn('CREDENTIALID')) {
|
||||||
|
$table->addColumn('CREDENTIALID', (new StringType())->getName())
|
||||||
|
->setLength(self::FIELDLENGTH_CREDID)
|
||||||
|
->setFixed(false)
|
||||||
|
->setNotnull(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$table->hasColumn('CREDENTIAL')) {
|
||||||
|
$table->addColumn('CREDENTIAL', (new StringType())->getName())
|
||||||
|
->setLength(self::FIELDLENGTH_CREDENTIAL)
|
||||||
|
->setFixed(false)
|
||||||
|
->setNotnull(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$table->hasColumn('OXTIMESTAMP')) {
|
||||||
|
$table->addColumn('OXTIMESTAMP', (new DateTimeType())->getName())
|
||||||
|
->setType(new DateTimeType())
|
||||||
|
->setNotnull(true)
|
||||||
|
// can't set default value via default method
|
||||||
|
->setColumnDefinition('timestamp DEFAULT CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$table->hasPrimaryKey()) {
|
||||||
|
$table->setPrimaryKey(['OXID']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$table->hasIndex('SHOPUSER_IDX')) {
|
||||||
|
$table->addIndex(['OXUSERID', 'OXSHOPID'], 'SHOPUSER_IDX');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$table->hasIndex('CREDENTIALID_IDX')) {
|
||||||
|
$table->addIndex(['CREDENTIALID'], 'CREDENTIALID_IDX');
|
||||||
|
}
|
||||||
|
|
||||||
|
$table->setComment('WebAuthn Credentials');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema) : void
|
||||||
|
{
|
||||||
|
if ($schema->hasTable('d3wa_usercredentials')) {
|
||||||
|
$schema->dropTable('d3wa_usercredentials');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
name: D3 Twofactor Passwordless
|
||||||
|
migrations_namespace: D3\Webauthn\Migrations
|
||||||
|
table_name: d3wa_migrations
|
||||||
|
migrations_directory: data
|
|
@ -15,6 +15,7 @@
|
||||||
<filter>
|
<filter>
|
||||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||||
<directory suffix=".php">../Application</directory>
|
<directory suffix=".php">../Application</directory>
|
||||||
|
<directory suffix=".php">../migration</directory>
|
||||||
<directory suffix=".php">../Modules</directory>
|
<directory suffix=".php">../Modules</directory>
|
||||||
<directory suffix=".php">../Setup</directory>
|
<directory suffix=".php">../Setup</directory>
|
||||||
<exclude>
|
<exclude>
|
||||||
|
|
|
@ -19,9 +19,9 @@ use D3\TestingTools\Development\CanAccessRestricted;
|
||||||
use D3\Webauthn\Setup\Actions;
|
use D3\Webauthn\Setup\Actions;
|
||||||
use D3\Webauthn\tests\unit\WAUnitTestCase;
|
use D3\Webauthn\tests\unit\WAUnitTestCase;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use OxidEsales\DoctrineMigrationWrapper\Migrations;
|
||||||
|
use OxidEsales\DoctrineMigrationWrapper\MigrationsBuilder;
|
||||||
use OxidEsales\Eshop\Application\Controller\FrontendController;
|
use OxidEsales\Eshop\Application\Controller\FrontendController;
|
||||||
use OxidEsales\Eshop\Core\Database\Adapter\DatabaseInterface;
|
|
||||||
use OxidEsales\Eshop\Core\Database\Adapter\Doctrine\Database;
|
|
||||||
use OxidEsales\Eshop\Core\DbMetaDataHandler;
|
use OxidEsales\Eshop\Core\DbMetaDataHandler;
|
||||||
use OxidEsales\Eshop\Core\Registry;
|
use OxidEsales\Eshop\Core\Registry;
|
||||||
use OxidEsales\Eshop\Core\SeoEncoder;
|
use OxidEsales\Eshop\Core\SeoEncoder;
|
||||||
|
@ -45,141 +45,35 @@ class ActionsTest extends WAUnitTestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @param $tableExist
|
|
||||||
* @param $expectedInvocation
|
|
||||||
* @return void
|
* @return void
|
||||||
* @throws ReflectionException
|
* @throws ReflectionException
|
||||||
* @covers \D3\Webauthn\Setup\Actions::setupModule
|
* @covers \D3\Webauthn\Setup\Actions::runModuleMigrations()
|
||||||
* @dataProvider canSetupModuleDataProvider
|
|
||||||
*/
|
*/
|
||||||
public function canSetupModule($tableExist, $expectedInvocation)
|
public function canRunModuleMigrations()
|
||||||
{
|
{
|
||||||
/** @var Actions|MockObject $sut */
|
/** @var Migrations|MockObject $migrationMock */
|
||||||
$sut = $this->getMockBuilder(Actions::class)
|
$migrationMock = $this->getMockBuilder(Migrations::class)
|
||||||
->onlyMethods(['tableExists', 'executeSQL'])
|
|
||||||
->getMock();
|
|
||||||
$sut->method('tableExists')->willReturn($tableExist);
|
|
||||||
$sut->expects($expectedInvocation)->method('executeSQL')->willReturn(true);
|
|
||||||
|
|
||||||
$this->callMethod(
|
|
||||||
$sut,
|
|
||||||
'setupModule'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array[]
|
|
||||||
*/
|
|
||||||
public function canSetupModuleDataProvider(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'table exist' => [true, $this->never()],
|
|
||||||
'table not exist' => [false, $this->once()],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
* @return void
|
|
||||||
* @throws ReflectionException
|
|
||||||
* @covers \D3\Webauthn\Setup\Actions::tableExists
|
|
||||||
*/
|
|
||||||
public function canCheckTableExists()
|
|
||||||
{
|
|
||||||
$expected = true;
|
|
||||||
|
|
||||||
/** @var DbMetaDataHandler|MockObject $DbMetaDataMock */
|
|
||||||
$DbMetaDataMock = $this->getMockBuilder(DbMetaDataHandler::class)
|
|
||||||
->onlyMethods(['tableExists'])
|
|
||||||
->getMock();
|
|
||||||
$DbMetaDataMock->expects($this->once())->method('tableExists')->willReturn($expected);
|
|
||||||
d3GetOxidDIC()->set('d3ox.webauthn.'.DbMetaDataHandler::class, $DbMetaDataMock);
|
|
||||||
|
|
||||||
/** @var Actions $sut */
|
|
||||||
$sut = oxNew(Actions::class);
|
|
||||||
|
|
||||||
$this->assertSame(
|
|
||||||
$expected,
|
|
||||||
$this->callMethod(
|
|
||||||
$sut,
|
|
||||||
'tableExists',
|
|
||||||
['testTable']
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
* @return void
|
|
||||||
* @throws ReflectionException
|
|
||||||
* @covers \D3\Webauthn\Setup\Actions::d3GetDb
|
|
||||||
*/
|
|
||||||
public function d3GetDbReturnsRightInstance()
|
|
||||||
{
|
|
||||||
$sut = oxNew(Actions::class);
|
|
||||||
|
|
||||||
$this->assertInstanceOf(
|
|
||||||
DatabaseInterface::class,
|
|
||||||
$this->callMethod(
|
|
||||||
$sut,
|
|
||||||
'd3GetDb'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
* @return void
|
|
||||||
* @throws ReflectionException
|
|
||||||
* @covers \D3\Webauthn\Setup\Actions::executeSQL
|
|
||||||
*/
|
|
||||||
public function canExecuteSQL()
|
|
||||||
{
|
|
||||||
/** @var Database|MockObject $dbMock */
|
|
||||||
$dbMock = $this->getMockBuilder(Database::class)
|
|
||||||
->onlyMethods(['execute'])
|
->onlyMethods(['execute'])
|
||||||
|
->disableOriginalConstructor()
|
||||||
->getMock();
|
->getMock();
|
||||||
$dbMock->expects($this->once())->method('execute');
|
$migrationMock->expects($this->atLeastOnce())->method('execute')->with(
|
||||||
|
$this->identicalTo('migrations:migrate'),
|
||||||
$sut = $this->getMockBuilder(Actions::class)
|
$this->identicalTo('d3webauthn')
|
||||||
->onlyMethods(['d3GetDb'])
|
|
||||||
->getMock();
|
|
||||||
$sut->method('d3GetDb')->willReturn($dbMock);
|
|
||||||
|
|
||||||
$this->callMethod(
|
|
||||||
$sut,
|
|
||||||
'executeSQL',
|
|
||||||
['query']
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** @var MigrationsBuilder|MockObject $migrationsBuilderMock */
|
||||||
* @test
|
$migrationsBuilderMock = $this->getMockBuilder(MigrationsBuilder::class)
|
||||||
* @return void
|
->onlyMethods(['build'])
|
||||||
* @throws ReflectionException
|
|
||||||
* @covers \D3\Webauthn\Setup\Actions::fieldExists
|
|
||||||
*/
|
|
||||||
public function canCheckFieldExists()
|
|
||||||
{
|
|
||||||
$expected = true;
|
|
||||||
|
|
||||||
/** @var DbMetaDataHandler|MockObject $DbMetaDataMock */
|
|
||||||
$DbMetaDataMock = $this->getMockBuilder(DbMetaDataHandler::class)
|
|
||||||
->onlyMethods(['fieldExists'])
|
|
||||||
->getMock();
|
->getMock();
|
||||||
$DbMetaDataMock->expects($this->once())->method('fieldExists')->willReturn($expected);
|
$migrationsBuilderMock->method('build')->willReturn($migrationMock);
|
||||||
d3GetOxidDIC()->set('d3ox.webauthn.'.DbMetaDataHandler::class, $DbMetaDataMock);
|
d3GetOxidDIC()->set('d3ox.webauthn.'.MigrationsBuilder::class, $migrationsBuilderMock);
|
||||||
|
|
||||||
/** @var Actions $sut */
|
/** @var Actions $sut */
|
||||||
$sut = oxNew(Actions::class);
|
$sut = oxNew(Actions::class);
|
||||||
|
|
||||||
$this->assertSame(
|
|
||||||
$expected,
|
|
||||||
$this->callMethod(
|
$this->callMethod(
|
||||||
$sut,
|
$sut,
|
||||||
'fieldExists',
|
'runModuleMigrations'
|
||||||
['testField', 'testTable']
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,303 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* https://www.d3data.de
|
||||||
|
*
|
||||||
|
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||||
|
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
|
||||||
|
* @link https://www.oxidmodule.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace D3\Webauthn\tests\unit\migration\data;
|
||||||
|
|
||||||
|
use D3\TestingTools\Development\CanAccessRestricted;
|
||||||
|
use D3\Webauthn\Migrations\Version20230209212939;
|
||||||
|
use D3\Webauthn\tests\unit\WAUnitTestCase;
|
||||||
|
use Doctrine\DBAL\Connection;
|
||||||
|
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||||
|
use Doctrine\DBAL\Platforms\MySQL57Platform;
|
||||||
|
use Doctrine\DBAL\Schema\AbstractSchemaManager;
|
||||||
|
use Doctrine\DBAL\Schema\Column;
|
||||||
|
use Doctrine\DBAL\Schema\MySqlSchemaManager;
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\DBAL\Schema\Table;
|
||||||
|
use Doctrine\Migrations\Configuration\Configuration;
|
||||||
|
use Doctrine\Migrations\Version\Version;
|
||||||
|
use Generator;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
use ReflectionException;
|
||||||
|
|
||||||
|
class Version20230209212939Test extends WAUnitTestCase
|
||||||
|
{
|
||||||
|
use CanAccessRestricted;
|
||||||
|
|
||||||
|
/** @var Version20230209212939 */
|
||||||
|
protected $sut;
|
||||||
|
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp(); // TODO: Change the autogenerated stub
|
||||||
|
|
||||||
|
/** @var AbstractPlatform|MockObject $databasePlatformMock */
|
||||||
|
$databasePlatformMock = $this->getMockBuilder(MySQL57Platform::class)
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
/** @var AbstractSchemaManager|MockObject $schemaManagerMock */
|
||||||
|
$schemaManagerMock = $this->getMockBuilder(MySqlSchemaManager::class)
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
/** @var Connection|MockObject $connectionMock */
|
||||||
|
$connectionMock = $this->getMockBuilder(Connection::class)
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->onlyMethods(['getDatabasePlatform', 'getSchemaManager'])
|
||||||
|
->getMock();
|
||||||
|
$connectionMock->method('getDatabasePlatform')->willReturn($databasePlatformMock);
|
||||||
|
$connectionMock->method('getSchemaManager')->willReturn($schemaManagerMock);
|
||||||
|
|
||||||
|
/** @var Configuration|MockObject $configurationMock */
|
||||||
|
$configurationMock = $this->getMockBuilder(Configuration::class)
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->onlyMethods(['getConnection'])
|
||||||
|
->getMock();
|
||||||
|
$configurationMock->method('getConnection')->willReturn($connectionMock);
|
||||||
|
|
||||||
|
/** @var Version|MockObject $versionMock */
|
||||||
|
$versionMock = $this->getMockBuilder(Version::class)
|
||||||
|
->onlyMethods(['getConfiguration'])
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
$versionMock->method('getConfiguration')->willReturn($configurationMock);
|
||||||
|
|
||||||
|
$this->sut = oxNew(Version20230209212939::class, $versionMock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @return void
|
||||||
|
* @throws ReflectionException
|
||||||
|
* @covers \D3\Webauthn\Migrations\Version20230209212939::getDescription
|
||||||
|
*/
|
||||||
|
public function canGetDescription()
|
||||||
|
{
|
||||||
|
$this->assertIsString(
|
||||||
|
$this->callMethod(
|
||||||
|
$this->sut,
|
||||||
|
'getDescription'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @return void
|
||||||
|
* @throws ReflectionException
|
||||||
|
* @covers \D3\Webauthn\Migrations\Version20230209212939::up
|
||||||
|
* @dataProvider canUpTableDataProvider
|
||||||
|
*/
|
||||||
|
public function canUpTable($tableExist, $invocationCount)
|
||||||
|
{
|
||||||
|
/** @var Table|MockObject $tableMock */
|
||||||
|
$tableMock = $this->getMockBuilder(Table::class)
|
||||||
|
->onlyMethods(['hasColumn', 'hasPrimaryKey', 'hasIndex'])
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
$tableMock->method('hasColumn')->willReturn(true);
|
||||||
|
$tableMock->method('hasPrimaryKey')->willReturn(true);
|
||||||
|
$tableMock->method('hasIndex')->willReturn(true);
|
||||||
|
|
||||||
|
/** @var Schema|MockObject $schemaMock */
|
||||||
|
$schemaMock = $this->getMockBuilder(Schema::class)
|
||||||
|
->onlyMethods(['hasTable', 'createTable', 'getTable'])
|
||||||
|
->getMock();
|
||||||
|
$schemaMock->method('hasTable')->willReturn($tableExist);
|
||||||
|
$schemaMock->expects($invocationCount)->method('createTable')->willReturn($tableMock);
|
||||||
|
$schemaMock->method('getTable')->willReturn($tableMock);
|
||||||
|
|
||||||
|
$this->callMethod(
|
||||||
|
$this->sut,
|
||||||
|
'up',
|
||||||
|
[$schemaMock]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Generator
|
||||||
|
*/
|
||||||
|
public function canUpTableDataProvider(): Generator
|
||||||
|
{
|
||||||
|
yield 'table not exist' => [false, $this->once()];
|
||||||
|
yield 'table exist' => [true, $this->never()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @return void
|
||||||
|
* @throws ReflectionException
|
||||||
|
* @covers \D3\Webauthn\Migrations\Version20230209212939::up
|
||||||
|
* @dataProvider canUpColumnDataProvider
|
||||||
|
*/
|
||||||
|
public function canUpColumn($columnExist, $invocationCount)
|
||||||
|
{
|
||||||
|
/** @var Column|MockObject $columnMock */
|
||||||
|
$columnMock = $this->getMockBuilder(Column::class)
|
||||||
|
->onlyMethods(['setLength'])
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
$columnMock->method('setLength')->willReturnSelf();
|
||||||
|
|
||||||
|
/** @var Table|MockObject $tableMock */
|
||||||
|
$tableMock = $this->getMockBuilder(Table::class)
|
||||||
|
->onlyMethods(['hasColumn', 'addColumn', 'hasPrimaryKey', 'hasIndex'])
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
$tableMock->method('hasColumn')->willReturn($columnExist);
|
||||||
|
$tableMock->expects($invocationCount)->method('addColumn')->willReturn($columnMock);
|
||||||
|
$tableMock->method('hasPrimaryKey')->willReturn(true);
|
||||||
|
$tableMock->method('hasIndex')->willReturn(true);
|
||||||
|
|
||||||
|
/** @var Schema|MockObject $schemaMock */
|
||||||
|
$schemaMock = $this->getMockBuilder(Schema::class)
|
||||||
|
->onlyMethods(['hasTable', 'getTable'])
|
||||||
|
->getMock();
|
||||||
|
$schemaMock->method('hasTable')->willReturn(true);
|
||||||
|
$schemaMock->method('getTable')->willReturn($tableMock);
|
||||||
|
|
||||||
|
$this->callMethod(
|
||||||
|
$this->sut,
|
||||||
|
'up',
|
||||||
|
[$schemaMock]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Generator
|
||||||
|
*/
|
||||||
|
public function canUpColumnDataProvider(): Generator
|
||||||
|
{
|
||||||
|
yield 'column not exist' => [false, $this->atLeast(7)];
|
||||||
|
yield 'column exist' => [true, $this->never()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @return void
|
||||||
|
* @throws ReflectionException
|
||||||
|
* @covers \D3\Webauthn\Migrations\Version20230209212939::up
|
||||||
|
* @dataProvider canUpPrimaryKeyDataProvider
|
||||||
|
*/
|
||||||
|
public function canUpPrimaryKey($pKeyExist, $invocationCount)
|
||||||
|
{
|
||||||
|
/** @var Table|MockObject $tableMock */
|
||||||
|
$tableMock = $this->getMockBuilder(Table::class)
|
||||||
|
->onlyMethods(['hasColumn', 'addColumn', 'hasPrimaryKey', 'hasIndex', 'setPrimaryKey'])
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
$tableMock->method('hasColumn')->willReturn(true);
|
||||||
|
$tableMock->method('hasPrimaryKey')->willReturn($pKeyExist);
|
||||||
|
$tableMock->method('hasIndex')->willReturn(true);
|
||||||
|
$tableMock->expects($invocationCount)->method('setPrimaryKey');
|
||||||
|
|
||||||
|
/** @var Schema|MockObject $schemaMock */
|
||||||
|
$schemaMock = $this->getMockBuilder(Schema::class)
|
||||||
|
->onlyMethods(['hasTable', 'getTable'])
|
||||||
|
->getMock();
|
||||||
|
$schemaMock->method('hasTable')->willReturn(true);
|
||||||
|
$schemaMock->method('getTable')->willReturn($tableMock);
|
||||||
|
|
||||||
|
$this->callMethod(
|
||||||
|
$this->sut,
|
||||||
|
'up',
|
||||||
|
[$schemaMock]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Generator
|
||||||
|
*/
|
||||||
|
public function canUpPrimaryKeyDataProvider(): Generator
|
||||||
|
{
|
||||||
|
yield 'pk not exist' => [false, $this->once()];
|
||||||
|
yield 'pk exist' => [true, $this->never()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @return void
|
||||||
|
* @throws ReflectionException
|
||||||
|
* @covers \D3\Webauthn\Migrations\Version20230209212939::up
|
||||||
|
* @dataProvider canUpIndexDataProvider
|
||||||
|
*/
|
||||||
|
public function canUpIndex($indexExist, $invocationCount)
|
||||||
|
{
|
||||||
|
/** @var Table|MockObject $tableMock */
|
||||||
|
$tableMock = $this->getMockBuilder(Table::class)
|
||||||
|
->onlyMethods(['hasColumn', 'addColumn', 'hasPrimaryKey', 'hasIndex', 'addIndex', 'setComment'])
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
$tableMock->method('hasColumn')->willReturn(true);
|
||||||
|
$tableMock->method('hasPrimaryKey')->willReturn(true);
|
||||||
|
$tableMock->method('hasIndex')->willReturn($indexExist);
|
||||||
|
$tableMock->expects($invocationCount)->method('addIndex');
|
||||||
|
$tableMock->expects($this->once())->method('setComment');
|
||||||
|
|
||||||
|
/** @var Schema|MockObject $schemaMock */
|
||||||
|
$schemaMock = $this->getMockBuilder(Schema::class)
|
||||||
|
->onlyMethods(['hasTable', 'getTable'])
|
||||||
|
->getMock();
|
||||||
|
$schemaMock->method('hasTable')->willReturn(true);
|
||||||
|
$schemaMock->method('getTable')->willReturn($tableMock);
|
||||||
|
|
||||||
|
$this->callMethod(
|
||||||
|
$this->sut,
|
||||||
|
'up',
|
||||||
|
[$schemaMock]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Generator
|
||||||
|
*/
|
||||||
|
public function canUpIndexDataProvider(): Generator
|
||||||
|
{
|
||||||
|
yield 'index not exist' => [false, $this->atLeast(2)];
|
||||||
|
yield 'index exist' => [true, $this->never()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @return void
|
||||||
|
* @throws ReflectionException
|
||||||
|
* @covers \D3\Webauthn\Migrations\Version20230209212939::down
|
||||||
|
* @dataProvider canDownTableDataProvider
|
||||||
|
*/
|
||||||
|
public function canDownTable($tableExist, $invocationCount)
|
||||||
|
{
|
||||||
|
/** @var Schema|MockObject $schemaMock */
|
||||||
|
$schemaMock = $this->getMockBuilder(Schema::class)
|
||||||
|
->onlyMethods(['hasTable', 'dropTable'])
|
||||||
|
->getMock();
|
||||||
|
$schemaMock->method('hasTable')->willReturn($tableExist);
|
||||||
|
$schemaMock->expects($invocationCount)->method('dropTable');
|
||||||
|
|
||||||
|
$this->callMethod(
|
||||||
|
$this->sut,
|
||||||
|
'down',
|
||||||
|
[$schemaMock]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Generator
|
||||||
|
*/
|
||||||
|
public function canDownTableDataProvider(): Generator
|
||||||
|
{
|
||||||
|
yield 'table exist' => [true, $this->once()];
|
||||||
|
yield 'table not exist' => [false, $this->never()];
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue