This commit is contained in:
pika 2025-04-03 14:08:11 +02:00
parent 0a31714a93
commit 66fe31eabe
3 changed files with 419 additions and 206 deletions

View file

@ -234,6 +234,27 @@ def app_new(server_id=None):
documentation = request.form.get("documentation", "")
url = request.form.get("url", "")
# Validate application name
if not name:
flash("Application name is required", "danger")
return render_template(
"dashboard/app_form.html",
edit_mode=False,
servers=servers,
selected_server_id=server_id
)
# Check for duplicate application names on the same server
existing_app = App.query.filter_by(name=name, server_id=server_id).first()
if existing_app:
flash(f"An application with the name '{name}' already exists on this server", "danger")
return render_template(
"dashboard/app_form.html",
edit_mode=False,
servers=servers,
selected_server_id=server_id
)
# Process port data from form
port_data = []
port_numbers = request.form.getlist("port_numbers[]")
@ -245,36 +266,75 @@ def app_new(server_id=None):
protocol = protocols[i] if i < len(protocols) else "TCP"
description = descriptions[i] if i < len(descriptions) else ""
port_data.append((port_numbers[i], protocol, description))
# Check for port conflicts proactively
conflicts = []
seen_ports = set() # To track ports already seen in this submission
for i, (port_number, protocol, _) in enumerate(port_data):
try:
clean_port = int(port_number)
# Check if this port has already been seen in this submission
port_key = f"{clean_port}/{protocol}"
if port_key in seen_ports:
conflicts.append((clean_port, protocol, "Duplicate port in submission"))
continue
seen_ports.add(port_key)
# Server-side validation
from app.utils.app_utils import save_app
# Check if the port is in use by another application
in_use, conflicting_app_name = is_port_in_use(
clean_port, protocol, server_id
)
if in_use:
conflicts.append((clean_port, protocol, f"Port {clean_port}/{protocol} is already in use by application '{conflicting_app_name}'"))
except (ValueError, TypeError):
continue
success, app, error = save_app(name, server_id, documentation, port_data, url=url)
if conflicts:
for conflict in conflicts:
flash(f"Conflict: {conflict[0]}/{conflict[1]} - {conflict[2]}", "danger")
return render_template(
"dashboard/app_form.html",
edit_mode=False,
servers=servers,
selected_server_id=server_id
)
if success:
flash(f"Application '{name}' created successfully", "success")
return redirect(url_for("dashboard.app_view", app_id=app.id))
else:
flash(error, "danger")
# Create the application
try:
new_app = App(
name=name,
server_id=server_id,
documentation=documentation,
url=url
)
db.session.add(new_app)
db.session.flush() # Get the app ID without committing
# Check if it's a port conflict and provide direct link
if "already in use by application" in error:
try:
app_name = error.split("'")[1] # Extract app name from error
conflict_app = App.query.filter_by(name=app_name, server_id=server_id).first()
if conflict_app:
edit_url = url_for('dashboard.app_edit', app_id=conflict_app.id)
flash(f'<a href="{edit_url}" class="alert-link">Edit conflicting application</a>', "info")
except:
pass
# Add ports
for port_number, protocol, description in port_data:
new_port = Port(
app_id=new_app.id,
port_number=int(port_number),
protocol=protocol,
description=description
)
db.session.add(new_port)
db.session.commit()
flash(f"Application '{name}' created successfully", "success")
return redirect(url_for("dashboard.app_view", app_id=new_app.id))
except Exception as e:
db.session.rollback()
flash(f"Error creating application: {str(e)}", "danger")
# GET request or validation failed - render the form
return render_template(
"dashboard/app_form.html",
title="New Application",
edit_mode=False,
servers=servers,
selected_server_id=server_id,
selected_server_id=server_id
)
@ -308,6 +368,32 @@ def app_edit(app_id):
documentation = request.form.get("documentation", "")
url = request.form.get("url", "") # Get the URL
# Validate application name
if not name:
flash("Application name is required", "danger")
return render_template(
"dashboard/app_form.html",
edit_mode=True,
app=app,
servers=servers
)
# Check for duplicate application names on the same server (excluding this app)
existing_app = App.query.filter(
App.name == name,
App.server_id == server_id,
App.id != app_id
).first()
if existing_app:
flash(f"An application with the name '{name}' already exists on this server", "danger")
return render_template(
"dashboard/app_form.html",
edit_mode=True,
app=app,
servers=servers
)
# Process port data from form
port_data = []
port_numbers = request.form.getlist("port_numbers[]")
@ -347,7 +433,12 @@ def app_edit(app_id):
if conflicts:
for conflict in conflicts:
flash(f"Conflict: {conflict[0]}/{conflict[1]} - {conflict[2]}", "danger")
return render_template("dashboard/app_edit.html", app=app, servers=servers)
return render_template(
"dashboard/app_form.html",
edit_mode=True,
app=app,
servers=servers
)
# Update application details
app.name = name
@ -372,7 +463,12 @@ def app_edit(app_id):
flash("Application updated successfully", "success")
return redirect(url_for("dashboard.app_view", app_id=app_id))
return render_template("dashboard/app_edit.html", app=app, servers=servers)
return render_template(
"dashboard/app_form.html",
edit_mode=True,
app=app,
servers=servers
)
@bp.route("/app/<int:app_id>/delete", methods=["POST"])