User Manager app translation

This commit is contained in:
Eduardo Silva
2025-04-15 12:16:50 -03:00
parent 1bd4c04475
commit 77ed501cfc
8 changed files with 375 additions and 93 deletions

View File

@@ -3,23 +3,25 @@ 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 django.utils.translation import gettext_lazy as _
from wireguard.models import PeerGroup
from .models import UserAcl
class UserAclForm(forms.Form):
username = forms.CharField(max_length=150)
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")
username = forms.CharField(max_length=150, label=_("Username"))
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=_("Console"))
enable_reload = forms.BooleanField(required=False, label=_("Reload WireGuard"))
enable_restart = forms.BooleanField(required=False, label=_("Restart WireGuard"))
enable_enhanced_filter = forms.BooleanField(required=False, label=_("Enhanced Filter"))
user_level = forms.ChoiceField(choices=UserAcl.user_level.field.choices, required=True, label=_("User Level"))
peer_groups = forms.ModelMultipleChoiceField(
queryset=PeerGroup.objects.all(),
required=False,
label=_("Peer Groups"),
)
def __init__(self, *args, **kwargs):
@@ -42,17 +44,15 @@ class UserAclForm(forms.Form):
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"
delete_label = _("Delete")
back_label = _("Back")
self.helper = FormHelper()
self.helper.form_method = 'post'
if self.instance:
delete_html = "<a href='javascript:void(0)' class='btn btn-outline-danger' data-command='delete' onclick='openCommandDialog(this)'>Delete</a>"
delete_html = f"<a href='javascript:void(0)' class='btn btn-outline-danger' data-command='delete' onclick='openCommandDialog(this)'>{delete_label}</a>"
else:
delete_html = ''
@@ -95,8 +95,8 @@ class UserAclForm(forms.Form):
),
Row(
Column(
Submit('submit', 'Save', css_class='btn btn-success'),
HTML(' <a class="btn btn-secondary" href="/user/list/">Back</a> '),
Submit('submit', _('Save'), css_class='btn btn-success'),
HTML(f' <a class="btn btn-secondary" href="/user/list/">{back_label}</a> '),
HTML(delete_html),
css_class='col-md-12'),
css_class='form-row'
@@ -116,15 +116,15 @@ class UserAclForm(forms.Form):
if not self.instance:
if not password1:
raise ValidationError("Password is required for new users.")
raise ValidationError(_("Password is required for new users."))
if not password2:
raise ValidationError("Password confirmation is required for new users.")
raise ValidationError(_("Password confirmation is required for new users."))
if password1 or password2:
if password1 != password2:
raise ValidationError("The two password fields didn't match.")
raise ValidationError(_("The two password fields didn't match."))
if len(password1) < 8:
raise ValidationError("Password must be at least 8 characters long.")
raise ValidationError(_("Password must be at least 8 characters long."))
return cleaned_data
@@ -174,11 +174,16 @@ class PeerGroupForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user_id = kwargs.pop('user_id', None)
super().__init__(*args, **kwargs)
self.fields['name'].label = _("Name")
self.fields['peer'].label = _("Peer")
self.fields['server_instance'].label = _("Server Instance")
back_label = _("Back")
delete_label = _("Delete")
self.helper = FormHelper()
self.helper.form_method = 'post'
if self.instance.pk:
delete_html = "<a href='javascript:void(0)' class='btn btn-outline-danger' data-command='delete' onclick='openCommandDialog(this)'>Delete</a>"
delete_html = f"<a href='javascript:void(0)' class='btn btn-outline-danger' data-command='delete' onclick='openCommandDialog(this)'>{delete_label}</a>"
else:
delete_html = ''
@@ -197,8 +202,8 @@ class PeerGroupForm(forms.ModelForm):
),
Row(
Column(
Submit('submit', 'Save', css_class='btn btn-success'),
HTML(' <a class="btn btn-secondary" href="/user/peer-group/list/">Back</a> '),
Submit('submit', _('Save'), css_class='btn btn-success'),
HTML(f' <a class="btn btn-secondary" href="/user/peer-group/list/">{back_label}</a> '),
HTML(delete_html),
css_class='col-md-12'),
css_class='form-row'
@@ -212,7 +217,7 @@ class PeerGroupForm(forms.ModelForm):
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.")
raise ValidationError(_("A peer group with that name already exists."))
return cleaned_data

View File

@@ -2,6 +2,7 @@ import uuid
from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import gettext_lazy as _
from wireguard.models import PeerGroup
@@ -9,11 +10,11 @@ from wireguard.models import PeerGroup
class UserAcl(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
user_level = models.PositiveIntegerField(default=0, choices=(
(10, 'Debugging Analyst'),
(20, 'View Only User'),
(30, 'Peer Manager'),
(40, 'Wireguard Manager'),
(50, 'Administrator'),
(10, _('Debugging Analyst')),
(20, _('View Only')),
(30, _('Peer Manager')),
(40, _('WireGuard Manager')),
(50, _('Administrator')),
))
peer_groups = models.ManyToManyField(PeerGroup, blank=True)
enable_console = models.BooleanField(default=True)

View File

@@ -1,19 +1,20 @@
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect, get_object_or_404
from user_manager.models import UserAcl
from .forms import UserAclForm
from django.contrib.auth.models import User
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.sessions.models import Session
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.translation import gettext_lazy as _
from user_manager.models import UserAcl
from wireguard.models import PeerGroup
from .forms import PeerGroupForm
from .forms import UserAclForm
@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'
page_title = _('Peer Groups')
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)
@@ -27,19 +28,19 @@ def view_peer_group_manage(request):
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
page_title = _('Edit Peer Group: ') + peer_group.name
if request.GET.get('action') == 'delete':
group_name = peer_group.name
if request.GET.get('confirmation') == 'delete':
peer_group.delete()
messages.success(request, 'Peer Group deleted|The peer group ' + group_name + ' has been deleted.')
messages.success(request, _('Peer Group deleted|Peer Group deleted: ') + group_name)
return redirect('/user/peer-group/list/')
else:
messages.warning(request, 'Peer Group not deleted|Invalid confirmation.')
messages.warning(request, _('Peer Group not deleted|Invalid confirmation.'))
return redirect('/user/peer-group/list/')
else:
form = PeerGroupForm(user_id=request.user.id)
page_title = 'Add Peer Group'
page_title = _('Add Peer Group')
if request.method == 'POST':
if peer_group:
@@ -54,13 +55,13 @@ def view_peer_group_manage(request):
form_description = {
'size': '',
'content': '''
'content': _('''
<h5>Peers</h5>
<p>Select which peers can be managed by users with this peer group.</p>
<h5>WireGuard Instances</h5>
<p>All peers in this WireGuard instance can be managed by users with this peer group, including adding or removing peers.</p>
'''
''')
}
context = {'page_title': page_title, 'form': form, 'peer_group': peer_group, 'instance': peer_group, 'form_description': form_description}
return render(request, 'generic_form.html', context)
@@ -70,7 +71,7 @@ def view_peer_group_manage(request):
def view_user_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 = 'User Manager'
page_title = _('User Manager')
user_acl_list = UserAcl.objects.all().order_by('user__username')
context = {'page_title': page_title, 'user_acl_list': user_acl_list}
return render(request, 'user_manager/list.html', context)
@@ -94,20 +95,20 @@ def view_manage_user(request):
'peer_groups': user_acl.peer_groups.all()
}
form = UserAclForm(initial=initial_data, instance=user, user_id=user.id)
page_title = 'Edit User '+ user.username
page_title = _('Edit User') + f' {user.username}'
if request.GET.get('action') == 'delete':
username = user.username
if request.GET.get('confirmation') == username:
user.delete()
messages.success(request, 'User deleted|The user '+ username +' has been deleted.')
messages.success(request, _('User deleted|User deleted: ') + username)
return redirect('/user/list/')
else:
messages.warning(request, 'User not deleted|Invalid confirmation.')
messages.warning(request, _('User not deleted|Invalid confirmation.'))
return redirect('/user/list/')
else:
form = UserAclForm()
page_title = 'Add User'
page_title = _('Add User')
if request.method == 'POST':
if user:
@@ -124,23 +125,23 @@ def view_manage_user(request):
if str(user.id) == session.get_decoded().get('_auth_user_id'):
session.delete()
if not user_disconnected:
messages.warning(request, 'User Disconnected|The user '+ user.username +' has been disconnected.')
messages.warning(request, _('User Disconnected|User Disconnected: ') + user.username)
user_disconnected = True
if user:
messages.success(request, 'User updated|The user '+ form.cleaned_data['username'] +' has been updated.')
messages.success(request, _('User updated|User updated: ') + form.cleaned_data['username'])
else:
messages.success(request, 'User added|The user '+ form.cleaned_data['username'] +' has been added.')
messages.success(request, _('User created|User created: ') + form.cleaned_data['username'])
return redirect('/user/list/')
form_description = {
'size': '',
'content': '''
'content': _('''
<h4>User Levels</h4>
<h5>Debugging Analyst</h5>
<p>Access to basic system information and logs for troubleshooting. No access to modify settings or view sensitive data such as peer keys.</p>
<h5>View Only User</h5>
<h5>View Only</h5>
<p>Full view access, including peer keys and configuration files. Cannot modify any settings or configurations.</p>
<h5>Peer Manager</h5>
@@ -162,7 +163,7 @@ def view_manage_user(request):
<h4>Enhanced Filter</h4>
<p>This option filters the API status response to include only peers that the user has access to. Depending on the size of your environment, enabling this option may impact performance. To mitigate this, consider increasing the "Web Refresh Interval" to reduce the number of requests.</p>
'''
''')
}
context = {
@@ -171,6 +172,6 @@ def view_manage_user(request):
'user_acl': user_acl,
'instance': user_acl,
'form_description': form_description,
'delete_confirmation_message': 'Please type the username to proceed.'
'delete_confirmation_message': _('Please type the username to proceed.')
}
return render(request, 'generic_form.html', context)