diff --git a/router_manager/forms.py b/router_manager/forms.py
index 486638e..b5fbb36 100644
--- a/router_manager/forms.py
+++ b/router_manager/forms.py
@@ -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 = "Delete"
+ 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 = "Delete"
+ else:
+ delete_html = ''
+ self.helper.layout = Layout(
+ 'name',
+ 'internal_notes',
+ 'routers',
+ 'default_group',
+ Row(
+ Column(
+ Submit('submit', 'Salvar', css_class='btn btn-success'),
+ HTML(' Back '),
+ 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 = "Delete"
+ 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(' Back '),
+ HTML(delete_html),
+ css_class='col-md-12'),
+ css_class='form-row'
+ )
+ )
diff --git a/router_manager/migrations/0004_router_internal_notes_alter_router_name_routergroup.py b/router_manager/migrations/0004_router_internal_notes_alter_router_name_routergroup.py
new file mode 100644
index 0000000..24d2e0e
--- /dev/null
+++ b/router_manager/migrations/0004_router_internal_notes_alter_router_name_routergroup.py
@@ -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')),
+ ],
+ ),
+ ]
diff --git a/router_manager/migrations/0005_alter_sshkey_name.py b/router_manager/migrations/0005_alter_sshkey_name.py
new file mode 100644
index 0000000..92d6132
--- /dev/null
+++ b/router_manager/migrations/0005_alter_sshkey_name.py
@@ -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),
+ ),
+ ]
diff --git a/router_manager/migrations/0006_routergroup_default_group.py b/router_manager/migrations/0006_routergroup_default_group.py
new file mode 100644
index 0000000..b13ba8a
--- /dev/null
+++ b/router_manager/migrations/0006_routergroup_default_group.py
@@ -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),
+ ),
+ ]
diff --git a/router_manager/migrations/0007_alter_routergroup_routers.py b/router_manager/migrations/0007_alter_routergroup_routers.py
new file mode 100644
index 0000000..49507c8
--- /dev/null
+++ b/router_manager/migrations/0007_alter_routergroup_routers.py
@@ -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'),
+ ),
+ ]
diff --git a/router_manager/models.py b/router_manager/models.py
index 9843ecf..c1165b4 100644
--- a/router_manager/models.py
+++ b/router_manager/models.py
@@ -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
diff --git a/router_manager/views.py b/router_manager/views.py
index a362a59..a3061de 100644
--- a/router_manager/views.py
+++ b/router_manager/views.py
@@ -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)
\ No newline at end of file
+ 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)
diff --git a/routerfleet/urls.py b/routerfleet/urls.py
index e632163..34b755d 100644
--- a/routerfleet/urls.py
+++ b/routerfleet/urls.py
@@ -3,7 +3,7 @@ from django.urls import path
from dashboard.views import view_dashboard, view_status
from user_manager.views import view_manage_user, view_user_list
from accounts.views import view_login, view_logout, view_create_first_user
-from router_manager.views import view_router_list, view_manage_router
+from router_manager.views import view_router_list, view_manage_router, view_router_group_list, view_ssh_key_list, view_manage_router_group, view_manage_sshkey
urlpatterns = [
path('admin/', admin.site.urls),
@@ -16,4 +16,8 @@ urlpatterns = [
path('accounts/logout/', view_logout, name='logout'),
path('router/list/', view_router_list, name='router_list'),
path('router/manage/', view_manage_router, name='manage_router'),
+ path('router/group_list/', view_router_group_list, name='router_group_list'),
+ path('router/ssh_keys/', view_ssh_key_list, name='ssh_keys_list'),
+ path('router/manage_group/', view_manage_router_group, name='manage_router_group'),
+ path('router/manage_sshkey/', view_manage_sshkey, name='manage_sshkey'),
]
diff --git a/templates/base.html b/templates/base.html
index b2a1243..760c9e2 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -23,8 +23,9 @@
-
+ {% comment %}
+ {% endcomment %}