Files
goodtimes/accounts/forms.py
2024-04-10 12:57:44 +05:30

360 lines
12 KiB
Python

from typing import Any
from django import forms
from django.core.exceptions import ValidationError
from django.core import validators
from django.utils.translation import gettext_lazy as _
from goodtimes import constants
from . import models
# from .backend import EmailBackend
from phonenumber_field.formfields import PhoneNumberField
from accounts.resource_action import PRINCIPAL_TYPE_ADMIN, PRINCIPAL_TYPE_SUBADMIN
from django.contrib.auth import authenticate
class CustomAuthenticationForm(forms.Form):
email = forms.EmailField(
max_length=254,
widget=forms.TextInput(attrs={"autofocus": True}),
label=_("Email"),
)
password = forms.CharField(
label=_("Password"),
strip=False,
widget=forms.PasswordInput(attrs={"autocomplete": "current-password"}),
)
def clean(self):
email = self.cleaned_data.get("email")
password = self.cleaned_data.get("password")
self.user = None
if email and password:
user = authenticate(email=email, password=password)
if user is None:
raise ValidationError({"__all__": [constants.INVALID_EMAIL_PASSWORD]})
elif not user.is_active:
raise ValidationError({"__all__": [constants.ACCOUNT_DEACTIVATED]})
self.user = user
return self.cleaned_data
class IAmPrincipalForm(forms.ModelForm):
password = forms.CharField(
widget=forms.PasswordInput(attrs={"autocomplete": "off"}),
validators=[
validators.MinLengthValidator(
limit_value=6, message="Password must be at least 6 characters long. "
)
],
)
confirm_password = forms.CharField(
widget=forms.PasswordInput(attrs={"autocomplete": "off"})
)
is_active = forms.BooleanField(
label="Active",
initial=True,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
required=False,
)
class Meta:
model = models.IAmPrincipal
fields = [
"principal_type",
"first_name",
"last_name",
"email",
"password",
"confirm_password",
"is_active",
]
def __init__(self, *args, **kwargs):
instance = kwargs.get("instance")
super().__init__(*args, **kwargs)
self.fields["principal_type"].queryset = models.IAmPrincipalType.objects.filter(
active=True, deleted=False
)
# If it's a create action, exclude 'is_active' field
if instance is None:
self.fields.pop("is_active", None)
else:
# Exclude 'password' and 'confirm_password' fields for updates
self.fields.pop("password", None)
self.fields.pop("confirm_password", None)
# Make the 'email' field read-only
self.fields["email"].widget.attrs["readonly"] = True
def clean_email(self):
email = self.cleaned_data.get("email")
# Skip uniqueness validation if it's an update action (instance exists)
if self.instance and self.instance.email == email:
return email
if models.IAmPrincipal.objects.filter(email=email).exists():
raise forms.ValidationError(constants.EMAIL_EXISTS)
return email
def save(self, commit=True):
instance = super().save(commit=False)
# Check if it's a new object (create action) or an existing one (update action)
if not instance.pk: # pk is None for new objects
instance.username = self.cleaned_data["email"]
instance.set_password(self.cleaned_data["password"])
principal_type = self.cleaned_data.get("principal_type")
if principal_type is not None:
# Set is_superuser and is_staff based on principal_type
if principal_type == models.IAmPrincipalType.objects.get(name=PRINCIPAL_TYPE_ADMIN):
instance.is_superuser = True
instance.is_staff = True
elif principal_type == models.IAmPrincipalType.objects.get(name=PRINCIPAL_TYPE_SUBADMIN):
instance.is_staff = True
instance.is_superuser = False
if commit:
instance.save()
return instance
class IAmPrincipalProfileForm(forms.ModelForm):
GENDER_CHOICES = (
("male", "Male"),
("female", "Female"),
("other", "Other"),
)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
email = forms.EmailField(required=True)
password = forms.CharField(
widget=forms.PasswordInput(attrs={"autocomplete": "off"})
)
confirm_password = forms.CharField(
widget=forms.PasswordInput(attrs={"autocomplete": "off"})
)
# date_of_birth = forms.CharField(widget=forms.DateInput(attrs={'type': 'date'}))
phone_number = PhoneNumberField(
widget=forms.TextInput(),
)
# is_staff = forms.BooleanField(
# label="Staff Status",
# label_suffix="",
# initial=True,
# required=False,
# help_text="Check this box to designate that this user will be assigned permissions in the future.",
# )
# is_superuser = forms.BooleanField(
# label="SuperAdmin Status",
# label_suffix="",
# required=False,
# help_text="Check this box to designates that this user has all permissions without explicitly assigning them.",
# )
# gender = forms.ChoiceField(choices=GENDER_CHOICES)
class Meta:
model = models.IAmPrincipal
fields = [
"principal_type",
"first_name",
"last_name",
"email",
"password",
"confirm_password",
# 'gender',
# 'date_of_birth',
"phone_number",
# 'address_line1',
# 'address_line2',
# 'city',
# 'state',
# 'country',
# 'post_code',
# 'profile_photo',
# "is_staff",
# "is_superuser",
]
def __init__(self, *args, **kwargs):
instance = kwargs.get("instance")
super().__init__(*args, **kwargs)
self.fields["principal_type"].queryset = models.IAmPrincipalType.objects.filter(
active=True, deleted=False
)
# self.fields['principal_source'].queryset = models.IAmPrincipalSource.objects.filter(active=True, deleted=False)
# Check if an instance is provided and customize the form fields accordingly
if instance is not None:
# Exclude the 'password' and 'confirm_password' fields
self.fields.pop("password", None)
self.fields.pop("confirm_password", None)
# Make the 'email' field read-only
self.fields["email"].widget.attrs["readonly"] = True
# Modify the 'is_superuser' field to be not required
# self.fields["is_superuser"].required = False
# self.fields["is_staff"].required = False
# Add or modify the 'is_active' field
self.fields["is_active"] = forms.BooleanField(
label="Active",
initial=instance.is_active,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
required=False,
)
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get("password")
confirm_password = cleaned_data.get("confirm_password")
if password and confirm_password and password != confirm_password:
self.add_error("confirm_password", "Password does not match")
return cleaned_data
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password"])
if commit:
user.save()
return user
class ProfileEditForm(forms.ModelForm):
profile_photo = forms.ImageField(required=False)
class Meta:
model = models.IAmPrincipal
fields = [
"profile_photo",
"first_name",
"last_name"
]
class IAmPrincipalGroupLinkForm(forms.ModelForm):
class Meta:
model = models.IAmPrincipal
fields = [
# "principal_type",
"email",
"principal_group",
]
# principal_type = forms.ModelChoiceField(
# label="Principal Type",
# queryset=models.IAmPrincipalType.objects.filter(active=True, deleted=False),
# widget=forms.widgets.TextInput(attrs={"readonly": True}),
# )
principal_group = forms.ModelMultipleChoiceField(
label="Groups",
queryset=models.IAmPrincipalGroup.objects.filter(active=True, deleted=False),
required=False,
widget=forms.widgets.SelectMultiple(
attrs={"class": "form_select js-example-basic-multiple"}
),
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Make the 'email' field read-only
# self.fields['principal_type'].widget.attrs['disabled'] = True
self.fields['email'].widget.attrs['readonly'] = True
class IAmPrincipalTypeForm(forms.ModelForm):
class Meta:
model = models.IAmPrincipalType
fields = ["name", "active"]
def __init__(self, *args, **kwargs):
instance = kwargs.get("instance")
super().__init__(*args, **kwargs)
if instance is None:
self.fields.pop("active")
class IAmPrincipalGroupRoleLinkForm(forms.ModelForm):
class Meta:
model = models.IAmPrincipalGroup
fields = ["name", "role", "active"]
role = forms.ModelMultipleChoiceField(
queryset=models.IAmRole.objects.filter(active=True, deleted=False),
required=False,
widget=forms.widgets.SelectMultiple(
attrs={"class": "form-select js-example-basic-multiple"}
),
)
def __init__(self, *args, **kwargs):
instance = kwargs.get("instance")
# data = kwargs.get('data')
super().__init__(*args, **kwargs)
if instance is None:
# This is an add operation, exclude the 'active' field
self.fields.pop("active")
class IAmPrincipalRoleAppResourceActionLinkForm(forms.ModelForm):
class Meta:
model = models.IAmRole
fields = ["name", "active", "app_resource_action"]
required = {"app_resource_action": False}
app_resource_action = forms.ModelMultipleChoiceField(
queryset=models.IAmAppResourceActionLink.objects.all(),
widget=forms.CheckboxSelectMultiple,
required=False,
)
def __init__(self, *args, **kwargs):
instance = kwargs.get("instance")
super().__init__(*args, **kwargs)
if instance is None:
self.fields.pop("active")
class IAmPrincipalResourceLinkForm(IAmPrincipalForm):
class Meta:
model = models.IAmPrincipal
fields = [
"principal_type",
"first_name",
"last_name",
"email",
# "password",
# "confirm_password",
"principal_resource",
]
principal_resource = forms.ModelMultipleChoiceField(
label="Module Permission",
queryset=models.IAmAppResource.objects.filter(active=True, deleted=False),
required=False,
widget=forms.widgets.SelectMultiple(
attrs={"class": "form_select js-example-basic-multiple"}
),
)
def save(self, commit=True):
# First, save the instance of the IAmPrincipal model as usual
principal = super().save(commit=False)
# If the principal_resource field has data
if self.cleaned_data['principal_resource']:
# Get the principal_resource data
principal_resource_data = self.cleaned_data['principal_resource']
# Update the many-to-many relationship
principal.principal_resource.set(principal_resource_data)
# Save the instance to the database
if commit:
principal.save()