mirror of
https://github.com/eduardogsilva/wireguard_webadmin.git
synced 2025-08-26 13:21:14 +00:00
VPN Invite app translation
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import Layout, Row, Column, Submit, HTML
|
||||
from crispy_forms.templatetags.crispy_forms_field import css_class
|
||||
from .models import InviteSettings
|
||||
from crispy_forms.layout import Column, HTML, Layout, Row, Submit
|
||||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from wireguard_tools.models import EmailSettings
|
||||
from .models import InviteSettings
|
||||
|
||||
|
||||
class InviteSettingsForm(forms.ModelForm):
|
||||
@@ -46,7 +46,7 @@ class InviteSettingsForm(forms.ModelForm):
|
||||
super(InviteSettingsForm, self).__init__(*args, **kwargs)
|
||||
|
||||
# Define boolean dropdown choices
|
||||
bool_choices = [(True, 'Enabled'), (False, 'Disabled')]
|
||||
bool_choices = [(True, _('Enabled')), (False, _('Disabled'))]
|
||||
bool_coerce = lambda x: True if x == 'True' else False
|
||||
|
||||
for field_name in [
|
||||
@@ -65,37 +65,42 @@ class InviteSettingsForm(forms.ModelForm):
|
||||
initial=self.instance.__dict__.get(field_name, True) if self.instance and self.instance.pk else True,
|
||||
)
|
||||
|
||||
self.fields['download_1_url'].label = 'URL'
|
||||
self.fields['download_2_url'].label = 'URL'
|
||||
self.fields['download_3_url'].label = 'URL'
|
||||
self.fields['download_4_url'].label = 'URL'
|
||||
self.fields['download_5_url'].label = 'URL'
|
||||
self.fields['download_1_label'].label = 'Text'
|
||||
self.fields['download_2_label'].label = 'Text'
|
||||
self.fields['download_3_label'].label = 'Text'
|
||||
self.fields['download_4_label'].label = 'Text'
|
||||
self.fields['download_5_label'].label = 'Text'
|
||||
self.fields['download_1_enabled'].label = 'Status'
|
||||
self.fields['download_2_enabled'].label = 'Status'
|
||||
self.fields['download_3_enabled'].label = 'Status'
|
||||
self.fields['download_4_enabled'].label = 'Status'
|
||||
self.fields['download_5_enabled'].label = 'Status'
|
||||
self.fields['download_instructions'].label = 'Web Page Instructions'
|
||||
self.fields['invite_email_subject'].label = 'Email Subject'
|
||||
self.fields['invite_email_body'].label = 'Email Message'
|
||||
self.fields['invite_email_enabled'].label = 'Email Enabled'
|
||||
self.fields['invite_whatsapp_body'].label = 'WhatsApp Message'
|
||||
self.fields['invite_whatsapp_enabled'].label = 'WhatsApp Enabled'
|
||||
self.fields['invite_text_body'].label = 'Text Message'
|
||||
self.fields['invite_expiration'].label = 'Expiration (minutes)'
|
||||
self.fields['enforce_random_password'].label = 'Random Password'
|
||||
self.fields['download_1_url'].label = _('URL')
|
||||
self.fields['download_2_url'].label = _('URL')
|
||||
self.fields['download_3_url'].label = _('URL')
|
||||
self.fields['download_4_url'].label = _('URL')
|
||||
self.fields['download_5_url'].label = _('URL')
|
||||
self.fields['download_1_label'].label = _('Text')
|
||||
self.fields['download_2_label'].label = _('Text')
|
||||
self.fields['download_3_label'].label = _('Text')
|
||||
self.fields['download_4_label'].label = _('Text')
|
||||
self.fields['download_5_label'].label = _('Text')
|
||||
self.fields['download_1_enabled'].label = _('Status')
|
||||
self.fields['download_2_enabled'].label = _('Status')
|
||||
self.fields['download_3_enabled'].label = _('Status')
|
||||
self.fields['download_4_enabled'].label = _('Status')
|
||||
self.fields['download_5_enabled'].label = _('Status')
|
||||
self.fields['download_instructions'].label = _('Web Page Instructions')
|
||||
self.fields['invite_email_subject'].label = _('Email Subject')
|
||||
self.fields['invite_email_body'].label = _('Email Message')
|
||||
self.fields['invite_email_enabled'].label = _('Email Enabled')
|
||||
self.fields['invite_whatsapp_body'].label = _('WhatsApp Message')
|
||||
self.fields['invite_whatsapp_enabled'].label = _('WhatsApp Enabled')
|
||||
self.fields['invite_text_body'].label = _('Text Message')
|
||||
self.fields['invite_expiration'].label = _('Expiration (minutes)')
|
||||
self.fields['enforce_random_password'].label = _('Random Password')
|
||||
self.fields['invite_url'].label = _('Invite URL')
|
||||
self.fields['required_user_level'].label = _('Required User Level')
|
||||
self.fields['default_password'].label = _('Default Password')
|
||||
self.fields['random_password_length'].label = _('Random Password Length')
|
||||
self.fields['random_password_complexity'].label = _('Random Password Complexity')
|
||||
self.helper = FormHelper()
|
||||
self.helper.form_method = 'post'
|
||||
|
||||
self.helper.layout = Layout(
|
||||
Row(
|
||||
Column(
|
||||
HTML("<h3>General Settings</h3>"),
|
||||
HTML("<h3>" + _("General Settings") + "</h3>"),
|
||||
Row(
|
||||
Column('invite_url', css_class='form-group col-md-12 mb-0'),
|
||||
),
|
||||
@@ -117,7 +122,7 @@ class InviteSettingsForm(forms.ModelForm):
|
||||
),
|
||||
HTML("<hr>"),
|
||||
Row(
|
||||
Column(HTML("<h5>Download Buttons</h5>"), css_class='form-group col-md-12 mb-0'),
|
||||
Column(HTML("<h5>" + _("Download Buttons") + "</h5>"), css_class='form-group col-md-12 mb-0'),
|
||||
Column('download_1_label', css_class='form-group col-md-3 mb-0'),
|
||||
Column('download_1_url', css_class='form-group col-md-6 mb-0'),
|
||||
Column('download_1_enabled', css_class='form-group col-md-3 mb-0'),
|
||||
@@ -147,24 +152,17 @@ class InviteSettingsForm(forms.ModelForm):
|
||||
Column('download_5_enabled', css_class='form-group col-md-3 mb-0'),
|
||||
css_class='form-row'
|
||||
),
|
||||
Row(
|
||||
Column(
|
||||
Submit('submit', 'Save', css_class='btn btn-success'),
|
||||
HTML(' <a class="btn btn-secondary" href="/vpn_invite/">Back</a> '),
|
||||
css_class='col-md-12'
|
||||
),
|
||||
css_class='form-row'
|
||||
),
|
||||
css_class='col-xl-6'),
|
||||
|
||||
css_class='col-xl-12'),
|
||||
Column(
|
||||
HTML("<h3>Message templates</h3>"),
|
||||
HTML("<h3>" + _('Message templates') + "</h3>"),
|
||||
Row(
|
||||
Column('download_instructions', css_class='form-group col-md-12 mb-0'),
|
||||
css_class='form-row'
|
||||
),
|
||||
HTML("<hr>"),
|
||||
Row(
|
||||
Column(HTML("<h5>Email Message Template</h5>"), css_class='form-group col-md-12 mb-0'),
|
||||
Column(HTML("<h5>" + _("Email Message Template") + "</h5>"), css_class='form-group col-md-12 mb-0'),
|
||||
Column('invite_email_subject', css_class='form-group col-md-12 mb-0'),
|
||||
Column('invite_email_body', css_class='form-group col-md-12 mb-0'),
|
||||
css_class='form-row'
|
||||
@@ -175,19 +173,26 @@ class InviteSettingsForm(forms.ModelForm):
|
||||
),
|
||||
HTML("<hr>"),
|
||||
Row(
|
||||
Column(HTML("<h5>WhatsApp Message Template</h5>"), css_class='form-group col-md-12 mb-0'),
|
||||
Column(HTML("<h5>" + _("WhatsApp Message Template") + "</h5>"), css_class='form-group col-md-12 mb-0'),
|
||||
Column('invite_whatsapp_body', css_class='form-group col-md-12 mb-0'),
|
||||
Column('invite_whatsapp_enabled', css_class='form-group col-md-12 mb-0'),
|
||||
css_class='form-row'
|
||||
),
|
||||
HTML("<hr>"),
|
||||
Row(
|
||||
Column(HTML("<h5>Text Message Template</h5>"), css_class='form-group col-md-12 mb-0'),
|
||||
Column(HTML("<h5>" + _("Text Message Template") + "</h5>"), css_class='form-group col-md-12 mb-0'),
|
||||
Column('invite_text_body', css_class='form-group col-md-12 mb-0'),
|
||||
css_class='form-row'
|
||||
),
|
||||
css_class='col-xl-6'),
|
||||
css_class='col-xl-12'),
|
||||
css_class='row'),
|
||||
Row(
|
||||
Column(
|
||||
Submit('submit', _('Save'), css_class='btn btn-success'),
|
||||
HTML(' <a class="btn btn-secondary" href="/vpn_invite/">' + _('Back') + '</a> '),
|
||||
css_class='col-md-12'
|
||||
),
|
||||
css_class='form-row'),
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
@@ -197,15 +202,15 @@ class InviteSettingsForm(forms.ModelForm):
|
||||
invite_url = cleaned_data.get('invite_url')
|
||||
if invite_url:
|
||||
if not invite_url.startswith("https://"):
|
||||
self.add_error('invite_url', "Invite URL must start with 'https://'.")
|
||||
self.add_error('invite_url', _("Invite URL must start with 'https://'."))
|
||||
if not invite_url.endswith("/invite/"):
|
||||
self.add_error('invite_url', "Invite URL must end with '/invite/'.")
|
||||
self.add_error('invite_url', _("Invite URL must end with '/invite/'."))
|
||||
|
||||
# Validate invite_expiration: must be between 1 and 1440 minutes
|
||||
invite_expiration = cleaned_data.get('invite_expiration')
|
||||
if invite_expiration is not None:
|
||||
if invite_expiration < 1 or invite_expiration > 1440:
|
||||
self.add_error('invite_expiration', "Expiration (minutes) must be between 1 and 1440.")
|
||||
self.add_error('invite_expiration', _("Expiration (minutes) must be between 1 and 1440."))
|
||||
|
||||
# Validate default_password based on enforce_random_password flag
|
||||
default_password = cleaned_data.get('default_password', '')
|
||||
@@ -214,16 +219,16 @@ class InviteSettingsForm(forms.ModelForm):
|
||||
if enforce_random_password is True:
|
||||
if default_password:
|
||||
self.add_error('default_password',
|
||||
"Default password must not be provided when random password is enabled.")
|
||||
_("Default password must not be provided when random password is enabled."))
|
||||
if random_password_length < 6:
|
||||
self.add_error('random_password_length', "Random password length must be at least 6 characters.")
|
||||
self.add_error('random_password_length', _("Random password length must be at least 6 characters."))
|
||||
else:
|
||||
# When random password is disabled, default password must be provided and have at least 6 characters.
|
||||
if not default_password:
|
||||
self.add_error('default_password',
|
||||
"Default password must be provided when random password is disabled.")
|
||||
_("Default password must be provided when random password is disabled."))
|
||||
elif len(default_password) < 6:
|
||||
self.add_error('default_password', "Default password must be at least 6 characters long.")
|
||||
self.add_error('default_password', _("Default password must be at least 6 characters long."))
|
||||
|
||||
# Validate download buttons: if enabled, the respective text and url fields must not be blank.
|
||||
for i in range(1, 6):
|
||||
@@ -233,9 +238,9 @@ class InviteSettingsForm(forms.ModelForm):
|
||||
if enabled:
|
||||
if not label:
|
||||
self.add_error(f'download_{i}_label',
|
||||
"Text field must not be empty when download button is enabled.")
|
||||
_("Text field must not be empty when download button is enabled."))
|
||||
if not url:
|
||||
self.add_error(f'download_{i}_url', "URL field must not be empty when download button is enabled.")
|
||||
self.add_error(f'download_{i}_url', _("URL field must not be empty when download button is enabled."))
|
||||
|
||||
# Validate that default_password is not contained in any message templates or the subject
|
||||
message_fields = ['invite_text_body', 'invite_email_subject', 'invite_email_body', 'invite_whatsapp_body']
|
||||
@@ -244,14 +249,14 @@ class InviteSettingsForm(forms.ModelForm):
|
||||
content = cleaned_data.get(field, '')
|
||||
if default_password in content:
|
||||
self.add_error('default_password',
|
||||
f"Default password must not be contained in {field.replace('_', ' ')}.")
|
||||
_("Default password must not be contained in any message template. Found at: ") + f"{field.replace('_', ' ')}.")
|
||||
|
||||
# Validate that all message templates include the placeholder '{invite_url}'
|
||||
for field in message_fields:
|
||||
if field != 'invite_email_subject':
|
||||
content = cleaned_data.get(field, '')
|
||||
if '{invite_url}' not in content:
|
||||
self.add_error(field, "The template must include the placeholder '{invite_url}'.")
|
||||
self.add_error(field, _("The template must include the placeholder '{invite_url}'."))
|
||||
|
||||
return cleaned_data
|
||||
|
||||
@@ -273,12 +278,12 @@ class EmailSettingsForm(forms.ModelForm):
|
||||
super(EmailSettingsForm, self).__init__(*args, **kwargs)
|
||||
|
||||
# Set custom labels for form fields
|
||||
self.fields['smtp_username'].label = 'Username'
|
||||
self.fields['smtp_password'].label = 'Password'
|
||||
self.fields['smtp_host'].label = 'Host'
|
||||
self.fields['smtp_port'].label = 'Port'
|
||||
self.fields['smtp_encryption'].label = 'Encryption'
|
||||
self.fields['smtp_from_address'].label = 'From Address'
|
||||
self.fields['smtp_username'].label = _('Username')
|
||||
self.fields['smtp_password'].label = _('Password')
|
||||
self.fields['smtp_host'].label = _('Host')
|
||||
self.fields['smtp_port'].label = _('Port')
|
||||
self.fields['smtp_encryption'].label = _('Encryption')
|
||||
self.fields['smtp_from_address'].label = _('From Address')
|
||||
|
||||
self.fields['smtp_password'].required = True
|
||||
self.fields['smtp_host'].required = True
|
||||
@@ -286,6 +291,7 @@ class EmailSettingsForm(forms.ModelForm):
|
||||
self.fields['smtp_encryption'].required = True
|
||||
self.fields['smtp_from_address'].required = True
|
||||
self.fields['smtp_username'].required = True
|
||||
self.fields['enabled'].label = _('Enabled')
|
||||
|
||||
# Use PasswordInput widget to hide the password
|
||||
self.fields['smtp_password'].widget = forms.PasswordInput(render_value=False)
|
||||
@@ -316,8 +322,8 @@ class EmailSettingsForm(forms.ModelForm):
|
||||
),
|
||||
Row(
|
||||
Column(
|
||||
Submit('submit', 'Save', css_class='btn btn-success'),
|
||||
HTML(' <a class="btn btn-secondary" href="/vpn_invite/">Back</a> '),
|
||||
Submit('submit', _('Save'), css_class='btn btn-success'),
|
||||
HTML(' <a class="btn btn-secondary" href="/vpn_invite/">' + _('Back') + '</a> '),
|
||||
css_class='col-md-12'
|
||||
),
|
||||
css_class='form-row'
|
||||
@@ -328,7 +334,7 @@ class EmailSettingsForm(forms.ModelForm):
|
||||
cleaned_data = super().clean()
|
||||
smtp_port = cleaned_data.get('smtp_port')
|
||||
if smtp_port is not None and smtp_port <= 0:
|
||||
self.add_error('smtp_port', "SMTP port must be a positive integer.")
|
||||
self.add_error('smtp_port', _("SMTP port must be between 1 and 65535."))
|
||||
|
||||
return cleaned_data
|
||||
|
||||
|
@@ -1,37 +1,34 @@
|
||||
import uuid
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from wireguard.models import Peer
|
||||
|
||||
DEFAULT_INVITE_MESSAGE = '''
|
||||
Hello,
|
||||
DEFAULT_INVITE_MESSAGE = _('''Hello,
|
||||
|
||||
You're invited to join our secure WireGuard VPN network. Please click the link below to access your personalized VPN configuration:
|
||||
|
||||
{invite_url}
|
||||
|
||||
Note: This invitation link will expire in {expire_minutes} minutes. If you need a new link after expiration, please request another invite.
|
||||
'''
|
||||
Note: This invitation link will expire in {expire_minutes} minutes. If you need a new link after expiration, please request another invite.''')
|
||||
|
||||
DEFAULT_HTML_MESSAGE = '''
|
||||
<h2>Welcome to Your VPN Setup</h2>
|
||||
DEFAULT_HTML_MESSAGE = _('''<h2>Welcome to Your VPN Setup</h2>
|
||||
<p>Begin by downloading the WireGuard app for your device using one of the links below.</p>
|
||||
<p>Once installed, you can either <strong>scan the QR code</strong> or <strong>download the configuration file</strong> to quickly import your settings and start using your secure VPN connection.</p>
|
||||
'''
|
||||
<p>Once installed, you can either <strong>scan the QR code</strong> or <strong>download the configuration file</strong> to quickly import your settings and start using your secure VPN connection.</p>''')
|
||||
|
||||
class InviteSettings(models.Model):
|
||||
name = models.CharField(max_length=16, default='default_settings', unique=True)
|
||||
default_password = models.CharField(max_length=32, default='', blank=True, null=True)
|
||||
enforce_random_password = models.BooleanField(default=True)
|
||||
required_user_level = models.PositiveIntegerField(default=50, choices=(
|
||||
(20, 'View Only User'), (30, 'Peer Manager'), (40, 'Wireguard Manager'), (50, 'Administrator'),
|
||||
(20, _('View Only')), (30, _('Peer Manager')), (40, _('WireGuard Manager')), (50, _('Administrator')),
|
||||
))
|
||||
random_password_length = models.IntegerField(default=6)
|
||||
random_password_complexity = models.CharField(
|
||||
max_length=22, default='letters_digits', choices=(
|
||||
('letters_digits_special', 'Letters, Digits, Special Characters'),
|
||||
('letters_digits', 'Letters, Digits'), ('letters', 'Letters'), ('digits', 'Digits')
|
||||
('letters_digits_special', _('Letters, Digits, Special Characters')),
|
||||
('letters_digits', _('Letters, Digits')), ('letters', _('Letters')), ('digits', _('Digits'))
|
||||
)
|
||||
)
|
||||
invite_expiration = models.IntegerField(default=30) # minutes
|
||||
@@ -55,13 +52,13 @@ class InviteSettings(models.Model):
|
||||
download_3_enabled = models.BooleanField(default=True)
|
||||
download_4_enabled = models.BooleanField(default=True)
|
||||
download_5_enabled = models.BooleanField(default=True)
|
||||
download_instructions = models.TextField(default='Download the WireGuard app for your device using one of the links below. After installation, you can scan the QR code or download the configuration file to import on your device.')
|
||||
download_instructions = models.TextField(default=_('Download the WireGuard app for your device using one of the links below. After installation, you can scan the QR code or download the configuration file to import on your device.'))
|
||||
|
||||
invite_url = models.URLField(default='')
|
||||
|
||||
invite_text_body = models.TextField(default=DEFAULT_INVITE_MESSAGE)
|
||||
|
||||
invite_email_subject = models.CharField(max_length=64, default='WireGuard VPN Invite', blank=True, null=True)
|
||||
invite_email_subject = models.CharField(max_length=64, default=_('WireGuard VPN Invite'), blank=True, null=True)
|
||||
invite_email_body = models.TextField(default=DEFAULT_INVITE_MESSAGE)
|
||||
invite_email_enabled = models.BooleanField(default=True)
|
||||
|
||||
|
@@ -1,12 +1,14 @@
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.shortcuts import render, redirect
|
||||
from user_manager.models import UserAcl
|
||||
from .models import InviteSettings, PeerInvite
|
||||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
from .forms import InviteSettingsForm, EmailSettingsForm
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.shortcuts import redirect, render
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from user_manager.models import UserAcl
|
||||
from wireguard_tools.models import EmailSettings
|
||||
from .forms import EmailSettingsForm, InviteSettingsForm
|
||||
from .models import InviteSettings, PeerInvite
|
||||
|
||||
|
||||
@login_required
|
||||
@@ -22,7 +24,7 @@ def view_vpn_invite_list(request):
|
||||
except:
|
||||
default_invite_url = 'https://wireguard-webadmin.example.com/invite/'
|
||||
|
||||
invite_settings, _ = InviteSettings.objects.get_or_create(
|
||||
invite_settings, invite_settings_created = InviteSettings.objects.get_or_create(
|
||||
name='default_settings', defaults={'invite_url': default_invite_url,}
|
||||
)
|
||||
|
||||
@@ -32,7 +34,7 @@ def view_vpn_invite_list(request):
|
||||
peer_invite_list = PeerInvite.objects.all().order_by('invite_expiration')
|
||||
peer_invite_list.filter(invite_expiration__lt=timezone.now()).delete()
|
||||
data = {
|
||||
'page_title': 'VPN Invite',
|
||||
'page_title': _('VPN Invite'),
|
||||
'peer_invite_list': peer_invite_list,
|
||||
}
|
||||
|
||||
@@ -48,11 +50,11 @@ def view_vpn_invite_settings(request):
|
||||
form = InviteSettingsForm(request.POST or None, instance=invite_settings)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(request, 'Invite Settings|Settings saved successfully.')
|
||||
messages.success(request, _('Invite Settings|Settings saved successfully.'))
|
||||
return redirect('/vpn_invite/')
|
||||
data = {
|
||||
'invite_settings': invite_settings,
|
||||
'page_title': 'VPN Invite Settings',
|
||||
'page_title': _('VPN Invite Settings'),
|
||||
'form': form,
|
||||
'form_size': 'col-lg-12'
|
||||
}
|
||||
@@ -63,16 +65,16 @@ def view_vpn_invite_settings(request):
|
||||
def view_email_settings(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'})
|
||||
email_settings, _ = EmailSettings.objects.get_or_create(name='email_settings')
|
||||
email_settings, email_settings_created = EmailSettings.objects.get_or_create(name='email_settings')
|
||||
|
||||
form = EmailSettingsForm(request.POST or None, instance=email_settings)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(request, 'Email Settings|Settings saved successfully.')
|
||||
messages.success(request, _('Email Settings|Settings saved successfully.'))
|
||||
return redirect('/vpn_invite/')
|
||||
data = {
|
||||
'email_settings': email_settings,
|
||||
'page_title': 'Email Settings',
|
||||
'page_title': _('Email Settings'),
|
||||
'form': form,
|
||||
'form_size': 'col-lg-12'
|
||||
}
|
||||
|
Reference in New Issue
Block a user