Search code examples
phpsymfonydoctrine-migrations

Symfony: migration of user table via browser


I have the following scenario: There's an app that can be installed by clients themselves and as not every webhoster provides console access, clients must be able to install and update the app via browser. (similar to the update process of e.g. Piwik)

Executing commands in specific controllers is no problem:

// src/CoreBundle/Controller/UpdateController.php
public function updateAction()
{
    $application = new Application($this->get('kernel'));
    $application->setAutoExit(false);

    $input = new ArrayInput(array(
       'command' => 'doctrine:migrations:migrate',
       '--no-interaction',
    ));

    $output = new BufferedOutput();
    $application->run($input, $output);

    return $this->render('system/update.html.twig', [
        'dump' => $output->fetch()
    ]);
}

Currently, this route can be disabled via configuration such that not every user of the app can start the update but only admins. (In the future, route access should be limited to admin accounts)

The problem comes into play when adding migrations for the user table:

// app/Resources/DoctrineMigrations/Version20160926090600.php
public function up(Schema $schema)
{
    $this->addSql('ALTER TABLE `user` ADD `gender` tinyint(1) unsigned NOT NULL DEFAULT 0');
}

As soon as this field is added to the user entity, web access fails as doctrine tries to fetch data from user.gender to populate account data for session / security context.

Is there a way to circumvent this issue? Is it possible to disable fetching data from user table for a specific route? Or even better, as the latter one won't work if authentication is needed to access /route: Is it possible to tell the session handling to only fetch a few columns?

Or do I need to never change anything in the user table if I need to handle updates via controllers?

The current security.yml:

security:
  providers:
    appuser:
      entity:
        class: CoreBundle:User
  firewalls:
    default:
      anonymous: ~
      http_basic: ~
      provider:  appuser
    dev:
      pattern:  ^/(_(profiler|wdt)|css|images|js)/
      security: false

Solution

  • As it seems that nobody has a good solution for that, I have to disable the complete firewall for this particular route. This does only work as long as no authentication is used (e.g. for admin accounts):

    security:
      firewalls:
        setup:
          pattern:  ^/(update|install)
          security: false