""" Forms for Accounts app CRUD operations. """ from django import forms from django.contrib.auth.forms import UserCreationForm, UserChangeForm from django.core.exceptions import ValidationError from .models import User, TwoFactorDevice, SocialAccount, UserSession, PasswordHistory class UserForm(forms.ModelForm): """ Form for updating user information. """ class Meta: model = User fields = [ 'email', ] widgets = { # 'first_name': forms.TextInput(attrs={'class': 'form-control'}), # 'last_name': forms.TextInput(attrs={'class': 'form-control'}), 'email': forms.EmailInput(attrs={'class': 'form-control'}), # 'phone_number': forms.TextInput(attrs={'class': 'form-control'}), # 'mobile_number': forms.TextInput(attrs={'class': 'form-control'}), # 'employee_id': forms.TextInput(attrs={'class': 'form-control'}), # 'role': forms.Select(attrs={'class': 'form-select'}), # 'department': forms.TextInput(attrs={'class': 'form-control'}), # 'bio': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), # 'user_timezone': forms.Select(attrs={'class': 'form-select'}), # 'language': forms.Select(attrs={'class': 'form-select'}), # 'theme': forms.Select(attrs={'class': 'form-select'}), # 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}), # 'is_approved': forms.CheckboxInput(attrs={'class': 'form-check-input'}), } class UserCreateForm(UserCreationForm): """ Form for creating new users. """ first_name = forms.CharField(max_length=150, required=True) last_name = forms.CharField(max_length=150, required=True) email = forms.EmailField(required=True) employee_id = forms.CharField(max_length=50, required=False) # role = forms.ChoiceField(choices=User._meta.get_field('role').choices, required=True) department = forms.CharField(max_length=100, required=False) class Meta: model = User fields = [ 'username', 'first_name', 'last_name', 'email', 'password1', 'password2' ] widgets = { 'username': forms.TextInput(attrs={'class': 'form-control'}), 'first_name': forms.TextInput(attrs={'class': 'form-control'}), 'last_name': forms.TextInput(attrs={'class': 'form-control'}), 'email': forms.EmailInput(attrs={'class': 'form-control'}), # 'employee_id': forms.TextInput(attrs={'class': 'form-control'}), # 'role': forms.Select(attrs={'class': 'form-select'}), # 'department': forms.TextInput(attrs={'class': 'form-control'}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['password1'].widget.attrs.update({'class': 'form-control'}) self.fields['password2'].widget.attrs.update({'class': 'form-control'}) class TwoFactorDeviceForm(forms.ModelForm): """ Form for two-factor device management. """ class Meta: model = TwoFactorDevice fields = ['user', 'name', 'device_type', 'phone_number', 'email_address'] widgets = { 'user': forms.Select(attrs={'class': 'form-select'}), 'name': forms.TextInput(attrs={'class': 'form-control'}), 'device_type': forms.Select(attrs={'class': 'form-select'}), 'phone_number': forms.TextInput(attrs={'class': 'form-control'}), 'email_address': forms.EmailInput(attrs={'class': 'form-control'}), } def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user and hasattr(user, 'tenant'): self.fields['user'].queryset = User.objects.filter( tenant=user.tenant, is_active=True ).order_by('last_name', 'first_name') def clean(self): cleaned_data = super().clean() device_type = cleaned_data.get('device_type') phone_number = cleaned_data.get('phone_number') email_address = cleaned_data.get('email_address') if device_type == 'SMS' and not phone_number: raise ValidationError('Phone number is required for SMS devices.') if device_type == 'EMAIL' and not email_address: raise ValidationError('Email address is required for email devices.') return cleaned_data class SocialAccountForm(forms.ModelForm): """ Form for social account management. """ class Meta: model = SocialAccount fields = ['user', 'provider', 'provider_id', 'display_name', 'profile_url'] widgets = { 'user': forms.Select(attrs={'class': 'form-select'}), 'provider': forms.TextInput(attrs={'class': 'form-control'}), 'provider_id': forms.TextInput(attrs={'class': 'form-control'}), 'display_name': forms.TextInput(attrs={'class': 'form-control'}), 'profile_url': forms.URLInput(attrs={'class': 'form-control'}), } def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user and hasattr(user, 'tenant'): self.fields['user'].queryset = User.objects.filter( tenant=user.tenant, is_active=True ).order_by('last_name', 'first_name') class AccountsSearchForm(forms.Form): """ Form for searching accounts data. """ search = forms.CharField( max_length=255, required=False, widget=forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Search users, sessions, devices...' }) ) # role = forms.ChoiceField( # choices=[('', 'All Roles')] + list(User._meta.get_field('role').choices), # required=False, # widget=forms.Select(attrs={'class': 'form-select'}) # ) status = forms.ChoiceField( choices=[ ('', 'All Status'), ('active', 'Active'), ('inactive', 'Inactive'), ('pending', 'Pending Approval') ], required=False, widget=forms.Select(attrs={'class': 'form-select'}) ) date_from = forms.DateField( required=False, widget=forms.DateInput(attrs={ 'class': 'form-control', 'type': 'date' }) ) date_to = forms.DateField( required=False, widget=forms.DateInput(attrs={ 'class': 'form-control', 'type': 'date' }) ) class PasswordChangeForm(forms.Form): """ Form for changing user passwords. """ old_password = forms.CharField( widget=forms.PasswordInput(attrs={'class': 'form-control'}), label='Current Password' ) new_password1 = forms.CharField( widget=forms.PasswordInput(attrs={'class': 'form-control'}), label='New Password' ) new_password2 = forms.CharField( widget=forms.PasswordInput(attrs={'class': 'form-control'}), label='Confirm New Password' ) def __init__(self, user, *args, **kwargs): self.user = user super().__init__(*args, **kwargs) def clean_old_password(self): old_password = self.cleaned_data.get('old_password') if not self.user.check_password(old_password): raise ValidationError('Your old password was entered incorrectly.') return old_password def clean(self): cleaned_data = super().clean() password1 = cleaned_data.get('new_password1') password2 = cleaned_data.get('new_password2') if password1 and password2: if password1 != password2: raise ValidationError('The two password fields didn\'t match.') return cleaned_data def save(self): password = self.cleaned_data['new_password1'] self.user.set_password(password) self.user.save() return self.user # from django import forms # from django.contrib.auth.forms import UserCreationForm, PasswordChangeForm # from django.contrib.auth.models import User, Group # from django.core.exceptions import ValidationError # from django.utils import timezone # from django.contrib.auth.password_validation import validate_password # from crispy_forms.helper import FormHelper # from crispy_forms.layout import Layout, Fieldset, Submit, Row, Column, HTML, Div # from crispy_forms.bootstrap import FormActions # # from .models import User, TwoFactorDevice, SocialAccount, UserSession, PasswordHistory # # # class UserRegistrationForm(UserCreationForm): # """ # Form for user registration in onboarding workflow # """ # first_name = forms.CharField( # max_length=150, # required=True, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # last_name = forms.CharField( # max_length=150, # required=True, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # email = forms.EmailField( # required=True, # widget=forms.EmailInput(attrs={'class': 'form-control'}) # ) # employee_id = forms.CharField( # max_length=50, # required=False, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # department = forms.ModelChoiceField( # queryset=None, # Will be set in __init__ # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # job_title = forms.CharField( # max_length=200, # required=True, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # phone_number = forms.CharField( # max_length=20, # required=False, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # start_date = forms.DateField( # required=True, # widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) # ) # manager = forms.ModelChoiceField( # queryset=None, # Will be set in __init__ # required=False, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # # class Meta: # model = User # fields = [ # 'username', 'first_name', 'last_name', 'email', 'employee_id', # 'department', 'job_title', 'phone_number', 'start_date', 'manager', # 'password1', 'password2' # ] # # def __init__(self, *args, **kwargs): # tenant = kwargs.pop('tenant', None) # super().__init__(*args, **kwargs) # # # Set querysets based on tenant # if tenant: # from core.models import Department # self.fields['department'].queryset = Department.objects.filter(tenant=tenant) # self.fields['manager'].queryset = User.objects.filter( # tenant=tenant, # is_active=True, # groups__name__in=['Managers', 'Department Heads'] # ) # # # Crispy forms helper # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'User Information', # Row( # Column('first_name', css_class='form-group col-md-6 mb-0'), # Column('last_name', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # Row( # Column('username', css_class='form-group col-md-6 mb-0'), # Column('email', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # Row( # Column('employee_id', css_class='form-group col-md-6 mb-0'), # Column('phone_number', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ) # ), # Fieldset( # 'Employment Information', # Row( # Column('department', css_class='form-group col-md-6 mb-0'), # Column('job_title', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # Row( # Column('start_date', css_class='form-group col-md-6 mb-0'), # Column('manager', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ) # ), # Fieldset( # 'Security', # Row( # Column('password1', css_class='form-group col-md-6 mb-0'), # Column('password2', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ) # ), # FormActions( # Submit('submit', 'Register User', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # def clean_email(self): # email = self.cleaned_data.get('email') # if User.objects.filter(email=email).exists(): # raise ValidationError('A user with this email already exists.') # return email # # def clean_employee_id(self): # employee_id = self.cleaned_data.get('employee_id') # if employee_id and User.objects.filter(employee_id=employee_id).exists(): # raise ValidationError('A user with this employee ID already exists.') # return employee_id # # # class AccountActivationForm(forms.Form): # """ # Form for account activation in onboarding workflow # """ # activation_code = forms.CharField( # max_length=100, # required=True, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # terms_accepted = forms.BooleanField( # required=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # privacy_policy_accepted = forms.BooleanField( # required=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Account Activation', # 'activation_code', # HTML('
'), # 'terms_accepted', # HTML(''), # HTML('
'), # HTML('
'), # 'privacy_policy_accepted', # HTML( # ''), # HTML('
') # ), # FormActions( # Submit('submit', 'Activate Account', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # # class TwoFactorSetupForm(forms.ModelForm): # """ # Form for two-factor authentication setup # """ # device_name = forms.CharField( # max_length=100, # required=True, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # device_type = forms.ChoiceField( # choices=[ # ('totp', 'Authenticator App (TOTP)'), # ('sms', 'SMS'), # ('email', 'Email'), # ('backup_codes', 'Backup Codes') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # phone_number = forms.CharField( # max_length=20, # required=False, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # verification_code = forms.CharField( # max_length=10, # required=True, # widget=forms.TextInput(attrs={'class': 'form-control'}) # ) # # class Meta: # model = TwoFactorDevice # fields = ['device_name', 'device_type', 'phone_number'] # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Two-Factor Authentication Setup', # 'device_name', # 'device_type', # 'phone_number', # HTML( # '
Enter the verification code from your authenticator app or device.
'), # 'verification_code' # ), # FormActions( # Submit('submit', 'Setup Two-Factor Auth', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # def clean(self): # cleaned_data = super().clean() # device_type = cleaned_data.get('device_type') # phone_number = cleaned_data.get('phone_number') # # if device_type == 'sms' and not phone_number: # raise ValidationError('Phone number is required for SMS two-factor authentication.') # # return cleaned_data # # # class PermissionManagementForm(forms.Form): # """ # Form for managing user permissions # """ # groups = forms.ModelMultipleChoiceField( # queryset=Group.objects.all(), # required=False, # widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}) # ) # is_staff = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # is_superuser = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # access_level = forms.ChoiceField( # choices=[ # ('basic', 'Basic Access'), # ('standard', 'Standard Access'), # ('advanced', 'Advanced Access'), # ('admin', 'Administrator Access') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # department_access = forms.ModelMultipleChoiceField( # queryset=None, # Will be set in __init__ # required=False, # widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}) # ) # # def __init__(self, *args, **kwargs): # tenant = kwargs.pop('tenant', None) # super().__init__(*args, **kwargs) # # if tenant: # from core.models import Department # self.fields['department_access'].queryset = Department.objects.filter(tenant=tenant) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'User Permissions', # 'access_level', # HTML('
'), # 'is_staff', # HTML(''), # HTML('
'), # HTML('
'), # 'is_superuser', # HTML(''), # HTML('
') # ), # Fieldset( # 'Group Memberships', # 'groups' # ), # Fieldset( # 'Department Access', # 'department_access' # ), # FormActions( # Submit('submit', 'Update Permissions', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # # class SecurityAuditForm(forms.Form): # """ # Form for security audit configuration # """ # audit_type = forms.ChoiceField( # choices=[ # ('comprehensive', 'Comprehensive Security Audit'), # ('password_policy', 'Password Policy Audit'), # ('access_review', 'Access Rights Review'), # ('session_audit', 'Session Security Audit'), # ('two_factor_audit', 'Two-Factor Authentication Audit') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # include_inactive_users = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # check_password_strength = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # review_login_attempts = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # analyze_session_security = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # generate_report = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Security Audit Configuration', # 'audit_type', # HTML('
'), # 'include_inactive_users', # HTML(''), # HTML('
'), # HTML('
'), # 'check_password_strength', # HTML( # ''), # HTML('
'), # HTML('
'), # 'review_login_attempts', # HTML(''), # HTML('
'), # HTML('
'), # 'analyze_session_security', # HTML( # ''), # HTML('
'), # HTML('
'), # 'generate_report', # HTML(''), # HTML('
') # ), # FormActions( # Submit('submit', 'Start Security Audit', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # # class SessionManagementForm(forms.Form): # """ # Form for session management configuration # """ # session_timeout = forms.IntegerField( # min_value=5, # max_value=1440, # initial=30, # widget=forms.NumberInput(attrs={'class': 'form-control'}) # ) # max_concurrent_sessions = forms.IntegerField( # min_value=1, # max_value=10, # initial=3, # widget=forms.NumberInput(attrs={'class': 'form-control'}) # ) # require_secure_cookies = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # enable_session_monitoring = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # log_session_events = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # auto_logout_inactive = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Session Configuration', # Row( # Column('session_timeout', css_class='form-group col-md-6 mb-0'), # Column('max_concurrent_sessions', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # HTML('
'), # 'require_secure_cookies', # HTML(''), # HTML('
'), # HTML('
'), # 'enable_session_monitoring', # HTML( # ''), # HTML('
'), # HTML('
'), # 'log_session_events', # HTML(''), # HTML('
'), # HTML('
'), # 'auto_logout_inactive', # HTML( # ''), # HTML('
') # ), # FormActions( # Submit('submit', 'Update Session Settings', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # # class ComplianceCheckForm(forms.Form): # """ # Form for compliance verification # """ # compliance_standards = forms.MultipleChoiceField( # choices=[ # ('hipaa', 'HIPAA Compliance'), # ('gdpr', 'GDPR Compliance'), # ('sox', 'SOX Compliance'), # ('pci_dss', 'PCI DSS Compliance'), # ('iso27001', 'ISO 27001 Compliance') # ], # required=True, # widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}) # ) # check_password_policies = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # verify_access_controls = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # audit_user_permissions = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # check_data_encryption = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # generate_compliance_report = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Compliance Standards', # 'compliance_standards' # ), # Fieldset( # 'Compliance Checks', # HTML('
'), # 'check_password_policies', # HTML( # ''), # HTML('
'), # HTML('
'), # 'verify_access_controls', # HTML(''), # HTML('
'), # HTML('
'), # 'audit_user_permissions', # HTML(''), # HTML('
'), # HTML('
'), # 'check_data_encryption', # HTML(''), # HTML('
'), # HTML('
'), # 'generate_compliance_report', # HTML( # ''), # HTML('
') # ), # FormActions( # Submit('submit', 'Start Compliance Check', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) # # # class AccountDeactivationForm(forms.Form): # """ # Form for account deactivation # """ # deactivation_reason = forms.ChoiceField( # choices=[ # ('termination', 'Employment Termination'), # ('resignation', 'Employee Resignation'), # ('transfer', 'Department Transfer'), # ('leave', 'Extended Leave'), # ('security', 'Security Concerns'), # ('other', 'Other Reason') # ], # required=True, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # deactivation_date = forms.DateField( # required=True, # initial=timezone.now().date(), # widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) # ) # backup_data = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # transfer_ownership = forms.BooleanField( # required=False, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # new_owner = forms.ModelChoiceField( # queryset=None, # Will be set in __init__ # required=False, # widget=forms.Select(attrs={'class': 'form-control'}) # ) # notify_stakeholders = forms.BooleanField( # required=False, # initial=True, # widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) # ) # additional_notes = forms.CharField( # required=False, # widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}) # ) # # def __init__(self, *args, **kwargs): # tenant = kwargs.pop('tenant', None) # super().__init__(*args, **kwargs) # # if tenant: # self.fields['new_owner'].queryset = User.objects.filter( # tenant=tenant, # is_active=True # ).exclude(id=self.instance.id if hasattr(self, 'instance') else None) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Deactivation Details', # Row( # Column('deactivation_reason', css_class='form-group col-md-6 mb-0'), # Column('deactivation_date', css_class='form-group col-md-6 mb-0'), # css_class='form-row' # ), # 'additional_notes' # ), # Fieldset( # 'Data Management', # HTML('
'), # 'backup_data', # HTML(''), # HTML('
'), # HTML('
'), # 'transfer_ownership', # HTML(''), # HTML('
'), # 'new_owner' # ), # Fieldset( # 'Notifications', # HTML('
'), # 'notify_stakeholders', # HTML(''), # HTML('
') # ), # FormActions( # Submit('submit', 'Deactivate Account', css_class='btn btn-danger'), # HTML('Cancel') # ) # ) # # def clean(self): # cleaned_data = super().clean() # transfer_ownership = cleaned_data.get('transfer_ownership') # new_owner = cleaned_data.get('new_owner') # # if transfer_ownership and not new_owner: # raise ValidationError('New owner must be selected when transferring ownership.') # # return cleaned_data # # # class PasswordResetForm(forms.Form): # """ # Form for password reset # """ # email = forms.EmailField( # required=True, # widget=forms.EmailInput(attrs={'class': 'form-control'}) # ) # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Password Reset', # 'email', # HTML( # '
Enter your email address and we will send you a link to reset your password.
') # ), # FormActions( # Submit('submit', 'Send Reset Link', css_class='btn btn-primary'), # HTML('Back to Login') # ) # ) # # def clean_email(self): # email = self.cleaned_data.get('email') # if not User.objects.filter(email=email, is_active=True).exists(): # raise ValidationError('No active user found with this email address.') # return email # # # class PasswordChangeForm(PasswordChangeForm): # """ # Enhanced password change form # """ # # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # # # Add CSS classes # for field in self.fields.values(): # field.widget.attrs['class'] = 'form-control' # # self.helper = FormHelper() # self.helper.layout = Layout( # Fieldset( # 'Change Password', # 'old_password', # 'new_password1', # 'new_password2', # HTML( # '
Your password must contain at least 8 characters and cannot be too similar to your other personal information.
') # ), # FormActions( # Submit('submit', 'Change Password', css_class='btn btn-primary'), # HTML('Cancel') # ) # ) #