226 lines
8.2 KiB
Python
226 lines
8.2 KiB
Python
"""
|
|
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 = [
|
|
'first_name', 'last_name', 'email', 'phone_number', 'mobile_number',
|
|
'employee_id', 'role', 'department', 'bio', 'user_timezone', 'language',
|
|
'theme', 'is_active', 'is_approved'
|
|
]
|
|
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', 'employee_id',
|
|
'role', 'department', '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
|
|
|