示例#1
0
    async def forgot_password(self, data: dict, ip: str) -> None:
        """POST /forgot_password

        Only for accounts with password.

        Args:
            data: {email: "*****@*****.**"}
            ip: ip from request

        Returns:
            None

        Raises:
            HTTPException:
                400 - validation or timeout.
                404 - email not found.
        """
        try:
            email = UserInForgotPassword(**data).email
        except ValidationError:
            raise HTTPException(400,
                                detail=get_error_message(
                                    "validation", self._language))

        item = await self._repo.get_by_email(email)

        if item is None:
            raise HTTPException(404,
                                detail=get_error_message(
                                    "email not found", self._language))

        if item.get("password") is None:
            raise HTTPException(406)

        id = item.get("id")

        if not await self._repo.is_password_reset_available(id):
            raise HTTPException(400,
                                detail=get_error_message(
                                    "reset before", self._language))
        logger.info(f"forgot_password ip={ip} email={email}")

        token = create_random_string()
        token_hash = hash_string(token)

        await self._repo.set_password_reset_token(id, token_hash)

        # if not self._debug:  # TODO
        email_client = self._create_email_client()
        await email_client.send_forgot_password_email(email, token)

        return None
示例#2
0
    async def password_reset(self, data: dict, token: str) -> None:
        token_hash = hash_string(token)

        id = await self._repo.get_id_for_password_reset(token_hash)
        if id is None:
            raise HTTPException(404)

        user_model = self._validate_user_model(UserInSetPassword, data)

        password_hash = get_password_hash(user_model.password1)
        await self._repo.set_password(id, password_hash)

        return None
示例#3
0
async def test_password_reset():
    token = create_random_string()
    token_hash = hash_string(token)
    service = PasswordService()
    await service._repo.set_password_reset_token(1, token_hash)

    await service.password_reset(
        {
            "password1": "87654321",
            "password2": "87654321",
        },
        token,
    )

    item = await service._repo.get(1)
    assert item.get("password") != "12345678"
示例#4
0
async def test_confirm_email():
    auth_service = AuthService()
    email = "*****@*****.**"
    token = create_random_string()
    token_hash = hash_string(token)
    await auth_service._repo.request_email_confirmation(email, token_hash)

    with pytest.raises(HTTPException) as e:
        await auth_service.confirm_email("wrongtoken")

    assert e.type is HTTPException
    assert e.value.args[0] == 403  # TODO: 400 maybe

    await auth_service.confirm_email(token)

    item = await auth_service._repo.get_by_email(email)
    assert item.get("confirmed")
示例#5
0
    async def confirm_email(self, token: str) -> None:
        """POST /confirm/{token}

        Hashes token, looks up hash in db, updates "confirmed" to True for email in a row.

        Returns:
            None

        Raises:
            HTTPException:
                403 - no hash in db.
        """
        token_hash = hash_string(token)
        if not await self._repo.confirm_email(token_hash):
            raise HTTPException(
                403)  # TODO: ??? 400 maybe, change frontend too

        return None
示例#6
0
 async def _request_email_confirmation(self, email: str) -> None:
     token = create_random_string()
     token_hash = hash_string(token)
     await self._repo.request_email_confirmation(email, token_hash)
     email_client = self._create_email_client()
     await email_client.send_confirmation_email(email, token)