it
This commit is contained in:
parent
72f7056bc7
commit
3511f18f9a
117
app.py
117
app.py
@ -1,3 +1,5 @@
|
|||||||
|
# dnsrecon-reduced/app.py
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Flask application entry point for DNSRecon web interface.
|
Flask application entry point for DNSRecon web interface.
|
||||||
Provides REST API endpoints and serves the web interface with user session support.
|
Provides REST API endpoints and serves the web interface with user session support.
|
||||||
@ -321,12 +323,18 @@ def export_results():
|
|||||||
@app.route('/api/providers', methods=['GET'])
|
@app.route('/api/providers', methods=['GET'])
|
||||||
def get_providers():
|
def get_providers():
|
||||||
"""Get information about available providers for the user session."""
|
"""Get information about available providers for the user session."""
|
||||||
print("=== API: /api/providers called ===")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get user-specific scanner
|
# Get user-specific scanner
|
||||||
user_session_id, scanner = get_user_scanner()
|
user_session_id, scanner = get_user_scanner()
|
||||||
|
|
||||||
|
if scanner:
|
||||||
|
completed_tasks = scanner.indicators_completed
|
||||||
|
enqueued_tasks = len(scanner.task_queue)
|
||||||
|
print(f"DEBUG: Tasks - Completed: {completed_tasks}, Enqueued: {enqueued_tasks}")
|
||||||
|
else:
|
||||||
|
print("DEBUG: No active scanner session found.")
|
||||||
|
|
||||||
provider_info = scanner.get_provider_info()
|
provider_info = scanner.get_provider_info()
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@ -401,113 +409,6 @@ def set_api_keys():
|
|||||||
'error': f'Internal server error: {str(e)}'
|
'error': f'Internal server error: {str(e)}'
|
||||||
}), 500
|
}), 500
|
||||||
|
|
||||||
# TODO buggy, remove
|
|
||||||
@app.route('/api/session/info', methods=['GET'])
|
|
||||||
def get_session_info():
|
|
||||||
"""Get information about the current user session."""
|
|
||||||
try:
|
|
||||||
user_session_id, scanner = get_user_scanner()
|
|
||||||
session_info = session_manager.get_session_info(user_session_id)
|
|
||||||
|
|
||||||
return jsonify({
|
|
||||||
'success': True,
|
|
||||||
'session_info': session_info
|
|
||||||
})
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"ERROR: Exception in get_session_info endpoint: {e}")
|
|
||||||
traceback.print_exc()
|
|
||||||
return jsonify({
|
|
||||||
'success': False,
|
|
||||||
'error': f'Internal server error: {str(e)}'
|
|
||||||
}), 500
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/session/terminate', methods=['POST'])
|
|
||||||
def terminate_session():
|
|
||||||
"""Terminate the current user session."""
|
|
||||||
try:
|
|
||||||
user_session_id = session.get('dnsrecon_session_id')
|
|
||||||
|
|
||||||
if user_session_id:
|
|
||||||
success = session_manager.terminate_session(user_session_id)
|
|
||||||
# Clear Flask session
|
|
||||||
session.pop('dnsrecon_session_id', None)
|
|
||||||
|
|
||||||
return jsonify({
|
|
||||||
'success': success,
|
|
||||||
'message': 'Session terminated' if success else 'Session not found'
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
return jsonify({
|
|
||||||
'success': False,
|
|
||||||
'error': 'No active session to terminate'
|
|
||||||
}), 400
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"ERROR: Exception in terminate_session endpoint: {e}")
|
|
||||||
traceback.print_exc()
|
|
||||||
return jsonify({
|
|
||||||
'success': False,
|
|
||||||
'error': f'Internal server error: {str(e)}'
|
|
||||||
}), 500
|
|
||||||
|
|
||||||
# TODO remove
|
|
||||||
@app.route('/api/admin/sessions', methods=['GET'])
|
|
||||||
def list_sessions():
|
|
||||||
"""Admin endpoint to list all active sessions."""
|
|
||||||
try:
|
|
||||||
sessions = session_manager.list_active_sessions()
|
|
||||||
stats = session_manager.get_statistics()
|
|
||||||
|
|
||||||
return jsonify({
|
|
||||||
'success': True,
|
|
||||||
'sessions': sessions,
|
|
||||||
'statistics': stats
|
|
||||||
})
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"ERROR: Exception in list_sessions endpoint: {e}")
|
|
||||||
traceback.print_exc()
|
|
||||||
return jsonify({
|
|
||||||
'success': False,
|
|
||||||
'error': f'Internal server error: {str(e)}'
|
|
||||||
}), 500
|
|
||||||
|
|
||||||
# TODO remove
|
|
||||||
@app.route('/api/health', methods=['GET'])
|
|
||||||
def health_check():
|
|
||||||
"""Health check endpoint."""
|
|
||||||
try:
|
|
||||||
# Get session stats
|
|
||||||
session_stats = session_manager.get_statistics()
|
|
||||||
|
|
||||||
return jsonify({
|
|
||||||
'success': True,
|
|
||||||
'status': 'healthy',
|
|
||||||
'timestamp': datetime.now(timezone.utc).isoformat(),
|
|
||||||
'version': '1.0.0-phase2',
|
|
||||||
'phase': 2,
|
|
||||||
'features': {
|
|
||||||
'multi_provider': True,
|
|
||||||
'concurrent_processing': True,
|
|
||||||
'real_time_updates': True,
|
|
||||||
'api_key_management': True,
|
|
||||||
'visualization': True,
|
|
||||||
'retry_logic': True,
|
|
||||||
'user_sessions': True,
|
|
||||||
'session_isolation': True
|
|
||||||
},
|
|
||||||
'session_statistics': session_stats
|
|
||||||
})
|
|
||||||
except Exception as e:
|
|
||||||
print(f"ERROR: Exception in health_check endpoint: {e}")
|
|
||||||
return jsonify({
|
|
||||||
'success': False,
|
|
||||||
'error': f'Health check failed: {str(e)}'
|
|
||||||
}), 500
|
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(404)
|
@app.errorhandler(404)
|
||||||
def not_found(error):
|
def not_found(error):
|
||||||
"""Handle 404 errors."""
|
"""Handle 404 errors."""
|
||||||
|
@ -703,7 +703,6 @@ class Scanner:
|
|||||||
'current_depth': self.current_depth,
|
'current_depth': self.current_depth,
|
||||||
'max_depth': self.max_depth,
|
'max_depth': self.max_depth,
|
||||||
'current_indicator': self.current_indicator,
|
'current_indicator': self.current_indicator,
|
||||||
'total_indicators_found': self.total_indicators_found,
|
|
||||||
'indicators_processed': self.indicators_processed,
|
'indicators_processed': self.indicators_processed,
|
||||||
'indicators_completed': self.indicators_completed,
|
'indicators_completed': self.indicators_completed,
|
||||||
'tasks_re_enqueued': self.tasks_re_enqueued,
|
'tasks_re_enqueued': self.tasks_re_enqueued,
|
||||||
@ -721,7 +720,6 @@ class Scanner:
|
|||||||
'current_depth': 0,
|
'current_depth': 0,
|
||||||
'max_depth': 0,
|
'max_depth': 0,
|
||||||
'current_indicator': '',
|
'current_indicator': '',
|
||||||
'total_indicators_found': 0,
|
|
||||||
'indicators_processed': 0,
|
'indicators_processed': 0,
|
||||||
'indicators_completed': 0,
|
'indicators_completed': 0,
|
||||||
'tasks_re_enqueued': 0,
|
'tasks_re_enqueued': 0,
|
||||||
@ -732,10 +730,11 @@ class Scanner:
|
|||||||
}
|
}
|
||||||
|
|
||||||
def _calculate_progress(self) -> float:
|
def _calculate_progress(self) -> float:
|
||||||
"""Calculate scan progress percentage."""
|
"""Calculate scan progress percentage based on task completion."""
|
||||||
if self.total_indicators_found == 0:
|
total_tasks = self.indicators_completed + len(self.task_queue)
|
||||||
|
if total_tasks == 0:
|
||||||
return 0.0
|
return 0.0
|
||||||
return min(100.0, (self.indicators_processed / self.total_indicators_found) * 100)
|
return min(100.0, (self.indicators_completed / total_tasks) * 100)
|
||||||
|
|
||||||
def get_graph_data(self) -> Dict[str, Any]:
|
def get_graph_data(self) -> Dict[str, Any]:
|
||||||
"""Get current graph data for visualization."""
|
"""Get current graph data for visualization."""
|
||||||
@ -798,9 +797,6 @@ class Scanner:
|
|||||||
'statistics': live_provider.get_statistics() if live_provider else temp_provider.get_statistics(),
|
'statistics': live_provider.get_statistics() if live_provider else temp_provider.get_statistics(),
|
||||||
'enabled': self.config.is_provider_enabled(provider_name),
|
'enabled': self.config.is_provider_enabled(provider_name),
|
||||||
'rate_limit': self.config.get_rate_limit(provider_name),
|
'rate_limit': self.config.get_rate_limit(provider_name),
|
||||||
'task_queue_size': len(self.task_queue),
|
|
||||||
'tasks_completed': self.indicators_completed,
|
|
||||||
'tasks_re_enqueued': self.tasks_re_enqueued,
|
|
||||||
}
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"✗ Failed to get info for provider from {filename}: {e}")
|
print(f"✗ Failed to get info for provider from {filename}: {e}")
|
||||||
|
@ -355,31 +355,6 @@ class SessionManager:
|
|||||||
|
|
||||||
time.sleep(300) # Sleep for 5 minutes
|
time.sleep(300) # Sleep for 5 minutes
|
||||||
|
|
||||||
def list_active_sessions(self) -> List[Dict[str, Any]]:
|
|
||||||
"""List all active sessions for admin purposes."""
|
|
||||||
try:
|
|
||||||
session_keys = self.redis_client.keys("dnsrecon:session:*")
|
|
||||||
sessions = []
|
|
||||||
|
|
||||||
for session_key in session_keys:
|
|
||||||
session_id = session_key.decode('utf-8').split(':')[-1]
|
|
||||||
session_data = self._get_session_data(session_id)
|
|
||||||
|
|
||||||
if session_data:
|
|
||||||
scanner = session_data.get('scanner')
|
|
||||||
sessions.append({
|
|
||||||
'session_id': session_id,
|
|
||||||
'created_at': session_data.get('created_at'),
|
|
||||||
'last_activity': session_data.get('last_activity'),
|
|
||||||
'scanner_status': scanner.status if scanner else 'unknown',
|
|
||||||
'current_target': scanner.current_target if scanner else None
|
|
||||||
})
|
|
||||||
|
|
||||||
return sessions
|
|
||||||
except Exception as e:
|
|
||||||
print(f"ERROR: Failed to list active sessions: {e}")
|
|
||||||
return []
|
|
||||||
|
|
||||||
def get_statistics(self) -> Dict[str, Any]:
|
def get_statistics(self) -> Dict[str, Any]:
|
||||||
"""Get session manager statistics."""
|
"""Get session manager statistics."""
|
||||||
try:
|
try:
|
||||||
|
@ -272,8 +272,24 @@ input[type="text"]:focus, select:focus {
|
|||||||
text-shadow: 0 0 3px rgba(0, 255, 65, 0.3);
|
text-shadow: 0 0 3px rgba(0, 255, 65, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.progress-container {
|
||||||
|
padding: 0 1.5rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: #999;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress-compact {
|
||||||
|
color: #00ff41;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
.progress-bar {
|
.progress-bar {
|
||||||
margin: 1rem 1.5rem;
|
|
||||||
height: 8px;
|
height: 8px;
|
||||||
background-color: #1a1a1a;
|
background-color: #1a1a1a;
|
||||||
border: 1px solid #444;
|
border: 1px solid #444;
|
||||||
|
@ -216,12 +216,8 @@ class GraphManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIX: Comment out the problematic context menu handler
|
|
||||||
this.network.on('oncontext', (params) => {
|
this.network.on('oncontext', (params) => {
|
||||||
params.event.preventDefault();
|
params.event.preventDefault();
|
||||||
// if (params.nodes.length > 0) {
|
|
||||||
// this.showNodeContextMenu(params.pointer.DOM, params.nodes[0]);
|
|
||||||
// }
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Stabilization events with progress
|
// Stabilization events with progress
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Main application logic for DNSRecon web interface
|
* Main application logic for DNSRecon web interface
|
||||||
* Handles UI interactions, API communication, and data flow
|
* Handles UI interactions, API communication, and data flow
|
||||||
* DEBUG VERSION WITH EXTRA LOGGING
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DNSReconApp {
|
class DNSReconApp {
|
||||||
@ -61,12 +60,8 @@ class DNSReconApp {
|
|||||||
scanStatus: document.getElementById('scan-status'),
|
scanStatus: document.getElementById('scan-status'),
|
||||||
targetDisplay: document.getElementById('target-display'),
|
targetDisplay: document.getElementById('target-display'),
|
||||||
depthDisplay: document.getElementById('depth-display'),
|
depthDisplay: document.getElementById('depth-display'),
|
||||||
progressDisplay: document.getElementById('progress-display'),
|
|
||||||
indicatorsDisplay: document.getElementById('indicators-display'),
|
|
||||||
relationshipsDisplay: document.getElementById('relationships-display'),
|
relationshipsDisplay: document.getElementById('relationships-display'),
|
||||||
taskQueueDisplay: document.getElementById('task-queue-display'),
|
progressCompact: document.getElementById('progress-compact'),
|
||||||
tasksCompletedDisplay: document.getElementById('tasks-completed-display'),
|
|
||||||
tasksReEnqueuedDisplay: document.getElementById('tasks-re-enqueued-display'),
|
|
||||||
progressFill: document.getElementById('progress-fill'),
|
progressFill: document.getElementById('progress-fill'),
|
||||||
|
|
||||||
// Provider elements
|
// Provider elements
|
||||||
@ -545,25 +540,18 @@ class DNSReconApp {
|
|||||||
if (this.elements.depthDisplay) {
|
if (this.elements.depthDisplay) {
|
||||||
this.elements.depthDisplay.textContent = `${status.current_depth}/${status.max_depth}`;
|
this.elements.depthDisplay.textContent = `${status.current_depth}/${status.max_depth}`;
|
||||||
}
|
}
|
||||||
if (this.elements.progressDisplay) {
|
|
||||||
this.elements.progressDisplay.textContent = `${status.progress_percentage.toFixed(1)}%`;
|
|
||||||
}
|
|
||||||
if (this.elements.indicatorsDisplay) {
|
|
||||||
this.elements.indicatorsDisplay.textContent = status.indicators_processed || 0;
|
|
||||||
}
|
|
||||||
if (this.elements.taskQueueDisplay) {
|
|
||||||
this.elements.taskQueueDisplay.textContent = status.task_queue_size || 0;
|
|
||||||
}
|
|
||||||
if (this.elements.tasksCompletedDisplay) {
|
|
||||||
this.elements.tasksCompletedDisplay.textContent = status.indicators_completed || 0;
|
|
||||||
}
|
|
||||||
if (this.elements.tasksReEnqueuedDisplay) {
|
|
||||||
this.elements.tasksReEnqueuedDisplay.textContent = status.tasks_re_enqueued || 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update progress bar with smooth animation
|
// Update progress bar and compact display
|
||||||
if (this.elements.progressFill) {
|
if (this.elements.progressFill) {
|
||||||
this.elements.progressFill.style.width = `${status.progress_percentage}%`;
|
const completed = status.indicators_completed || 0;
|
||||||
|
const enqueued = status.task_queue_size || 0;
|
||||||
|
const totalTasks = completed + enqueued;
|
||||||
|
const progressPercentage = totalTasks > 0 ? (completed / totalTasks) * 100 : 0;
|
||||||
|
|
||||||
|
this.elements.progressFill.style.width = `${progressPercentage}%`;
|
||||||
|
if (this.elements.progressCompact) {
|
||||||
|
this.elements.progressCompact.textContent = `${completed}/${totalTasks} - ${Math.round(progressPercentage)}%`;
|
||||||
|
}
|
||||||
|
|
||||||
// Add pulsing animation for active scans
|
// Add pulsing animation for active scans
|
||||||
if (status.status === 'running') {
|
if (status.status === 'running') {
|
||||||
@ -802,20 +790,6 @@ class DNSReconApp {
|
|||||||
<span class="provider-stat-value">${info.rate_limit}/min</span>
|
<span class="provider-stat-value">${info.rate_limit}/min</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="provider-task-stats">
|
|
||||||
<div class="provider-stat">
|
|
||||||
<span class="provider-stat-label">Task Queue:</span>
|
|
||||||
<span class="provider-stat-value">${info.task_queue_size || 0}</span>
|
|
||||||
</div>
|
|
||||||
<div class="provider-stat">
|
|
||||||
<span class="provider-stat-label">Tasks Completed:</span>
|
|
||||||
<span class="provider-stat-value">${info.tasks_completed || 0}</span>
|
|
||||||
</div>
|
|
||||||
<div class="provider-stat">
|
|
||||||
<span class="provider-stat-label">Tasks Re-enqueued:</span>
|
|
||||||
<span class="provider-stat-value">${info.tasks_re_enqueued || 0}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
this.elements.providerList.appendChild(providerItem);
|
this.elements.providerList.appendChild(providerItem);
|
||||||
|
@ -90,35 +90,21 @@
|
|||||||
<span class="status-label">Depth:</span>
|
<span class="status-label">Depth:</span>
|
||||||
<span id="depth-display" class="status-value">0/0</span>
|
<span id="depth-display" class="status-value">0/0</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="status-row">
|
|
||||||
<span class="status-label">Progress:</span>
|
|
||||||
<span id="progress-display" class="status-value">0%</span>
|
|
||||||
</div>
|
|
||||||
<div class="status-row">
|
|
||||||
<span class="status-label">Indicators:</span>
|
|
||||||
<span id="indicators-display" class="status-value">0</span>
|
|
||||||
</div>
|
|
||||||
<div class="status-row">
|
<div class="status-row">
|
||||||
<span class="status-label">Relationships:</span>
|
<span class="status-label">Relationships:</span>
|
||||||
<span id="relationships-display" class="status-value">0</span>
|
<span id="relationships-display" class="status-value">0</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="status-row">
|
|
||||||
<span class="status-label">Task Queue:</span>
|
|
||||||
<span id="task-queue-display" class="status-value">0</span>
|
|
||||||
</div>
|
|
||||||
<div class="status-row">
|
|
||||||
<span class="status-label">Tasks Completed:</span>
|
|
||||||
<span id="tasks-completed-display" class="status-value">0</span>
|
|
||||||
</div>
|
|
||||||
<div class="status-row">
|
|
||||||
<span class="status-label">Tasks Re-enqueued:</span>
|
|
||||||
<span id="tasks-re-enqueued-display" class="status-value">0</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="progress-container">
|
||||||
|
<div class="progress-info">
|
||||||
|
<span id="progress-label">Progress:</span>
|
||||||
|
<span id="progress-compact">0/0</span>
|
||||||
|
</div>
|
||||||
<div class="progress-bar">
|
<div class="progress-bar">
|
||||||
<div id="progress-fill" class="progress-fill"></div>
|
<div id="progress-fill" class="progress-fill"></div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="visualization-panel">
|
<section class="visualization-panel">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user