mirror of https://git.48k.eu/ogcp
views: add client search to scopes
Add a view to search clients by IP or MAC. Adapt parse_scopes_from_tree() to include the path of the scope in the tree.master
parent
655ffbc0bb
commit
dd4b7ad229
|
@ -0,0 +1,88 @@
|
|||
{% extends 'scopes.html' %}
|
||||
{% import "bootstrap/wtf.html" as wtf %}
|
||||
{% import "macros.html" as macros %}
|
||||
|
||||
{% set btn_back = true %}
|
||||
|
||||
{% block nav_client %} active {% endblock %}
|
||||
{% block nav_client_search %} active {% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<h2 class="mx-5 subhead-heading">
|
||||
{{ _('Search clients') }}
|
||||
</h2>
|
||||
|
||||
<div class="mx-5 my-3">
|
||||
<label for="name-filter">{{ _('Name') }}</label>
|
||||
<input type="text" id="name-filter" class="form-control mb-2">
|
||||
|
||||
<label for="ip-filter">{{ _('IP Address') }}</label>
|
||||
<input type="text" id="ip-filter" class="form-control mb-2">
|
||||
|
||||
<label for="mac-filter">{{ _('MAC') }}</label>
|
||||
<input type="text" id="mac-filter" class="form-control mb-2">
|
||||
|
||||
<button id="search-button" class="btn btn-primary">{{ _('Search') }}</button>
|
||||
</div>
|
||||
|
||||
<div id="clients-container" class="mx-5 mt-3"></div>
|
||||
|
||||
<script>
|
||||
let clients = {{ clients|tojson|safe }};
|
||||
|
||||
function renderClients(data) {
|
||||
const container = document.getElementById('clients-container');
|
||||
container.innerHTML = '';
|
||||
|
||||
let currentPath = null;
|
||||
let ul = null;
|
||||
|
||||
data.forEach(client => {
|
||||
if (client.tree_path !== currentPath) {
|
||||
currentPath = client.tree_path;
|
||||
|
||||
const pathElement = document.createElement('p');
|
||||
pathElement.innerHTML = `<strong>${currentPath}</strong>:`;
|
||||
container.appendChild(pathElement);
|
||||
|
||||
ul = document.createElement('ul');
|
||||
container.appendChild(ul);
|
||||
}
|
||||
|
||||
const li = document.createElement('li');
|
||||
li.textContent = `${client.name} (IP: ${client.ip.join(', ')} | MAC: ${client.mac})`;
|
||||
ul.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
||||
function filterClients() {
|
||||
const nameFilter = document.getElementById('name-filter').value.toLowerCase();
|
||||
const ipFilter = document.getElementById('ip-filter').value;
|
||||
const macFilter = document.getElementById('mac-filter').value;
|
||||
|
||||
const filtered = clients.filter(client => {
|
||||
const matchesName = nameFilter ? client.name.toLowerCase().includes(nameFilter) : true;
|
||||
const matchesIP = ipFilter ? client.ip.some(ip => ip.includes(ipFilter)) : true;
|
||||
const matchesMAC = macFilter ? client.mac.includes(macFilter) : true;
|
||||
return matchesName && matchesIP && matchesMAC;
|
||||
});
|
||||
|
||||
renderClients(filtered);
|
||||
}
|
||||
|
||||
renderClients(clients);
|
||||
document.getElementById('search-button').addEventListener('click', filterClients);
|
||||
|
||||
// Search on Enter key press
|
||||
document.querySelectorAll('#name-filter, #ip-filter, #mac-filter').forEach(input => {
|
||||
input.addEventListener('keydown', event => {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
filterClients();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
{% endblock %}
|
|
@ -42,6 +42,8 @@
|
|||
<input class="btn btn-light dropdown-item {% block nav_client_delete %}{% endblock %}" type="submit" value="{{ _('Delete client') }}"
|
||||
form="scopesForm" formaction="{{ url_for('action_client_delete') }}" formmethod="get">
|
||||
{% endif %}
|
||||
<input class="btn btn-light dropdown-item {% block nav_client_search %}{% endblock %}" type="submit" value="{{ _('Search client') }}"
|
||||
form="scopesForm" formaction="{{ url_for('action_client_search') }}" formmethod="get">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
|
@ -246,15 +246,17 @@ def get_all_repositories():
|
|||
return data
|
||||
|
||||
|
||||
def parse_scopes_from_tree(tree, scope_type):
|
||||
def parse_scopes_from_tree(tree, scope_type, tree_path=''):
|
||||
scopes = []
|
||||
for scope in tree['scope']:
|
||||
if scope['type'] == scope_type:
|
||||
if 'name' in tree:
|
||||
scope['parent'] = tree['name']
|
||||
scope['tree_path'] = tree_path
|
||||
scopes.append(scope)
|
||||
else:
|
||||
scopes += parse_scopes_from_tree(scope, scope_type)
|
||||
new_tree_path = f'{tree_path}{scope.get("name")}/'
|
||||
scopes += parse_scopes_from_tree(scope, scope_type, new_tree_path)
|
||||
return scopes
|
||||
|
||||
def add_state_and_ips(scope, clients, ips):
|
||||
|
@ -1998,6 +2000,23 @@ def action_client_delete():
|
|||
else:
|
||||
return redirect(url_for('scopes'))
|
||||
|
||||
@app.route('/action/client/search', methods=['GET'])
|
||||
@handle_server_errors('scopes')
|
||||
@login_required
|
||||
def action_client_search():
|
||||
scopes, clients = get_scopes()
|
||||
clients = parse_scopes_from_tree(scopes, 'computer')
|
||||
for client in clients:
|
||||
payload = {'client': [client['ip'][0]]}
|
||||
info_response = multi_request('get', '/client/info', payload)
|
||||
for res in info_response:
|
||||
mac = res['json']['mac'].lower()
|
||||
client['mac'] = mac
|
||||
|
||||
return render_template('actions/client_search.html',
|
||||
scopes=scopes,
|
||||
clients=clients)
|
||||
|
||||
@app.route('/action/cmd/run', methods=['GET', 'POST'])
|
||||
@handle_server_errors('commands')
|
||||
@login_required
|
||||
|
|
Loading…
Reference in New Issue