Merge branch '2.4' of github.com:MISP/MISP into 2.4

pull/5687/head
mokaddem 2020-03-06 16:38:22 +01:00
commit 5e15ab1ef1
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
17 changed files with 181 additions and 49 deletions

View File

@ -401,6 +401,7 @@ class ACLComponent extends Component
'releaseUpdateLock' => array(),
'resetRemoteAuthKey' => array(),
'rest' => array('perm_auth'),
'restartDeadWorkers' => array(),
'restartWorkers' => array(),
'serverSettings' => array(),
'serverSettingsEdit' => array(),

View File

@ -139,16 +139,25 @@ class DashboardsController extends AppController
$org_scope = $this->_isSiteAdmin() ? 0 : $this->Auth->user('org_id');
$lookup_hash = hash('sha256', $value['widget'] . $value['config']);
$data = $redis->get('misp:dashboard:' . $org_scope . ':' . $lookup_hash);
if (empty($data)) {
$cacheLifetime = isset($dashboardWidget->cacheLifetime) ? $dashboardWidget->cacheLifetime : 300;
if (!isset($dashboardWidget->cacheLifetime)) {
$dashboardWidget->cacheLifetime = false;
}
if (empty($dashboardWidget->cacheLifetime) || empty($data)) {
$data = $dashboardWidget->handler($this->Auth->user(), json_decode($value['config'], true));
$redis->set('misp:dashboard:' . $org_scope . ':' . $lookup_hash, json_encode(array('data' => $data)));
$redis->expire('misp:dashboard:' . $org_scope . ':' . $lookup_hash, $cacheLifetime);
if (!empty($dashboardWidget->cacheLifetime)) {
$redis->set('misp:dashboard:' . $org_scope . ':' . $lookup_hash, json_encode(array('data' => $data)));
$redis->expire('misp:dashboard:' . $org_scope . ':' . $lookup_hash, $dashboardWidget->cacheLifetime);
}
} else {
$data = json_decode($data, true)['data'];
}
$config = array(
'render' => $dashboardWidget->render,
'autoRefreshDelay' => empty($dashboardWidget->autoRefreshDelay) ? false : $dashboardWidget->autoRefreshDelay
);
$this->set('data', $data);
$this->render('/Dashboards/Widgets/' . $dashboardWidget->render);
$this->set('config', $config);
$this->render('widget_loader');
} else {
throw new MethodNotAllowedException(__('This endpoint can only be reached via POST requests.'));
}

View File

@ -1367,6 +1367,18 @@ class ServersController extends AppController
$this->redirect(array('controller' => 'servers', 'action' => 'serverSettings', 'workers'));
}
public function restartDeadWorkers()
{
if (!$this->_isSiteAdmin() || !$this->request->is('post')) {
throw new MethodNotAllowedException();
}
$this->Server->restartDeadWorkers($this->Auth->user());
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('Server', 'restartDeadWorkers', false, $this->response->type(), __('Restarting workers.'));
}
$this->redirect(array('controller' => 'servers', 'action' => 'serverSettings', 'workers'));
}
private function __manageFiles()
{
if (!$this->_isSiteAdmin()) {

View File

@ -8,7 +8,8 @@ class MispAdminResourceWidget
public $height = 2;
public $params = array();
public $description = 'Basic widget showing some server statistics in regards to MISP.';
public $cacheLifetime = 5;
public $cacheLifetime = false;
public $autoRefreshDelay = 3;
public function handler($user, $options = array())

View File

@ -8,7 +8,7 @@ class MispAdminSyncTestWidget
public $height = 2;
public $params = array();
public $description = 'Basic widget showing some server statistics in regards to MISP.';
public $cacheLifetime = 5;
public $cacheLifetime = 1;
public function handler($user, $options = array())
@ -19,6 +19,10 @@ class MispAdminSyncTestWidget
'conditions' => array('OR' => array('pull' => 1, 'push' => 1, 'caching_enabled' => 1)),
'recursive' => -1
));
$data = array();
if (empty($servers)) {
return array();
}
$syncTestErrorCodes = $this->Server->syncTestErrorCodes;
foreach ($servers as $server) {
$result = $this->Server->runConnectionTest($server['Server']['id']);

View File

@ -8,7 +8,8 @@ class MispAdminWorkerWidget
public $height = 2;
public $params = array();
public $description = 'Basic widget showing some server statistics in regards to MISP.';
public $cacheLifetime = 5;
public $cacheLifetime = false;
public $autoRefreshDelay = 5;
public function handler($user, $options = array())
@ -23,11 +24,13 @@ class MispAdminWorkerWidget
}
$total = 0;
$alive = 0;
foreach ($queue['workers'] as $worker) {
if ($worker['alive']) {
$alive += 1;
if (!empty($queue['workers'])) {
foreach ($queue['workers'] as $worker) {
if ($worker['alive']) {
$alive += 1;
}
$total += 1;
}
$total += 1;
}
$colour = 'green';
if ($alive == 0) {

View File

@ -6,12 +6,26 @@ class Dashboard extends AppModel
public function loadWidget($user, $name)
{
$name = str_replace('/', '', $name);
if (file_exists(APP . 'Lib/Dashboard/' . $name . '.php')) {
App::uses($name, 'Dashboard');
} else if (file_exists(APP . 'Lib/Dashboard/Custom/' . $name . '.php')) {
App::uses($name, 'Dashboard/Custom');
} else {
throw new NotFoundException(__('Invalid widget or widget not found.'));
$customdir = new Folder(APP . 'Lib/Dashboard/Custom');
$subDirectories = $customdir->read();
$found = false;
foreach ($subDirectories[0] as $subDir) {
$currentDir = new Folder(APP . 'Lib/Dashboard/' . $subDir);
if (file_exists(APP . 'Lib/Dashboard/Custom/' . $subDir . '/' . $name . '.php')) {
App::uses($name, 'Dashboard/Custom/' . $subDir);
$found = true;
break;
}
}
if (!$found) {
throw new NotFoundException(__('Invalid widget or widget not found.'));
}
}
$widget = new $name();
if (method_exists($widget, 'checkPermissions')) {
@ -24,31 +38,34 @@ class Dashboard extends AppModel
public function loadAllWidgets($user)
{
$dir = new Folder(APP . 'Lib/Dashboard');
$paths = array(
'/',
'/Custom'
);
$customdir = new Folder(APP . 'Lib/Dashboard/Custom');
$widgetFiles = $dir->find('.*Widget\.php');
$customWidgetFiles = $customdir->find('.*Widget\.php');
$widgets = array();
foreach ($widgetFiles as $widgetFile) {
$className = substr($widgetFile, 0, strlen($widgetFile) -4);
$temp = $this->__extractMeta($user, $className, false);
if ($temp !== false) {
$widgets[$className] = $temp;
}
$subDirectories = $customdir->read();
foreach ($subDirectories[0] as $subDir) {
$paths[] = '/Custom/' . $subDir;
}
foreach ($customWidgetFiles as $widgetFile) {
$className = substr($widgetFile, 0, strlen($widgetFile) -4);
$temp = $this->__extractMeta($user, $className, true);
if ($temp !== false) {
$widgets[$className] = $temp;
$widgetMeta = array();
$widgets = array();
foreach ($paths as $path) {
$currentDir = new Folder(APP . 'Lib/Dashboard' . $path);
$widgetFiles = $currentDir->find('.*Widget\.php');
foreach ($widgetFiles as $widgetFile) {
$className = substr($widgetFile, 0, strlen($widgetFile) -4);
$temp = $this->__extractMeta($user, $className, $path);
if ($temp !== false) {
$widgets[$className] = $temp;
}
}
}
return $widgets;
}
private function __extractMeta($user, $className, $custom)
private function __extractMeta($user, $className, $path)
{
App::uses($className, 'Dashboard' . ($custom ? '/Custom' : ''));
App::uses($className, 'Dashboard' . ($path === '/' ? '' : $path));
$widgetClass = new $className();
if (method_exists($widgetClass, 'checkPermissions')) {
if (!$widgetClass->checkPermissions($user)) {
@ -63,7 +80,8 @@ class Dashboard extends AppModel
'description' => empty($widgetClass->description) ? $widgetClass->title : $widgetClass->description,
'height' => empty($widgetClass->height) ? 1 : $widgetClass->height,
'width' => empty($widgetClass->width) ? 1 : $widgetClass->width,
'placeholder' => empty($widgetClass->placeholder) ? '' : $widgetClass->placeholder
'placeholder' => empty($widgetClass->placeholder) ? '' : $widgetClass->placeholder,
'autoRefreshDelay' => empty($widgetClass->autoRefreshDelay) ? false : $widgetClass->autoRefreshDelay,
);
return $widget;
}

View File

@ -5119,6 +5119,7 @@ class Server extends AppModel
} else {
$currentUser = trim(shell_exec('whoami'));
}
$killed = array();
foreach ($workers as $pid => $worker) {
if (!is_numeric($pid)) {
throw new MethodNotAllowedException('Non numeric PID found!');
@ -5127,8 +5128,14 @@ class Server extends AppModel
if ($worker['user'] == $currentUser && !$pidTest) {
$this->ResqueStatus->removeWorker($pid);
$this->__logRemoveWorker($user, $pid, $worker['queue'], true);
if (empty($killed[$worker['queue']])) {
$killed[$worker['queue']] = 1;
} else {
$killed[$worker['queue']] += 1;
}
}
}
return $killed;
}
private function __logRemoveWorker($user, $pid, $queue, $dead = false)
@ -5593,6 +5600,19 @@ class Server extends AppModel
return true;
}
public function restartDeadWorkers($user=false)
{
if (Configure::read('MISP.background_jobs')) {
$killed = $this->workerRemoveDead($user);
foreach ($killed as $queue => $count) {
for ($i = 0; $i < $count; $i++) {
$this->startWorker($queue);
}
}
}
return true;
}
public function restartWorker($pid)
{
if (Configure::read('MISP.background_jobs')) {

View File

@ -1,14 +0,0 @@
<?php
foreach ($data as $element) {
if (!empty($element['type']) && $element['type'] === 'gap') {
echo '<br />';
} else {
echo sprintf(
'<div><span class="bold">%s</span>: <span class="%s">%s</span>%s</div>',
h($element['title']),
empty($element['class']) ? 'blue' : h($element['class']),
!isset($element['value']) ? '' : h($element['value']),
empty($element['html']) ? '' : $element['html']
);
}
}

View File

@ -38,7 +38,7 @@ function resetDashboardGrid(grid) {
}
$(document).ready(function () {
var grid = GridStack.init();
var grid = GridStack.init({verticalMargin: 2});
resetDashboardGrid(grid);
grid.on('change', function(event, items) {
saveDashboardState();

View File

@ -0,0 +1,18 @@
<?php
$randomId = rand();
?>
<div id="widgetContentInner<?= $randomId ?>">
<?php
echo $this->element('/dashboard/Widgets/' . $config['render']);
?>
</div>
<script type="text/javascript">
$(document).ready(function() {
if (<?= $config['autoRefreshDelay'] ? 'true' : 'false' ?>) {
setTimeout( function(){
updateDashboardWidget($("#widgetContentInner<?= $randomId ?>").closest('.grid-stack-item'))},
<?= $config['autoRefreshDelay'] ? $config['autoRefreshDelay'] : 1 ?> * 1000
);
}
});
</script>

View File

@ -0,0 +1,32 @@
<table style="border-spacing:0px;">
<?php
if (!empty($data['logarithmic'])) {
$max = max($data['logarithmic']);
} else {
$max = max($data['data']);
}
foreach ($data['data'] as $entry => $count) {
$value = $count;
if (!empty($data['logarithmic'])) {
$value = $data['logarithmic'][$entry];
}
echo sprintf(
'<tr><td style="%s">%s</td><td style="%s">%s</td></tr>',
'text-align:right;width:33%;',
h($entry),
'width:100%',
sprintf(
'<div title="%s" style="%s">%s</div>',
h($entry) . ': ' . h($count),
sprintf(
'background-color:%s; width:%s; color:white; text-align:center;',
(empty($data['colours'][$entry]) ? '#0088cc' : h($data['colours'][$entry])),
100 * h($value) / $max . '%;'
),
h($count)
),
'&nbsp;'
);
}
?>
</table>

View File

@ -0,0 +1,28 @@
<?php
foreach ($data as $element) {
if (!empty($element['type']) && $element['type'] === 'gap') {
echo '<br />';
} else {
if (!empty($element['value'])) {
if (is_array($element['value'])) {
foreach ($element['value'] as &$value) {
if (is_array($value)) {
$value = 'Array';
} else {
$value = h($value);
}
}
$element['value'] = '<br />' . implode('<br />', $element['value']);
} else {
$element['value'] = h($element['value']);
}
}
echo sprintf(
'<div><span class="bold">%s</span>: <span class="%s">%s</span>%s</div>',
h($element['title']),
empty($element['class']) ? 'blue' : h($element['class']),
!isset($element['value']) ? '' : $element['value'],
empty($element['html']) ? '' : $element['html']
);
}
}

View File

@ -126,8 +126,8 @@
<?php
if ($worker_array['controls']) {
echo $this->Form->create('Server', array('url' => '/servers/restartWorkers'));
echo $this->Form->button(__('Restart all workers'), array('class' => 'btn btn-primary'));
echo $this->Form->create('Server', array('url' => '/servers/restartDeadWorkers'));
echo $this->Form->button(__('Restart dead workers'), array('class' => 'btn btn-primary'));
echo $this->Form->end();
}
?>

@ -1 +1 @@
Subproject commit 346503f433c23c8dca482ca713d5071bad4dd315
Subproject commit 3d57ee4fd2a78d3de6f210b16fd24ddf81c75d9a