feat: Add IP filtering to attack types pagination and detail views
This commit is contained in:
@@ -1955,6 +1955,7 @@ class DatabaseManager:
|
||||
page_size: int = 5,
|
||||
sort_by: str = "timestamp",
|
||||
sort_order: str = "desc",
|
||||
ip_filter: Optional[str] = None,
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Retrieve paginated list of detected attack types with access logs.
|
||||
@@ -1964,6 +1965,7 @@ class DatabaseManager:
|
||||
page_size: Number of results per page
|
||||
sort_by: Field to sort by (timestamp, ip, attack_type)
|
||||
sort_order: Sort order (asc or desc)
|
||||
ip_filter: Optional IP address to filter results
|
||||
|
||||
Returns:
|
||||
Dictionary with attacks list and pagination info
|
||||
@@ -1979,18 +1981,27 @@ class DatabaseManager:
|
||||
sort_order.lower() if sort_order.lower() in {"asc", "desc"} else "desc"
|
||||
)
|
||||
|
||||
# Base query filter
|
||||
base_filters = []
|
||||
if ip_filter:
|
||||
base_filters.append(AccessLog.ip == ip_filter)
|
||||
|
||||
# Count total unique access logs with attack detections
|
||||
total_attacks = (
|
||||
count_query = (
|
||||
session.query(AccessLog)
|
||||
.join(AttackDetection)
|
||||
.distinct(AccessLog.id)
|
||||
.count()
|
||||
)
|
||||
if base_filters:
|
||||
count_query = count_query.filter(*base_filters)
|
||||
total_attacks = count_query.distinct(AccessLog.id).count()
|
||||
|
||||
# Get paginated access logs with attack detections
|
||||
query = (
|
||||
session.query(AccessLog).join(AttackDetection).distinct(AccessLog.id)
|
||||
session.query(AccessLog).join(AttackDetection)
|
||||
)
|
||||
if base_filters:
|
||||
query = query.filter(*base_filters)
|
||||
query = query.distinct(AccessLog.id)
|
||||
|
||||
if sort_by == "timestamp":
|
||||
query = query.order_by(
|
||||
|
||||
@@ -241,10 +241,12 @@ async def htmx_attacks(
|
||||
page: int = Query(1),
|
||||
sort_by: str = Query("timestamp"),
|
||||
sort_order: str = Query("desc"),
|
||||
ip_filter: str = Query(None),
|
||||
):
|
||||
db = get_db()
|
||||
result = db.get_attack_types_paginated(
|
||||
page=max(1, page), page_size=5, sort_by=sort_by, sort_order=sort_order
|
||||
page=max(1, page), page_size=5, sort_by=sort_by, sort_order=sort_order,
|
||||
ip_filter=ip_filter,
|
||||
)
|
||||
|
||||
# Transform attack data for template (join attack_types list, map id to log_id)
|
||||
@@ -271,6 +273,7 @@ async def htmx_attacks(
|
||||
"pagination": result["pagination"],
|
||||
"sort_by": sort_by,
|
||||
"sort_order": sort_order,
|
||||
"ip_filter": ip_filter or "",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -185,6 +185,19 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Detected Attack Types table – only for attackers #}
|
||||
{% if stats.category and stats.category | lower == 'attacker' %}
|
||||
<div class="table-container alert-section" style="margin-top: 20px;">
|
||||
<h2>Detected Attack Types</h2>
|
||||
<div class="htmx-container"
|
||||
hx-get="{{ dashboard_path }}/htmx/attacks?page=1&ip_filter={{ ip_address }}"
|
||||
hx-trigger="revealed"
|
||||
hx-swap="innerHTML">
|
||||
<div class="htmx-indicator">Loading...</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Access History table #}
|
||||
<div class="table-container alert-section" style="margin-top: 20px;">
|
||||
<h2>Access History</h2>
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
<span class="pagination-info">Page {{ pagination.page }}/{{ pagination.total_pages }} — {{ pagination.total }} total</span>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<button class="pagination-btn"
|
||||
hx-get="{{ dashboard_path }}/htmx/attacks?page={{ pagination.page - 1 }}&sort_by={{ sort_by }}&sort_order={{ sort_order }}"
|
||||
hx-get="{{ dashboard_path }}/htmx/attacks?page={{ pagination.page - 1 }}&sort_by={{ sort_by }}&sort_order={{ sort_order }}{% if ip_filter %}&ip_filter={{ ip_filter }}{% endif %}"
|
||||
hx-target="closest .htmx-container"
|
||||
hx-swap="innerHTML"
|
||||
{% if pagination.page <= 1 %}disabled{% endif %}>Prev</button>
|
||||
<button class="pagination-btn"
|
||||
hx-get="{{ dashboard_path }}/htmx/attacks?page={{ pagination.page + 1 }}&sort_by={{ sort_by }}&sort_order={{ sort_order }}"
|
||||
hx-get="{{ dashboard_path }}/htmx/attacks?page={{ pagination.page + 1 }}&sort_by={{ sort_by }}&sort_order={{ sort_order }}{% if ip_filter %}&ip_filter={{ ip_filter }}{% endif %}"
|
||||
hx-target="closest .htmx-container"
|
||||
hx-swap="innerHTML"
|
||||
{% if pagination.page >= pagination.total_pages %}disabled{% endif %}>Next</button>
|
||||
@@ -23,7 +23,7 @@
|
||||
<th>Attack Types</th>
|
||||
<th>User-Agent</th>
|
||||
<th class="sortable {% if sort_by == 'timestamp' %}{{ sort_order }}{% endif %}"
|
||||
hx-get="{{ dashboard_path }}/htmx/attacks?page=1&sort_by=timestamp&sort_order={% if sort_by == 'timestamp' and sort_order == 'desc' %}asc{% else %}desc{% endif %}"
|
||||
hx-get="{{ dashboard_path }}/htmx/attacks?page=1&sort_by=timestamp&sort_order={% if sort_by == 'timestamp' and sort_order == 'desc' %}asc{% else %}desc{% endif %}{% if ip_filter %}&ip_filter={{ ip_filter }}{% endif %}"
|
||||
hx-target="closest .htmx-container"
|
||||
hx-swap="innerHTML">
|
||||
Time
|
||||
|
||||
Reference in New Issue
Block a user