diff --git a/gatekeeper/forms.py b/gatekeeper/forms.py index d5fa3b1..d80c950 100644 --- a/gatekeeper/forms.py +++ b/gatekeeper/forms.py @@ -39,7 +39,7 @@ class GatekeeperUserForm(forms.ModelForm): 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='col-md-12' ), css_class='row' ) @@ -73,7 +73,7 @@ class GatekeeperGroupForm(forms.ModelForm): 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='col-md-12' ), css_class='row' ) @@ -135,7 +135,7 @@ class AuthMethodForm(forms.ModelForm): 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='col-md-12' ), css_class='row' ) @@ -192,7 +192,7 @@ class GatekeeperIPAddressForm(forms.ModelForm): fields = ['auth_method', 'address', 'prefix_length', 'action', 'description'] labels = { 'auth_method': _('Authentication Method'), - 'address': _('IP/Network Address'), + 'address': _('IP Address'), 'prefix_length': _('Prefix Length'), 'action': _('Action'), 'description': _('Description'), @@ -209,20 +209,20 @@ class GatekeeperIPAddressForm(forms.ModelForm): css_class='row' ), Div( - Div('address', css_class='col-md-8'), - Div('prefix_length', css_class='col-md-4'), + Div('address', css_class='col-xl-6'), + Div('prefix_length', css_class='col-xl-6'), css_class='row' ), Div( - Div('action', css_class='col-md-4'), - Div('description', css_class='col-md-8'), + Div('action', css_class='col-xl-4'), + Div('description', css_class='col-xl-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='col-md-12' ), css_class='row' ) @@ -252,7 +252,7 @@ class AuthMethodAllowedDomainForm(forms.ModelForm): 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='col-md-12' ), css_class='row' ) @@ -283,7 +283,7 @@ class AuthMethodAllowedEmailForm(forms.ModelForm): 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='col-md-12' ), css_class='row' ) diff --git a/gatekeeper/migrations/0003_alter_authmethodalloweddomain_auth_method_and_more.py b/gatekeeper/migrations/0003_alter_authmethodalloweddomain_auth_method_and_more.py new file mode 100644 index 0000000..1ec45ea --- /dev/null +++ b/gatekeeper/migrations/0003_alter_authmethodalloweddomain_auth_method_and_more.py @@ -0,0 +1,24 @@ +# Generated by Django 5.2.12 on 2026-03-12 17:50 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('gatekeeper', '0002_alter_authmethod_auth_type_gatekeeperipaddress'), + ] + + operations = [ + migrations.AlterField( + model_name='authmethodalloweddomain', + name='auth_method', + field=models.ForeignKey(limit_choices_to={'auth_type': 'oidc'}, on_delete=django.db.models.deletion.CASCADE, related_name='allowed_domains', to='gatekeeper.authmethod'), + ), + migrations.AlterField( + model_name='authmethodallowedemail', + name='auth_method', + field=models.ForeignKey(limit_choices_to={'auth_type': 'oidc'}, on_delete=django.db.models.deletion.CASCADE, related_name='allowed_emails', to='gatekeeper.authmethod'), + ), + ] diff --git a/gatekeeper/models.py b/gatekeeper/models.py index c31c760..bd791e5 100644 --- a/gatekeeper/models.py +++ b/gatekeeper/models.py @@ -33,7 +33,7 @@ class AuthMethod(models.Model): class AuthMethodAllowedDomain(models.Model): - auth_method = models.ForeignKey(AuthMethod, on_delete=models.CASCADE, related_name='allowed_domains') + auth_method = models.ForeignKey(AuthMethod, on_delete=models.CASCADE, related_name='allowed_domains', limit_choices_to={'auth_type': 'oidc'}) domain = models.CharField(max_length=255) created = models.DateTimeField(auto_now_add=True) @@ -48,7 +48,7 @@ class AuthMethodAllowedDomain(models.Model): class AuthMethodAllowedEmail(models.Model): - auth_method = models.ForeignKey(AuthMethod, on_delete=models.CASCADE, related_name='allowed_emails') + auth_method = models.ForeignKey(AuthMethod, on_delete=models.CASCADE, related_name='allowed_emails', limit_choices_to={'auth_type': 'oidc'}) email = models.EmailField() created = models.DateTimeField(auto_now_add=True) @@ -104,10 +104,7 @@ class GatekeeperIPAddress(models.Model): limit_choices_to={'auth_type': 'ip_address'} ) address = models.GenericIPAddressField() - prefix_length = models.PositiveSmallIntegerField( - null=True, blank=True, - help_text=_("CIDR prefix length (e.g.: 24 for /24). Leave blank for a single host.") - ) + prefix_length = models.PositiveSmallIntegerField(null=True, blank=True) action = models.CharField(max_length=8, choices=(('allow', _('Allow')), ('deny', _('Deny'))), default='allow') description = models.CharField(max_length=255, blank=True) diff --git a/gatekeeper/views.py b/gatekeeper/views.py index f85f539..f0e7852 100644 --- a/gatekeeper/views.py +++ b/gatekeeper/views.py @@ -48,25 +48,22 @@ def view_manage_gatekeeper_user(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') + gatekeeper_user_uuid = request.GET.get('uuid') - if obj_uuid: - obj = get_object_or_404(GatekeeperUser, uuid=obj_uuid) + if gatekeeper_user_uuid: + gatekeeper_user = get_object_or_404(GatekeeperUser, uuid=gatekeeper_user_uuid) title = _('Edit Gatekeeper User') else: - obj = None + gatekeeper_user = None title = _('Create Gatekeeper User') cancel_url = reverse('gatekeeper_list') + '?tab=users' - if request.method == 'POST': - form = GatekeeperUserForm(request.POST, instance=obj, cancel_url=cancel_url) - if form.is_valid(): - form.save() - messages.success(request, _('Gatekeeper User saved successfully.')) - return redirect(cancel_url) - else: - form = GatekeeperUserForm(instance=obj, cancel_url=cancel_url) + form = GatekeeperUserForm(request.POST or None, instance=gatekeeper_user, cancel_url=cancel_url) + if form.is_valid(): + form.save() + messages.success(request, _('Gatekeeper User saved successfully.')) + return redirect(cancel_url) context = { 'form': form, @@ -81,21 +78,20 @@ def view_delete_gatekeeper_user(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(GatekeeperUser, uuid=obj_uuid) + gatekeeper_user = get_object_or_404(GatekeeperUser, uuid=request.GET.get('uuid')) cancel_url = reverse('gatekeeper_list') + '?tab=users' if request.method == 'POST': - obj.delete() + gatekeeper_user.delete() messages.success(request, _('Gatekeeper User deleted successfully.')) return redirect(cancel_url) context = { - 'object': obj, + 'gatekeeper_user': gatekeeper_user, 'title': _('Delete Gatekeeper User'), 'cancel_url': cancel_url, - 'text': _('Are you sure you want to delete the user "%(username)s"?') % {'username': obj.username} + 'text': _('Are you sure you want to delete the user "%(username)s"?') % {'username': gatekeeper_user.username} } return render(request, 'generic_delete_confirmation.html', context) @@ -105,25 +101,22 @@ def view_manage_gatekeeper_group(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') + gatekeeper_group_uuid = request.GET.get('uuid') - if obj_uuid: - obj = get_object_or_404(GatekeeperGroup, uuid=obj_uuid) + if gatekeeper_group_uuid: + gatekeeper_group = get_object_or_404(GatekeeperGroup, uuid=gatekeeper_group_uuid) title = _('Edit Gatekeeper Group') else: - obj = None + gatekeeper_group = None title = _('Create Gatekeeper Group') cancel_url = reverse('gatekeeper_list') + '?tab=groups' - if request.method == 'POST': - form = GatekeeperGroupForm(request.POST, instance=obj, cancel_url=cancel_url) - if form.is_valid(): - form.save() - messages.success(request, _('Gatekeeper Group saved successfully.')) - return redirect(cancel_url) - else: - form = GatekeeperGroupForm(instance=obj, cancel_url=cancel_url) + form = GatekeeperGroupForm(request.POST or None, instance=gatekeeper_group, cancel_url=cancel_url) + if form.is_valid(): + form.save() + messages.success(request, _('Gatekeeper Group saved successfully.')) + return redirect(cancel_url) context = { 'form': form, @@ -138,21 +131,20 @@ def view_delete_gatekeeper_group(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(GatekeeperGroup, uuid=obj_uuid) + gatekeeper_group = get_object_or_404(GatekeeperGroup, uuid=request.GET.get('uuid')) cancel_url = reverse('gatekeeper_list') + '?tab=groups' if request.method == 'POST': - obj.delete() + gatekeeper_group.delete() messages.success(request, _('Gatekeeper Group deleted successfully.')) return redirect(cancel_url) context = { - 'object': obj, + 'gatekeeper_group': gatekeeper_group, 'title': _('Delete Gatekeeper Group'), 'cancel_url': cancel_url, - 'text': _('Are you sure you want to delete the group "%(name)s"?') % {'name': obj.name} + 'text': _('Are you sure you want to delete the group "%(name)s"?') % {'name': gatekeeper_group.name} } return render(request, 'generic_delete_confirmation.html', context) @@ -162,25 +154,22 @@ def view_manage_auth_method(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') + auth_method_uuid = request.GET.get('uuid') - if obj_uuid: - obj = get_object_or_404(AuthMethod, uuid=obj_uuid) + if auth_method_uuid: + auth_method = get_object_or_404(AuthMethod, uuid=auth_method_uuid) title = _('Edit Authentication Method') else: - obj = None + auth_method = None title = _('Create Authentication Method') cancel_url = reverse('gatekeeper_list') + '?tab=auth_methods' - if request.method == 'POST': - form = AuthMethodForm(request.POST, instance=obj, cancel_url=cancel_url) - if form.is_valid(): - form.save() - messages.success(request, _('Authentication Method saved successfully.')) - return redirect(cancel_url) - else: - form = AuthMethodForm(instance=obj, cancel_url=cancel_url) + form = AuthMethodForm(request.POST or None, instance=auth_method, cancel_url=cancel_url) + if form.is_valid(): + form.save() + messages.success(request, _('Authentication Method saved successfully.')) + return redirect(cancel_url) form_description = { 'size': '', @@ -209,21 +198,20 @@ def view_delete_auth_method(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(AuthMethod, uuid=obj_uuid) + auth_method = get_object_or_404(AuthMethod, uuid=request.GET.get('uuid')) cancel_url = reverse('gatekeeper_list') + '?tab=auth_methods' if request.method == 'POST': - obj.delete() + auth_method.delete() messages.success(request, _('Authentication Method deleted successfully.')) return redirect(cancel_url) context = { - 'object': obj, + 'auth_method': auth_method, 'title': _('Delete Authentication Method'), 'cancel_url': cancel_url, - 'text': _('Are you sure you want to delete the authentication method "%(name)s"?') % {'name': obj.name} + 'text': _('Are you sure you want to delete the authentication method "%(name)s"?') % {'name': auth_method.name} } return render(request, 'generic_delete_confirmation.html', context) @@ -269,25 +257,22 @@ def view_manage_auth_domain(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') + auth_domain_uuid = request.GET.get('uuid') - if obj_uuid: - obj = get_object_or_404(AuthMethodAllowedDomain, uuid=obj_uuid) + if auth_domain_uuid: + auth_domain = get_object_or_404(AuthMethodAllowedDomain, uuid=auth_domain_uuid) title = _('Edit Allowed Domain') else: - obj = None + auth_domain = None title = _('Add Allowed Domain') cancel_url = reverse('gatekeeper_list') + '?tab=allowed_identities' - if request.method == 'POST': - form = AuthMethodAllowedDomainForm(request.POST, instance=obj, cancel_url=cancel_url) - if form.is_valid(): - form.save() - messages.success(request, _('Allowed Domain saved successfully.')) - return redirect(cancel_url) - else: - form = AuthMethodAllowedDomainForm(instance=obj, cancel_url=cancel_url) + form = AuthMethodAllowedDomainForm(request.POST or None, instance=auth_domain, cancel_url=cancel_url) + if form.is_valid(): + form.save() + messages.success(request, _('Allowed Domain saved successfully.')) + return redirect(cancel_url) context = { 'form': form, @@ -302,21 +287,20 @@ def view_delete_auth_domain(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(AuthMethodAllowedDomain, uuid=obj_uuid) + auth_domain = get_object_or_404(AuthMethodAllowedDomain, uuid=request.GET.get('uuid')) cancel_url = reverse('gatekeeper_list') + '?tab=allowed_identities' if request.method == 'POST': - obj.delete() + auth_domain.delete() messages.success(request, _('Allowed Domain deleted successfully.')) return redirect(cancel_url) context = { - 'object': obj, + 'auth_domain': auth_domain, 'title': _('Delete Allowed Domain'), 'cancel_url': cancel_url, - 'text': _('Are you sure you want to delete the allowed domain "%(domain)s"?') % {'domain': obj.domain} + 'text': _('Are you sure you want to delete the allowed domain "%(domain)s"?') % {'domain': auth_domain.domain} } return render(request, 'generic_delete_confirmation.html', context) @@ -326,25 +310,22 @@ def view_manage_auth_email(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') + auth_email_uuid = request.GET.get('uuid') - if obj_uuid: - obj = get_object_or_404(AuthMethodAllowedEmail, uuid=obj_uuid) + if auth_email_uuid: + auth_email = get_object_or_404(AuthMethodAllowedEmail, uuid=auth_email_uuid) title = _('Edit Allowed Email') else: - obj = None + auth_email = None title = _('Add Allowed Email') cancel_url = reverse('gatekeeper_list') + '?tab=allowed_identities' - if request.method == 'POST': - form = AuthMethodAllowedEmailForm(request.POST, instance=obj, cancel_url=cancel_url) - if form.is_valid(): - form.save() - messages.success(request, _('Allowed Email saved successfully.')) - return redirect(cancel_url) - else: - form = AuthMethodAllowedEmailForm(instance=obj, cancel_url=cancel_url) + form = AuthMethodAllowedEmailForm(request.POST or None, instance=auth_email, cancel_url=cancel_url) + if form.is_valid(): + form.save() + messages.success(request, _('Allowed Email saved successfully.')) + return redirect(cancel_url) context = { 'form': form, @@ -359,21 +340,20 @@ def view_delete_auth_email(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(AuthMethodAllowedEmail, uuid=obj_uuid) + auth_email = get_object_or_404(AuthMethodAllowedEmail, uuid=request.GET.get('uuid')) cancel_url = reverse('gatekeeper_list') + '?tab=allowed_identities' if request.method == 'POST': - obj.delete() + auth_email.delete() messages.success(request, _('Allowed Email deleted successfully.')) return redirect(cancel_url) context = { - 'object': obj, + 'auth_email': auth_email, 'title': _('Delete Allowed Email'), 'cancel_url': cancel_url, - 'text': _('Are you sure you want to delete the allowed email "%(email)s"?') % {'email': obj.email} + 'text': _('Are you sure you want to delete the allowed email "%(email)s"?') % {'email': auth_email.email} } return render(request, 'generic_delete_confirmation.html', context) @@ -383,25 +363,22 @@ 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') + gatekeeper_ip_uuid = request.GET.get('uuid') - if obj_uuid: - obj = get_object_or_404(GatekeeperIPAddress, uuid=obj_uuid) + if gatekeeper_ip_uuid: + gatekeeper_ip = get_object_or_404(GatekeeperIPAddress, uuid=gatekeeper_ip_uuid) title = _('Edit IP Address') else: - obj = None + gatekeeper_ip = 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) + form = GatekeeperIPAddressForm(request.POST or None, instance=gatekeeper_ip, cancel_url=cancel_url) + if form.is_valid(): + form.save() + messages.success(request, _('IP Address saved successfully.')) + return redirect(cancel_url) context = { 'form': form, @@ -416,20 +393,19 @@ 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) + gatekeeper_ip = get_object_or_404(GatekeeperIPAddress, uuid=request.GET.get('uuid')) cancel_url = reverse('gatekeeper_list') + '?tab=ip_addresses' if request.method == 'POST': - obj.delete() + gatekeeper_ip.delete() messages.success(request, _('IP Address deleted successfully.')) return redirect(cancel_url) context = { - 'object': obj, + 'gatekeeper_ip': gatekeeper_ip, 'title': _('Delete IP Address'), 'cancel_url': cancel_url, - 'text': _('Are you sure you want to delete the IP address "%(address)s"?') % {'address': obj.address} + 'text': _('Are you sure you want to delete the IP address "%(address)s"?') % {'address': gatekeeper_ip.address} } return render(request, 'generic_delete_confirmation.html', context)