diff --git a/gatekeeper/forms.py b/gatekeeper/forms.py index 953d4eb..19b1383 100644 --- a/gatekeeper/forms.py +++ b/gatekeeper/forms.py @@ -5,7 +5,7 @@ from django import forms from django.utils.translation import gettext_lazy as _ from gatekeeper.models import GatekeeperUser, GatekeeperGroup, AuthMethod, AuthMethodAllowedDomain, \ - AuthMethodAllowedEmail + AuthMethodAllowedEmail, GatekeeperIPAddress class GatekeeperUserForm(forms.ModelForm): @@ -186,6 +186,48 @@ class AuthMethodForm(forms.ModelForm): return cleaned_data +class GatekeeperIPAddressForm(forms.ModelForm): + class Meta: + model = GatekeeperIPAddress + fields = ['auth_method', 'address', 'prefix_length', 'action', 'description'] + labels = { + 'auth_method': _('Authentication Method'), + 'address': _('IP/Network Address'), + 'prefix_length': _('Prefix Length'), + 'action': _('Action'), + 'description': _('Description'), + } + + def __init__(self, *args, **kwargs): + cancel_url = kwargs.pop('cancel_url', '#') + super().__init__(*args, **kwargs) + + self.helper = FormHelper() + self.helper.layout = Layout( + Div( + Div('auth_method', css_class='col-md-12'), + css_class='row' + ), + Div( + Div('address', css_class='col-md-8'), + Div('prefix_length', css_class='col-md-4'), + css_class='row' + ), + Div( + Div('action', css_class='col-md-4'), + Div('description', css_class='col-md-8'), + css_class='row' + ), + Div( + Div( + Submit('submit', _('Save'), css_class='btn btn-primary'), + HTML(f'{_("Cancel")}'), + css_class='col-12 d-flex justify-content-end gap-2 mt-3' + ), + css_class='row' + ) + ) + class AuthMethodAllowedDomainForm(forms.ModelForm): class Meta: model = AuthMethodAllowedDomain diff --git a/gatekeeper/urls.py b/gatekeeper/urls.py index 61c66fb..3ad1dbc 100644 --- a/gatekeeper/urls.py +++ b/gatekeeper/urls.py @@ -25,4 +25,8 @@ urlpatterns = [ # Auth Method Allowed Emails path('email/manage/', views.view_manage_auth_email, name='manage_gatekeeper_email'), path('email/delete/', views.view_delete_auth_email, name='delete_gatekeeper_email'), + + # Gatekeeper IP Addresses + path('ip/manage/', views.view_manage_gatekeeper_ip, name='manage_gatekeeper_ip'), + path('ip/delete/', views.view_delete_gatekeeper_ip, name='delete_gatekeeper_ip'), ] diff --git a/gatekeeper/views.py b/gatekeeper/views.py index 43b010a..0a174e0 100644 --- a/gatekeeper/views.py +++ b/gatekeeper/views.py @@ -5,9 +5,9 @@ from django.urls import reverse from django.utils.translation import gettext as _ from gatekeeper.forms import GatekeeperUserForm, GatekeeperGroupForm, AuthMethodForm, AuthMethodAllowedDomainForm, \ - AuthMethodAllowedEmailForm + AuthMethodAllowedEmailForm, GatekeeperIPAddressForm from gatekeeper.models import GatekeeperUser, GatekeeperGroup, AuthMethod, AuthMethodAllowedDomain, \ - AuthMethodAllowedEmail + AuthMethodAllowedEmail, GatekeeperIPAddress from user_manager.models import UserAcl @@ -22,6 +22,7 @@ def view_gatekeeper_list(request): auth_methods = AuthMethod.objects.all().order_by('name') auth_domains = AuthMethodAllowedDomain.objects.all().order_by('domain') auth_emails = AuthMethodAllowedEmail.objects.all().order_by('email') + auth_ips = GatekeeperIPAddress.objects.all().order_by('address') tab = request.GET.get('tab', 'users') @@ -31,6 +32,7 @@ def view_gatekeeper_list(request): 'auth_methods': auth_methods, 'auth_domains': auth_domains, 'auth_emails': auth_emails, + 'auth_ips': auth_ips, 'active_tab': tab, } return render(request, 'gatekeeper/gatekeeper_list.html', context) @@ -333,3 +335,60 @@ def view_delete_auth_email(request): 'text': _('Are you sure you want to delete the allowed email "%(email)s"?') % {'email': obj.email} } return render(request, 'generic_delete_confirmation.html', context) + + +@login_required +def view_manage_gatekeeper_ip(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')}) + + obj_uuid = request.GET.get('uuid') + + if obj_uuid: + obj = get_object_or_404(GatekeeperIPAddress, uuid=obj_uuid) + title = _('Edit IP Address') + else: + obj = None + title = _('Add IP Address') + + cancel_url = reverse('gatekeeper_list') + '?tab=ip_addresses' + + if request.method == 'POST': + form = GatekeeperIPAddressForm(request.POST, instance=obj, cancel_url=cancel_url) + if form.is_valid(): + form.save() + messages.success(request, _('IP Address saved successfully.')) + return redirect(cancel_url) + else: + form = GatekeeperIPAddressForm(instance=obj, cancel_url=cancel_url) + + context = { + 'form': form, + 'title': title, + 'page_title': title, + } + return render(request, 'generic_form.html', context) + + +@login_required +def view_delete_gatekeeper_ip(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')}) + + obj_uuid = request.GET.get('uuid') + obj = get_object_or_404(GatekeeperIPAddress, uuid=obj_uuid) + + cancel_url = reverse('gatekeeper_list') + '?tab=ip_addresses' + + if request.method == 'POST': + obj.delete() + messages.success(request, _('IP Address deleted successfully.')) + return redirect(cancel_url) + + context = { + 'object': obj, + 'title': _('Delete IP Address'), + 'cancel_url': cancel_url, + 'text': _('Are you sure you want to delete the IP address "%(address)s"?') % {'address': obj.address} + } + return render(request, 'generic_delete_confirmation.html', context) diff --git a/templates/gatekeeper/gatekeeper_list.html b/templates/gatekeeper/gatekeeper_list.html index 3aedde1..47de553 100644 --- a/templates/gatekeeper/gatekeeper_list.html +++ b/templates/gatekeeper/gatekeeper_list.html @@ -24,6 +24,12 @@ {% trans 'Allowed Emails & Domains' %} +
| {% trans 'IP Address' %} | +{% trans 'Prefix Length' %} | +{% trans 'Action' %} | +{% trans 'Auth Method' %} | +{% trans 'Manage' %} | +
|---|---|---|---|---|
| {{ ip.address }} | +{% if ip.prefix_length %}/{{ ip.prefix_length }}{% endif %} | ++ {% if ip.action == 'allow' %} + {% trans 'Allow' %} + {% else %} + {% trans 'Deny' %} + {% endif %} + | +{{ ip.auth_method.name }} | ++ + + + + + + | +