diff --git a/modules/cron/lib/Controller/Cron.php b/modules/cron/lib/Controller/Cron.php new file mode 100644 index 0000000000000000000000000000000000000000..10eb967f9a2a8e10ee793adbd8f9dfcb40c6a3ae --- /dev/null +++ b/modules/cron/lib/Controller/Cron.php @@ -0,0 +1,150 @@ +<?php + +namespace SimpleSAML\Module\cron\Controller; + +use SimpleSAML\Auth; +use SimpleSAML\Auth\AuthenticationFactory; +use SimpleSAML\Configuration; +use SimpleSAML\Error; +use SimpleSAML\HTTP\RunnableResponse; +use SimpleSAML\Logger; +use SimpleSAML\Module; +use SimpleSAML\Session; +use SimpleSAML\Utils; +use SimpleSAML\XHTML\Template; +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Response; + +/** + * Controller class for the cron module. + * + * This class serves the different views available in the module. + * + * @package SimpleSAML\Module\cron + */ +class Cron +{ + /** @var \SimpleSAML\Configuration */ + protected $config; + + /** @var \SimpleSAML\Configuration */ + protected $cronconfig; + + /** @var \SimpleSAML\Session */ + protected $session; + + + /** + * Controller constructor. + * + * It initializes the global configuration and auth source configuration for the controllers implemented here. + * + * @param \SimpleSAML\Configuration $config The configuration to use by the controllers. + * @param \SimpleSAML\Configuration $moduleConfig The module-configuration to use by the controllers. + * @param \SimpleSAML\Session $session The session to use by the controllers. + * + * @throws \Exception + */ + public function __construct( + Configuration $config, + Session $session + ) { + $this->config = $config; + $this->cronconfig = Configuration::getConfig('module_cron.php'); + $this->session = $session; + } + + + /** + * Show cron info. + * + * @return \SimpleSAML\XHTML\Template + * An HTML template or a redirection if we are not authenticated. + */ + public function info() + { + Utils\Auth::requireAdmin(); + + $key = $this->cronconfig->getValue('key', 'secret'); + $tags = $this->cronconfig->getValue('allowed_tags'); + + $def = [ + 'weekly' => "22 0 * * 0", + 'daily' => "02 0 * * *", + 'hourly' => "01 * * * *", + 'default' => "XXXXXXXXXX", + ]; + + $urls = []; + foreach ($tags as $tag) { + $urls[] = [ + 'exec_href' => Module::getModuleURL('cron') . '/run/' . $tag . '/' . $key, + 'href' => Module::getModuleURL('cron') . '/run/' . $tag . '/' . $key . '/xhtml', + 'tag' => $tag, + 'int' => (array_key_exists($tag, $def) ? $def[$tag] : $def['default']), + ]; + } + + $t = new Template($this->config, 'cron:croninfo.tpl.php', 'cron:cron'); + $t->data['urls'] = $urls; + return $t; + } + + + /** + * Execute a cronjob. + * + * This controller will start a cron operation + * + * @param string $tag The tag + * @param string $key The secret key + * @param string|null $output The output format, defaulting to xhtml + * + * @return \SimpleSAML\XHTML\Template|\Symfony\Component\HttpFoundation\Response + * An HTML template, a redirect or a "runnable" response. + * + * @throws \SimpleSAML\Error\Exception + */ + public function run($tag, $key, $output) + { + $configKey = $this->cronconfig->getValue('key', 'secret'); + if ($key !== $configKey) { + Logger::error('Cron - Wrong key provided. Cron will not run.'); + exit; + } + + $cron = new \SimpleSAML\Module\cron\Cron(); + if ($tag === null || !$cron->isValidTag($tag)) { + Logger::error('Cron - Illegal tag [' . $tag . '].'); + exit; + } + + $url = Utils\HTTP::getSelfURL(); + $time = date(DATE_RFC822); + + $croninfo = $cron->runTag($tag); + $summary = $croninfo['summary']; + + if ($this->cronconfig->getValue('sendemail', true) && count($summary) > 0) { + $mail = new Utils\EMail('SimpleSAMLphp cron report'); + $mail->setData(['url' => $url, 'tag' => $croninfo['tag'], 'summary' => $croninfo['summary']]); + try { + $mail->send(); + } catch (\PHPMailer\PHPMailer\Exception $e) { + Logger::warning("Unable to send cron report"); + } + } + + if ($output === 'xhtml') { + $t = new Template($this->config, 'cron:croninfo-result.tpl.php', 'cron:cron'); + $t->data['tag'] = $croninfo['tag']; + $t->data['time'] = $time; + $t->data['url'] = $url; + $t->data['mail_required'] = isset($mail); + $t->data['mail_sent'] = !isset($e); + $t->data['summary'] = $summary; + return $t; + } + return new Response(); + } +} diff --git a/modules/cron/routing/routes/routes.yaml b/modules/cron/routing/routes/routes.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d25718ad1571cdfd3a44821af605c898fd79af8a --- /dev/null +++ b/modules/cron/routing/routes/routes.yaml @@ -0,0 +1,6 @@ +cron-croninfo: + path: /info + defaults: { _controller: 'SimpleSAML\Module\cron\Controller\Cron::info' } +cron-run: + path: /run/{tag}/{key}/{output} + defaults: { _controller: 'SimpleSAML\Module\cron\Controller\Cron::run', output: null } diff --git a/modules/cron/templates/croninfo-result.twig b/modules/cron/templates/croninfo-result.twig index f226ffe07e9c24c14680f98223b10bb0b5ce7ef2..eb755dd2e464b5cee924a501821643b4960e2255 100644 --- a/modules/cron/templates/croninfo-result.twig +++ b/modules/cron/templates/croninfo-result.twig @@ -22,9 +22,14 @@ Tag: {{ tag }} {% for sum in summary %} <li> {{ sum }}</li> {% endfor %} -</ul><br /> -</p> +</ul> +</p><br /> </code> +</div> +{% if mail_required == true and mail_sent == false %} +<div class="message-box error"> +Cron-report was not emailed due to an error. </div> +{% endif %} {% endblock %} diff --git a/modules/cron/templates/croninfo.tpl.php b/modules/cron/templates/croninfo.tpl.php index 50efe15a1ec53e6ef527448cc4b3e72cb5aa13b8..dc1bf0583098993a14127e1214e9385f8e05afdc 100644 --- a/modules/cron/templates/croninfo.tpl.php +++ b/modules/cron/templates/croninfo.tpl.php @@ -13,7 +13,7 @@ $run_text = $this->t('run_text'); <?php foreach ($this->data['urls'] as $url) { echo "# ".$run_text. ' ['.$url['tag'].']'."\n"; - echo $url['int']." curl --silent \"".$url['href']."\" > /dev/null 2>&1\n"; + echo $url['int']." curl --silent \"".$url['exec_href']."\" > /dev/null 2>&1\n"; } ?> </code></pre> @@ -23,7 +23,7 @@ foreach ($this->data['urls'] as $url) { <ul> <?php foreach ($this->data['urls'] as $url) { - echo ' <li><a href="'.$url['href'].'&output=xhtml">'.$run_text.' ['.$url['tag'].']'.'</a></li>'; + echo ' <li><a href="'.$url['href'].'">'.$run_text.' ['.$url['tag'].']'.'</a></li>'; } ?> </ul> diff --git a/modules/cron/templates/croninfo.twig b/modules/cron/templates/croninfo.twig index d2ea32988d69d46edbd58b76d1e48de895df60f2..12d9813ffcf9e2137f66ca3412739f067ea0f8ae 100644 --- a/modules/cron/templates/croninfo.twig +++ b/modules/cron/templates/croninfo.twig @@ -14,16 +14,17 @@ <code id="cronlist"> {% for url in urls %} # {{ 'Run cron:'|trans }} [{{ url.tag }}]<br /> - {{ url.int }} curl --silent "{{ url.href }}" > /dev/null 2>&1<br /> + {{ url.int }} curl --silent "{{ url.exec_href }}" > /dev/null 2>&1<br /> {% endfor %} - </code></div><br /> + <br /> + </code> + </div> - <p>{{ 'Click here to run the cron jobs:'|trans }}</p> - <ul> + <p>{{ 'Click here to run the cron jobs:'|trans }} + <ul> {% for url in urls %} - <li><a href="{{ url.href }}&output=xhtml">{{ 'Run cron:'|trans }} {{ url.tag }}</a></li> + <li><a href="{{ url.href }}">{{ 'Run cron:'|trans }} {{ url.tag }}</a></li> {% endfor %} - </ul> - </p> + </ul> {% endblock %} diff --git a/modules/cron/www/assets/css/cron.css b/modules/cron/www/assets/css/cron.css index 73cc3f9a4ba1091d36e7cc40bdc06a853c63bfbc..1f26a78d05023baa187fc0368d1f375de7de2807 100644 --- a/modules/cron/www/assets/css/cron.css +++ b/modules/cron/www/assets/css/cron.css @@ -1,4 +1,4 @@ code#cronlist { - font-size: 0.8vw; + font-size: 0.7vw; white-space: nowrap; } diff --git a/modules/cron/www/cron.php b/modules/cron/www/cron.php index 2afe851fbc9230f1fff10eaabf122f5dbaadca19..d77b307bed35618aa4cf9f365befa619ac9c0ad3 100644 --- a/modules/cron/www/cron.php +++ b/modules/cron/www/cron.php @@ -1,38 +1,19 @@ <?php -$config = \SimpleSAML\Configuration::getInstance(); -$cronconfig = \SimpleSAML\Configuration::getConfig('module_cron.php'); +namespace SimpleSAML\Module\cron; -if (!is_null($cronconfig->getValue('key'))) { - if ($_REQUEST['key'] !== $cronconfig->getValue('key')) { - \SimpleSAML\Logger::error('Cron - Wrong key provided. Cron will not run.'); - exit; - } -} +use SimpleSAML\Configuration; +use SimpleSAML\Session; +use Symfony\Component\HttpFoundation\Request; -$cron = new \SimpleSAML\Module\cron\Cron(); -if (!$cron->isValidTag($_REQUEST['tag'])) { - SimpleSAML\Logger::error('Cron - Illegal tag [' . $_REQUEST['tag'] . '].'); - exit; -} +$config = Configuration::getInstance(); +$session = Session::getSessionFromRequest(); +$request = Request::createFromGlobals(); -$url = \SimpleSAML\Utils\HTTP::getSelfURL(); -$time = date(DATE_RFC822); +$tag = $request->get('tag'); +$key = $request->get('key'); +$output = $request->get('output'); -$croninfo = $cron->runTag($_REQUEST['tag']); -$summary = $croninfo['summary']; - -if ($cronconfig->getValue('sendemail', true) && count($summary) > 0) { - $mail = new \SimpleSAML\Utils\EMail('SimpleSAMLphp cron report'); - $mail->setData(['url' => $url, 'tag' => $croninfo['tag'], 'summary' => $croninfo['summary']]); - $mail->send(); -} - -if (isset($_REQUEST['output']) && $_REQUEST['output'] == "xhtml") { - $t = new \SimpleSAML\XHTML\Template($config, 'cron:croninfo-result.tpl.php', 'cron:cron'); - $t->data['tag'] = $croninfo['tag']; - $t->data['time'] = $time; - $t->data['url'] = $url; - $t->data['summary'] = $summary; - $t->show(); -} +$controller = new Controller\Cron($config, $session); +$response = $controller->run($tag, $key, $output); +$response->send(); diff --git a/modules/cron/www/croninfo.php b/modules/cron/www/croninfo.php index 8a0aac4d52a90de827a0344822163813ce15cfc4..ffabdb0fb5c0b2d06e3ff68f923e744c2a4c992d 100644 --- a/modules/cron/www/croninfo.php +++ b/modules/cron/www/croninfo.php @@ -5,35 +5,16 @@ * initializes the SimpleSAMLphp config class with the correct path. */ -require_once('_include.php'); -// Load SimpleSAMLphp configuration and metadata -$config = \SimpleSAML\Configuration::getInstance(); -$session = \SimpleSAML\Session::getSessionFromRequest(); +namespace SimpleSAML\Module\cron; -\SimpleSAML\Utils\Auth::requireAdmin(); +use SimpleSAML\Configuration; +use SimpleSAML\Session; +use Symfony\Component\HttpFoundation\Request; -$cronconfig = \SimpleSAML\Configuration::getConfig('module_cron.php'); +$config = Configuration::getInstance(); +$session = Session::getSessionFromRequest(); -$key = $cronconfig->getValue('key', ''); -$tags = $cronconfig->getValue('allowed_tags'); - -$def = [ - 'weekly' => "22 0 * * 0", - 'daily' => "02 0 * * *", - 'hourly' => "01 * * * *", - 'default' => "XXXXXXXXXX", -]; - -$urls = []; -foreach ($tags as $tag) { - $urls[] = [ - 'href' => \SimpleSAML\Module::getModuleURL('cron/cron.php', ['key' => $key, 'tag' => $tag]), - 'tag' => $tag, - 'int' => (array_key_exists($tag, $def) ? $def[$tag] : $def['default']), - ]; -} - -$t = new \SimpleSAML\XHTML\Template($config, 'cron:croninfo.tpl.php', 'cron:cron'); -$t->data['urls'] = $urls; -$t->show(); +$controller = new Controller\Cron($config, $session); +$response = $controller->info(); +$response->send();