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 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') ## check if given username is unique on both facility users and admins, whatever the casing # # Change: don't allow (only through the form) the same username either in the same facility, # or even in the same zone. # Change: Use 'all_objects' instead of 'objects' in order to return soft deleted users as well. users_with_same_username = FacilityUser.all_objects.filter(username__iexact=username, facility=facility) \ or FacilityUser.all_objects.filter(username__iexact=username) \ .filter(Q(signed_by__devicezone__zone=zone) | Q(zone_fallback=zone)) # within the same zone username_taken = users_with_same_username.count() > 0 username_changed = not self.instance or self.instance.username != username if username_taken and username_changed: error_message = _("A user with this username already exists. Please choose a new username and try again.") self.set_field_error(field_name='username', message=error_message) elif User.objects.filter(username__iexact=username).count() > 0: # Admin (django) user exists with the same name; we don't want overlap there! self.set_field_error(field_name='username', message=_("The specified username is unavailable. 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: self.set_field_error(field_name='password_first', message=ve.messages[0]) ## 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') ## check if given username is unique on both facility users and admins, whatever the casing # # Change: don't allow (only through the form) the same username either in the same facility, # or even in the same zone. users_with_same_username = FacilityUser.objects.filter(username__iexact=username, facility=facility) \ or FacilityUser.objects.filter(username__iexact=username) \ .filter(Q(signed_by__devicezone__zone=zone) | Q(zone_fallback=zone)) # within the same zone username_taken = users_with_same_username.count() > 0 username_changed = not self.instance or self.instance.username != username if username_taken and username_changed: error_message = _("A user with this username already exists. Please choose a new username and try again.") self.set_field_error(field_name='username', message=error_message) elif User.objects.filter(username__iexact=username).count() > 0: # Admin (django) user exists with the same name; we don't want overlap there! self.set_field_error(field_name='username', message=_("The specified username is unavailable. 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: self.set_field_error(field_name='password_first', message=ve.messages[0]) ## Warn the user during sign up or adding user if a user with this first and last name already exists in the faiclity 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 handle(self, *args, **options): if len(args) != 1: raise CommandError("need exactly one argument (username)") if args: username, = args try: u = FacilityUser.objects.using(options.get('database')).get(username=username) except FacilityUser.DoesNotExist: raise CommandError("user '%s' does not exist" % username) self.stdout.write("Changing password for user '%s'\n" % u.username) if options['noinput']: p1 = generate_random_password() self.stdout.write("Generated new password for user '%s': '%s'\n" % (username, p1)) else: MAX_TRIES = 3 count = 0 p1, p2 = 1, 2 # To make them initially mismatch. while p1 != p2 and count < MAX_TRIES: p1 = self._get_pass() try: verify_raw_password(p1) except ValidationError as e: self.stderr.write(unicode(e) + "\n") count += 1 continue p2 = self._get_pass("Password (again): ") if p1 != p2: self.stdout.write("Passwords do not match. Please try again.\n") count = count + 1 if count == MAX_TRIES: raise CommandError("Aborting password change for user '%s' after %s attempts" % (username, count)) u.set_password(p1) u.save() return "Password changed successfully for user '%s'\n" % u.username
def clean(self): facility = self.cleaned_data.get('facility') username = self.cleaned_data.get('username', '') zone = self.cleaned_data.get('zone_fallback') ## check if given username is unique on both facility users and admins, whatever the casing # # Change: don't allow (only through the form) the same username either in the same facility, # or even in the same zone. users_with_same_username = FacilityUser.objects.filter(username__iexact=username, facility=facility) \ or FacilityUser.objects.filter(username__iexact=username) \ .filter(Q(signed_by__devicezone__zone=zone) | Q(zone_fallback=zone)) # within the same zone username_taken = users_with_same_username.count() > 0 username_changed = not self.instance or self.instance.username != username if username_taken and username_changed: error_message = _( "A user with this username already exists. Please choose a new username and try again." ) self.set_field_error(field_name='username', message=error_message) elif User.objects.filter(username__iexact=username).count() > 0: # Admin (django) user exists with the same name; we don't want overlap there! self.set_field_error( field_name='username', message= _("The specified username is unavailable. 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 (self.instance and not self.instance.password) or password_first: # No password set, or password is being reset try: verify_raw_password(password_first) except ValidationError as ve: self.set_field_error(field_name='password_first', message=ve.messages[0]) 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." )) ## Check the name combo; do it here so it's a general error. if not self.cleaned_data.get("warned", False): 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 this name already exist(s)%(username_list)s." ) % { "num_users": users_with_same_name.count(), "username_list": "" if not self.admin_access else " " + str([ user["username"] for user in users_with_same_name.values("username") ]), }, _("Please consider choosing another name, or re-submit to complete." )) 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()