wip
This commit is contained in:
parent
f939933a7c
commit
be6f7cfcbb
35 changed files with 1897 additions and 733 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -9,23 +9,14 @@ import ipaddress
|
|||
bp = Blueprint('api', __name__, url_prefix='/api')
|
||||
|
||||
@bp.route('/subnets', methods=['GET'])
|
||||
@login_required
|
||||
def get_subnets():
|
||||
"""Get all subnets"""
|
||||
subnets = Subnet.query.all()
|
||||
result = []
|
||||
|
||||
for subnet in subnets:
|
||||
result.append({
|
||||
'id': subnet.id,
|
||||
'cidr': subnet.cidr,
|
||||
'location': subnet.location,
|
||||
'used_ips': subnet.used_ips,
|
||||
'auto_scan': subnet.auto_scan,
|
||||
'created_at': subnet.created_at.strftime('%Y-%m-%d %H:%M:%S')
|
||||
})
|
||||
|
||||
return jsonify({'subnets': result})
|
||||
return jsonify([{
|
||||
'id': subnet.id,
|
||||
'cidr': subnet.cidr,
|
||||
'location': subnet.location
|
||||
} for subnet in subnets])
|
||||
|
||||
@bp.route('/subnets/<int:subnet_id>', methods=['GET'])
|
||||
@login_required
|
||||
|
@ -306,4 +297,14 @@ def delete_port(port_id):
|
|||
db.session.delete(port)
|
||||
db.session.commit()
|
||||
|
||||
return jsonify({'success': True})
|
||||
return jsonify({'success': True})
|
||||
|
||||
@bp.route('/subnets/<int:subnet_id>/servers', methods=['GET'])
|
||||
def get_subnet_servers(subnet_id):
|
||||
"""Get all servers for a specific subnet"""
|
||||
servers = Server.query.filter_by(subnet_id=subnet_id).all()
|
||||
return jsonify([{
|
||||
'id': server.id,
|
||||
'hostname': server.hostname,
|
||||
'ip_address': server.ip_address
|
||||
} for server in servers])
|
|
@ -41,24 +41,19 @@ def register():
|
|||
|
||||
if request.method == 'POST':
|
||||
email = request.form.get('email')
|
||||
username = request.form.get('username')
|
||||
password = request.form.get('password')
|
||||
|
||||
# Validation
|
||||
if not email or not username or not password:
|
||||
flash('All fields are required', 'danger')
|
||||
if not email or not password:
|
||||
flash('Email and password are required', 'danger')
|
||||
return render_template('auth/register.html', title='Register')
|
||||
|
||||
if User.query.filter_by(email=email).first():
|
||||
flash('Email already registered', 'danger')
|
||||
return render_template('auth/register.html', title='Register')
|
||||
|
||||
if User.query.filter_by(username=username).first():
|
||||
flash('Username already taken', 'danger')
|
||||
return render_template('auth/register.html', title='Register')
|
||||
|
||||
# Create new user
|
||||
user = User(email=email, username=username)
|
||||
user = User(email=email)
|
||||
user.set_password(password)
|
||||
|
||||
db.session.add(user)
|
||||
|
|
|
@ -129,30 +129,48 @@ def server_new():
|
|||
def server_edit(server_id):
|
||||
"""Edit an existing server"""
|
||||
server = Server.query.get_or_404(server_id)
|
||||
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', '')
|
||||
|
||||
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))
|
||||
return render_template(
|
||||
'dashboard/server_form.html',
|
||||
title='Edit Server',
|
||||
server=server,
|
||||
subnets=subnets
|
||||
)
|
||||
|
||||
# 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))
|
||||
return render_template(
|
||||
'dashboard/server_form.html',
|
||||
title='Edit Server',
|
||||
server=server,
|
||||
subnets=subnets
|
||||
)
|
||||
|
||||
# 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))
|
||||
return render_template(
|
||||
'dashboard/server_form.html',
|
||||
title='Edit Server',
|
||||
server=server,
|
||||
subnets=subnets
|
||||
)
|
||||
|
||||
# Update server
|
||||
server.hostname = hostname
|
||||
server.ip_address = ip_address
|
||||
server.subnet_id = subnet_id
|
||||
server.documentation = documentation
|
||||
|
||||
db.session.commit()
|
||||
|
||||
|
@ -160,9 +178,8 @@ def server_edit(server_id):
|
|||
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',
|
||||
'dashboard/server_form.html',
|
||||
title=f'Edit Server - {server.hostname}',
|
||||
server=server,
|
||||
subnets=subnets
|
||||
|
@ -277,62 +294,44 @@ def app_edit(app_id):
|
|||
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[]')
|
||||
if not name or not server_id:
|
||||
flash('All required fields must be filled', 'danger')
|
||||
return render_template(
|
||||
'dashboard/app_form.html',
|
||||
title='Edit Application',
|
||||
app=app,
|
||||
servers=servers
|
||||
)
|
||||
|
||||
# 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)
|
||||
# Check if name changed and already exists on the same server
|
||||
existing_app = App.query.filter(App.name == name,
|
||||
App.server_id == server_id,
|
||||
App.id != app.id).first()
|
||||
if existing_app:
|
||||
flash('Application with this name already exists on the selected server', 'danger')
|
||||
return render_template(
|
||||
'dashboard/app_form.html',
|
||||
title='Edit Application',
|
||||
app=app,
|
||||
servers=servers
|
||||
)
|
||||
|
||||
# Update app
|
||||
# Update application
|
||||
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()
|
||||
db.session.commit()
|
||||
|
||||
# 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')
|
||||
flash('Application updated successfully', 'success')
|
||||
return redirect(url_for('dashboard.app_view', app_id=app.id))
|
||||
|
||||
return render_template('dashboard/app_form.html',
|
||||
title='Edit Application',
|
||||
app=app,
|
||||
servers=servers,
|
||||
edit_mode=True)
|
||||
return render_template(
|
||||
'dashboard/app_form.html',
|
||||
title=f'Edit Application - {app.name}',
|
||||
app=app,
|
||||
servers=servers
|
||||
)
|
||||
|
||||
@bp.route('/app/<int:app_id>/delete', methods=['POST'])
|
||||
@login_required
|
||||
|
@ -345,4 +344,40 @@ def app_delete(app_id):
|
|||
db.session.commit()
|
||||
|
||||
flash('Application deleted successfully', 'success')
|
||||
return redirect(url_for('dashboard.server_view', server_id=server_id))
|
||||
return redirect(url_for('dashboard.server_view', server_id=server_id))
|
||||
|
||||
@bp.route('/settings', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def settings():
|
||||
"""User settings page"""
|
||||
if request.method == 'POST':
|
||||
# Handle user settings update
|
||||
current_password = request.form.get('current_password')
|
||||
new_password = request.form.get('new_password')
|
||||
confirm_password = request.form.get('confirm_password')
|
||||
|
||||
# Validate inputs
|
||||
if not current_password:
|
||||
flash('Current password is required', 'danger')
|
||||
return redirect(url_for('dashboard.settings'))
|
||||
|
||||
if new_password != confirm_password:
|
||||
flash('New passwords do not match', 'danger')
|
||||
return redirect(url_for('dashboard.settings'))
|
||||
|
||||
# Verify current password
|
||||
if not current_user.check_password(current_password):
|
||||
flash('Current password is incorrect', 'danger')
|
||||
return redirect(url_for('dashboard.settings'))
|
||||
|
||||
# Update password
|
||||
current_user.set_password(new_password)
|
||||
db.session.commit()
|
||||
|
||||
flash('Password updated successfully', 'success')
|
||||
return redirect(url_for('dashboard.settings'))
|
||||
|
||||
return render_template(
|
||||
'dashboard/settings.html',
|
||||
title='User Settings'
|
||||
)
|
|
@ -192,4 +192,69 @@ def subnet_scan(subnet_id):
|
|||
db.session.rollback()
|
||||
flash(f'Error scanning subnet: {str(e)}', 'danger')
|
||||
|
||||
return redirect(url_for('ipam.subnet_view', subnet_id=subnet_id))
|
||||
return redirect(url_for('ipam.subnet_view', subnet_id=subnet_id))
|
||||
|
||||
@bp.route('/subnet/<int:subnet_id>/force-delete', methods=['POST'])
|
||||
@login_required
|
||||
def subnet_force_delete(subnet_id):
|
||||
"""Force delete a subnet and all its related servers and applications"""
|
||||
subnet = Subnet.query.get_or_404(subnet_id)
|
||||
|
||||
try:
|
||||
# Get all servers to be deleted for reporting
|
||||
servers = Server.query.filter_by(subnet_id=subnet_id).all()
|
||||
server_count = len(servers)
|
||||
|
||||
# This will cascade delete all related servers and their applications
|
||||
db.session.delete(subnet)
|
||||
db.session.commit()
|
||||
|
||||
flash(f'Subnet {subnet.cidr} and {server_count} related servers were deleted successfully', 'success')
|
||||
return redirect(url_for('dashboard.ipam_home'))
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
flash(f'Error deleting subnet: {str(e)}', 'danger')
|
||||
return redirect(url_for('dashboard.subnet_view', subnet_id=subnet_id))
|
||||
|
||||
@bp.route('/subnet/create-ajax', methods=['POST'])
|
||||
@login_required
|
||||
def subnet_create_ajax():
|
||||
"""Create a subnet via AJAX"""
|
||||
data = request.json
|
||||
if not data:
|
||||
return jsonify({'success': False, 'error': 'No data provided'})
|
||||
|
||||
cidr = data.get('cidr')
|
||||
location = data.get('location')
|
||||
auto_scan = data.get('auto_scan', False)
|
||||
|
||||
if not cidr or not location:
|
||||
return jsonify({'success': False, 'error': 'CIDR and location are required'})
|
||||
|
||||
# Validate CIDR
|
||||
try:
|
||||
network = ipaddress.ip_network(cidr, strict=False)
|
||||
except ValueError as e:
|
||||
return jsonify({'success': False, 'error': f'Invalid CIDR: {str(e)}'})
|
||||
|
||||
# Create subnet
|
||||
subnet = Subnet(
|
||||
cidr=cidr,
|
||||
location=location,
|
||||
auto_scan=auto_scan,
|
||||
active_hosts=json.dumps([])
|
||||
)
|
||||
|
||||
try:
|
||||
db.session.add(subnet)
|
||||
db.session.commit()
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'subnet_id': subnet.id,
|
||||
'cidr': subnet.cidr,
|
||||
'location': subnet.location
|
||||
})
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
return jsonify({'success': False, 'error': str(e)})
|
Loading…
Add table
Add a link
Reference in a new issue