homedocs/app/routes/dashboard.py
2025-03-30 20:10:26 +02:00

348 lines
No EOL
12 KiB
Python

from flask import Blueprint, render_template, redirect, url_for, request, flash, jsonify
from flask_login import login_required, current_user
import markdown
from app.core.models import Server, App, Subnet, Port
from app.core.extensions import db, limiter
from datetime import datetime
bp = Blueprint('dashboard', __name__, url_prefix='/dashboard')
@bp.route('/')
@login_required
def dashboard_home():
"""Main dashboard view showing server statistics"""
server_count = Server.query.count()
app_count = App.query.count()
subnet_count = Subnet.query.count()
# Get latest added servers
latest_servers = Server.query.order_by(Server.created_at.desc()).limit(5).all()
# Get subnets with usage stats
subnets = Subnet.query.all()
for subnet in subnets:
subnet.usage_percent = subnet.used_ips / 254 * 100 if subnet.cidr.endswith('/24') else 0
return render_template(
'dashboard/index.html',
title='Dashboard',
server_count=server_count,
app_count=app_count,
subnet_count=subnet_count,
latest_servers=latest_servers,
subnets=subnets,
now=datetime.now()
)
@bp.route('/servers')
@login_required
def server_list():
"""List all servers"""
servers = Server.query.order_by(Server.hostname).all()
return render_template(
'dashboard/server_list.html',
title='Servers',
servers=servers,
now=datetime.now()
)
@bp.route('/server/<int:server_id>')
@login_required
def server_view(server_id):
"""View server details"""
server = Server.query.get_or_404(server_id)
apps = App.query.filter_by(server_id=server_id).all()
return render_template(
'dashboard/server_view.html',
title=f'Server - {server.hostname}',
server=server,
apps=apps,
now=datetime.now()
)
@bp.route('/server/new', methods=['GET', 'POST'])
@login_required
def server_new():
"""Create a new server"""
subnets = Subnet.query.all()
if request.method == 'POST':
hostname = request.form.get('hostname')
ip_address = request.form.get('ip_address')
subnet_id = request.form.get('subnet_id')
documentation = request.form.get('documentation', '')
# Basic validation
if not hostname or not ip_address or not subnet_id:
flash('Please fill in all required fields', 'danger')
return render_template(
'dashboard/server_form.html',
title='New Server',
subnets=subnets,
now=datetime.now()
)
# Check if hostname or IP already exists
if Server.query.filter_by(hostname=hostname).first():
flash('Hostname already exists', 'danger')
return render_template(
'dashboard/server_form.html',
title='New Server',
subnets=subnets,
now=datetime.now()
)
if Server.query.filter_by(ip_address=ip_address).first():
flash('IP address already exists', 'danger')
return render_template(
'dashboard/server_form.html',
title='New Server',
subnets=subnets,
now=datetime.now()
)
# Create new server
server = Server(
hostname=hostname,
ip_address=ip_address,
subnet_id=subnet_id,
documentation=documentation
)
db.session.add(server)
db.session.commit()
flash('Server created successfully', 'success')
return redirect(url_for('dashboard.server_view', server_id=server.id))
return render_template(
'dashboard/server_form.html',
title='New Server',
subnets=subnets,
now=datetime.now()
)
@bp.route('/server/<int:server_id>/edit', methods=['GET', 'POST'])
@login_required
def server_edit(server_id):
"""Edit an existing server"""
server = Server.query.get_or_404(server_id)
if request.method == 'POST':
hostname = request.form.get('hostname')
ip_address = request.form.get('ip_address')
subnet_id = request.form.get('subnet_id')
if not hostname or not ip_address or not subnet_id:
flash('All fields are required', 'danger')
return redirect(url_for('dashboard.server_edit', server_id=server_id))
# Check if hostname changed and already exists
if hostname != server.hostname and Server.query.filter_by(hostname=hostname).first():
flash('Hostname already exists', 'danger')
return redirect(url_for('dashboard.server_edit', server_id=server_id))
# Check if IP changed and already exists
if ip_address != server.ip_address and Server.query.filter_by(ip_address=ip_address).first():
flash('IP address already exists', 'danger')
return redirect(url_for('dashboard.server_edit', server_id=server_id))
# Update server
server.hostname = hostname
server.ip_address = ip_address
server.subnet_id = subnet_id
db.session.commit()
flash('Server updated successfully', 'success')
return redirect(url_for('dashboard.server_view', server_id=server.id))
# GET request - show form with current values
subnets = Subnet.query.all()
return render_template(
'dashboard/server_edit.html',
title=f'Edit Server - {server.hostname}',
server=server,
subnets=subnets
)
@bp.route('/server/<int:server_id>/delete', methods=['POST'])
@login_required
def server_delete(server_id):
"""Delete a server"""
server = Server.query.get_or_404(server_id)
# Delete all apps associated with this server
App.query.filter_by(server_id=server_id).delete()
# Delete the server
db.session.delete(server)
db.session.commit()
flash('Server deleted successfully', 'success')
return redirect(url_for('dashboard.dashboard_home'))
@bp.route('/app/new', methods=['GET', 'POST'])
@login_required
def app_new():
"""Create a new application"""
servers = Server.query.all()
if request.method == 'POST':
name = request.form.get('name')
server_id = request.form.get('server_id')
documentation = request.form.get('documentation', '')
# Get port data from form
port_numbers = request.form.getlist('port_numbers[]')
protocols = request.form.getlist('protocols[]')
port_descriptions = request.form.getlist('port_descriptions[]')
# Basic validation
if not name or not server_id:
flash('Please fill in all required fields', 'danger')
return render_template(
'dashboard/app_form.html',
title='New Application',
servers=servers
)
# Create new app
app = App(
name=name,
server_id=server_id,
documentation=documentation
)
db.session.add(app)
db.session.flush() # Get the app ID without committing
# Add ports if provided
for i in range(len(port_numbers)):
if port_numbers[i] and port_numbers[i].strip():
try:
port_num = int(port_numbers[i])
# Get protocol and description, handling index errors
protocol = protocols[i] if i < len(protocols) else 'TCP'
description = port_descriptions[i] if i < len(port_descriptions) else ''
new_port = Port(
app_id=app.id,
port_number=port_num,
protocol=protocol,
description=description
)
db.session.add(new_port)
except (ValueError, IndexError):
continue
db.session.commit()
flash('Application created successfully', 'success')
return redirect(url_for('dashboard.server_view', server_id=server_id))
return render_template(
'dashboard/app_form.html',
title='New Application',
servers=servers
)
@bp.route('/app/<int:app_id>', methods=['GET'])
@login_required
def app_view(app_id):
"""View a specific application"""
app = App.query.get_or_404(app_id)
server = Server.query.get(app.server_id)
return render_template(
'dashboard/app_view.html',
title=f'Application - {app.name}',
app=app,
server=server,
now=datetime.now()
)
@bp.route('/app/<int:app_id>/edit', methods=['GET', 'POST'])
@login_required
def app_edit(app_id):
"""Edit an existing application"""
app = App.query.get_or_404(app_id)
servers = Server.query.all()
if request.method == 'POST':
name = request.form.get('name')
server_id = request.form.get('server_id')
documentation = request.form.get('documentation', '')
# Get port data from form
port_numbers = request.form.getlist('port_numbers[]')
protocols = request.form.getlist('protocols[]')
port_descriptions = request.form.getlist('port_descriptions[]')
# Validate inputs
if not all([name, server_id]):
flash('All fields are required', 'danger')
return render_template('dashboard/app_form.html',
title='Edit Application',
app=app,
servers=servers,
edit_mode=True)
# Update app
app.name = name
app.server_id = server_id
app.documentation = documentation
# Delete existing ports and recreate them
# This simplifies handling additions, deletions, and updates
Port.query.filter_by(app_id=app.id).delete()
# Add new ports
for i in range(len(port_numbers)):
if port_numbers[i] and port_numbers[i].strip():
try:
port_num = int(port_numbers[i])
# Get protocol and description, handling index errors
protocol = protocols[i] if i < len(protocols) else 'TCP'
description = port_descriptions[i] if i < len(port_descriptions) else ''
new_port = Port(
app_id=app.id,
port_number=port_num,
protocol=protocol,
description=description
)
db.session.add(new_port)
except (ValueError, IndexError):
continue
try:
db.session.commit()
flash(f'Application {name} has been updated', 'success')
return redirect(url_for('dashboard.server_view', server_id=app.server_id))
except Exception as e:
db.session.rollback()
flash(f'Error updating application: {str(e)}', 'danger')
return render_template('dashboard/app_form.html',
title='Edit Application',
app=app,
servers=servers,
edit_mode=True)
@bp.route('/app/<int:app_id>/delete', methods=['POST'])
@login_required
def app_delete(app_id):
"""Delete an application"""
app = App.query.get_or_404(app_id)
server_id = app.server_id
db.session.delete(app)
db.session.commit()
flash('Application deleted successfully', 'success')
return redirect(url_for('dashboard.server_view', server_id=server_id))