Add user permissions for reload and restart

This commit is contained in:
Eduardo Silva 2025-04-11 11:05:20 -03:00
parent b140362e86
commit a58d233546
9 changed files with 114 additions and 23 deletions

View File

@ -251,16 +251,26 @@
Your WireGuard settings have been modified. To apply these changes, please update the configuration and reload the WireGuard service.
</p>
<p>
<a href="/tools/export_wireguard_config/?action=update_and_restart" class="btn btn-secondary">Update and restart service</a>
<a href="/tools/export_wireguard_config/?action=update_and_reload" class="btn btn-secondary">Update and reload service</a>
<a
{% if user_acl.enable_restart %}
href="/tools/export_wireguard_config/?action=update_and_restart" class="btn btn-secondary"
{% else %}
href="#" class="btn btn-secondary disabled"
{% endif %}
>Update and restart service</a>
<a
{% if user_acl.enable_reload %}
href="/tools/export_wireguard_config/?action=update_and_reload" class="btn btn-secondary"
{% else %}
href="#" class="btn btn-secondary disabled"
{% endif %}
>Update and reload service</a>
</p>
</div>
{% endif %}
{% block content %}{% endblock %}
</div><!-- /.container-fluid -->
</section>

View File

@ -1,15 +1,14 @@
{% extends "base.html" %}
{% block content %}
<table class="table table-striped">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Username</th>
<th>User Level</th>
<th>Peer Groups</th>
<th></th>
<th></th>
<th></th>
<th colspan="4">Permissions</th>
<th><i class="far fa-edit"></i></th>
</tr>
</thead>
<tbody>
@ -26,16 +25,29 @@
Any
{% endif %}
</td>
<td style="width: 1%; white-space: nowrap;">
{% if user_acl.enable_restart %}
<i class="fas fa-power-off" title="Restart Enabled"></i>
{% endif %}
</td>
<td style="width: 1%; white-space: nowrap;">
{% if user_acl.enable_reload %}
<i class="fas fa-sync-alt" title="Reload Enabled"></i>
{% endif %}
</td>
<td style="width: 1%; white-space: nowrap;">
{% if user_acl.enable_console %}
<i class="fas fa-terminal" title="Console Enabled"></i>
{% endif %}
</td>
<td style="width: 1%; white-space: nowrap;">
{% if user_acl.enable_enhanced_filter %}
<i class="fas fa-eye-slash" title="Enhanced Filter Enabled"></i>
{% endif %}
</td>
<td style="width: 1%; white-space: nowrap;">
<a href="/user/manage/?uuid={{ user_acl.uuid }}" ><i class="far fa-edit"></i></a>
</td>

View File

@ -7,8 +7,21 @@
<div class="card card-primary card-outline">
<div class="card-header">
<a href='/tools/export_wireguard_config/' class='btn btn-outline-primary'>Update Configuration</a>
<a href='/tools/restart_wireguard/' class='btn btn-outline-primary'>Restart Wireguard service</a>
<a href='/tools/restart_wireguard/?mode=reload' class='btn btn-outline-primary'>Reload Wireguard service</a>
<a
{% if user_acl.enable_restart %}
href='/tools/restart_wireguard/' class='btn btn-outline-primary'
{% else %}
href='#' class='btn btn-outline-primary disabled'
{% endif %}
>Restart Wireguard service</a>
<a
{% if user_acl.enable_reload %}
href='/tools/restart_wireguard/?mode=reload' class='btn btn-outline-primary'
{% else %}
href='#' class='btn btn-outline-primary disabled'
{% endif %}
>Reload Wireguard service</a>
<div class="btn-group float-right" role="group" aria-label="Graph interval">
<a href="?period=6h" data-period="6h" class="btn btn-outline-primary">6h</a>

View File

@ -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
}
)

View File

@ -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),
),
]

View File

@ -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)

View File

@ -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}

View File

@ -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:

View File

@ -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 *