diff --git a/scheduler/models.py b/scheduler/models.py index d03c9cf..ec6baec 100644 --- a/scheduler/models.py +++ b/scheduler/models.py @@ -22,6 +22,9 @@ class ScheduleProfile(models.Model): updated = models.DateTimeField(auto_now=True) uuid = models.UUIDField(editable=False, default=uuid.uuid4) + def __str__(self): + return self.name + class ScheduleSlot(models.Model): profile = models.ForeignKey(ScheduleProfile, on_delete=models.CASCADE, related_name="time_interval") diff --git a/templates/wireguard/wireguard_manage_peer.html b/templates/wireguard/wireguard_manage_peer.html index 57eef2e..eae3fdd 100644 --- a/templates/wireguard/wireguard_manage_peer.html +++ b/templates/wireguard/wireguard_manage_peer.html @@ -22,6 +22,62 @@ + +
+ +
+
+ {% if current_peer.suspended %} + {% trans 'Suspended' %} + {% if current_peer.suspend_reason %} + {{ current_peer.suspend_reason }} + {% endif %} + {% else %} + {% trans 'Active' %} + {% endif %} + + {% if peer_scheduling.next_manual_suspend_at %} + {% trans 'Scheduled suspend' %}: {{ peer_scheduling.next_manual_suspend_at|date:"Y-m-d H:i" }} + {% endif %} + {% if peer_scheduling.next_manual_unsuspend_at %} + {% trans 'Scheduled unsuspend' %}: {{ peer_scheduling.next_manual_unsuspend_at|date:"Y-m-d H:i" }} + {% endif %} +
+ + + +
+
+ + +
+ +
+
+ {% if peer_scheduling.profile %} + {{ peer_scheduling.profile.name }} + {% if current_peer.disabled_by_schedule %} + {% trans 'Disabled by schedule' %} + {% if peer_scheduling.next_scheduled_enable_at %} + {% trans 'Next enable' %}: {{ peer_scheduling.next_scheduled_enable_at|date:"Y-m-d H:i" }} + {% endif %} + {% else %} + {% trans 'Enabled by schedule' %} + {% if peer_scheduling.next_scheduled_disable_at %} + {% trans 'Next disable' %}: {{ peer_scheduling.next_scheduled_disable_at|date:"Y-m-d H:i" }} + {% endif %} + {% endif %} + {% else %} + {% trans 'No profile associated' %} + {% endif %} +
+ + + +
+
+
diff --git a/wireguard_peer/forms.py b/wireguard_peer/forms.py index b17a4e6..fe9deda 100644 --- a/wireguard_peer/forms.py +++ b/wireguard_peer/forms.py @@ -188,3 +188,34 @@ class PeerSuspensionForm(forms.ModelForm): raise forms.ValidationError(_('Scheduled unsuspension time must be at least 10 minutes in the future.')) return cleaned_data + + +class PeerScheduleProfileForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + self.peer = kwargs.pop('peer', None) + super().__init__(*args, **kwargs) + self.helper = FormHelper() + self.helper.form_method = 'post' + + self.helper.layout = Layout( + Row(Div(Field('profile'), css_class='col-md-12')), + Row( + Div( + FormActions( + Submit('save', _('Save'), css_class='btn-primary'), + HTML( + '{}'.format( + reverse_lazy('wireguard_peer_manage'), + self.peer.uuid, + _("Back") + ) + ), + ), + css_class='col-md-12' + ) + ) + ) + + class Meta: + model = PeerScheduling + fields = ['profile'] diff --git a/wireguard_peer/views.py b/wireguard_peer/views.py index 292756c..1feef1d 100644 --- a/wireguard_peer/views.py +++ b/wireguard_peer/views.py @@ -16,7 +16,8 @@ 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 from wireguard.models import Peer, PeerAllowedIP, WireGuardInstance -from wireguard_peer.forms import PeerAllowedIPForm, PeerNameForm, PeerKeepaliveForm, PeerKeysForm, PeerSuspensionForm +from wireguard_peer.forms import PeerAllowedIPForm, PeerNameForm, PeerKeepaliveForm, PeerKeysForm, PeerSuspensionForm, \ + PeerScheduleProfileForm def generate_peer_default(wireguard_instance): @@ -231,10 +232,17 @@ def view_wireguard_peer_manage(request): page_title = _('Peer Configuration: ') + str(current_peer) peer_ip_list = current_peer.peerallowedip_set.filter(config_file='server').order_by('priority') peer_client_ip_list = current_peer.peerallowedip_set.filter(config_file='client').order_by('priority') + + # Try to get peer scheduling, if it doesn't exist, it will be None + try: + peer_scheduling = current_peer.schedule + except PeerScheduling.DoesNotExist: + peer_scheduling = None context = { 'page_title': page_title, 'current_instance': current_instance, 'current_peer': current_peer, - 'peer_ip_list': peer_ip_list, 'peer_client_ip_list': peer_client_ip_list + 'peer_ip_list': peer_ip_list, 'peer_client_ip_list': peer_client_ip_list, + 'peer_scheduling': peer_scheduling } return render(request, 'wireguard/wireguard_manage_peer.html', context) @@ -457,3 +465,32 @@ def view_wireguard_peer_suspend(request): 'form': form, } return render(request, 'generic_form.html', context) + + +@login_required +def view_wireguard_peer_schedule_profile(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 + + peer_scheduling, created = PeerScheduling.objects.get_or_create(peer=current_peer) + form = PeerScheduleProfileForm(request.POST or None, instance=peer_scheduling, peer=current_peer) + + if form.is_valid(): + form.save() + messages.success(request, _('Peer scheduling profile updated successfully.')) + current_peer.wireguard_instance.pending_changes = True + current_peer.wireguard_instance.save() + return redirect('/peer/manage/?peer=' + str(current_peer.uuid)) + + context = { + 'page_title': _('Manage Peer Schedule Profile'), + 'current_peer': current_peer, + 'form': form, + } + return render(request, 'generic_form.html', context) diff --git a/wireguard_webadmin/urls.py b/wireguard_webadmin/urls.py index 22b5be6..2f2af11 100644 --- a/wireguard_webadmin/urls.py +++ b/wireguard_webadmin/urls.py @@ -42,7 +42,7 @@ from wireguard.views import view_apply_db_patches, view_wireguard_manage_instanc view_server_list, view_server_detail from wireguard_peer.views import view_manage_ip_address, view_wireguard_peer_list, view_wireguard_peer_manage, \ view_wireguard_peer_sort, view_apply_route_template, view_wireguard_peer_create, view_wireguard_peer_edit_field, \ - view_wireguard_peer_suspend + view_wireguard_peer_suspend, view_wireguard_peer_schedule_profile from wireguard_tools.views import download_config_or_qrcode, export_wireguard_configs, restart_wireguard_interfaces urlpatterns = [ @@ -62,6 +62,7 @@ urlpatterns = [ path('peer/create/', view_wireguard_peer_create, name='wireguard_peer_create'), path('peer/edit/', view_wireguard_peer_edit_field, name='wireguard_peer_edit_field'), path('peer/suspend/', view_wireguard_peer_suspend, name='wireguard_peer_suspend'), + path('peer/schedule_profile/', view_wireguard_peer_schedule_profile, name='wireguard_peer_schedule_profile'), 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'),