"""The public buyer sign-up form. This is the only place on the platform a password minimum is enforced — the realm has no password policy set and no mail service exists — so the rules live here and are deliberately plain: long enough, not the email or the company name, and typed twice the same. The form is also the first line of duplicate-email handling; Keycloak refuses a second account with the same address, and the view turns that into the same sentence. """ from django import forms from apps.users.models import User MIN_PASSWORD_LENGTH = 12 DUPLICATE_EMAIL_MESSAGE = "An account with this email already exists — sign in instead." class BuyerSignupForm(forms.Form): full_name = forms.CharField( max_length=255, label="Full name", widget=forms.TextInput(attrs={"class": "form-control", "autocomplete": "name"}), ) company_name = forms.CharField( max_length=255, label="Company name", widget=forms.TextInput(attrs={"class": "form-control", "autocomplete": "organization"}), ) email = forms.EmailField( label="Email", widget=forms.EmailInput(attrs={"class": "form-control", "autocomplete": "email"}), ) password = forms.CharField( label="Password", widget=forms.PasswordInput(attrs={"class": "form-control", "autocomplete": "new-password"}), help_text=f"At least {MIN_PASSWORD_LENGTH} characters.", ) confirm_password = forms.CharField( label="Confirm password", widget=forms.PasswordInput(attrs={"class": "form-control", "autocomplete": "new-password"}), ) def clean_email(self): email = self.cleaned_data["email"].strip().lower() if User.objects.filter(email__iexact=email).exists(): raise forms.ValidationError(DUPLICATE_EMAIL_MESSAGE) return email def clean(self): cleaned = super().clean() password = cleaned.get("password") confirm = cleaned.get("confirm_password") if password and confirm and password != confirm: self.add_error("confirm_password", "The two passwords do not match.") if password: if len(password) < MIN_PASSWORD_LENGTH: self.add_error( "password", f"Use at least {MIN_PASSWORD_LENGTH} characters.", ) email = (cleaned.get("email") or "").strip().lower() company = (cleaned.get("company_name") or "").strip().lower() if password.lower() in (email, company) and password: self.add_error( "password", "Choose a password that is not your email address or company name.", ) return cleaned