Add cascade delete on ApiLog accountId.

Also add a postConnect listener to enable foreign keys in sqlite
This commit is contained in:
Benoît Burnichon
2015-12-09 12:26:41 +01:00
parent 2c51ee645e
commit 5bb8d4167b
6 changed files with 224 additions and 3 deletions

View File

@@ -83,6 +83,9 @@ use Alchemy\Phrasea\Twig\JSUniqueID;
use Alchemy\Phrasea\Twig\PhraseanetExtension;
use Alchemy\Phrasea\Utilities\CachedTranslator;
use Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Event\ConnectionEventArgs;
use Doctrine\DBAL\Events;
use Doctrine\ORM\Configuration;
use FFMpeg\FFMpegServiceProvider;
use Gedmo\DoctrineExtensions as GedmoExtension;
@@ -1012,13 +1015,28 @@ class Application extends SilexApplication
$this['dbs.event_manager'] = $this->share($this->extend('dbs.event_manager', function ($eventManagers, $app) {
foreach ($eventManagers->keys() as $name) {
$app['dbal.evm.register.listeners']($eventManagers[$name]);
/** @var EventManager $eventManager */
$eventManager = $eventManagers[$name];
$app['dbal.evm.register.listeners']($eventManager);
$eventManager->addEventListener(Events::postConnect, $this);
}
return $eventManagers;
}));
}
/**
* @param ConnectionEventArgs $args
* @throws \Doctrine\DBAL\DBALException
*/
public function postConnect(ConnectionEventArgs $args)
{
if ('sqlite' == $args->getDatabasePlatform()->getName()) {
$args->getConnection()->exec('PRAGMA foreign_keys = ON');
}
}
private function setupMediaAlchemyst()
{
$this['media-alchemyst.configuration'] = $this->share(function (Application $app) {

View File

@@ -16,7 +16,7 @@ class Version
/**
* @var string
*/
private $number = '4.0.0-alpha.3';
private $number = '4.0.0-alpha.4';
/**
* @var string

View File

@@ -28,7 +28,12 @@ class ApiLog
/**
* @ORM\ManyToOne(targetEntity="ApiAccount")
* @ORM\JoinColumn(name="account_id", referencedColumnName="id", nullable=false)
* @ORM\JoinColumn(
* name="account_id",
* referencedColumnName="id",
* nullable=false,
* onDelete="CASCADE"
* )
*
* @return ApiAccount
**/

View File

@@ -0,0 +1,36 @@
<?php
namespace Alchemy\Phrasea\Setup\DoctrineMigrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20151209101524 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('ALTER TABLE ApiLogs DROP FOREIGN KEY FK_91E90F309B6B5FBA');
$this->addSql('ALTER TABLE ApiLogs ADD CONSTRAINT FK_91E90F309B6B5FBA FOREIGN KEY (account_id) REFERENCES ApiAccounts (id) ON DELETE CASCADE');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('ALTER TABLE ApiLogs DROP FOREIGN KEY FK_91E90F309B6B5FBA');
$this->addSql('ALTER TABLE ApiLogs ADD CONSTRAINT FK_91E90F309B6B5FBA FOREIGN KEY (account_id) REFERENCES ApiAccounts (id)');
}
}

View File

@@ -0,0 +1,64 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2015 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
class patch_400alpha4a implements patchInterface
{
/** @var string */
private $release = '4.0.0-alpha.4';
/** @var array */
private $concern = [base::APPLICATION_BOX];
/**
* {@inheritdoc}
*/
public function get_release()
{
return $this->release;
}
/**
* {@inheritdoc}
*/
public function getDoctrineMigrations()
{
return [
'20151209101524'
];
}
/**
* {@inheritdoc}
*/
public function require_all_upgrades()
{
return false;
}
/**
* {@inheritdoc}
*/
public function concern()
{
return $this->concern;
}
/**
* {@inheritdoc}
*/
public function apply(base $databox, Application $app)
{
return true;
}
}

View File

@@ -0,0 +1,98 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2015 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Tests\Phrasea\Functional;
use Alchemy\Phrasea\Model\Entities\ApiAccount;
use Alchemy\Phrasea\Model\Entities\ApiApplication;
use Alchemy\Phrasea\Model\Entities\User;
use Alchemy\Phrasea\Model\Manipulator\ApiAccountManipulator;
use Alchemy\Phrasea\Model\Manipulator\ApiApplicationManipulator;
use Alchemy\Phrasea\Model\Manipulator\ApiLogManipulator;
use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
use Alchemy\Phrasea\Model\Repositories\ApiLogRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* @group functional
* @group authenticated
* @group web
*/
class UserDeletionTest extends \PhraseanetAuthenticatedWebTestCase
{
/** @var UserManipulator */
private $userManipulator;
/** @var User */
private $user;
/** @var ApiApplicationManipulator */
private $apiApplicationManipulator;
/** @var ApiApplication */
private $apiApplication;
public function setUp()
{
parent::setUp();
$app = $this->getApplication();
$this->userManipulator = $app['manipulator.user'];
$this->user = $this->userManipulator->createUser('login', "test", 'test@example.com');
$this->apiApplicationManipulator = $app['manipulator.api-application'];
$this->apiApplication = $this->apiApplicationManipulator->create(
'test-desktop',
ApiApplication::WEB_TYPE,
'',
'http://website.com/',
$this->user,
'http://callback.com/callback/'
);
$this->apiApplication->setGrantPassword(true);
$this->apiApplicationManipulator->update($this->apiApplication);
}
public function testRemoveUserWhichLoggedViaOAuthDoesNotThrowException()
{
$app = $this->getApplication();
/** @var ApiLogManipulator $apiLogManipulator */
$apiLogManipulator = $app['manipulator.api-log'];
/** @var ApiLogRepository $apiLogRepository */
$apiLogRepository = $app['repo.api-logs'];
/** @var ApiAccountManipulator $apiAccountManipulator */
$apiAccountManipulator = $app['manipulator.api-account'];
$account = $apiAccountManipulator->create($this->apiApplication, $this->user);
$this->assertInstanceOf(ApiAccount::class, $account);
$apiLog = $apiLogManipulator->create($account, new Request(), new Response());
$apiLogId = $apiLog->getId();
$this->userManipulator->delete($this->user);
$this->assertTrue($this->user->isDeleted(), 'User was not properly deleted');
$apiLogRepository->clear();
$this->assertNull($apiLogRepository->find($apiLogId), 'Created api log should have been deleted');
$this->user = null;
$this->apiApplication = null;
}
public function tearDown()
{
if ($this->apiApplication) {
$this->apiApplicationManipulator->delete($this->apiApplication);
}
if ($this->user) {
$this->userManipulator->delete($this->user);
}
parent::tearDown();
}
}