def test_check_password(user_account): user = user_account() user.set_password("CORRECT_PASSWORD") user.save(update_fields=("password", )) with pytest.raises(WrongPasswordError): PasswordService.check_password(user, "INCORRECT_PASSWORD")
class ConfirmResetPasswordSerializer(serializers.Serializer): password = serializers.CharField(max_length=128, write_only=True, style={"input_type": "password"}) signature = serializers.CharField(max_length=71, write_only=True) def __init__(self, *args, **kwargs): super(ConfirmResetPasswordSerializer, self).__init__(*args, **kwargs) self.password_service = PasswordService() def validate_password(self, password): try: self.password_service.validate_password(password) except InvalidPasswordError as e: raise ValidationError(e) from e return password def save(self, **kwargs): new_password = self.validated_data["password"] signature = self.validated_data["signature"] try: self.password_service.reset_password(signature, new_password) except InvalidResetPasswordSignatureError as e: raise ValidationError({"signature": e.message}) from e def create(self, validated_data): assert False, "Do not use update directly" def update(self, instance, validated_data): assert False, "Do not use update directly"
def test_send_reset_password_link_success(settings, user_account, mocker): user = user_account() domain_name = "test_send_reset_password_link_success.com" signature = "signature" site = Site.objects.create(domain=domain_name, name=domain_name) settings.SITE_ID = site.pk mocked_generate_reset_password_signature = mocker.patch( f"{PASSWORD_SERVICE_PATH}._generate_reset_password_signature", return_value=signature) mocked_send_notification = mocker.patch( f"{PASSWORD_SERVICE_PATH}._send_notification") PasswordService.send_reset_password_link(user.email) mocked_generate_reset_password_signature.assert_called_once_with(user) mocked_send_notification.assert_called_once_with( user.pk, { "user_notification_salutation": "Dear client", "domain_name": domain_name, "reset_password_link": f"https://{domain_name}/reset-password/{signature}", }, )
def test_reset_password_success(user_account, mocker): new_password = "******" # nosec user = user_account() reset_password_signature = TimestampSigner().sign(user.pk) mocked_change_password = mocker.patch( f"{PASSWORD_SERVICE_PATH}.change_password") PasswordService.reset_password(reset_password_signature, new_password) mocked_change_password.assert_called_once_with(user, new_password)
def test_reset_password_user_failure(mocker): new_password = "******" # nosec assert UserAccount.objects.count() == 0 reset_password_signature = TimestampSigner().sign(uuid.uuid4()) mocked_change_password = mocker.patch( f"{PASSWORD_SERVICE_PATH}.change_password") with pytest.raises(InvalidResetPasswordSignatureError): PasswordService.reset_password(reset_password_signature, new_password) assert mocked_change_password.call_count == 0
def test_send_reset_password_link_failure(mocker): assert UserAccount.objects.count() == 0 mocked_generate_reset_password_signature = mocker.patch( f"{PASSWORD_SERVICE_PATH}._generate_reset_password_signature") mocked_send_notification = mocker.patch( f"{PASSWORD_SERVICE_PATH}._send_notification") PasswordService.send_reset_password_link("*****@*****.**") assert mocked_generate_reset_password_signature.call_count == 0 assert mocked_send_notification.call_count == 0
def test_reset_password_signature_failure(mocker, settings, exception): new_password = "******" # nosec reset_password_signature = "reset_password_signature" # nosec mocker.patch("django.core.signing.TimestampSigner.unsign", side_effect=exception("Some message")) settings.HONEY_MONEY_RESET_PASSWORD_EXPIRATION_DELTA = 42 mocked_change_password = mocker.patch( f"{PASSWORD_SERVICE_PATH}.change_password") with pytest.raises(InvalidResetPasswordSignatureError): PasswordService.reset_password(reset_password_signature, new_password) assert mocked_change_password.call_count == 0
def test_change_password(user_account): old_password = "******" # nosec new_password = "******" # nosec user = user_account() user.set_password(old_password) user.save(update_fields=("password", )) assert user.check_password(old_password) PasswordService.change_password(user, new_password) user.refresh_from_db() assert user.check_password(new_password)
class ResetPasswordSerializer(serializers.Serializer): email = serializers.EmailField(max_length=128, write_only=True) def __init__(self, *args, **kwargs): super(ResetPasswordSerializer, self).__init__(*args, **kwargs) self.password_service = PasswordService() def save(self, **kwargs): email = self.validated_data["email"] self.password_service.send_reset_password_link(email) def create(self, validated_data): assert False, "Do not use update directly" def update(self, instance, validated_data): assert False, "Do not use update directly"
class ChangePasswordSerializer(serializers.Serializer): old_password = serializers.CharField(max_length=128, write_only=True, style={"input_type": "password"}) new_password = serializers.CharField(max_length=128, write_only=True, style={"input_type": "password"}) def __init__(self, *args, **kwargs): super(ChangePasswordSerializer, self).__init__(*args, **kwargs) self.request = self.context.get("request") self.user = getattr(self.request, "user", None) self.password_service = PasswordService() def validate_old_password(self, old_password): try: self.password_service.check_password(self.user, old_password) except WrongPasswordError as e: raise serializers.ValidationError(e.message) from e return old_password def validate_new_password(self, new_password): try: self.password_service.validate_password(new_password, user=self.user) except InvalidPasswordError as e: raise serializers.ValidationError(e.messages) from e return new_password def create(self, validated_data): assert False, "Do not use update directly" def update(self, instance, validated_data): assert False, "Do not use update directly" def save(self, **kwargs): self.password_service.change_password( self.user, self.validated_data["new_password"])
def __init__(self, *args, **kwargs): super(ResetPasswordSerializer, self).__init__(*args, **kwargs) self.password_service = PasswordService()
def __init__(self, *args, **kwargs): super(ChangePasswordSerializer, self).__init__(*args, **kwargs) self.request = self.context.get("request") self.user = getattr(self.request, "user", None) self.password_service = PasswordService()
class RegistrationSerializer(serializers.ModelSerializer): email = serializers.EmailField(write_only=True, max_length=128) password = serializers.CharField(write_only=True, max_length=128) first_name = serializers.CharField(required=True, max_length=30) last_name = serializers.CharField(required=True, max_length=30) family_uuid = serializers.UUIDField(write_only=True, required=True, allow_null=True) family_name = serializers.CharField(write_only=True, required=False, allow_null=True) class Meta: model = UserAccount fields = ("email", "first_name", "last_name", "password", "family_uuid", "family_name") def __init__(self, *args, **kwargs): super(RegistrationSerializer, self).__init__(*args, **kwargs) self.password_service = PasswordService() def validate_email(self, email): if UserAccount.objects.filter(email=email).exists(): raise ValidationError( gettext("Could not create account with this email.")) return super().validate(email) def validate_family_uuid(self, family_uuid): if family_uuid is not None and not Family.objects.filter( uuid=family_uuid).exists(): raise ValidationError( gettext("Could not find family with that uuid")) return family_uuid def validate_password(self, new_password): try: self.password_service.validate_password(new_password) except InvalidPasswordError as e: raise serializers.ValidationError(e.messages) from e return new_password def save(self, **kwargs): self.instance = UserAccount.objects.create_user( self.validated_data.get("email"), self.validated_data.get("password")) self.instance.first_name = self.validated_data.get("first_name") self.instance.last_name = self.validated_data.get("last_name") family_uuid = self.validated_data.pop("family_uuid") if family_uuid is None: family = Family.create_family( name=self.validated_data.get( "family_name", f"{self.instance.get_full_name()} Family"), creator=self.instance, ) else: family = Family.objects.get(pk=family_uuid) self.instance.family = family raw_password = self.validated_data.get("password") self.instance.set_password(raw_password) self.instance.save() return self.instance
def test_generate_reset_password_signature(user_account): user = user_account() expected_reset_password_signature = TimestampSigner().sign(user.pk) assert PasswordService._generate_reset_password_signature( user) == expected_reset_password_signature
def test_validate_password(mocker): mocker.patch("django.contrib.auth.password_validation.validate_password", side_effect=ValidationError("exception")) with pytest.raises(InvalidPasswordError): PasswordService.validate_password("SOME_PASSWORD")