| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- from django import forms
- from django.conf import settings
- from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm as DjangoPasswordChangeForm
- from django.contrib.postgres.forms import SimpleArrayField
- from django.utils.html import mark_safe
- from django.utils.translation import gettext as _
- from ipam.formfields import IPNetworkFormField
- from netbox.preferences import PREFERENCES
- from utilities.forms import BootstrapMixin, DateTimePicker
- from utilities.utils import flatten_dict
- from .models import Token, UserConfig
- class LoginForm(BootstrapMixin, AuthenticationForm):
- pass
- class PasswordChangeForm(BootstrapMixin, DjangoPasswordChangeForm):
- pass
- class UserConfigFormMetaclass(forms.models.ModelFormMetaclass):
- def __new__(mcs, name, bases, attrs):
- # Emulate a declared field for each supported user preference
- preference_fields = {}
- for field_name, preference in PREFERENCES.items():
- description = f'{preference.description}<br />' if preference.description else ''
- help_text = f'{description}<code>{field_name}</code>'
- field_kwargs = {
- 'label': preference.label,
- 'choices': preference.choices,
- 'help_text': mark_safe(help_text),
- 'coerce': preference.coerce,
- 'required': False,
- 'widget': forms.Select,
- }
- preference_fields[field_name] = forms.TypedChoiceField(**field_kwargs)
- attrs.update(preference_fields)
- return super().__new__(mcs, name, bases, attrs)
- class UserConfigForm(BootstrapMixin, forms.ModelForm, metaclass=UserConfigFormMetaclass):
- fieldsets = (
- ('User Interface', (
- 'pagination.per_page',
- 'pagination.placement',
- 'ui.colormode',
- )),
- ('Miscellaneous', (
- 'data_format',
- )),
- )
- # List of clearable preferences
- pk = forms.MultipleChoiceField(
- choices=[],
- required=False
- )
- class Meta:
- model = UserConfig
- fields = ()
- def __init__(self, *args, instance=None, **kwargs):
- # Get initial data from UserConfig instance
- initial_data = flatten_dict(instance.data)
- kwargs['initial'] = initial_data
- super().__init__(*args, instance=instance, **kwargs)
- # Compile clearable preference choices
- self.fields['pk'].choices = (
- (f'tables.{table_name}', '') for table_name in instance.data.get('tables', [])
- )
- def save(self, *args, **kwargs):
- # Set UserConfig data
- for pref_name, value in self.cleaned_data.items():
- if pref_name == 'pk':
- continue
- self.instance.set(pref_name, value, commit=False)
- # Clear selected preferences
- for preference in self.cleaned_data['pk']:
- self.instance.clear(preference)
- return super().save(*args, **kwargs)
- @property
- def plugin_fields(self):
- return [
- name for name in self.fields.keys() if name.startswith('plugins.')
- ]
- class TokenForm(BootstrapMixin, forms.ModelForm):
- key = forms.CharField(
- required=False,
- help_text=_("If no key is provided, one will be generated automatically.")
- )
- allowed_ips = SimpleArrayField(
- base_field=IPNetworkFormField(),
- required=False,
- label=_('Allowed IPs'),
- help_text=_('Allowed IPv4/IPv6 networks from where the token can be used. Leave blank for no restrictions. '
- 'Example: <code>10.1.1.0/24,192.168.10.16/32,2001:db8:1::/64</code>'),
- )
- class Meta:
- model = Token
- fields = [
- 'key', 'write_enabled', 'expires', 'description', 'allowed_ips',
- ]
- widgets = {
- 'expires': DateTimePicker(),
- }
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- # Omit the key field if token retrieval is not permitted
- if self.instance.pk and not settings.ALLOW_TOKEN_RETRIEVAL:
- del self.fields['key']
|