def set_password(self, raw_password=None, hashed_password=None, cached_password=None): """Set a password with the raw password string, or the pre-hashed password. If using the raw string, """ assert hashed_password is None or settings.DEBUG, "Only use hashed_password in debug mode." assert raw_password is not None or hashed_password is not None, "Must be passing in raw or hashed password" assert not (raw_password is not None and hashed_password is not None), "Must be specifying only one--not both." if raw_password: verify_raw_password(raw_password) if hashed_password: self.password = hashed_password # Can't save a cached password from a hash, so just make sure there is none. # Note: Need to do this, even if they're not enabled--we don't want to risk # being out of sync (if people turn on/off/on the feature CachedPassword.invalidate_cached_password(user=self) else: n_iters = settings.PASSWORD_ITERATIONS_TEACHER_SYNCED if self.is_teacher else settings.PASSWORD_ITERATIONS_STUDENT_SYNCED self.password = crypt(raw_password, iterations=n_iters) if self.id: CachedPassword.set_cached_password(self, raw_password)
def clean(self): facility = self.cleaned_data.get('facility') username = self.cleaned_data.get('username', '') zone = self.cleaned_data.get('zone_fallback') # Don't allow (only through the form) the same username within the same facility, or conflicting with the admin. users_with_same_username = FacilityUser.objects.filter(username__iexact=username, facility=facility) username_taken = users_with_same_username.count() > 0 username_changed = not self.instance or self.instance.username != username if username_taken and username_changed or User.objects.filter(username__iexact=username).count() > 0: self.set_field_error(field_name='username', message=_("A user with this username already exists. Please choose a new username and try again.")) ## Check password password_first = self.cleaned_data.get('password_first', "") password_recheck = self.cleaned_data.get('password_recheck', "") # If they have put anything in the new password field, it must match the password check field if password_first != password_recheck: self.set_field_error(field_name='password_recheck', message=_("The passwords didn't match. Please re-enter the passwords.")) # Next, enforce length if they submitted a password if password_first: try: verify_raw_password(password_first) except ValidationError as ve: # MUST: The ValidationError constructor sets the error message into a list with # `self.messages = [message]` so we get the first message from the list. It # should have assigned the value to `self.message = message` too but maybe on # newer Django versions this is fixed. message = '' if hasattr(ve, 'messages') and isinstance(ve.messages, list) and ve.messages: message = ve.messages[0] self.set_field_error(field_name='password_first', message=message) elif (self.instance and not self.instance.password) or password_first or password_recheck: # Only perform check on a new user or a password change if password_first != password_recheck: self.set_field_error(field_name='password_recheck', message=_("The passwords didn't match. Please re-enter the passwords.")) ## Warn the user during sign up or adding user if a user with this first and last name already exists in the facility if not self.cleaned_data.get("warned", False) and (self.cleaned_data["first_name"] or self.cleaned_data["last_name"]): users_with_same_name = FacilityUser.objects.filter(first_name__iexact=self.cleaned_data["first_name"], last_name__iexact=self.cleaned_data["last_name"]) \ .filter(Q(signed_by__devicezone__zone=zone) | Q(zone_fallback=zone)) # within the same facility if users_with_same_name and (not self.instance or self.instance not in users_with_same_name): self.data = copy.deepcopy(self.data) self.data["warned"] = self.cleaned_data["warned"] = True msg = "%s %s" % (_("%(num_users)d user(s) with first name '%(f_name)s' and last name '%(l_name)s' already exist(s).") % { "num_users": users_with_same_name.count(), "f_name": self.cleaned_data["first_name"], "l_name": self.cleaned_data["last_name"], }, _("If you are sure you want to create this user, you may re-submit the form to complete the process.")) self.set_field_error(message=msg) # general error, not associated with a field. if self.has_errors(): return self.cleaned_data else: return super(FacilityUserForm, self).clean()
def clean(self): facility = self.cleaned_data.get('facility') username = self.cleaned_data.get('username', '') zone = self.cleaned_data.get('zone_fallback') # Don't allow (only through the form) the same username within the same facility, or conflicting with the admin. users_with_same_username = FacilityUser.objects.filter( username__iexact=username, facility=facility) username_taken = users_with_same_username.count() > 0 username_changed = not self.instance or self.instance.username != username if username_taken and username_changed or User.objects.filter( username__iexact=username).count() > 0: self.set_field_error( field_name='username', message= _("A user with this username already exists. Please choose a new username and try again." )) ## Check password password_first = self.cleaned_data.get('password_first', "") password_recheck = self.cleaned_data.get('password_recheck', "") # If they have put anything in the new password field, it must match the password check field if password_first != password_recheck: self.set_field_error( field_name='password_recheck', message=_( "The passwords didn't match. Please re-enter the passwords." )) # Next, enforce length if they submitted a password if password_first: try: verify_raw_password(password_first) except ValidationError as ve: # MUST: The ValidationError constructor sets the error message into a list with # `self.messages = [message]` so we get the first message from the list. It # should have assigned the value to `self.message = message` too but maybe on # newer Django versions this is fixed. message = '' if hasattr(ve, 'messages') and isinstance( ve.messages, list) and ve.messages: message = ve.messages[0] self.set_field_error(field_name='password_first', message=message) elif (self.instance and not self.instance.password ) or password_first or password_recheck: # Only perform check on a new user or a password change if password_first != password_recheck: self.set_field_error( field_name='password_recheck', message= _("The passwords didn't match. Please re-enter the passwords." )) ## Warn the user during sign up or adding user if a user with this first and last name already exists in the facility if not self.cleaned_data.get( "warned", False) and (self.cleaned_data["first_name"] or self.cleaned_data["last_name"]): users_with_same_name = FacilityUser.objects.filter(first_name__iexact=self.cleaned_data["first_name"], last_name__iexact=self.cleaned_data["last_name"]) \ .filter(Q(signed_by__devicezone__zone=zone) | Q(zone_fallback=zone)) # within the same facility if users_with_same_name and (not self.instance or self.instance not in users_with_same_name): self.data = copy.deepcopy(self.data) self.data["warned"] = self.cleaned_data["warned"] = True msg = "%s %s" % ( _("%(num_users)d user(s) with first name '%(f_name)s' and last name '%(l_name)s' already exist(s)." ) % { "num_users": users_with_same_name.count(), "f_name": self.cleaned_data["first_name"], "l_name": self.cleaned_data["last_name"], }, _("If you are sure you want to create this user, you may re-submit the form to complete the process." )) self.set_field_error( message=msg) # general error, not associated with a field. if self.has_errors(): return self.cleaned_data else: return super(FacilityUserForm, self).clean()