From d2b27957f4de9a30295520946b1cb162368fd624 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 7 Nov 2024 11:51:29 +0100 Subject: [PATCH 1/3] Split up AccountForm into external and internal External means managed by ldap for example and internal is a user made by nav --- python/nav/web/useradmin/forms.py | 69 ++++++++++++++++++++----------- python/nav/web/useradmin/views.py | 9 +++- 2 files changed, 51 insertions(+), 27 deletions(-) diff --git a/python/nav/web/useradmin/forms.py b/python/nav/web/useradmin/forms.py index 5fb31c38cc..2ce2c6bd40 100644 --- a/python/nav/web/useradmin/forms.py +++ b/python/nav/web/useradmin/forms.py @@ -98,40 +98,28 @@ def __init__(self, *args, **kwargs): self.helper.form_action = '' self.helper.form_method = 'POST' - fieldset_name = 'Account' - fieldset_args = [fieldset_name] - default_args = ['login', 'name', 'password1', 'password2'] - if account: self.fields['password1'].required = False submit_value = 'Save changes' - # This should really be two different forms because of this - if kwargs['instance'].ext_sync: - # We don't want to enable local password editing for accounts that are - # managed externally. - authenticator = ( - "

External authenticator: %s

" - % kwargs["instance"].ext_sync - ) - del self.fields['password1'] - del self.fields['password2'] - self.fields['login'].widget.attrs['readonly'] = True - fieldset_args.extend(['login', 'name', HTML(authenticator)]) - else: - fieldset_args.extend(default_args) if kwargs["instance"].id == Account.DEFAULT_ACCOUNT: # We don't want to enable significant changes to the anonymous account - for field in ("password1", "password2", "login"): - self.fields[field].widget.attrs["readonly"] = True + self.fields["password1"].widget.attrs["readonly"] = True + self.fields["password2"].widget.attrs["readonly"] = True + self.fields["login"].widget.attrs["readonly"] = True else: submit_value = 'Create account' - fieldset_args.extend(default_args) - submit = Submit('submit_account', submit_value, css_class='small') - fieldset_args.extend([submit]) - fieldset = Fieldset(*fieldset_args) - self.helper.layout = Layout(fieldset) + self.helper.layout = Layout( + Fieldset( + 'Account', + 'login', + 'name', + 'password1', + 'password2', + Submit('submit_account', submit_value, css_class='small'), + ) + ) def clean_password1(self): """Validate password""" @@ -157,6 +145,37 @@ class Meta(object): exclude = ('password', 'ext_sync', 'organizations', 'preferences') +class ExternalAccountForm(AccountForm): + """Form for editing an externally managed account""" + + def __init__(self, *args, **kwargs): + super(AccountForm, self).__init__(*args, **kwargs) + self.helper = FormHelper() + self.helper.form_action = '' + self.helper.form_method = 'POST' + + if kwargs['instance'].ext_sync: + # We don't want to enable local password editing for accounts that are + # managed externally. + authenticator = ( + "

External authenticator: %s

" + % kwargs["instance"].ext_sync + ) + del self.fields['password1'] + del self.fields['password2'] + self.fields['login'].widget.attrs['readonly'] = True + + self.helper.layout = Layout( + Fieldset( + 'Account', + 'login', + 'name', + HTML(authenticator), + Submit('submit_account', 'Save changes', css_class='small'), + ) + ) + + class PrivilegeForm(forms.Form): """Form for adding a privilege to a group from the group page""" diff --git a/python/nav/web/useradmin/views.py b/python/nav/web/useradmin/views.py index bb9b63fcf7..68d62c4551 100644 --- a/python/nav/web/useradmin/views.py +++ b/python/nav/web/useradmin/views.py @@ -59,13 +59,18 @@ def account_detail(request, account_id=None): account = None old_account = copy.deepcopy(account) - account_form = forms.AccountForm(instance=account) + external_authentication = getattr(account, "ext_sync", False) + if external_authentication: + account_form_class = forms.ExternalAccountForm + else: + account_form_class = forms.AccountForm + account_form = account_form_class(instance=account) org_form = forms.OrganizationAddForm(account) group_form = forms.GroupAddForm(account) if request.method == 'POST': if 'submit_account' in request.POST: - account_form = forms.AccountForm(request.POST, instance=account) + account_form = account_form_class(request.POST, instance=account) if account_form.is_valid(): return save_account(request, account_form, old_account) From b5f60ba23212f3551f1ac4543a1d404e0c850508 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 7 Nov 2024 11:40:25 +0100 Subject: [PATCH 2/3] Add template for info box for external users --- .../templates/useradmin/frag-external-account-fieldset.html | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 python/nav/web/templates/useradmin/frag-external-account-fieldset.html diff --git a/python/nav/web/templates/useradmin/frag-external-account-fieldset.html b/python/nav/web/templates/useradmin/frag-external-account-fieldset.html new file mode 100644 index 0000000000..1e9b1f82da --- /dev/null +++ b/python/nav/web/templates/useradmin/frag-external-account-fieldset.html @@ -0,0 +1,6 @@ +{% extends "custom_crispy_templates/flat_fieldset.html" %} + +{% block fieldset_fields %} +

External authenticator: {{ account.ext_sync }}

+ {{ block.super }} +{% endblock %} From 075c26b779c7a85a7156df2b2ae27402fa10d7ad Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 7 Nov 2024 11:57:38 +0100 Subject: [PATCH 3/3] Uncrispify (External)AccountForm in useradmin The information box about externally managed accounts is moved into HTML templates --- .../templates/useradmin/account_detail.html | 3 +- python/nav/web/useradmin/forms.py | 85 +++++++++---------- 2 files changed, 40 insertions(+), 48 deletions(-) diff --git a/python/nav/web/templates/useradmin/account_detail.html b/python/nav/web/templates/useradmin/account_detail.html index 07a425f71e..a82ed3d587 100644 --- a/python/nav/web/templates/useradmin/account_detail.html +++ b/python/nav/web/templates/useradmin/account_detail.html @@ -1,5 +1,4 @@ {% extends "useradmin/base.html" %} -{% load crispy_forms_tags %} {% block content %} @@ -63,7 +62,7 @@

{% comment %} ACCOUNT FORM {% endcomment %} {% if account_form %}
- {% crispy account_form %} + {% include 'custom_crispy_templates/flat_form.html' with form=account_form %}
{% endif %} diff --git a/python/nav/web/useradmin/forms.py b/python/nav/web/useradmin/forms.py index 2ce2c6bd40..56d0222527 100644 --- a/python/nav/web/useradmin/forms.py +++ b/python/nav/web/useradmin/forms.py @@ -21,13 +21,6 @@ from django import forms from django.utils.encoding import force_str -from crispy_forms.helper import FormHelper -from crispy_forms_foundation.layout import ( - Layout, - Fieldset, - Submit, - HTML, -) from nav.web.crispyforms import ( set_flat_form_attributes, FlatFieldset, @@ -94,31 +87,33 @@ class AccountForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(AccountForm, self).__init__(*args, **kwargs) account = kwargs.get('instance', False) - self.helper = FormHelper() - self.helper.form_action = '' - self.helper.form_method = 'POST' if account: self.fields['password1'].required = False - submit_value = 'Save changes' if kwargs["instance"].id == Account.DEFAULT_ACCOUNT: # We don't want to enable significant changes to the anonymous account self.fields["password1"].widget.attrs["readonly"] = True self.fields["password2"].widget.attrs["readonly"] = True self.fields["login"].widget.attrs["readonly"] = True - else: - submit_value = 'Create account' - - self.helper.layout = Layout( - Fieldset( - 'Account', - 'login', - 'name', - 'password1', - 'password2', - Submit('submit_account', submit_value, css_class='small'), - ) + + submit_value = "Save changes" if account else "Create account" + + self.attrs = set_flat_form_attributes( + form_fields=[ + FlatFieldset( + legend="Account", + fields=[ + self["login"], + self["name"], + self["password1"], + self["password2"], + SubmitField( + "submit_account", submit_value, css_classes="small" + ), + ], + ) + ], ) def clean_password1(self): @@ -150,29 +145,27 @@ class ExternalAccountForm(AccountForm): def __init__(self, *args, **kwargs): super(AccountForm, self).__init__(*args, **kwargs) - self.helper = FormHelper() - self.helper.form_action = '' - self.helper.form_method = 'POST' - - if kwargs['instance'].ext_sync: - # We don't want to enable local password editing for accounts that are - # managed externally. - authenticator = ( - "

External authenticator: %s

" - % kwargs["instance"].ext_sync - ) - del self.fields['password1'] - del self.fields['password2'] - self.fields['login'].widget.attrs['readonly'] = True - - self.helper.layout = Layout( - Fieldset( - 'Account', - 'login', - 'name', - HTML(authenticator), - Submit('submit_account', 'Save changes', css_class='small'), - ) + + # We don't want to enable local password editing for accounts that are + # managed externally. + del self.fields['password1'] + del self.fields['password2'] + self.fields['login'].widget.attrs['readonly'] = True + + self.attrs = set_flat_form_attributes( + form_fields=[ + FlatFieldset( + legend="Account", + fields=[ + self["login"], + self["name"], + SubmitField( + "submit_account", "Save changes", css_classes="small" + ), + ], + template="useradmin/frag-external-account-fieldset.html", + ) + ], )