127 lines
7.1 KiB
PHP
127 lines
7.1 KiB
PHP
<?php if (empty($findings)): ?>
|
|
<div class="alert alert-info">Находок по выбранным фильтрам нет.</div>
|
|
<?php else: ?>
|
|
<?php
|
|
$sort = $filters['sort'] ?? 'ip';
|
|
$dir = $filters['dir'] ?? 'asc';
|
|
$sortLink = static function (string $field, string $label) use ($filters, $sort, $dir): string {
|
|
$nextDir = ($sort === $field && $dir === 'asc') ? 'desc' : 'asc';
|
|
$params = array_filter([
|
|
'range_id' => $filters['range_id'] ?? null,
|
|
'scan_job_id' => $filters['scan_job_id'] ?? null,
|
|
'status' => $filters['status'] ?? 'all',
|
|
'sort' => $field,
|
|
'dir' => $nextDir,
|
|
], static fn ($value) => $value !== null && $value !== '');
|
|
$mark = $sort === $field ? ($dir === 'asc' ? ' ↑' : ' ↓') : '';
|
|
return '<a href="/discoveries?' . htmlspecialchars(http_build_query($params)) . '" class="text-dark text-decoration-none">' .
|
|
htmlspecialchars($label . $mark) . '</a>';
|
|
};
|
|
?>
|
|
<table class="table table-sm align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th><?= $sortLink('ip', 'IP') ?></th>
|
|
<th><?= $sortLink('hostname', 'Hostname') ?></th>
|
|
<th><?= $sortLink('mac', 'MAC') ?></th>
|
|
<th><?= $sortLink('vendor', 'Vendor') ?></th>
|
|
<th><?= $sortLink('ports', 'Порты') ?></th>
|
|
<th><?= $sortLink('range', 'Диапазон') ?></th>
|
|
<th><?= $sortLink('status', 'Статус') ?></th>
|
|
<th><?= $sortLink('device', 'Устройство') ?></th>
|
|
<th>Действия</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($findings as $host): ?>
|
|
<?php $ports = json_decode($host['open_ports_json'] ?? '[]', true) ?: []; ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($host['ip_address']) ?></td>
|
|
<td><?= htmlspecialchars($host['hostname'] ?? '-') ?></td>
|
|
<td><?= htmlspecialchars($host['mac_address'] ?? '-') ?></td>
|
|
<td><?= htmlspecialchars($host['vendor'] ?? '-') ?></td>
|
|
<td class="ports-cell">
|
|
<?php if (empty($ports)): ?>
|
|
-
|
|
<?php else: ?>
|
|
<?= htmlspecialchars(implode(', ', array_slice($ports, 0, 6))) ?>
|
|
<?php if (count($ports) > 6): ?>
|
|
<span class="text-muted">+<?= count($ports) - 6 ?></span>
|
|
<?php endif; ?>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<?php if (!empty($host['range_name'])): ?>
|
|
<?= htmlspecialchars($host['range_name']) ?>
|
|
<small class="text-muted"><?= htmlspecialchars($host['range_cidr'] ?? '') ?></small>
|
|
<?php else: ?>
|
|
-
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= htmlspecialchars($host['status']) ?></td>
|
|
<td>
|
|
<?php if (!empty($host['device_id'])): ?>
|
|
<a href="/devices/<?= (int)$host['device_id'] ?>" class="badge text-bg-success text-decoration-none">
|
|
<?= htmlspecialchars($host['device_name'] ?? 'Устройство создано') ?>
|
|
</a>
|
|
<?php else: ?>
|
|
<?php
|
|
$suggestedDeviceId = null;
|
|
$suggestedDeviceName = null;
|
|
$suggestionReason = null;
|
|
$suggestionConfidence = null;
|
|
if (!empty($host['suggested_mac_device_id'])) {
|
|
$suggestedDeviceId = (int)$host['suggested_mac_device_id'];
|
|
$suggestedDeviceName = $host['suggested_mac_device_name'];
|
|
$suggestionReason = 'MAC';
|
|
$suggestionConfidence = 90;
|
|
} elseif (!empty($host['suggested_hostname_device_id'])) {
|
|
$suggestedDeviceId = (int)$host['suggested_hostname_device_id'];
|
|
$suggestedDeviceName = $host['suggested_hostname_device_name'];
|
|
$suggestionReason = 'hostname';
|
|
$suggestionConfidence = 60;
|
|
} elseif (!empty($host['suggested_ip_device_id'])) {
|
|
$suggestedDeviceId = (int)$host['suggested_ip_device_id'];
|
|
$suggestedDeviceName = $host['suggested_ip_device_name'];
|
|
$suggestionReason = 'IP';
|
|
$suggestionConfidence = 40;
|
|
}
|
|
?>
|
|
<?php if ($suggestedDeviceId !== null): ?>
|
|
<span class="badge text-bg-warning">
|
|
Похоже на <?= htmlspecialchars($suggestedDeviceName ?? ('#' . $suggestedDeviceId)) ?>
|
|
(<?= htmlspecialchars($suggestionReason ?? '') ?>, <?= (int)$suggestionConfidence ?>%)
|
|
</span>
|
|
<?php else: ?>
|
|
<span class="badge text-bg-secondary">нет</span>
|
|
<?php endif; ?>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<?php if (empty($host['device_id']) && ($suggestedDeviceId ?? null) !== null && $host['status'] === 'new'): ?>
|
|
<form method="POST" action="/discoveries/merge" class="d-inline">
|
|
<input type="hidden" name="host_id" value="<?= (int)$host['id'] ?>">
|
|
<input type="hidden" name="device_id" value="<?= (int)$suggestedDeviceId ?>">
|
|
<button type="submit" class="btn btn-sm btn-outline-success">Объединить</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
<?php if (empty($host['device_id']) && $host['status'] === 'new'): ?>
|
|
<form method="POST" action="/devices/from-host" class="d-inline">
|
|
<input type="hidden" name="host_id" value="<?= (int)$host['id'] ?>">
|
|
<input type="hidden" name="name" value="<?= htmlspecialchars($host['hostname'] ?: $host['ip_address']) ?>">
|
|
<button type="submit" class="btn btn-sm btn-outline-primary">Создать устройство</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
<?php if ($host['status'] === 'new'): ?>
|
|
<form method="POST" action="/discovery/hosts/ignore" class="d-inline">
|
|
<input type="hidden" name="host_id" value="<?= (int)$host['id'] ?>">
|
|
<button type="submit" class="btn btn-sm btn-outline-secondary">Игнорировать</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php endif; ?>
|