diff --git a/templates/base.html b/templates/base.html index 23dd129..2d1d5b7 100644 --- a/templates/base.html +++ b/templates/base.html @@ -251,16 +251,26 @@ Your WireGuard settings have been modified. To apply these changes, please update the configuration and reload the WireGuard service.

- Update and restart service - Update and reload service + Update and restart service + + Update and reload service

{% endif %} - - - {% block content %}{% endblock %} diff --git a/templates/user_manager/list.html b/templates/user_manager/list.html index be45bb0..919e7f9 100644 --- a/templates/user_manager/list.html +++ b/templates/user_manager/list.html @@ -1,15 +1,14 @@ {% extends "base.html" %} {% block content %} - +
- - - + + @@ -26,16 +25,29 @@ Any {% endif %} + + + + + diff --git a/templates/wireguard/wireguard_status.html b/templates/wireguard/wireguard_status.html index a31aef7..c470677 100644 --- a/templates/wireguard/wireguard_status.html +++ b/templates/wireguard/wireguard_status.html @@ -7,8 +7,21 @@
Update Configuration - Restart Wireguard service - Reload Wireguard service + Restart Wireguard service + + Reload Wireguard service
6h diff --git a/user_manager/forms.py b/user_manager/forms.py index fc8a0e4..eacc21b 100644 --- a/user_manager/forms.py +++ b/user_manager/forms.py @@ -1,11 +1,11 @@ -from django import forms -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 from crispy_forms.helper import FormHelper -from crispy_forms.layout import Layout, Row, Column, Submit, HTML +from crispy_forms.layout import Column, HTML, Layout, Row, Submit +from django import forms +from django.contrib.auth.models import User +from django.core.exceptions import ValidationError + +from wireguard.models import PeerGroup +from .models import UserAcl class UserAclForm(forms.Form): @@ -13,6 +13,8 @@ class UserAclForm(forms.Form): password1 = forms.CharField(widget=forms.PasswordInput, required=False, label="Password") password2 = forms.CharField(widget=forms.PasswordInput, required=False, label="Password confirmation") enable_console = forms.BooleanField(required=False, label="Enable Console") + enable_reload = forms.BooleanField(required=False, label="Enable Reload") + enable_restart = forms.BooleanField(required=False, label="Enable Restart") enable_enhanced_filter = forms.BooleanField(required=False, label="Enable Enhanced Filter") user_level = forms.ChoiceField(choices=UserAcl.user_level.field.choices, required=True, label="User Level") peer_groups = forms.ModelMultipleChoiceField( @@ -30,14 +32,20 @@ class UserAclForm(forms.Form): self.fields['username'].widget.attrs['readonly'] = True self.fields['peer_groups'].initial = self.instance.useracl.peer_groups.all() self.fields['enable_console'].initial = self.instance.useracl.enable_console + self.fields['enable_reload'].initial = self.instance.useracl.enable_reload + self.fields['enable_restart'].initial = self.instance.useracl.enable_restart self.fields['enable_enhanced_filter'].initial = self.instance.useracl.enable_enhanced_filter else: self.fields['password1'].required = True self.fields['password2'].required = True self.fields['enable_console'].initial = True + self.fields['enable_reload'].initial = True + self.fields['enable_restart'].initial = True self.fields['enable_enhanced_filter'].initial = False self.fields['enable_console'].label = "Console" + self.fields['enable_reload'].label = "Reload" + self.fields['enable_restart'].label = "Restart" self.fields['enable_enhanced_filter'].label = "Enhanced Filter" self.helper = FormHelper() @@ -73,6 +81,14 @@ class UserAclForm(forms.Form): Column('enable_console', css_class='form-group col-md-12 mb-0'), css_class='form-row' ), + Row( + Column('enable_reload', css_class='form-group col-md-12 mb-0'), + css_class='form-row' + ), + Row( + Column('enable_restart', css_class='form-group col-md-12 mb-0'), + css_class='form-row' + ), Row( Column('enable_enhanced_filter', css_class='form-group col-md-12 mb-0'), css_class='form-row' @@ -118,6 +134,8 @@ class UserAclForm(forms.Form): user_level = self.cleaned_data['user_level'] peer_groups = self.cleaned_data.get('peer_groups', []) enable_console = self.cleaned_data.get('enable_console', False) + enable_reload = self.cleaned_data.get('enable_reload', False) + enable_restart = self.cleaned_data.get('enable_restart', False) enable_enhanced_filter = self.cleaned_data.get('enable_enhanced_filter', False) if self.instance: @@ -136,6 +154,8 @@ class UserAclForm(forms.Form): defaults={ 'user_level': user_level, 'enable_console': enable_console, + 'enable_reload': enable_reload, + 'enable_restart': enable_restart, 'enable_enhanced_filter': enable_enhanced_filter } ) diff --git a/user_manager/migrations/0006_useracl_enable_reload_useracl_enable_restart.py b/user_manager/migrations/0006_useracl_enable_reload_useracl_enable_restart.py new file mode 100644 index 0000000..68be83f --- /dev/null +++ b/user_manager/migrations/0006_useracl_enable_reload_useracl_enable_restart.py @@ -0,0 +1,23 @@ +# Generated by Django 5.2 on 2025-04-11 13:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('user_manager', '0005_useracl_enable_console_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='useracl', + name='enable_reload', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='useracl', + name='enable_restart', + field=models.BooleanField(default=True), + ), + ] diff --git a/user_manager/models.py b/user_manager/models.py index 56c4bea..33d4318 100644 --- a/user_manager/models.py +++ b/user_manager/models.py @@ -1,6 +1,8 @@ -from django.db import models -from django.contrib.auth.models import User import uuid + +from django.contrib.auth.models import User +from django.db import models + from wireguard.models import PeerGroup @@ -16,6 +18,8 @@ class UserAcl(models.Model): peer_groups = models.ManyToManyField(PeerGroup, blank=True) enable_console = models.BooleanField(default=True) enable_enhanced_filter = models.BooleanField(default=False) + enable_reload = models.BooleanField(default=True) + enable_restart = models.BooleanField(default=True) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) diff --git a/wireguard/context_processors.py b/wireguard/context_processors.py index b2fd68c..4790caa 100644 --- a/wireguard/context_processors.py +++ b/wireguard/context_processors.py @@ -1,9 +1,11 @@ +from user_manager.models import UserAcl from .models import WireGuardInstance def pending_changes_warning(request): + user_acl = UserAcl.objects.filter(user=request.user).first() if request.user.is_authenticated: pending = WireGuardInstance.objects.filter(pending_changes=True).exists() else: pending = False - return {'pending_changes_warning': pending} + return {'pending_changes_warning': pending, 'user_acl': user_acl} diff --git a/wireguard_tools/views.py b/wireguard_tools/views.py index 875b1b7..da6b3bc 100644 --- a/wireguard_tools/views.py +++ b/wireguard_tools/views.py @@ -218,7 +218,8 @@ def download_config_or_qrcode(request): @login_required def restart_wireguard_interfaces(request): - if not UserAcl.objects.filter(user=request.user).filter(user_level__gte=30).exists(): + user_acl = UserAcl.objects.filter(user=request.user).filter(user_level__gte=30).first() + if not user_acl: return render(request, 'access_denied.html', {'page_title': 'Access Denied'}) mode = request.GET.get('mode', 'restart') config_dir = "/etc/wireguard" @@ -228,6 +229,9 @@ def restart_wireguard_interfaces(request): if filename.endswith(".conf"): interface_name = filename[:-5] if mode == "reload": + if not user_acl.enable_reload: + return render(request, 'access_denied.html', {'page_title': 'Access Denied'}) + config_path = os.path.join(config_dir, filename) with open(config_path, 'r') as f: lines = f.readlines() @@ -253,6 +257,9 @@ def restart_wireguard_interfaces(request): interface_count += 1 else: + if not user_acl.enable_restart: + return render(request, 'access_denied.html', {'page_title': 'Access Denied'}) + stop_command = f"wg-quick down {interface_name}" stop_result = subprocess.run(stop_command, shell=True, capture_output=True, text=True) if stop_result.returncode != 0: diff --git a/wireguard_webadmin/settings.py b/wireguard_webadmin/settings.py index 2676f09..ef7eacb 100644 --- a/wireguard_webadmin/settings.py +++ b/wireguard_webadmin/settings.py @@ -136,6 +136,6 @@ STATICFILES_DIRS = [ DNS_CONFIG_FILE = '/etc/dnsmasq/wireguard_webadmin_dns.conf' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' -WIREGUARD_WEBADMIN_VERSION = 9963 +WIREGUARD_WEBADMIN_VERSION = 9964 from wireguard_webadmin.production_settings import *
Username User Level Peer GroupsPermissions
+ {% if user_acl.enable_restart %} + + {% endif %} + + {% if user_acl.enable_reload %} + + {% endif %} + {% if user_acl.enable_console %} {% endif %} {% if user_acl.enable_enhanced_filter %} {% endif %}