router manager navigation and form validation improvements

This commit is contained in:
Eduardo Silva 2024-03-16 18:03:01 -03:00
parent 2a95f0c77f
commit a8952676d7
13 changed files with 491 additions and 30 deletions

View file

@ -1,10 +1,14 @@
from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Submit, Row, Column, HTML
from .models import Router
from .models import Router, RouterGroup, SSHKey
import ipaddress
import socket
class RouterForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput, required=False)
class Meta:
model = Router
fields = ['name', 'address', 'username', 'password', 'ssh_key', 'monitoring', 'router_type', 'enabled']
@ -15,6 +19,8 @@ class RouterForm(forms.ModelForm):
self.helper.form_method = 'post'
if self.instance.pk:
delete_html = "<a href='javascript:void(0)' class='btn btn-outline-danger' data-command='delete' onclick='openCommandDialog(this)'>Delete</a>"
if self.instance.password:
self.fields['password'].widget.attrs['placeholder'] = '************'
else:
delete_html = ''
self.helper.layout = Layout(
@ -29,7 +35,6 @@ class RouterForm(forms.ModelForm):
css_class='form-row'
),
'ssh_key',
'router_type',
'monitoring',
'enabled',
@ -42,3 +47,121 @@ class RouterForm(forms.ModelForm):
css_class='form-row'
)
)
def clean(self):
cleaned_data = super().clean()
name = cleaned_data.get('name')
ssh_key = cleaned_data.get('ssh_key')
password = cleaned_data.get('password')
address = cleaned_data.get('address')
if name:
name = name.strip()
cleaned_data['name'] = name
if ssh_key and password:
raise forms.ValidationError('You must provide a password or an SSH Key, not both')
if not ssh_key and not password and not self.instance.password:
raise forms.ValidationError('You must provide a password or an SSH Key')
if not password and self.instance.password:
cleaned_data['password'] = self.instance.password
if ssh_key and not password:
cleaned_data['password'] = ''
if address:
address = address.lower()
cleaned_data['address'] = address
try:
socket.gethostbyname(address)
except socket.gaierror:
try:
ipaddress.ip_address(address)
except ValueError:
raise forms.ValidationError('The address field must be a valid hostname or IP address.')
return cleaned_data
class RouterGroupForm(forms.ModelForm):
class Meta:
model = RouterGroup
fields = ['name', 'default_group', 'internal_notes', 'routers']
widgets = {
'internal_notes': forms.Textarea(attrs={'rows': 4, 'cols': 40}), # Define como um Textarea simples
}
def __init__(self, *args, **kwargs):
super(RouterGroupForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = 'post'
if self.instance.pk:
delete_html = "<a href='javascript:void(0)' class='btn btn-outline-danger' data-command='delete' onclick='openCommandDialog(this)'>Delete</a>"
else:
delete_html = ''
self.helper.layout = Layout(
'name',
'internal_notes',
'routers',
'default_group',
Row(
Column(
Submit('submit', 'Salvar', css_class='btn btn-success'),
HTML(' <a class="btn btn-secondary" href="/router/group_list/">Back</a> '),
HTML(delete_html),
css_class='col-md-12'),
css_class='form-row'
)
)
def clean(self):
cleaned_data = super().clean()
name = cleaned_data.get('name')
default_group = cleaned_data.get('default_group')
if name:
name = name.strip()
cleaned_data['name'] = name
if default_group:
RouterGroup.objects.filter(default_group=True).update(default_group=False)
return cleaned_data
class SSHKeyForm(forms.ModelForm):
class Meta:
model = SSHKey
fields = ['name', 'public_key', 'private_key']
widgets = {
'public_key': forms.Textarea(attrs={'rows': 4, 'cols': 40}),
'private_key': forms.Textarea(attrs={'rows': 4, 'cols': 40}),
}
def __init__(self, *args, **kwargs):
super(SSHKeyForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = 'post'
if self.instance.pk:
delete_html = "<a href='javascript:void(0)' class='btn btn-outline-danger' data-command='delete' onclick='openCommandDialog(this)'>Delete</a>"
else:
delete_html = ''
self.helper.layout = Layout(
Row(
Column('name', css_class='form-group col-md-12 mb-0'),
),
Row(
Column('public_key', css_class='form-group col-md-12 mb-0'),
),
Row(
Column('private_key', css_class='form-group col-md-12 mb-0'),
),
Row(
Column(
Submit('submit', 'Salvar', css_class='btn btn-success'),
HTML(' <a class="btn btn-secondary" href="/router/ssh_keys/">Back</a> '),
HTML(delete_html),
css_class='col-md-12'),
css_class='form-row'
)
)

View file

@ -0,0 +1,36 @@
# Generated by Django 5.0.3 on 2024-03-16 18:27
import uuid
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('router_manager', '0003_routerstatus'),
]
operations = [
migrations.AddField(
model_name='router',
name='internal_notes',
field=models.TextField(blank=True, null=True),
),
migrations.AlterField(
model_name='router',
name='name',
field=models.CharField(max_length=100, unique=True),
),
migrations.CreateModel(
name='RouterGroup',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, unique=True)),
('internal_notes', models.TextField(blank=True, null=True)),
('updated', models.DateTimeField(auto_now=True)),
('created', models.DateTimeField(auto_now_add=True)),
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
('routers', models.ManyToManyField(to='router_manager.router')),
],
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 5.0.3 on 2024-03-16 18:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('router_manager', '0004_router_internal_notes_alter_router_name_routergroup'),
]
operations = [
migrations.AlterField(
model_name='sshkey',
name='name',
field=models.CharField(max_length=100, unique=True),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 5.0.3 on 2024-03-16 19:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('router_manager', '0005_alter_sshkey_name'),
]
operations = [
migrations.AddField(
model_name='routergroup',
name='default_group',
field=models.BooleanField(default=False),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 5.0.3 on 2024-03-16 20:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('router_manager', '0006_routergroup_default_group'),
]
operations = [
migrations.AlterField(
model_name='routergroup',
name='routers',
field=models.ManyToManyField(blank=True, to='router_manager.router'),
),
]

View file

@ -3,7 +3,7 @@ import uuid
class SSHKey(models.Model):
name = models.CharField(max_length=100)
name = models.CharField(max_length=100, unique=True)
public_key = models.TextField()
private_key = models.TextField()
@ -16,7 +16,8 @@ class SSHKey(models.Model):
class Router(models.Model):
name = models.CharField(max_length=100)
name = models.CharField(max_length=100, unique=True)
internal_notes = models.TextField(null=True, blank=True)
address = models.CharField(max_length=15)
username = models.CharField(max_length=100, default='admin')
password = models.CharField(max_length=100, null=True, blank=True)
@ -44,3 +45,16 @@ class RouterStatus(models.Model):
created = models.DateTimeField(auto_now_add=True)
uuid = models.UUIDField(unique=True, editable=False, default=uuid.uuid4)
class RouterGroup(models.Model):
name = models.CharField(max_length=100, unique=True)
default_group = models.BooleanField(default=False)
internal_notes = models.TextField(null=True, blank=True)
routers = models.ManyToManyField(Router, blank=True)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
uuid = models.UUIDField(unique=True, editable=False, default=uuid.uuid4)
def __str__(self):
return self.name

View file

@ -1,17 +1,28 @@
from django.contrib import messages
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from .models import Router
from .forms import RouterForm
from .models import Router, RouterGroup, RouterStatus, SSHKey
from .forms import RouterForm, RouterGroupForm, SSHKeyForm
@login_required
def view_router_list(request):
router_list = Router.objects.all()
router_list = Router.objects.all().order_by('name')
filter_group = None
if request.GET.get('filter_group'):
if request.GET.get('filter_group') == 'all':
pass
else:
filter_group = get_object_or_404(RouterGroup, uuid=request.GET.get('filter_group'))
router_list = router_list.filter(routergroup=filter_group)
if not filter_group and request.GET.get('filter_group') != 'all':
filter_group = RouterGroup.objects.filter(default_group=True).first()
context = {
'router_list': router_list,
'page_title': 'Router List',
'filter_group_list': RouterGroup.objects.all().order_by('name'),
'filter_group': filter_group,
}
return render(request, 'router_manager/router_list.html', context=context)
@ -42,4 +53,80 @@ def view_manage_router(request):
'page_title': 'Manage Router',
'instance': router
}
return render(request, 'generic_form.html', context=context)
return render(request, 'generic_form.html', context=context)
@login_required()
def view_router_group_list(request):
context = {
'router_group_list': RouterGroup.objects.all().order_by('name'),
'page_title': 'Router Group List',
}
return render(request, 'router_manager/router_group_list.html', context=context)
@login_required()
def view_manage_router_group(request):
if request.GET.get('uuid'):
router_group = get_object_or_404(RouterGroup, uuid=request.GET.get('uuid'))
if request.GET.get('action') == 'delete':
if request.GET.get('confirmation') == 'delete':
router_group.delete()
messages.success(request, 'Router Group deleted successfully')
return redirect('router_group_list')
else:
messages.warning(request, 'Router Group not deleted|Invalid confirmation')
return redirect('router_group_list')
else:
router_group = None
form = RouterGroupForm(request.POST or None, instance=router_group)
if form.is_valid():
form.save()
messages.success(request, 'Router Group saved successfully')
return redirect('router_group_list')
context = {
'form': form,
'page_title': 'Manage Router Group',
'instance': router_group
}
return render(request, 'generic_form.html', context=context)
@login_required()
def view_ssh_key_list(request):
context = {
'sshkey_list': SSHKey.objects.all().order_by('name'),
'page_title': 'SSH Key List',
}
return render(request, 'router_manager/sshkey_list.html', context=context)
@login_required()
def view_manage_sshkey(request):
if request.GET.get('uuid'):
sshkey = get_object_or_404(SSHKey, uuid=request.GET.get('uuid'))
if request.GET.get('action') == 'delete':
if request.GET.get('confirmation') == 'delete':
sshkey.delete()
messages.success(request, 'SSH Key deleted successfully')
return redirect('ssh_keys_list')
else:
messages.warning(request, 'SSH Key not deleted|Invalid confirmation')
return redirect('ssh_keys_list')
else:
sshkey = None
form = SSHKeyForm(request.POST or None, instance=sshkey)
if form.is_valid():
form.save()
messages.success(request, 'SSH Key saved successfully')
return redirect('ssh_keys_list')
context = {
'form': form,
'page_title': 'Manage SSH Key',
'instance': sshkey
}
return render(request, 'generic_form.html', context=context)