This commit is contained in:
pika 2025-03-31 13:47:34 +02:00
parent 5a309a0f6d
commit 1ab129b798
5 changed files with 499 additions and 107 deletions

View file

@ -295,25 +295,36 @@ def add_app_port(app_id):
protocol = request.form.get("protocol", "TCP")
description = request.form.get("description", "")
# Validate port data
# Validate port data with server-side conflict check
valid, clean_port, error = validate_port_data(
port_number, protocol, description
port_number, protocol, description, app.server_id, app_id
)
if not valid:
flash(error, "danger")
# If port is in use by another app, provide a direct link
if "already in use by application" in error:
app_name = error.split("'")[1] # Extract app name from error message
conflict_app = App.query.filter_by(name=app_name, server_id=app.server_id).first()
if conflict_app:
edit_url = url_for('dashboard.app_edit', app_id=conflict_app.id)
edit_link = f'<a href="{edit_url}">Edit {app_name}</a>'
flash(f"Would you like to edit the conflicting application? {edit_link}", "info")
return (
redirect(url_for("dashboard.app_view", app_id=app_id))
if not is_ajax
else jsonify({"success": False, "error": error})
), 400
# Check if port already exists
# Check if port already exists for this app
existing_port = Port.query.filter_by(
app_id=app_id, port_number=clean_port
app_id=app_id, port_number=clean_port, protocol=protocol
).first()
if existing_port:
error_msg = f"Port {clean_port} already exists for this application"
error_msg = f"Port {clean_port}/{protocol} already exists for this application"
flash(error_msg, "warning")
return (
redirect(url_for("dashboard.app_view", app_id=app_id))
@ -457,3 +468,84 @@ def get_free_port(server_id):
return jsonify(
{"success": False, "error": "No free ports available in the range 8000-9000"}
)
@bp.route("/validate/app-name", methods=["GET"])
@login_required
def validate_app_name():
"""API endpoint to validate application name in real-time"""
name = request.args.get("name", "").strip()
server_id = request.args.get("server_id")
app_id = request.args.get("app_id")
if not name or not server_id:
return jsonify({"valid": False, "message": "Missing required parameters"})
# Check for existing app with same name
query = App.query.filter(App.name == name, App.server_id == server_id)
if app_id:
query = query.filter(App.id != int(app_id))
existing_app = query.first()
if existing_app:
return jsonify({
"valid": False,
"message": f"Application '{name}' already exists on this server",
"app_id": existing_app.id,
"edit_url": url_for('dashboard.app_edit', app_id=existing_app.id)
})
# Check for similar names
similar_apps = App.query.filter(
App.name.ilike(f"%{name}%"),
App.server_id == server_id
).limit(3).all()
if similar_apps and (not app_id or not any(str(app.id) == app_id for app in similar_apps)):
similar_names = [{"name": app.name, "id": app.id} for app in similar_apps]
return jsonify({
"valid": True,
"warning": "Similar application names found",
"similar_apps": similar_names
})
return jsonify({"valid": True})
@bp.route("/validate/app-port", methods=["GET"])
@login_required
def validate_app_port():
"""API endpoint to validate port in real-time"""
port_number = request.args.get("port_number", "").strip()
protocol = request.args.get("protocol", "TCP")
server_id = request.args.get("server_id")
app_id = request.args.get("app_id")
if not port_number or not server_id:
return jsonify({"valid": False, "message": "Missing required parameters"})
try:
clean_port = int(port_number)
if clean_port < 1 or clean_port > 65535:
return jsonify({"valid": False, "message": "Port must be between 1 and 65535"})
in_use, app_name = is_port_in_use(
clean_port, protocol, server_id,
exclude_app_id=app_id if app_id else None
)
if in_use:
conflict_app = App.query.filter_by(name=app_name, server_id=server_id).first()
return jsonify({
"valid": False,
"message": f"Port {clean_port}/{protocol} is already in use by application '{app_name}'",
"app_id": conflict_app.id if conflict_app else None,
"edit_url": url_for('dashboard.app_edit', app_id=conflict_app.id) if conflict_app else None
})
return jsonify({"valid": True})
except ValueError:
return jsonify({"valid": False, "message": "Invalid port number"})