Merge branch 'feat/dashboard-single-ip-page' into feat/add-search-bar
This commit is contained in:
@@ -850,6 +850,72 @@ class DatabaseManager:
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
raise
|
||||
|
||||
def get_access_logs_paginated(
|
||||
self,
|
||||
page: int = 1,
|
||||
page_size: int = 25,
|
||||
ip_filter: Optional[str] = None,
|
||||
suspicious_only: bool = False,
|
||||
since_minutes: Optional[int] = None,
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Retrieve access logs with pagination and optional filtering.
|
||||
|
||||
Args:
|
||||
page: Page to retrieve
|
||||
page_size: Number of records for page
|
||||
ip_filter: Filter by IP address
|
||||
suspicious_only: Only return suspicious requests
|
||||
since_minutes: Only return logs from the last N minutes
|
||||
|
||||
Returns:
|
||||
List of access log dictionaries
|
||||
"""
|
||||
session = self.session
|
||||
try:
|
||||
offset = (page - 1) * page_size
|
||||
query = session.query(AccessLog).order_by(AccessLog.timestamp.desc())
|
||||
|
||||
if ip_filter:
|
||||
query = query.filter(AccessLog.ip == sanitize_ip(ip_filter))
|
||||
if suspicious_only:
|
||||
query = query.filter(AccessLog.is_suspicious == True)
|
||||
if since_minutes is not None:
|
||||
cutoff_time = datetime.now() - timedelta(minutes=since_minutes)
|
||||
query = query.filter(AccessLog.timestamp >= cutoff_time)
|
||||
|
||||
logs = query.offset(offset).limit(page_size).all()
|
||||
# Get total count of attackers
|
||||
total_access_logs = (
|
||||
session.query(AccessLog)
|
||||
.filter(AccessLog.ip == sanitize_ip(ip_filter))
|
||||
.count()
|
||||
)
|
||||
total_pages = (total_access_logs + page_size - 1) // page_size
|
||||
|
||||
return {
|
||||
"access_logs": [
|
||||
{
|
||||
"id": log.id,
|
||||
"ip": log.ip,
|
||||
"path": log.path,
|
||||
"user_agent": log.user_agent,
|
||||
"method": log.method,
|
||||
"is_suspicious": log.is_suspicious,
|
||||
"is_honeypot_trigger": log.is_honeypot_trigger,
|
||||
"timestamp": log.timestamp.isoformat(),
|
||||
"attack_types": [d.attack_type for d in log.attack_detections],
|
||||
}
|
||||
for log in logs
|
||||
],
|
||||
"pagination": {
|
||||
"page": page,
|
||||
"page_size": page_size,
|
||||
"total_logs": total_access_logs,
|
||||
"total_pages": total_pages,
|
||||
},
|
||||
}
|
||||
finally:
|
||||
self.close_session()
|
||||
|
||||
@@ -1018,6 +1084,8 @@ class DatabaseManager:
|
||||
"region": stat.region,
|
||||
"region_name": stat.region_name,
|
||||
"timezone": stat.timezone,
|
||||
"latitude": stat.latitude,
|
||||
"longitude": stat.longitude,
|
||||
"isp": stat.isp,
|
||||
"reverse": stat.reverse,
|
||||
"asn": stat.asn,
|
||||
@@ -1687,14 +1755,23 @@ class DatabaseManager:
|
||||
offset = (page - 1) * page_size
|
||||
|
||||
results = (
|
||||
session.query(AccessLog.ip, func.count(AccessLog.id).label("count"))
|
||||
.group_by(AccessLog.ip)
|
||||
session.query(
|
||||
AccessLog.ip,
|
||||
func.count(AccessLog.id).label("count"),
|
||||
IpStats.category,
|
||||
)
|
||||
.outerjoin(IpStats, AccessLog.ip == IpStats.ip)
|
||||
.group_by(AccessLog.ip, IpStats.category)
|
||||
.all()
|
||||
)
|
||||
|
||||
# Filter out local/private IPs and server IP, then sort
|
||||
filtered = [
|
||||
{"ip": row.ip, "count": row.count}
|
||||
{
|
||||
"ip": row.ip,
|
||||
"count": row.count,
|
||||
"category": row.category or "unknown",
|
||||
}
|
||||
for row in results
|
||||
if is_valid_public_ip(row.ip, server_ip)
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user