Merge branch 'db_fix' into 2.4

nibbler
iglocska 2019-11-29 15:24:50 +01:00
commit 785d6e8f2c
No known key found for this signature in database
GPG Key ID: BEA224F1FEF113AC
7 changed files with 134 additions and 21 deletions

View File

@ -2215,7 +2215,21 @@ misp.direct_call(relative_path, body)
if (!$this->_isSiteAdmin()) {
throw new MethodNotAllowedException(__('Only site admin accounts get the DB schema diagnostic.'));
}
return $this->RestResponse->viewData($this->Server->dbSchemaDiagnostic(), $this->response->type());
$dbSchemaDiagnostics = $this->Server->dbSchemaDiagnostic();
if ($this->_isRest()) {
return $this->RestResponse->viewData($dbSchemaDiagnostics, $this->response->type());
} else {
$this->set('checkedTableColumn', $dbSchemaDiagnostics['checked_table_column']);
$this->set('dbSchemaDiagnostics', $dbSchemaDiagnostics['diagnostic']);
$this->set('expectedDbVersion', $dbSchemaDiagnostics['expected_db_version']);
$this->set('actualDbVersion', $dbSchemaDiagnostics['actual_db_version']);
$this->set('error', $dbSchemaDiagnostics['error']);
$this->set('remainingLockTime', $dbSchemaDiagnostics['remaining_lock_time']);
$this->set('updateFailNumberReached', $dbSchemaDiagnostics['update_fail_number_reached']);
$this->set('updateLocked', $dbSchemaDiagnostics['update_locked']);
$this->render('/Elements/healthElements/db_schema_diagnostic');
}
}
public function viewDeprecatedFunctionUse()

View File

@ -4387,7 +4387,7 @@ class Server extends AppModel
*/
private function __attachRecoveryQuery($field, $table)
{
if ($field['is_critical']) {
if (isset($field['error_type'])) {
$length = false;
if (in_array($field['error_type'], array('missing_column', 'column_different'))) {
if ($field['expected']['data_type'] === 'int') {
@ -4404,30 +4404,57 @@ class Server extends AppModel
switch($field['error_type']) {
case 'missing_column':
$field['sql'] = sprintf(
'ALTER TABLE `%s` ADD COLUMN `%s` %s%s %s %s;',
'ALTER TABLE `%s` ADD COLUMN `%s` %s%s %s %s %s;',
$table,
$field['column_name'],
$field['expected']['data_type'],
$length !== null ? sprintf('(%d)', $length) : '',
isset($field['expected']['default']) ? 'DEFAULT "' . $field['expected']['default'] . '"' : '',
isset($field['expected']['column_default']) ? $field['expected']['column_default'] . '"' : '',
$field['expected']['is_nullable'] === 'NO' ? 'NOT NULL' : 'NULL',
empty($field['expected']['collation_name']) ? '' : 'COLLATE ' . $field['expected']['collation_name']
);
break;
case 'column_different':
$field['sql'] = sprintf(
'ALTER TABLE `%s` CHANGE `%s` `%s` %s%s %s %s;',
'ALTER TABLE `%s` MODIFY COLUMN `%s` %s%s %s %s %s;',
$table,
$field['column_name'],
$field['column_name'],
$field['expected']['data_type'],
$length !== null ? sprintf('(%d)', $length) : '',
isset($field['expected']['default']) ? 'DEFAULT "' . $field['expected']['default'] . '"' : '',
isset($field['expected']['column_default']) ? 'DEFAULT "' . $field['expected']['column_default'] . '"' : '',
$field['expected']['is_nullable'] === 'NO' ? 'NOT NULL' : 'NULL',
empty($field['expected']['collation_name']) ? '' : 'COLLATE ' . $field['expected']['collation_name']
);
break;
}
} elseif($field['error_type'] == 'missing_table') {
$allFields = array();
foreach ($field['expected_table'] as $expectedField) {
$length = false;
if ($expectedField['data_type'] === 'int') {
$length = 11;
} elseif ($expectedField['data_type'] === 'tinyint') {
$length = 1;
} elseif ($expectedField['data_type'] === 'varchar') {
$length = $expectedField['character_maximum_length'];
} elseif ($expectedField['data_type'] === 'text') {
$length = null;
}
$fieldSql = sprintf('`%s` %s%s %s %s %s',
$expectedField['column_name'],
$expectedField['data_type'],
$length !== null ? sprintf('(%d)', $length) : '',
isset($expectedField['column_default']) ? 'DEFAULT "' . $expectedField['column_default'] . '"' : '',
$expectedField['is_nullable'] === 'NO' ? 'NOT NULL' : 'NULL',
empty($expectedField['collation_name']) ? '' : 'COLLATE ' . $expectedField['collation_name']
);
$allFields[] = $fieldSql;
}
$field['sql'] = __("% The command below is a suggestion and might be incorrect. Please ask if you are not sure what you are doing.") . "</br></br>" . sprintf(
"CREATE TABLE IF NOT EXISTS `%s` ( %s ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;",
$table,
implode(', ', $allFields)
);
}
}
return $field;
@ -4468,7 +4495,8 @@ class Server extends AppModel
'character_maximum_length',
'numeric_precision',
// 'datetime_precision', -- Only available on MySQL 5.6+
'collation_name'
'collation_name',
'column_default'
)
){
$dbActualSchema = array();
@ -4508,6 +4536,7 @@ class Server extends AppModel
$dbDiff[$tableName][] = array(
'description' => sprintf(__('Table `%s` does not exist'), $tableName),
'error_type' => 'missing_table',
'expected_table' => $columns,
'column_name' => $tableName,
'is_critical' => true
);

View File

@ -46,19 +46,39 @@
?>
<?php
$hasAtLeastOneCriticalWarning = false;
foreach ($dbSchemaDiagnostics as $tableName => $tableDiagnostic) {
foreach ($tableDiagnostic as $i => $columnDiagnostic) {
if ($columnDiagnostic['is_critical']) {
$hasAtLeastOneCriticalWarning = true;
break;
}
}
if ($hasAtLeastOneCriticalWarning) {
break;
}
}
if (count($dbSchemaDiagnostics) > 0) {
echo sprintf('<span style="margin-bottom: 5px;" class="label label-important" title="%s">%s<i style="font-size: larger;" class="fas fa-times"></i></span>',
__('The current database schema does not match the expected format.'),
__('Database schema diagnostic: ')
);
echo sprintf('<div class="alert alert-error"><strong>%s</strong> %s <br/>%s</div>',
__('Critical warning!'),
__('The MISP database seems to be in an inconsistent state. Immediate attention is required.'),
__('⚠ This diagnostic tool is in experimental state - the highlighted issues may be benign. If you are unsure, please open an issue on with the issues identified over at https://github.com/MISP/MISP for clarification.')
);
if ($hasAtLeastOneCriticalWarning) {
echo sprintf('<div class="alert alert-error"><strong>%s</strong> %s <br/>%s</div>',
__('Warning'),
__('The MISP database state does not match the expected schema. Resolving these issues is recommended.'),
__('⚠ This diagnostic tool is in experimental state - the highlighted issues may be benign. If you are unsure, please open an issue on with the issues identified over at https://github.com/MISP/MISP for clarification.')
);
} else {
echo sprintf('<div class="alert alert-warning"><strong>%s</strong> %s <br/>%s</div>',
__('Warning'),
__('The MISP database state does not match the expected schema. Resolving these issues is recommended.'),
__('⚠ This diagnostic tool is in experimental state - the highlighted issues may be benign. If you are unsure, please open an issue on with the issues identified over at https://github.com/MISP/MISP for clarification.')
);
}
$table = sprintf('%s%s%s',
'<table class="table table-bordered table-condensed">',
sprintf('<thead><th>%s</th><th>%s</th><th>%s</th><th>%s</th></thead>', __('Table name'), __('Description'), __('Expected schema'), __('Actual schema')),
sprintf('<thead><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th></th></thead>', __('Table name'), __('Description'), __('Expected schema'), __('Actual schema')),
'<tbody>'
);
$rows = '';
@ -88,6 +108,15 @@
$rows .= sprintf('<td class="dbColumnDiagnosticRow" data-table="%s" data-index="%s">%s</td>', h($tableName), h($i), implode(' ', $saneExpected));
$rows .= sprintf('<td class="dbColumnDiagnosticRow" data-table="%s" data-index="%s">%s</td>', h($tableName), h($i), implode(' ', $saneActual));
}
$rows .= sprintf('<td class="" data-table="%s" data-index="%s">%s</td>', h($tableName), h($i),
empty($columnDiagnostic['sql']) ? '' :
sprintf(
'<i class="fa fa-wrench useCursorPointer" onclick="quickFixSchema(this, \'%s\')" title="%s" data-query="%s"></i>',
h($columnDiagnostic['sql']),
__('Fix Database schema'),
h($columnDiagnostic['sql'])
)
);
$rows .= '</tr>';
}
}
@ -167,4 +196,10 @@ $(document).ready(function() {
trigger: 'hover'
});
});
function quickFixSchema(clicked, sqlQuery) {
var message = "<?php echo sprintf('<div class=\"alert alert-error\" style=\"margin-bottom: 5px;\"><h5>%s</h5> %s</div>', __('Warning'), __('Executing this query might take some time and may harm your database. Please review the query below or backup your database in case of doubt.')) ?>"
message += "<div class=\"well\"><kbd>" + sqlQuery + "</kbd></div>"
openPopover(clicked, message, undefined, 'left');
}
</script>

View File

@ -227,8 +227,8 @@
echo '</div>';
?>
<h4><?php echo __('Schema status');?></h4>
<div style="width: 70vw; padding-left: 10px;">
<?php echo $this->element('/healthElements/db_schema_status', array(
<div id="schemaStatusDiv" style="width: 70vw; padding-left: 10px;">
<?php echo $this->element('/healthElements/db_schema_diagnostic', array(
'checkedTableColumn' => $dbSchemaDiagnostics['checked_table_column'],
'dbSchemaDiagnostics' => $dbSchemaDiagnostics['diagnostic'],
'expectedDbVersion' => $dbSchemaDiagnostics['expected_db_version'],

View File

@ -0,0 +1,10 @@
<?php echo $this->element('/healthElements/db_schema_diagnostic', array(
'checkedTableColumn' => $dbSchemaDiagnostics['checked_table_column'],
'dbSchemaDiagnostics' => $dbSchemaDiagnostics['diagnostic'],
'expectedDbVersion' => $dbSchemaDiagnostics['expected_db_version'],
'actualDbVersion' => $dbSchemaDiagnostics['actual_db_version'],
'error' => $dbSchemaDiagnostics['error'],
'remainingLockTime' => $dbSchemaDiagnostics['remaining_lock_time'],
'updateFailNumberReached' => $dbSchemaDiagnostics['update_fail_number_reached'],
'updateLocked' => $dbSchemaDiagnostics['update_locked']
)); ?>

View File

@ -1687,13 +1687,15 @@ function popoverPopup(clicked, id, context, target, admin) {
}
// create a confirm popover on the clicked html node.
function popoverConfirm(clicked) {
function popoverConfirm(clicked, message, placement) {
var $clicked = $(clicked);
var popoverContent = '<div>';
popoverContent += '<button id="popoverConfirmOK" class="btn btn-primary" onclick=submitPopover(this)>Yes</button>';
popoverContent += message === undefined ? '' : '<p>' + message + '</p>';
popoverContent += '<button id="popoverConfirmOK" class="btn btn-primary" style="margin-right: 5px;" onclick=submitPopover(this)>Yes</button>';
popoverContent += '<button class="btn btn-inverse" style="float: right;" onclick=cancelPrompt()>Cancel</button>';
popoverContent += '</div>';
openPopover($clicked, popoverContent);
placement = placement === undefined ? 'auto' : placement;
openPopover($clicked, popoverContent, undefined, placement);
$("#popoverConfirmOK")
.focus()
.bind("keydown", function(e) {
@ -1713,7 +1715,30 @@ function submitPopover(clicked) {
var dismissid = $clicked.closest('div.popover').attr('data-dismissid');
$form = $('[data-dismissid="' + dismissid + '"]').closest('form');
}
$form.submit();
if ($form.data('ajax')) {
$.ajax({
data: $form.serialize(),
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
location.reload();
},
error:function() {
showMessage('fail', 'Could not perform query.');
},
complete:function() {
$(".loading").hide();
$("#popover_form").fadeOut();
$("#gray_out").fadeOut();
$('#temp').remove();
},
type:"post",
url: $form.attr('action')
});
} else {
$form.submit();
}
}
function simplePopup(url) {

File diff suppressed because one or more lines are too long