134 lines
No EOL
4.1 KiB
Python
134 lines
No EOL
4.1 KiB
Python
"""
|
|
API routes for the NetViz application.
|
|
"""
|
|
from flask import jsonify, request, abort
|
|
from flask_login import login_required, current_user
|
|
|
|
from app.api import api_bp
|
|
from app.models.network import Network, Subnet, Device, FirewallRule
|
|
from app.extensions import db, limiter
|
|
|
|
|
|
@api_bp.route("/health")
|
|
def health_check():
|
|
"""Health check endpoint."""
|
|
return jsonify({"status": "ok"})
|
|
|
|
|
|
@api_bp.route("/networks")
|
|
@login_required
|
|
@limiter.limit("60/minute")
|
|
def get_networks():
|
|
"""Get all networks for the current user."""
|
|
networks = Network.query.filter_by(user_id=current_user.id).all()
|
|
return jsonify([{
|
|
"id": network.id,
|
|
"name": network.name,
|
|
"description": network.description,
|
|
"created_at": network.created_at.isoformat(),
|
|
"updated_at": network.updated_at.isoformat(),
|
|
"subnet_count": len(network.subnets),
|
|
"device_count": len(network.devices)
|
|
} for network in networks])
|
|
|
|
|
|
@api_bp.route("/networks/<int:network_id>")
|
|
@login_required
|
|
@limiter.limit("60/minute")
|
|
def get_network(network_id):
|
|
"""Get a specific network."""
|
|
network = Network.query.get_or_404(network_id)
|
|
|
|
# Security check
|
|
if network.user_id != current_user.id:
|
|
abort(403)
|
|
|
|
return jsonify(network.to_dict())
|
|
|
|
|
|
@api_bp.route("/networks/<int:network_id>/export")
|
|
@login_required
|
|
@limiter.limit("10/minute")
|
|
def export_network(network_id):
|
|
"""Export a network as JSON."""
|
|
network = Network.query.get_or_404(network_id)
|
|
|
|
# Security check
|
|
if network.user_id != current_user.id:
|
|
abort(403)
|
|
|
|
return jsonify(network.to_dict())
|
|
|
|
|
|
@api_bp.route("/networks/import", methods=["POST"])
|
|
@login_required
|
|
@limiter.limit("5/minute")
|
|
def import_network():
|
|
"""Import a network from JSON."""
|
|
if not request.is_json:
|
|
return jsonify({"error": "Request must be JSON"}), 400
|
|
|
|
data = request.get_json()
|
|
|
|
try:
|
|
# Create network
|
|
network = Network.from_dict(data, current_user.id)
|
|
db.session.add(network)
|
|
db.session.flush() # Get ID without committing
|
|
|
|
# Create subnets
|
|
for subnet_data in data.get("subnets", []):
|
|
subnet = Subnet(
|
|
name=subnet_data["name"],
|
|
cidr=subnet_data["cidr"],
|
|
vlan=subnet_data.get("vlan"),
|
|
description=subnet_data.get("description", ""),
|
|
network_id=network.id
|
|
)
|
|
db.session.add(subnet)
|
|
|
|
db.session.flush()
|
|
|
|
# Create devices
|
|
for device_data in data.get("devices", []):
|
|
device = Device(
|
|
name=device_data["name"],
|
|
ip_address=device_data.get("ip_address"),
|
|
mac_address=device_data.get("mac_address"),
|
|
device_type=device_data.get("device_type"),
|
|
os=device_data.get("os"),
|
|
description=device_data.get("description", ""),
|
|
network_id=network.id,
|
|
subnet_id=device_data.get("subnet_id")
|
|
)
|
|
if "properties" in device_data:
|
|
device.set_properties(device_data["properties"])
|
|
db.session.add(device)
|
|
|
|
# Create firewall rules
|
|
for rule_data in data.get("firewall_rules", []):
|
|
rule = FirewallRule(
|
|
name=rule_data["name"],
|
|
source=rule_data["source"],
|
|
destination=rule_data["destination"],
|
|
protocol=rule_data.get("protocol"),
|
|
port_range=rule_data.get("port_range"),
|
|
action=rule_data["action"],
|
|
description=rule_data.get("description", ""),
|
|
network_id=network.id
|
|
)
|
|
db.session.add(rule)
|
|
|
|
db.session.commit()
|
|
|
|
return jsonify({
|
|
"message": "Network imported successfully",
|
|
"network_id": network.id
|
|
}), 201
|
|
|
|
except KeyError as e:
|
|
db.session.rollback()
|
|
return jsonify({"error": f"Missing required field: {str(e)}"}), 400
|
|
except Exception as e:
|
|
db.session.rollback()
|
|
return jsonify({"error": str(e)}), 400 |