Merge pull request #117 from BlessedRebuS/fix/access-history-time-order
Fix/access history time order
This commit is contained in:
@@ -2,8 +2,8 @@ apiVersion: v2
|
|||||||
name: krawl-chart
|
name: krawl-chart
|
||||||
description: A Helm chart for Krawl honeypot server
|
description: A Helm chart for Krawl honeypot server
|
||||||
type: application
|
type: application
|
||||||
version: 1.1.2
|
version: 1.1.3
|
||||||
appVersion: 1.1.2
|
appVersion: 1.1.3
|
||||||
keywords:
|
keywords:
|
||||||
- honeypot
|
- honeypot
|
||||||
- security
|
- security
|
||||||
|
|||||||
@@ -883,6 +883,7 @@ class DatabaseManager:
|
|||||||
ip_filter: Optional[str] = None,
|
ip_filter: Optional[str] = None,
|
||||||
suspicious_only: bool = False,
|
suspicious_only: bool = False,
|
||||||
since_minutes: Optional[int] = None,
|
since_minutes: Optional[int] = None,
|
||||||
|
sort_order: str = "desc",
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Retrieve access logs with pagination and optional filtering.
|
Retrieve access logs with pagination and optional filtering.
|
||||||
@@ -893,6 +894,7 @@ class DatabaseManager:
|
|||||||
ip_filter: Filter by IP address
|
ip_filter: Filter by IP address
|
||||||
suspicious_only: Only return suspicious requests
|
suspicious_only: Only return suspicious requests
|
||||||
since_minutes: Only return logs from the last N minutes
|
since_minutes: Only return logs from the last N minutes
|
||||||
|
sort_order: Sort direction for timestamp ('asc' or 'desc')
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of access log dictionaries
|
List of access log dictionaries
|
||||||
@@ -900,7 +902,12 @@ class DatabaseManager:
|
|||||||
session = self.session
|
session = self.session
|
||||||
try:
|
try:
|
||||||
offset = (page - 1) * page_size
|
offset = (page - 1) * page_size
|
||||||
query = session.query(AccessLog).order_by(AccessLog.timestamp.desc())
|
order = (
|
||||||
|
AccessLog.timestamp.asc()
|
||||||
|
if sort_order == "asc"
|
||||||
|
else AccessLog.timestamp.desc()
|
||||||
|
)
|
||||||
|
query = session.query(AccessLog).order_by(order)
|
||||||
|
|
||||||
if ip_filter:
|
if ip_filter:
|
||||||
query = query.filter(AccessLog.ip == sanitize_ip(ip_filter))
|
query = query.filter(AccessLog.ip == sanitize_ip(ip_filter))
|
||||||
|
|||||||
@@ -180,7 +180,10 @@ async def htmx_access_logs_by_ip(
|
|||||||
):
|
):
|
||||||
db = get_db()
|
db = get_db()
|
||||||
result = db.get_access_logs_paginated(
|
result = db.get_access_logs_paginated(
|
||||||
page=max(1, page), page_size=25, ip_filter=ip_filter
|
page=max(1, page),
|
||||||
|
page_size=25,
|
||||||
|
ip_filter=ip_filter,
|
||||||
|
sort_order=sort_order if sort_order in ("asc", "desc") else "desc",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Normalize pagination key (DB returns total_attackers, template expects total)
|
# Normalize pagination key (DB returns total_attackers, template expects total)
|
||||||
|
|||||||
@@ -45,7 +45,10 @@
|
|||||||
<td>{{ log.timestamp | format_ts }}</td>
|
<td>{{ log.timestamp | format_ts }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% if log.id %}
|
{% if log.id %}
|
||||||
<button class="view-btn" @click="viewRawRequest({{ log.id }})">View Request</button>
|
<button class="view-btn" @click="viewRawRequest({{ log.id }})" title="View Request">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d="M9.4 16.6 4.8 12l4.6-4.6L8 6l-6 6 6 6zm5.2 0L19.2 12l-4.6-4.6L16 6l6 6-6 6z"/></svg>
|
||||||
|
<span class="view-btn-tooltip">View Request</span>
|
||||||
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -62,7 +62,10 @@
|
|||||||
<td>{{ attack.timestamp | format_ts }}</td>
|
<td>{{ attack.timestamp | format_ts }}</td>
|
||||||
<td style="display: flex; gap: 6px; flex-wrap: wrap;">
|
<td style="display: flex; gap: 6px; flex-wrap: wrap;">
|
||||||
{% if attack.log_id %}
|
{% if attack.log_id %}
|
||||||
<button class="view-btn" @click="viewRawRequest({{ attack.log_id }})">View Request</button>
|
<button class="view-btn" @click="viewRawRequest({{ attack.log_id }})" title="View Request">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d="M9.4 16.6 4.8 12l4.6-4.6L8 6l-6 6 6 6zm5.2 0L19.2 12l-4.6-4.6L16 6l6 6-6 6z"/></svg>
|
||||||
|
<span class="view-btn-tooltip">View Request</span>
|
||||||
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button class="inspect-btn" @click="openIpInsight('{{ attack.ip | e }}')" title="Inspect IP">
|
<button class="inspect-btn" @click="openIpInsight('{{ attack.ip | e }}')" title="Inspect IP">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"/></svg>
|
||||||
|
|||||||
@@ -118,7 +118,10 @@
|
|||||||
<td>{{ attack.timestamp | format_ts }}</td>
|
<td>{{ attack.timestamp | format_ts }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% if attack.log_id %}
|
{% if attack.log_id %}
|
||||||
<button class="view-btn" @click="viewRawRequest({{ attack.log_id }})">View Request</button>
|
<button class="view-btn" @click="viewRawRequest({{ attack.log_id }})" title="View Request">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d="M9.4 16.6 4.8 12l4.6-4.6L8 6l-6 6 6 6zm5.2 0L19.2 12l-4.6-4.6L16 6l6 6-6 6z"/></svg>
|
||||||
|
<span class="view-btn-tooltip">View Request</span>
|
||||||
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -26,7 +26,10 @@
|
|||||||
<td>{{ activity.timestamp | format_ts(time_only=True) }}</td>
|
<td>{{ activity.timestamp | format_ts(time_only=True) }}</td>
|
||||||
<td style="display: flex; gap: 6px; flex-wrap: wrap;">
|
<td style="display: flex; gap: 6px; flex-wrap: wrap;">
|
||||||
{% if activity.log_id %}
|
{% if activity.log_id %}
|
||||||
<button class="view-btn" @click="viewRawRequest({{ activity.log_id }})">View Request</button>
|
<button class="view-btn" @click="viewRawRequest({{ activity.log_id }})" title="View Request">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d="M9.4 16.6 4.8 12l4.6-4.6L8 6l-6 6 6 6zm5.2 0L19.2 12l-4.6-4.6L16 6l6 6-6 6z"/></svg>
|
||||||
|
<span class="view-btn-tooltip">View Request</span>
|
||||||
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button class="inspect-btn" @click="openIpInsight('{{ activity.ip | e }}')" title="Inspect IP">
|
<button class="inspect-btn" @click="openIpInsight('{{ activity.ip | e }}')" title="Inspect IP">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"/></svg>
|
||||||
|
|||||||
@@ -1603,19 +1603,45 @@ tbody {
|
|||||||
|
|
||||||
/* Dynamically injected button styles (previously in JS) */
|
/* Dynamically injected button styles (previously in JS) */
|
||||||
.view-btn {
|
.view-btn {
|
||||||
padding: 4px 10px;
|
position: relative;
|
||||||
background: #21262d;
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 4px;
|
||||||
|
background: none;
|
||||||
|
color: #8b949e;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.2s, background 0.2s;
|
||||||
|
}
|
||||||
|
.view-btn:hover {
|
||||||
color: #58a6ff;
|
color: #58a6ff;
|
||||||
|
background: rgba(88, 166, 255, 0.1);
|
||||||
|
}
|
||||||
|
.view-btn svg {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
fill: currentColor;
|
||||||
|
}
|
||||||
|
.view-btn-tooltip {
|
||||||
|
position: absolute;
|
||||||
|
bottom: calc(100% + 6px);
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
padding: 4px 8px;
|
||||||
|
background: #1c2128;
|
||||||
|
color: #e6edf3;
|
||||||
border: 1px solid #30363d;
|
border: 1px solid #30363d;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: opacity 0.15s;
|
||||||
}
|
}
|
||||||
.view-btn:hover {
|
.view-btn:hover .view-btn-tooltip {
|
||||||
background: #30363d;
|
opacity: 1;
|
||||||
border-color: #58a6ff;
|
|
||||||
}
|
}
|
||||||
.inspect-btn {
|
.inspect-btn {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@@ -1630,8 +1656,8 @@ tbody {
|
|||||||
transition: color 0.2s, background 0.2s;
|
transition: color 0.2s, background 0.2s;
|
||||||
}
|
}
|
||||||
.inspect-btn svg {
|
.inspect-btn svg {
|
||||||
width: 16px;
|
width: 18px;
|
||||||
height: 16px;
|
height: 18px;
|
||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
}
|
}
|
||||||
.inspect-btn:hover {
|
.inspect-btn:hover {
|
||||||
|
|||||||
Reference in New Issue
Block a user