diff --git a/templates/user_manager/list.html b/templates/user_manager/list.html index d1928f7..2bf04e3 100644 --- a/templates/user_manager/list.html +++ b/templates/user_manager/list.html @@ -21,7 +21,6 @@ {% endfor %} - - Add User + {% include "user_manager/list_buttons.html" %} {% endblock %} diff --git a/templates/user_manager/list_buttons.html b/templates/user_manager/list_buttons.html new file mode 100644 index 0000000..f3d10e4 --- /dev/null +++ b/templates/user_manager/list_buttons.html @@ -0,0 +1,4 @@ +Add User +List Users +List Peer Groups +Add Peer Group \ No newline at end of file diff --git a/templates/user_manager/manage_peer_group.html b/templates/user_manager/manage_peer_group.html new file mode 100644 index 0000000..6cdd3de --- /dev/null +++ b/templates/user_manager/manage_peer_group.html @@ -0,0 +1,77 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+

{{ form.instance.pk|yesno:"Edit Peer Group,Create New Peer Group" }}

+
+
+
+
+
+ {% csrf_token %} + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ +
+ + Back + {% if peer_group %}Delete Peer Group{% endif %} +
+
+
+ + +
+ +
Peers
+

Select which peers can be managed by users with this peer group.

+ +
WireGuard Instances
+

All peers in this WireGuard instance can be managed by users with this peer group, including adding or removing peers.

+ +
+ +
+
+
+
+{% endblock %} + +{% block custom_page_scripts %} + +{% endblock %} \ No newline at end of file diff --git a/templates/user_manager/peer_group_list.html b/templates/user_manager/peer_group_list.html new file mode 100644 index 0000000..47e250e --- /dev/null +++ b/templates/user_manager/peer_group_list.html @@ -0,0 +1,37 @@ +{% extends "base.html" %} + +{% block content %} + + + + + + + + + + + {% for peer_group in peer_group_list %} + + + + + + + {% endfor %} + +
NamePeersServer Instance
{{ peer_group.name }} + {% for peer in peer_group.peer.all %} + {{ peer }}{% if not forloop.last %}, {% endif %} + {% endfor %} + + {% for instance in peer_group.server_instance.all %} + {{ instance }}{% if not forloop.last %}, {% endif %} + {% endfor %} + + +
+ + {% include "user_manager/list_buttons.html" %} + +{% endblock %} diff --git a/user_manager/forms.py b/user_manager/forms.py index 392b8d6..8d4c448 100644 --- a/user_manager/forms.py +++ b/user_manager/forms.py @@ -3,6 +3,7 @@ from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from .models import UserAcl from django.core.exceptions import ValidationError +from wireguard.models import PeerGroup class UserAclForm(UserCreationForm): @@ -44,3 +45,34 @@ class UserAclForm(UserCreationForm): ) return user + + + +class PeerGroupForm(forms.ModelForm): + class Meta: + model = PeerGroup + fields = ['name', 'peer', 'server_instance'] + + def __init__(self, *args, **kwargs): + self.user_id = kwargs.pop('user_id', None) + super().__init__(*args, **kwargs) + + + def clean(self): + cleaned_data = super().clean() + name = cleaned_data.get('name') + peers = cleaned_data.get('peer') + server_instances = cleaned_data.get('server_instance') + + if PeerGroup.objects.filter(name=name).exclude(pk=self.instance.pk if self.instance else None).exists(): + raise ValidationError("A peer group with that name already exists.") + + return cleaned_data + def save(self, commit=True): + peer_group = super().save(commit=False) + + if commit: + peer_group.save() + + return peer_group + diff --git a/user_manager/views.py b/user_manager/views.py index 6eb6e1b..6e1361d 100644 --- a/user_manager/views.py +++ b/user_manager/views.py @@ -5,6 +5,54 @@ from .forms import UserAclForm from django.contrib.auth.models import User from django.contrib import messages from django.contrib.sessions.models import Session +from wireguard.models import PeerGroup +from .forms import PeerGroupForm + + +@login_required +def view_peer_group_list(request): + if not UserAcl.objects.filter(user=request.user).filter(user_level__gte=50).exists(): + return render(request, 'access_denied.html', {'page_title': 'Access Denied'}) + page_title = 'Peer Group Manager' + peer_group_list = PeerGroup.objects.all().order_by('name') + context = {'page_title': page_title, 'peer_group_list': peer_group_list} + return render(request, 'user_manager/peer_group_list.html', context) + + +@login_required +def view_peer_group_manage(request): + if not UserAcl.objects.filter(user=request.user).filter(user_level__gte=50).exists(): + return render(request, 'access_denied.html', {'page_title': 'Access Denied'}) + peer_group = None + if 'uuid' in request.GET: + peer_group = get_object_or_404(PeerGroup, uuid=request.GET['uuid']) + form = PeerGroupForm(instance=peer_group, user_id=request.user.id) + page_title = 'Edit Peer Group ' + peer_group.name + if request.GET.get('action') == 'delete': + group_name = peer_group.name + if request.GET.get('confirmation') == group_name: + peer_group.delete() + messages.success(request, 'Peer Group deleted|The peer group ' + group_name + ' has been deleted.') + return redirect('/user/peer-group/list/') + + return redirect('/user/peer-group/list/') + else: + form = PeerGroupForm(user_id=request.user.id) + page_title = 'Add Peer Group' + + if request.method == 'POST': + if peer_group: + form = PeerGroupForm(request.POST, instance=peer_group, user_id=request.user.id) + else: + form = PeerGroupForm(request.POST, user_id=request.user.id) + + if form.is_valid(): + peer_group = form.save() + form.save_m2m() + return redirect('/user/peer-group/list/') + context = {'page_title': page_title, 'form': form, 'peer_group': peer_group} + return render(request, 'user_manager/manage_peer_group.html', context) + @login_required def view_user_list(request): diff --git a/wireguard/migrations/0024_alter_peergroup_uuid.py b/wireguard/migrations/0024_alter_peergroup_uuid.py new file mode 100644 index 0000000..c84d3a5 --- /dev/null +++ b/wireguard/migrations/0024_alter_peergroup_uuid.py @@ -0,0 +1,19 @@ +# Generated by Django 5.1.5 on 2025-01-20 13:53 + +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wireguard', '0023_peergroup'), + ] + + operations = [ + migrations.AlterField( + model_name='peergroup', + name='uuid', + field=models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False), + ), + ] diff --git a/wireguard/models.py b/wireguard/models.py index 409d556..c83cd51 100644 --- a/wireguard/models.py +++ b/wireguard/models.py @@ -129,12 +129,5 @@ class PeerGroup(models.Model): created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) - uuid = models.UUIDField(primary_key=True, editable=False) + uuid = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4) - def clean(self): - if self.peer.exists() and self.server_instance.exists(): - raise ValidationError("Please choose either WireGuard Instances or Peers, not both.") - - def save(self, *args, **kwargs): - self.clean() - super().save(*args, **kwargs) diff --git a/wireguard_webadmin/urls.py b/wireguard_webadmin/urls.py index 375c8b9..4b3662c 100644 --- a/wireguard_webadmin/urls.py +++ b/wireguard_webadmin/urls.py @@ -19,7 +19,7 @@ from django.urls import path from wireguard.views import view_welcome, view_wireguard_status, view_wireguard_manage_instance from wireguard_peer.views import view_wireguard_peer_list, view_wireguard_peer_manage, view_manage_ip_address from console.views import view_console -from user_manager.views import view_user_list, view_manage_user +from user_manager.views import view_user_list, view_manage_user, view_peer_group_list, view_peer_group_manage from accounts.views import view_create_first_user, view_login, view_logout from wireguard_tools.views import export_wireguard_configs, download_config_or_qrcode, restart_wireguard_interfaces from api.views import wireguard_status, cron_check_updates, cron_update_peer_latest_handshake, routerfleet_get_user_token, routerfleet_authenticate_session @@ -41,6 +41,8 @@ urlpatterns = [ path('console/', view_console, name='console'), path('user/list/', view_user_list, name='user_list'), path('user/manage/', view_manage_user, name='manage_user'), + path('user/peer-group/list/', view_peer_group_list, name='peer_group_list'), + path('user/peer-group/manage/', view_peer_group_manage, name='peer_group_manage'), path('tools/export_wireguard_config/', export_wireguard_configs, name='export_wireguard_configs'), path('tools/download_peer_config/', download_config_or_qrcode, name='download_config_or_qrcode'), path('tools/restart_wireguard/', restart_wireguard_interfaces, name='restart_wireguard_interfaces'),