From a9baffe725e0549ac83051c3f09a9f7fdd67ee11 Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Fri, 13 Mar 2026 20:12:29 -0300 Subject: [PATCH] add policy type selection for access policies --- app_gateway/forms.py | 77 +++++++++++++++---- app_gateway/urls.py | 1 + app_gateway/views.py | 69 ++++++++++++++++- .../access_policy_type_select.html | 55 +++++++++++++ templates/app_gateway/app_gateway_list.html | 2 +- .../app_gateway/app_gateway_policy_form.html | 40 ---------- 6 files changed, 182 insertions(+), 62 deletions(-) create mode 100644 templates/app_gateway/access_policy_type_select.html delete mode 100644 templates/app_gateway/app_gateway_policy_form.html diff --git a/app_gateway/forms.py b/app_gateway/forms.py index 79425e2..dadc893 100644 --- a/app_gateway/forms.py +++ b/app_gateway/forms.py @@ -104,29 +104,72 @@ class AccessPolicyForm(forms.ModelForm): def __init__(self, *args, **kwargs): cancel_url = kwargs.pop('cancel_url', '#') + policy_type = kwargs.pop('policy_type', None) super().__init__(*args, **kwargs) + if self.instance and self.instance.pk: + policy_type = self.instance.policy_type + + if policy_type and not self.initial.get('policy_type'): + self.initial['policy_type'] = policy_type + + self.fields['policy_type'].widget = forms.HiddenInput() + self.helper = FormHelper() - self.helper.layout = Layout( - Div( - Div('name', css_class='col-md-6'), - Div('policy_type', css_class='col-md-6'), - css_class='row' - ), - Div( - Div('groups', css_class='col-md-6'), - Div('methods', css_class='col-md-6'), - css_class='row' - ), - Div( + + if policy_type in ['public', 'deny']: + self.helper.layout = Layout( Div( - Submit('submit', _('Save'), css_class='btn btn-primary'), - HTML(f'{_("Cancel")}'), - css_class='col-md-12' + Div('name', css_class='col-md-12'), + 'policy_type', + css_class='row' ), - css_class='row' + Div( + Div( + Submit('submit', _('Save'), css_class='btn btn-primary'), + HTML(f'{_("Cancel")}'), + css_class='col-md-12' + ), + css_class='row' + ) ) - ) + else: + self.helper.layout = Layout( + Div( + Div('name', css_class='col-md-12'), + 'policy_type', + css_class='row' + ), + Div(Div('methods', css_class='col-md-12'), css_class='row'), + Div(Div('groups', css_class='col-md-12'), css_class='row'), + Div( + Div( + Submit('submit', _('Save'), css_class='btn btn-primary'), + HTML(f'{_("Cancel")}'), + css_class='col-md-12' + ), + css_class='row' + ) + ) + + def clean(self): + cleaned_data = super().clean() + policy_type = cleaned_data.get('policy_type') + groups = cleaned_data.get('groups') + methods = cleaned_data.get('methods') + + if policy_type == 'protected': + if groups and len(groups) > 0: + has_local_password = False + if methods: + for method in methods: + if method.auth_type == 'local_password': + has_local_password = True + break + if not has_local_password: + self.add_error(None, _("User groups can only be used with local user authentication.")) + + return cleaned_data class ApplicationPolicyForm(forms.ModelForm): diff --git a/app_gateway/urls.py b/app_gateway/urls.py index fac4c35..f0311aa 100644 --- a/app_gateway/urls.py +++ b/app_gateway/urls.py @@ -16,6 +16,7 @@ urlpatterns = [ path('host/delete/', views.view_delete_application_host, name='delete_application_host'), # Access Policies + path('policy/select-type/', views.view_select_policy_type, name='select_policy_type'), path('policy/manage/', views.view_manage_access_policy, name='manage_access_policy'), path('policy/delete/', views.view_delete_access_policy, name='delete_access_policy'), diff --git a/app_gateway/views.py b/app_gateway/views.py index fe96609..7d2e614 100644 --- a/app_gateway/views.py +++ b/app_gateway/views.py @@ -1,5 +1,6 @@ from django.contrib import messages from django.contrib.auth.decorators import login_required +from django.db.models import ProtectedError from django.shortcuts import render, get_object_or_404, redirect from django.urls import reverse from django.utils.translation import gettext as _ @@ -78,10 +79,24 @@ def view_manage_application(request): messages.success(request, _('Application saved successfully.')) return redirect(cancel_url) + form_description = { + 'size': 'col-lg-6', + 'content': _(''' +
Application
+

Define the main details of the application you want to expose through the gateway.

+ + ''') + } + context = { 'form': form, 'title': title, 'page_title': title, + 'form_description': form_description, } return render(request, 'generic_form.html', context) @@ -168,34 +183,77 @@ def view_delete_application_host(request): return render(request, 'generic_delete_confirmation.html', context) +@login_required +def view_select_policy_type(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')}) + + context = { + 'page_title': _('Select Access Policy Type'), + } + return render(request, 'app_gateway/access_policy_type_select.html', context) + + @login_required def view_manage_access_policy(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')}) access_policy_uuid = request.GET.get('uuid') + policy_type = request.GET.get('policy_type') if access_policy_uuid: access_policy = get_object_or_404(AccessPolicy, uuid=access_policy_uuid) title = _('Edit Access Policy') + policy_type = access_policy.policy_type else: access_policy = None title = _('Create Access Policy') cancel_url = reverse('app_gateway_list') + '?tab=policies' - form = AccessPolicyForm(request.POST or None, instance=access_policy, cancel_url=cancel_url) + form = AccessPolicyForm(request.POST or None, instance=access_policy, cancel_url=cancel_url, policy_type=policy_type) if form.is_valid(): form.save() messages.success(request, _('Access Policy saved successfully.')) return redirect(cancel_url) + if policy_type == 'public': + form_description = { + 'size': 'col-lg-6', + 'content': _(''' +
Public Policy
+

A Public policy allows access to the application without requiring any authentication.

+ ''') + } + elif policy_type == 'deny': + form_description = { + 'size': 'col-lg-6', + 'content': _(''' +
Deny Policy
+

A Deny policy blocks all access to the matched routes.

+ ''') + } + else: + form_description = { + 'size': 'col-lg-6', + 'content': _(''' +
Protected Policy
+

A Protected policy requires users to authenticate before accessing the application.

+ + ''') + } + context = { 'form': form, 'title': title, 'page_title': title, + 'form_description': form_description, } - return render(request, 'app_gateway/app_gateway_policy_form.html', context) + return render(request, 'generic_form.html', context) @login_required @@ -208,8 +266,11 @@ def view_delete_access_policy(request): cancel_url = reverse('app_gateway_list') + '?tab=policies' if request.method == 'POST': - access_policy.delete() - messages.success(request, _('Access Policy deleted successfully.')) + try: + access_policy.delete() + messages.success(request, _('Access Policy deleted successfully.')) + except ProtectedError: + messages.error(request, _('Cannot delete this Access Policy because it is currently in use by an Application Route or Application Default Policy.')) return redirect(cancel_url) context = { diff --git a/templates/app_gateway/access_policy_type_select.html b/templates/app_gateway/access_policy_type_select.html new file mode 100644 index 0000000..2fb16ca --- /dev/null +++ b/templates/app_gateway/access_policy_type_select.html @@ -0,0 +1,55 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block content %} +
+
+
+
+

{% trans 'Select Access Policy Type' %}

+
+
+

{% trans 'Choose the type of access policy you want to create.' %}

+
+ +
+
+
+ +
{% trans 'Public' %}
+

{% trans 'Allow access to everyone without authentication.' %}

+ {% trans 'Select' %} +
+
+
+ +
+
+
+ +
{% trans 'Protected' %}
+

{% trans 'Require authentication using specified methods or groups.' %}

+ {% trans 'Select' %} +
+
+
+ +
+
+
+ +
{% trans 'Deny' %}
+

{% trans 'Deny all access.' %}

+ {% trans 'Select' %} +
+
+
+
+
+ +
+
+
+{% endblock %} diff --git a/templates/app_gateway/app_gateway_list.html b/templates/app_gateway/app_gateway_list.html index 184b6d3..ad72d44 100644 --- a/templates/app_gateway/app_gateway_list.html +++ b/templates/app_gateway/app_gateway_list.html @@ -119,7 +119,7 @@ {% elif active_tab == 'policies' %}
- + {% trans 'Add Access Policy' %}
diff --git a/templates/app_gateway/app_gateway_policy_form.html b/templates/app_gateway/app_gateway_policy_form.html deleted file mode 100644 index df995b1..0000000 --- a/templates/app_gateway/app_gateway_policy_form.html +++ /dev/null @@ -1,40 +0,0 @@ -{% extends 'base.html' %} -{% load crispy_forms_tags %} - -{% block content %} -
-
-
- {% if page_title %} -
-

{{ page_title }}

-
- {% endif %} -
-
- {% csrf_token %} - {% crispy form %} -
-
-
-
- - {% if form_description %} -
-
- -
-
- {{ form_description.content|safe }} -
-
-
-
- {% endif %} - -
-{% endblock %} - -{% block custom_page_scripts %} - -{% endblock %} \ No newline at end of file