From 2a61a0549935632d800b26f99c7e45ee90c60cb6 Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Thu, 22 Jan 2026 15:30:42 -0300 Subject: [PATCH] add route template application functionality for peers --- templates/wireguard/apply_route_template.html | 67 +++++++++++++++++++ .../wireguard/wireguard_manage_peer.html | 10 ++- wireguard_peer/views.py | 54 ++++++++++++++- wireguard_webadmin/urls.py | 3 +- 4 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 templates/wireguard/apply_route_template.html diff --git a/templates/wireguard/apply_route_template.html b/templates/wireguard/apply_route_template.html new file mode 100644 index 0000000..8bda0ef --- /dev/null +++ b/templates/wireguard/apply_route_template.html @@ -0,0 +1,67 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block content %} + +
+
+

{% trans 'Apply Route Template' %}

+
+
+
+
+

{% trans 'Select a routing template to apply to the peer' %} {{ current_peer }}.

+ {% if current_template %} +
+ {% trans 'Current Active Template:' %} {{ current_template.name }} +
+ {% endif %} +
+
+ +
+ + + + + + + + + + {% for template in available_templates %} + + + + + + {% empty %} + + + + {% endfor %} + +
{% trans 'Template Name' %}{% trans 'Type' %}{% trans 'Actions' %}
{{ template.name }}{{ template.get_route_type_display }} + {% if template != current_template %} +
+ {% csrf_token %} + + +
+ {% else %} + +
+ {% csrf_token %} + + +
+ {% endif %} +
{% trans 'No routing templates available for this interface.' %}
+
+
+ +
+ +{% endblock %} \ No newline at end of file diff --git a/templates/wireguard/wireguard_manage_peer.html b/templates/wireguard/wireguard_manage_peer.html index acf690a..b920ba1 100644 --- a/templates/wireguard/wireguard_manage_peer.html +++ b/templates/wireguard/wireguard_manage_peer.html @@ -112,10 +112,14 @@
- {% trans 'Add Client route' %} +
+ {% trans 'Apply template' %} + {% trans 'Add Client route' %} +
+

diff --git a/wireguard_peer/views.py b/wireguard_peer/views.py index f0ee7ae..a849607 100644 --- a/wireguard_peer/views.py +++ b/wireguard_peer/views.py @@ -9,6 +9,7 @@ from django.shortcuts import get_object_or_404, redirect, render from django.utils.translation import gettext_lazy as _ from cluster.models import ClusterSettings, Worker +from routing_templates.models import RoutingTemplate from user_manager.models import UserAcl from wgwadmlibrary.tools import check_sort_order_conflict, deduplicate_sort_order, default_sort_peers, \ user_allowed_instances, user_allowed_peers, user_has_access_to_instance, user_has_access_to_peer @@ -283,4 +284,55 @@ def view_manage_ip_address(request): return render(request, 'wireguard/wireguard_manage_ip.html', { 'page_title': page_title, 'form': form, 'current_peer': current_peer, 'current_ip': current_ip - }) + }) + + +@login_required +def view_apply_route_template(request): + if not UserAcl.objects.filter(user=request.user).filter(user_level__gte=30).exists(): + return render(request, 'access_denied.html', {'page_title': 'Access Denied'}) + + user_acl = get_object_or_404(UserAcl, user=request.user) + current_peer = get_object_or_404(Peer, uuid=request.GET.get('peer')) + + if not user_has_access_to_peer(user_acl, current_peer): + raise Http404 + + wireguard_instance = current_peer.wireguard_instance + available_templates = RoutingTemplate.objects.filter(wireguard_instance=wireguard_instance) + current_template = current_peer.routing_template + + if request.method == 'POST': + if request.POST.get('action') == 'unlink': + current_peer.routing_template = None + current_peer.save() + current_peer.wireguard_instance.pending_changes = True + current_peer.wireguard_instance.save() + messages.success(request, _('Route template unlinked successfully.')) + return redirect('/peer/manage/?peer=' + str(current_peer.uuid)) + + template_uuid = request.POST.get('template_uuid') + if template_uuid: + selected_template = get_object_or_404(RoutingTemplate, uuid=template_uuid) + + # Validation + if not selected_template.allow_peer_custom_routes: + if current_peer.peerallowedip_set.filter(config_file='client', priority__gte=1).exists(): + messages.error(request, _('Cannot apply template: This template does not allow custom routes, but the peer has custom client routes defined.')) + return redirect('/peer/apply_route_template/?peer=' + str(current_peer.uuid)) + + current_peer.routing_template = selected_template + current_peer.save() + current_peer.wireguard_instance.pending_changes = True + current_peer.wireguard_instance.save() + messages.success(request, _('Route template applied successfully.')) + return redirect('/peer/manage/?peer=' + str(current_peer.uuid)) + + context = { + 'page_title': _('Apply Route Template'), + 'current_peer': current_peer, + 'available_templates': available_templates, + 'current_template': current_template, + } + return render(request, 'wireguard/apply_route_template.html', context) + diff --git a/wireguard_webadmin/urls.py b/wireguard_webadmin/urls.py index ff78b70..cbc8bb5 100644 --- a/wireguard_webadmin/urls.py +++ b/wireguard_webadmin/urls.py @@ -38,7 +38,7 @@ from vpn_invite_public.views import view_public_vpn_invite from wgrrd.views import view_rrd_graph from wireguard.views import view_apply_db_patches, view_wireguard_manage_instance, view_wireguard_status from wireguard_peer.views import view_manage_ip_address, view_wireguard_peer_list, view_wireguard_peer_manage, \ - view_wireguard_peer_sort + view_wireguard_peer_sort, view_apply_route_template from wireguard_tools.views import download_config_or_qrcode, export_wireguard_configs, restart_wireguard_interfaces urlpatterns = [ @@ -55,6 +55,7 @@ urlpatterns = [ path('peer/list/', view_wireguard_peer_list, name='wireguard_peer_list'), path('peer/sort/', view_wireguard_peer_sort, name='wireguard_peer_sort'), path('peer/manage/', view_wireguard_peer_manage, name='wireguard_peer_manage'), + path('peer/apply_route_template/', view_apply_route_template, name='apply_route_template'), path('peer/manage_ip_address/', view_manage_ip_address, name='manage_ip_address'), path('rrd/graph/', view_rrd_graph, name='rrd_graph'), path('console/', view_console, name='console'),