Skip to content
This repository was archived by the owner on Sep 5, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 18 additions & 0 deletions doc/core/maintenance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Maintenance
=====

Pum allow you to easily switch your website to a maintenance mode.
Your application will be closed except for people whitelisted by their IP address.

You can either add some IP to the configuration, or from the Pum global parameters form.

Even in maintenance mode, the backend side will still be available for administrators.

##Configuration
```
pum_core:
maintenance:
template: 'pum://my_maintenance.html.twig'
whiteIps: [ 127.0.0.1 ]
whitePaths: [ 'login' ]
```
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ msgstr "All rights"
################################################# Settings #####################################################
msgid "pum.form.config.tabs.woodwork.label"
msgstr "Woodwork"
msgid "pum.form.config.tabs.maintenance.label"
msgstr "Maintenance"
msgid "pum.form.config.tabs.project.admin.label"
msgstr "Project Admin"
msgid "pum.form.config.tabs.type.extra.label"
Expand All @@ -281,6 +283,10 @@ msgid "pum.form.config.tabs.woodwork.ww.show.export.import.button.label"
msgstr "Show export/import button"
msgid "pum.form.config.tabs.woodwork.ww.show.clone.button.label"
msgstr "Show clone button"
msgid "pum.form.config.tabs.maintenance.maintenance.mode.label"
msgstr "Maintenance mode"
msgid "pum.form.config.tabs.maintenance.maintenance.restriction.ips.label"
msgstr "Allowed IPs"
msgid "pum.form.config.tabs.project.admin.pa.default.tableview.truncatecols.value.label"
msgstr "Max columns showed in default Tableview"
msgid "pum.form.config.tabs.project.admin.pa.disable.default.tableview.truncatecols.label"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ msgstr "Tous les droits"
################################################# Settings #####################################################
msgid "pum.form.config.tabs.woodwork.label"
msgstr "Woodwork"
msgid "pum.form.config.tabs.maintenance.label"
msgstr "Maintenance"
msgid "pum.form.config.tabs.project.admin.label"
msgstr "Project Admin"
msgid "pum.form.config.tabs.type.extra.label"
Expand All @@ -283,6 +285,10 @@ msgid "pum.form.config.tabs.woodwork.ww.show.export.import.button.label"
msgstr "Afficher les boutons d'import/export"
msgid "pum.form.config.tabs.woodwork.ww.show.clone.button.label"
msgstr "Afficher les boutons de clonage"
msgid "pum.form.config.tabs.maintenance.maintenance.mode.label"
msgstr "Mettre en maintenance"
msgid "pum.form.config.tabs.maintenance.maintenance.restriction.ips.label"
msgstr "Adresses IP autorisées"
msgid "pum.form.config.tabs.project.admin.pa.default.tableview.truncatecols.value.label"
msgstr "Nombre de colonnes maximum affichées dans la Tableview par défaut"
msgid "pum.form.config.tabs.project.admin.pa.disable.default.tableview.truncatecols.label"
Expand Down
119 changes: 68 additions & 51 deletions src/Pum/Bundle/CoreBundle/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,68 +13,85 @@ public function getConfigTreeBuilder()

$builder
->root('pum_core')
->children()
->booleanNode('validation')->defaultTrue()->end()
->booleanNode('em_factory')->defaultFalse()->end()
->arrayNode('doctrine')
->useAttributeAsKey('name')
->treatNullLike(array())
->prototype('scalar')->end()
->defaultValue(array('_pum' => array('dql' => array())))
->prototype('array')
->beforeNormalization()
->ifTrue(function($v) {
return !isset($v['dql']);
})
->then(function($v) {
return array('dql' => array());
})
->end()
->children()
->arrayNode('dql')
->fixXmlConfig('string_function')
->fixXmlConfig('numeric_function')
->fixXmlConfig('datetime_function')
->children()
->arrayNode('string_functions')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->arrayNode('numeric_functions')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->arrayNode('datetime_functions')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->children()
->booleanNode('validation')->defaultTrue()->end()
->booleanNode('em_factory')->defaultFalse()->end()
->arrayNode('doctrine')
->useAttributeAsKey('name')
->treatNullLike(array())
->prototype('scalar')->end()
->defaultValue(array('_pum' => array('dql' => array())))
->prototype('array')
->beforeNormalization()
->ifTrue(function($v) {
return !isset($v['dql']);
})
->then(function($v) {
return array('dql' => array());
})
->end()
->children()
->arrayNode('dql')
->fixXmlConfig('string_function')
->fixXmlConfig('numeric_function')
->fixXmlConfig('datetime_function')
->children()
->arrayNode('string_functions')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->arrayNode('numeric_functions')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->arrayNode('datetime_functions')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->end()
->end()
->end()
->end()
->end()
->end()
->arrayNode('view')
->addDefaultsIfNotSet()
->children()
->booleanNode('enabled')->defaultFalse()->end()
->arrayNode('mode')
->prototype('scalar')->end()
->defaultValue(array('filesystem'))
->arrayNode('view')
->addDefaultsIfNotSet()
->children()
->booleanNode('enabled')->defaultFalse()->end()
->arrayNode('mode')
->prototype('scalar')->end()
->defaultValue(array('filesystem'))
->end()
->end()
->end()
->end()
->arrayNode('notification')
->addDefaultsIfNotSet()
->children()
->scalarNode('from')->defaultValue('notification@kitea.fr')->end()
->arrayNode('content')
->children()
->scalarNode('title')->end()
->arrayNode('notification')
->addDefaultsIfNotSet()
->children()
->scalarNode('from')->defaultValue('notification@kitea.fr')->end()
->arrayNode('content')
->children()
->scalarNode('title')->end()
->end()
->end()
->end()
->end()
->arrayNode('maintenance')
->addDefaultsIfNotSet()
->children()
->scalarNode('template')->defaultValue('pum://maintenance.html.twig')->end()
->arrayNode('whitePaths')
->prototype('scalar')
->end()
->end()
->arrayNode('whiteIps')
->prototype('scalar')
->end()
->end()
->end()
->end()
->arrayNode('assetic_bundles')
->prototype('scalar')
->end()
->end()
->arrayNode('assetic_bundles')->prototype('scalar')->end()->end()
;

return $builder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public function load(array $configs, ContainerBuilder $container)
$loader->load('translation.xml');
$loader->load('templating.xml');
$loader->load('mailer.xml');
$loader->load('maintenance.xml');
$loader->load('notification.xml');

$container->setParameter('pum_core.assetic_bundles', $config['assetic_bundles']);
Expand Down Expand Up @@ -97,6 +98,22 @@ public function load(array $configs, ContainerBuilder $container)
if ($config['notification']) {
$container->setParameter('pum_core.notification', $config['notification']);
}

if ($config['maintenance']) {
$whiteIps = array();
if (isset($config['maintenance']['whiteIps'])) {
$whiteIps = $config['maintenance']['whiteIps'];
}

$whitePaths = array();
if (isset($config['maintenance']['whitePaths'])) {
$whitePaths = $config['maintenance']['whitePaths'];
}

$container->setParameter('pum_core.maintenance.template', $config['maintenance']['template']);
$container->setParameter('pum_core.maintenance.whiteIps', $whiteIps);
$container->setParameter('pum_core.maintenance.whitePaths', $whitePaths);
}
}

private function registerPumViewFolders(ContainerBuilder $container)
Expand All @@ -105,7 +122,6 @@ private function registerPumViewFolders(ContainerBuilder $container)

$folders = array();
foreach ($container->getParameter('kernel.bundles') as $bundle => $class) {

if (is_dir($dir = $container->getParameter('kernel.root_dir').'/Resources/'.$bundle.'/pum_views')) {
$folders[$bundle] = $dir;
}
Expand All @@ -116,6 +132,8 @@ private function registerPumViewFolders(ContainerBuilder $container)
}
}

$folders = array_reverse($folders);

$container->setParameter('pum_core.view.folders', $folders);
}
}
71 changes: 71 additions & 0 deletions src/Pum/Bundle/CoreBundle/EventListener/MaintenanceListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace Pum\Bundle\CoreBundle\EventListener;

use Pum\Core\Config\ConfigInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Bridge\Twig\TwigEngine;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Response;
use Pum\Bundle\AppBundle\Entity\User;

class MaintenanceListener
{
private $config;
private $tokenStorage;
private $twigEngine;

private $isUnderMaintenance = false;
private $template;
private $whiteIps;
private $whitePaths;

public function __construct(ConfigInterface $config, TokenStorage $tokenStorage, TwigEngine $twigEngine, $template, array $whiteIps, array $whitePaths)
{
$this->config = $config;
$this->tokenStorage = $tokenStorage;
$this->twigEngine = $twigEngine;

$this->template = $template;
$this->whiteIps = array_unique(array_merge($whiteIps, $this->config->get('maintenance_restriction_ips', array())));
$this->whitePaths = array_unique(array_merge($whitePaths, array('_profiler', '_wdt', 'pum-login', 'pum-login-check', 'js', 'css', 'images')));
}

public function onKernelRequest(GetResponseEvent $event)
{
$this->isUnderMaintenance = $this->config->get('maintenance_mode', false);

if ($this->isUnderMaintenance) {
$clientIp = $event->getRequest()->getClientIp();

// is IP authorized
if (!empty($this->whiteIps)) {
foreach ($this->whiteIps as $ip) {
if ($ip === $clientIp) {
return true;
}
}
}

// is User connected and authorized
$token = $this->tokenStorage->getToken();
if ($token != null) {
$user = $token->getUser();
if ($user instanceof User && $user->getGroup()->isAdmin()) {
return true;
}
}

// is Path authorized
$path = trim($event->getRequest()->getPathInfo(), '/');
foreach ($this->whitePaths as $pattern) {
if (preg_match('/^' . $pattern . '/', $path)) {
return true;
}
}

$event->setResponse(new Response($this->twigEngine->render($this->template), 503));
$event->stopPropagation();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Pum\Bundle\CoreBundle\Form\TypeExtension;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
* Extends form and give opportunity to pass block prefixes as options.
*/
class MaintenanceConfigTypeExtension extends AbstractTypeExtension
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->get('tabs')
->add(
$builder->create('maintenance', 'pum_tab')
->add('maintenance_mode', 'checkbox', array('required' => false))
->add('maintenance_restriction_ips', 'collection', array(
'type' => 'text',
'max_length' => 45, // IPv6
'allow_add' => true,
'allow_delete' => true,
))
);
}

/**
* {@inheritdoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'translation_domain' => 'pum_form'
));
}

/**
* {@inheritdoc}
*/
public function getExtendedType()
{
return 'pum_config';
}
}
4 changes: 4 additions & 0 deletions src/Pum/Bundle/CoreBundle/Resources/config/form.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
<tag name="form.type_extension" alias="pum_config" />
</service>

<service id="form.type_extension.maintenance_config" class="Pum\Bundle\CoreBundle\Form\TypeExtension\MaintenanceConfigTypeExtension">
<tag name="form.type_extension" alias="pum_config" />
</service>

<service id="form.type_extension.projectadmin_config" class="Pum\Bundle\ProjectAdminBundle\Form\TypeExtension\ProjectAdminConfigTypeExtension">
<tag name="form.type_extension" alias="pum_config" />
</service>
Expand Down
Loading