from django import forms from django.contrib.auth.forms import PasswordResetForm from django.utils.http import urlsafe_base64_encode from django.utils.encoding import force_bytes from django.contrib.auth.tokens import default_token_generator from django.contrib.auth.password_validation import (validate_password, get_password_validators, MinimumLengthValidator, UserAttributeSimilarityValidator, CommonPasswordValidator, NumericPasswordValidator,) from django.conf import settings from .models import CustomUser from django.core.exceptions import ValidationError from django.utils.translation import gettext_lazy as _ from at_django_boilerplate.utils.hash_utils import hexdigest import logging logger = logging.getLogger(__name__) class UserSignUpForm(forms.ModelForm): password = forms.CharField(widget=forms.PasswordInput) confirm_password = forms.CharField(widget=forms.PasswordInput) terms_accepted = forms.BooleanField(required=True, label='I accept the terms and conditions') class Meta: model = CustomUser fields = ['first_name', 'last_name', 'email','contact_number','dob','password','confirm_password','terms_accepted'] widgets = { 'dob': forms.DateInput(attrs={'type': 'date'}), 'first_name': forms.TextInput(attrs={'type': 'text'}), 'last_name': forms.TextInput(attrs={'type': 'text'}), 'email': forms.EmailInput(attrs={'type': 'email'}), 'contact_number': forms.TextInput(attrs={'type': 'text'}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['password'].help_text = self.get_password_requirements() def get_password_requirements(self): password_validators = get_password_validators(settings.AUTH_PASSWORD_VALIDATORS) requirements = [] for validator in password_validators: if isinstance(validator, MinimumLengthValidator): requirements.append(f"*Password must be at least {validator.min_length} characters long.
") elif isinstance(validator, UserAttributeSimilarityValidator): requirements.append("*Password cannot be too similar to your other personal information.
") elif isinstance(validator, CommonPasswordValidator): requirements.append("*Password cannot be a commonly used password.
") elif isinstance(validator, NumericPasswordValidator): requirements.append("*Password cannot be entirely numeric.
") return " ".join(requirements) def clean(self): cleaned_data = super().clean() password = cleaned_data.get("password") confirm_password = cleaned_data.get("confirm_password") if password and confirm_password: try: validate_password(password, self.instance) except forms.ValidationError as error: self.add_error('password', error) return cleaned_data if password != confirm_password: self.add_error('confirm_password', "Passwords do not match") return cleaned_data class SigninForm(forms.Form): username = forms.CharField(max_length=65) password = forms.CharField(max_length=65, widget=forms.PasswordInput) class CustomPasswordResetForm(PasswordResetForm): def get_users(self, email): """Given an email, return matching user(s) who should receive a reset.""" email_hash = hexdigest(email) active_custom_users = CustomUser.objects.filter(email_hash=email_hash) active_users = [user for user in active_custom_users ] valid_users = [u for u in active_users if u.has_usable_password()] return valid_users def save(self, domain_override=None, subject_template_name='reset/password_reset_subject.txt', email_template_name='reset/password_reset_email.html', use_https=False, token_generator=default_token_generator, from_email=None, request=None, html_email_template_name=None, extra_email_context=None): """ Generates a one-use only link for resetting password and sends to the user. """ email = self.cleaned_data["email"] for user in self.get_users(email): context = { 'email': email, 'domain': domain_override or request.get_host(), 'request':request, 'site_name': 'we-kwick', 'uid': urlsafe_base64_encode(force_bytes(user.pk)), 'user': user, 'token': token_generator.make_token(user), 'protocol': 'https' if use_https else 'http', **(extra_email_context or {}), } from_email = settings.EMAIL_HOST_USER # print('From:',from_email) # print('Email Template:',email_template_name) # print('HTML Email Template:',html_email_template_name) self.send_mail( subject_template_name, email_template_name, context, from_email, email, html_email_template_name=html_email_template_name, ) class ProfileUpdateForm(forms.ModelForm): class Meta: model = CustomUser fields = [ 'contact_number'] widgets = { 'dob': forms.DateInput(attrs={'type': 'date'}), } class UpdateProfileForm(forms.ModelForm): class Meta: model = CustomUser fields = [ 'contact_number'] widgets = { 'dob': forms.DateInput(attrs={'type': 'date'}), } def validate_image(file): valid_mime_types = ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml'] valid_file_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.svg','.JPG'] file_mime_type = file.content_type if file_mime_type not in valid_mime_types: raise ValidationError(_('Unsupported file type. Please upload a JPEG, PNG, GIF, or SVG image.')) extension = file.name.split('.')[-1].lower() if not any(file.name.endswith(ext) for ext in valid_file_extensions): raise ValidationError(_('Unsupported file extension.')) class ProfilePictureUpdateForm(forms.ModelForm): profile_photo = forms.ImageField( widget=forms.ClearableFileInput(attrs={'accept': 'image/jpeg,image/png,image/gif,image/svg+xml'}), validators=[validate_image] ) class Meta: model = CustomUser fields = ['profile_photo']