base setup

This commit is contained in:
2026-01-07 12:09:20 +05:30
commit 0c275efea1
278 changed files with 11228 additions and 0 deletions

View File

@@ -0,0 +1,165 @@
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.<br>")
elif isinstance(validator, UserAttributeSimilarityValidator):
requirements.append("*Password cannot be too similar to your other personal information.<br>")
elif isinstance(validator, CommonPasswordValidator):
requirements.append("*Password cannot be a commonly used password.<br>")
elif isinstance(validator, NumericPasswordValidator):
requirements.append("*Password cannot be entirely numeric.<br>")
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']