Exemplo n.º 1
0
    async def authenticate(
        self, credentials: OAuth2PasswordRequestForm
    ) -> Optional[UD]:
        """
        Authenticate and return a user following an phone and a password.

        Will automatically upgrade password hash if necessary.
        """
        user = await self.get_by_phone(credentials.username)

        if user is None:
            # Run the hasher to mitigate timing attack
            # Inspired from Django: https://code.djangoproject.com/ticket/20760
            password.get_password_hash(credentials.password)
            return None

        verified, updated_password_hash = password.verify_and_update_password(
            credentials.password, user.hashed_password
        )
        if not verified:
            return None
        # Update password hash to a more robust one if needed
        if updated_password_hash is not None:
            user.hashed_password = updated_password_hash
            await self.update(user)

        return user
Exemplo n.º 2
0
async def test_queries(sqlalchemy_user_db: SQLAlchemyUserDatabase[UserDB]):
    user = UserDB(
        email="*****@*****.**",
        hashed_password=get_password_hash("guinevere"),
    )

    # Create
    user_db = await sqlalchemy_user_db.create(user)
    assert user_db.id is not None
    assert user_db.is_active is True
    assert user_db.is_superuser is False
    assert user_db.email == user.email

    # Update
    user_db.is_superuser = True
    await sqlalchemy_user_db.update(user_db)

    # Get by id
    id_user = await sqlalchemy_user_db.get(user.id)
    assert id_user is not None
    assert id_user.id == user_db.id
    assert id_user.is_superuser is True

    # Get by email
    email_user = await sqlalchemy_user_db.get_by_email(str(user.email))
    assert email_user is not None
    assert email_user.id == user_db.id

    # Exception when inserting existing email
    with pytest.raises(sqlite3.IntegrityError):
        await sqlalchemy_user_db.create(user)

    # Exception when inserting non-nullable fields
    with pytest.raises(sqlite3.IntegrityError):
        wrong_user = UserDB(hashed_password="******")
        await sqlalchemy_user_db.create(wrong_user)

    # Unknown user
    unknown_user = await sqlalchemy_user_db.get_by_email("*****@*****.**")
    assert unknown_user is None

    # Delete user
    await sqlalchemy_user_db.delete(user)
    deleted_user = await sqlalchemy_user_db.get(user.id)
    assert deleted_user is None

    # Exception when creating/updating a OAuth user
    user_oauth = UserDBOAuth(
        email="*****@*****.**",
        hashed_password=get_password_hash("guinevere"),
    )
    with pytest.raises(NotSetOAuthAccountTableError):
        await sqlalchemy_user_db.create(user_oauth)
    with pytest.raises(NotSetOAuthAccountTableError):
        await sqlalchemy_user_db.update(user_oauth)

    # Exception when trying to get by OAuth account
    with pytest.raises(NotSetOAuthAccountTableError):
        await sqlalchemy_user_db.get_by_oauth_account("foo", "bar")
Exemplo n.º 3
0
async def edit_user_profile(
    user_update: UserUpdate,
    user: User = Depends(fastapi_users.get_current_active_user)
):
    # Email and Password field not provided in JSON argument
    if user_update.email is None and user_update.password is None:
        raise HTTPException(status_code=400, detail="An email or password is needed.")

    # Email field provided
    current_email = user.email
    if user_update.email is not None:
        new_email = user_update.email
        user_in_db = mongo_db_users_reg.find_json({"email": new_email})
        if user_in_db is None:
            mongo_db_users_reg.collection.update_one(
                {"email": user.email}, 
                {"$set": {"email": new_email}}
            )
            current_email = new_email
        else:
            raise HTTPException(
            status_code=400, detail="Email is already used.")
    
    # password field provided
    if user_update.password is not None:
        new_password = user_update.password
        hashed_password = get_password_hash(new_password)
        mongo_db_users_reg.collection.update_one(
            {"email": current_email}, 
            {"$set": {"hashed_password": hashed_password}}
        )
    
    return {"Message": "Success", "Email": current_email}
Exemplo n.º 4
0
    async def reset_password(token: str = Body(...),
                             password: str = Body(...)):
        try:
            data = jwt.decode(
                token,
                reset_password_token_secret,
                audience=reset_password_token_audience,
                algorithms=[JWT_ALGORITHM],
            )
            user_id = data.get("user_id")
            if user_id is None:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=ErrorCode.RESET_PASSWORD_BAD_TOKEN,
                )

            user = await user_db.get(user_id)
            if user is None or not user.is_active:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=ErrorCode.RESET_PASSWORD_BAD_TOKEN,
                )

            user.hashed_password = get_password_hash(password)
            await user_db.update(user)
        except jwt.PyJWTError:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=ErrorCode.RESET_PASSWORD_BAD_TOKEN,
            )
Exemplo n.º 5
0
    async def create(
        self, user: models.UC, safe: bool = False, request: Optional[Request] = None
    ) -> models.UD:
        """
        Create a user in database.

        Triggers the on_after_register handler on success.

        :param user: The UserCreate model to create.
        :param safe: If True, sensitive values like is_superuser or is_verified
        will be ignored during the creation, defaults to False.
        :param request: Optional FastAPI request that
        triggered the operation, defaults to None.
        :raises UserAlreadyExists: A user already exists with the same e-mail.
        :return: A new user.
        """
        await self.validate_password(user.password, user)

        existing_user = await self.user_db.get_by_email(user.email)
        if existing_user is not None:
            raise UserAlreadyExists()

        hashed_password = get_password_hash(user.password)
        user_dict = (
            user.create_update_dict() if safe else user.create_update_dict_superuser()
        )
        db_user = self.user_db_model(**user_dict, hashed_password=hashed_password)

        created_user = await self.user_db.create(db_user)

        await self.on_after_register(created_user, request)

        return created_user
Exemplo n.º 6
0
async def test_queries_oauth(
    ormar_user_db_oauth: OrmarUserDatabase[UserDBOAuth],
    oauth_account1,
    oauth_account2,
    oauth_account3,
):
    user = UserDBOAuth(
        email="*****@*****.**",
        hashed_password=get_password_hash("guinevere"),
        oauth_accounts=[oauth_account1, oauth_account2],
    )

    # Create
    user_db = await ormar_user_db_oauth.create(user)
    assert user_db.id is not None
    assert hasattr(user_db, "oauth_accounts")
    assert len(user_db.oauth_accounts) == 2

    # Update
    user_db.oauth_accounts[0].access_token = "NEW_TOKEN"
    await ormar_user_db_oauth.update(user_db)

    # Get by id
    id_user = await ormar_user_db_oauth.get(user.id)
    assert id_user is not None
    assert id_user.id == user_db.id
    assert id_user.oauth_accounts[0].access_token == "NEW_TOKEN"

    # Add new oauth
    id_user.oauth_accounts.append(oauth_account3)
    await ormar_user_db_oauth.update(id_user)
    id_user_updated = await ormar_user_db_oauth.get(user.id)
    assert len(id_user_updated.oauth_accounts) == 3

    # Remove oauth2 and update
    id_user.oauth_accounts = [
        oauth for oauth in id_user.oauth_accounts
        if oauth.id != oauth_account2.id
    ]
    await ormar_user_db_oauth.update(id_user)
    id_user_updated = await ormar_user_db_oauth.get(user.id)
    assert len(id_user_updated.oauth_accounts) == 2

    # Get by email
    email_user = await ormar_user_db_oauth.get_by_email(str(user.email))
    assert email_user is not None
    assert email_user.id == user_db.id
    assert len(email_user.oauth_accounts) == 2

    # Get by OAuth account
    oauth_user = await ormar_user_db_oauth.get_by_oauth_account(
        oauth_account1.oauth_name, oauth_account1.account_id)
    assert oauth_user is not None
    assert oauth_user.id == user.id

    # Unknown OAuth account
    unknown_oauth_user = await ormar_user_db_oauth.get_by_oauth_account(
        "foo", "bar")
    assert unknown_oauth_user is None
Exemplo n.º 7
0
 async def _update_user(user: models.BaseUserDB, update_dict: Dict[str, Any]):
     for field in update_dict:
         if field == "password":
             hashed_password = get_password_hash(update_dict[field])
             user.hashed_password = hashed_password
         else:
             setattr(user, field, update_dict[field])
     return await user_db.update(user)
Exemplo n.º 8
0
async def test_queries(ormar_user_db: OrmarUserDatabase[UserDB]):
    user = UserDB(
        email="*****@*****.**",
        hashed_password=get_password_hash("guinevere"),
    )

    # Create
    user_db = await ormar_user_db.create(user)
    assert user_db.id is not None
    assert user_db.is_active is True
    assert user_db.is_superuser is False
    assert user_db.email == user.email

    # Update
    user_db.is_superuser = True
    await ormar_user_db.update(user_db)

    # Exception when updating a user with a not existing id
    id_backup = user_db.id
    user_db.id = uuid.uuid4()
    with pytest.raises(NoMatch):
        await ormar_user_db.update(user_db)
    user_db.id = id_backup

    # Get by id
    id_user = await ormar_user_db.get(user.id)
    assert id_user is not None
    assert id_user.id == user_db.id
    assert id_user.is_superuser is True

    # Get by email
    email_user = await ormar_user_db.get_by_email(str(user.email))
    assert email_user is not None
    assert email_user.id == user_db.id

    # Get by uppercased email
    email_user = await ormar_user_db.get_by_email("*****@*****.**")
    assert email_user is not None
    assert email_user.id == user_db.id

    # Exception when inserting existing email
    with pytest.raises(IntegrityError):
        await ormar_user_db.create(user)

    # Exception when inserting non-nullable fields
    with pytest.raises(ValueError):
        wrong_user = UserDB(hashed_password="******")
        await ormar_user_db.create(wrong_user)

    # Unknown user
    unknown_user = await ormar_user_db.get_by_email("*****@*****.**")
    assert unknown_user is None

    # Delete user
    await ormar_user_db.delete(user)
    deleted_user = await ormar_user_db.get(user.id)
    assert deleted_user is None
Exemplo n.º 9
0
class UserFactory(factory.alchemy.SQLAlchemyModelFactory):
    class Meta:
        model = models.User

    id = factory.LazyAttribute(lambda _: uuid4())
    email = factory.Faker('email')
    hashed_password = factory.LazyAttribute(lambda obj: get_password_hash('test'))
    is_active = True
    is_verified = True
    is_superuser = False
Exemplo n.º 10
0
 async def _update_user(
         user: models.UserDB,
         update_dict: typing.Dict[str, typing.Any]  # type: ignore
 ):
     for field in update_dict:
         if field == "password":
             hashed_password = get_password_hash(update_dict[field])
             user.hashed_password = hashed_password
         else:
             setattr(user, field, update_dict[field])
     return await user_db.update(user)
Exemplo n.º 11
0
 async def _update_user(user: models.BaseUserDB,
                        update_dict: Dict[str, Any], request: Request):
     for field in update_dict:
         if field == "password":
             hashed_password = get_password_hash(update_dict[field])
             user.hashed_password = hashed_password
         else:
             setattr(user, field, update_dict[field])
     updated_user = await user_db.update(user)
     if after_update:
         await run_handler(after_update, updated_user, update_dict, request)
     return updated_user
Exemplo n.º 12
0
    async def reset_password(
        request: Request, token: str = Body(...), password: str = Body(...)
    ):
        try:
            data = jwt.decode(
                token,
                reset_password_token_secret,
                audience=RESET_PASSWORD_TOKEN_AUDIENCE,
                algorithms=[JWT_ALGORITHM],
            )
            user_id = data.get("user_id")
            if user_id is None:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=ErrorCode.RESET_PASSWORD_BAD_TOKEN,
                )

            try:
                user_uiid = UUID4(user_id)
            except ValueError:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=ErrorCode.RESET_PASSWORD_BAD_TOKEN,
                )

            user = await user_db.get(user_uiid)
            if user is None or not user.is_active:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=ErrorCode.RESET_PASSWORD_BAD_TOKEN,
                )

            if validate_password:
                try:
                    await validate_password(password, user)
                except InvalidPasswordException as e:
                    raise HTTPException(
                        status_code=status.HTTP_400_BAD_REQUEST,
                        detail={
                            "code": ErrorCode.RESET_PASSWORD_INVALID_PASSWORD,
                            "reason": e.reason,
                        },
                    )

            user.hashed_password = get_password_hash(password)
            await user_db.update(user)
            if after_reset_password:
                await run_handler(after_reset_password, user, request)
        except jwt.PyJWTError:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=ErrorCode.RESET_PASSWORD_BAD_TOKEN,
            )
Exemplo n.º 13
0
async def _update_user(
    user: UserDB, update_dict: Dict[str, Any], request: Request
):
    #TODO: implement changing roles
    for field in update_dict:
        if field == "password":
            hashed_password = get_password_hash(update_dict[field])
            user.hashed_password = hashed_password
        else:
            setattr(user, field, update_dict[field])
    updated_user = await user_db.update(user)
    return updated_user
Exemplo n.º 14
0
async def update_user(user_id: UUID4, update_dict: Dict[str, Any]) -> UserDB:
    user = await get_or_404(user_id)
    user = dict(user)
    for field in update_dict:
        if field == "password" and update_dict[field]:
            hashed_password = get_password_hash(update_dict[field])
            user["hashed_password"] = hashed_password
        elif update_dict[field] is not None:
            user[field] = update_dict[field]
    updated_user = await user_db.update(UserDB(**user))

    return updated_user
Exemplo n.º 15
0
    async def create_user(user: models.BaseUserCreate,
                          safe: bool = False) -> models.BaseUserDB:
        existing_user = await user_db.get_by_email(user.email)

        if existing_user is not None:
            raise UserAlreadyExists()

        hashed_password = get_password_hash(user.password)
        user_dict = (user.create_update_dict()
                     if safe else user.create_update_dict_superuser())
        db_user = user_db_model(**user_dict, hashed_password=hashed_password)
        return await user_db.create(db_user)
Exemplo n.º 16
0
async def test_queries(tortoise_user_db: TortoiseUserDatabase[UserDB]):
    user = UserDB(
        id="111",
        email="*****@*****.**",
        hashed_password=get_password_hash("guinevere"),
    )

    # Create
    user_db = await tortoise_user_db.create(user)
    assert user_db.id is not None
    assert user_db.is_active is True
    assert user_db.is_superuser is False
    assert user_db.email == user.email

    # Update
    user_db.is_superuser = True
    await tortoise_user_db.update(user_db)

    # Get by id
    id_user = await tortoise_user_db.get(user.id)
    assert id_user is not None
    assert id_user.id == user_db.id
    assert id_user.is_superuser is True

    # Get by email
    email_user = await tortoise_user_db.get_by_email(str(user.email))
    assert email_user is not None
    assert email_user.id == user_db.id

    # List
    users = await tortoise_user_db.list()
    assert len(users) == 1
    first_user = users[0]
    assert first_user.id == user_db.id

    # Exception when inserting existing email
    with pytest.raises(IntegrityError):
        await tortoise_user_db.create(user)

    # Exception when inserting non-nullable fields
    with pytest.raises(ValueError):
        wrong_user = UserDB(id="222", hashed_password="******")
        await tortoise_user_db.create(wrong_user)

    # Unknown user
    unknown_user = await tortoise_user_db.get_by_email("*****@*****.**")
    assert unknown_user is None

    # Delete user
    await tortoise_user_db.delete(user)
    deleted_user = await tortoise_user_db.get(user.id)
    assert deleted_user is None
Exemplo n.º 17
0
async def test_email_query(
    mongodb_user_db: MongoDBUserDatabase[UserDB], email: str, query: str, found: bool
):
    user = UserDB(email=email, hashed_password=get_password_hash("guinevere"),)
    await mongodb_user_db.create(user)

    email_user = await mongodb_user_db.get_by_email(query)

    if found:
        assert email_user is not None
        assert email_user.id == user.id
    else:
        assert email_user is None
Exemplo n.º 18
0
async def test_queries_custom_fields(ormar_user_db: OrmarUserDatabase[UserDB]):
    """It should output custom fields in query result."""
    user = UserDB(
        email="*****@*****.**",
        hashed_password=get_password_hash("guinevere"),
        first_name="Lancelot",
    )
    await ormar_user_db.create(user)

    id_user = await ormar_user_db.get(user.id)
    assert id_user is not None
    assert id_user.id == user.id
    assert id_user.first_name == user.first_name
Exemplo n.º 19
0
async def test_queries_oauth(
    tortoise_user_db_oauth: TortoiseUserDatabase[UserDBOAuth],
    oauth_account1,
    oauth_account2,
):
    user = UserDBOAuth(
        id="111",
        email="*****@*****.**",
        hashed_password=get_password_hash("guinevere"),
        oauth_accounts=[oauth_account1, oauth_account2],
    )

    # Create
    user_db = await tortoise_user_db_oauth.create(user)
    assert user_db.id is not None
    assert hasattr(user_db, "oauth_accounts")
    assert len(user_db.oauth_accounts) == 2

    # Update
    user_db.oauth_accounts[0].access_token = "NEW_TOKEN"
    await tortoise_user_db_oauth.update(user_db)

    # Get by id
    id_user = await tortoise_user_db_oauth.get(user.id)
    assert id_user is not None
    assert id_user.id == user_db.id
    assert id_user.oauth_accounts[0].access_token == "NEW_TOKEN"

    # Get by email
    email_user = await tortoise_user_db_oauth.get_by_email(str(user.email))
    assert email_user is not None
    assert email_user.id == user_db.id
    assert len(email_user.oauth_accounts) == 2

    # List
    users = await tortoise_user_db_oauth.list()
    assert len(users) == 1
    first_user = users[0]
    assert first_user.id == user_db.id
    assert len(first_user.oauth_accounts) == 2

    # Get by OAuth account
    oauth_user = await tortoise_user_db_oauth.get_by_oauth_account(
        oauth_account1.oauth_name, oauth_account1.account_id)
    assert oauth_user is not None
    assert oauth_user.id == user.id

    # Unknown OAuth account
    unknown_oauth_user = await tortoise_user_db_oauth.get_by_oauth_account(
        "foo", "bar")
    assert unknown_oauth_user is None
Exemplo n.º 20
0
    async def oauth_callback(
        self, oauth_account: models.BaseOAuthAccount, request: Optional[Request] = None
    ) -> models.UD:
        """
        Handle the callback after a successful OAuth authentication.

        If the user already exists with this OAuth account, the token is updated.

        If a user with the same e-mail already exists,
        the OAuth account is linked to it.

        If the user does not exist, it is created and the on_after_register handler
        is triggered.

        :param oauth_account: The new OAuth account to create.
        :param request: Optional FastAPI request that
        triggered the operation, defaults to None
        :return: A user.
        """
        try:
            user = await self.get_by_oauth_account(
                oauth_account.oauth_name, oauth_account.account_id
            )
        except UserNotExists:
            try:
                # Link account
                user = await self.get_by_email(oauth_account.account_email)
                user.oauth_accounts.append(oauth_account)  # type: ignore
                await self.user_db.update(user)
            except UserNotExists:
                # Create account
                password = generate_password()
                user = self.user_db_model(
                    email=oauth_account.account_email,
                    hashed_password=get_password_hash(password),
                    oauth_accounts=[oauth_account],
                )
                await self.user_db.create(user)
                await self.on_after_register(user, request)
        else:
            # Update oauth
            updated_oauth_accounts = []
            for existing_oauth_account in user.oauth_accounts:  # type: ignore
                if existing_oauth_account.account_id == oauth_account.account_id:
                    updated_oauth_accounts.append(oauth_account)
                else:
                    updated_oauth_accounts.append(existing_oauth_account)
            user.oauth_accounts = updated_oauth_accounts  # type: ignore
            await self.user_db.update(user)

        return user
Exemplo n.º 21
0
async def test_queries(tortoise_user_db: TortoiseUserDatabase[UserDB]):
    user = UserDB(
        phone="*****@*****.**",
        hashed_password=get_password_hash("guinevere"),
    )

    # Create
    user_db = await tortoise_user_db.create(user)
    assert user_db.id is not None
    assert user_db.is_active is True
    assert user_db.is_superuser is False
    assert user_db.phone == user.phone

    # Update
    user_db.is_superuser = True
    await tortoise_user_db.update(user_db)

    # Get by id
    id_user = await tortoise_user_db.get(user.id)
    assert id_user is not None
    assert id_user.id == user_db.id
    assert id_user.is_superuser is True

    # Get by phone
    phone_user = await tortoise_user_db.get_by_phone(str(user.phone))
    assert phone_user is not None
    assert phone_user.id == user_db.id

    # Get by uppercased phone
    phone_user = await tortoise_user_db.get_by_phone("*****@*****.**")
    assert phone_user is not None
    assert phone_user.id == user_db.id

    # Exception when inserting existing phone
    with pytest.raises(IntegrityError):
        await tortoise_user_db.create(user)

    # Exception when inserting non-nullable fields
    with pytest.raises(ValueError):
        wrong_user = UserDB(hashed_password="******")
        await tortoise_user_db.create(wrong_user)

    # Unknown user
    unknown_user = await tortoise_user_db.get_by_phone("*****@*****.**")
    assert unknown_user is None

    # Delete user
    await tortoise_user_db.delete(user)
    deleted_user = await tortoise_user_db.get(user.id)
    assert deleted_user is None
Exemplo n.º 22
0
async def test_phone_query(mongodb_user_db: MongoDBUserDatabase[UserDB],
                           phone: str, query: str, found: bool):
    user = UserDB(
        phone=phone,
        hashed_password=get_password_hash("guinevere"),
    )
    await mongodb_user_db.create(user)

    phone_user = await mongodb_user_db.get_by_phone(query)

    if found:
        assert phone_user is not None
        assert phone_user.id == user.id
    else:
        assert phone_user is None
Exemplo n.º 23
0
 async def _update(self, user: models.UD, update_dict: Dict[str, Any]) -> models.UD:
     for field, value in update_dict.items():
         if field == "email" and value != user.email:
             try:
                 await self.get_by_email(value)
                 raise UserAlreadyExists()
             except UserNotExists:
                 user.email = value
                 user.is_verified = False
         elif field == "password":
             await self.validate_password(value, user)
             hashed_password = get_password_hash(value)
             user.hashed_password = hashed_password
         else:
             setattr(user, field, value)
     return await self.user_db.update(user)
Exemplo n.º 24
0
async def test_queries(mongodb_user_db: MongoDBUserDatabase[UserDB]):
    user = UserDB(
        id="111",
        email="*****@*****.**",
        hashed_password=get_password_hash("guinevere"),
    )

    # Create
    user_db = await mongodb_user_db.create(user)
    assert user_db.id is not None
    assert user_db.is_active is True
    assert user_db.is_superuser is False
    assert user_db.email == user.email

    # Update
    user_db.is_superuser = True
    await mongodb_user_db.update(user_db)

    # Get by id
    id_user = await mongodb_user_db.get(user.id)
    assert id_user is not None
    assert id_user.id == user_db.id
    assert id_user.is_superuser is True

    # Get by email
    email_user = await mongodb_user_db.get_by_email(str(user.email))
    assert email_user is not None
    assert email_user.id == user_db.id

    # List
    users = await mongodb_user_db.list()
    assert len(users) == 1
    first_user = users[0]
    assert first_user.id == user_db.id

    # Exception when inserting existing email
    with pytest.raises(pymongo.errors.DuplicateKeyError):
        await mongodb_user_db.create(user)

    # Unknown user
    unknown_user = await mongodb_user_db.get_by_email("*****@*****.**")
    assert unknown_user is None

    # Delete user
    await mongodb_user_db.delete(user)
    deleted_user = await mongodb_user_db.get(user.id)
    assert deleted_user is None
Exemplo n.º 25
0
    async def register(user: models.UserCreate):  # type: ignore
        existing_user = await user_db.get_by_email(user.email)

        if existing_user is not None:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=ErrorCode.REGISTER_USER_ALREADY_EXISTS,
            )

        hashed_password = get_password_hash(user.password)
        db_user = models.UserDB(**user.create_update_dict(),
                                hashed_password=hashed_password)
        created_user = await user_db.create(db_user)

        await router.run_handlers(Event.ON_AFTER_REGISTER, created_user)

        return created_user
Exemplo n.º 26
0
async def test_queries(mongodb_user_db: MongoDBUserDatabase[UserDB]):
    user = UserDB(
        phone="*****@*****.**",
        hashed_password=get_password_hash("guinevere"),
    )

    # Create
    user_db = await mongodb_user_db.create(user)
    assert user_db.id is not None
    assert user_db.is_active is True
    assert user_db.is_superuser is False
    assert user_db.phone == user.phone

    # Update
    user_db.is_superuser = True
    await mongodb_user_db.update(user_db)

    # Get by id
    id_user = await mongodb_user_db.get(user.id)
    assert id_user is not None
    assert id_user.id == user_db.id
    assert id_user.is_superuser is True

    # Get by phone
    phone_user = await mongodb_user_db.get_by_phone(str(user.phone))
    assert phone_user is not None
    assert phone_user.id == user_db.id

    # Get by uppercased phone
    phone_user = await mongodb_user_db.get_by_phone("*****@*****.**")
    assert phone_user is not None
    assert phone_user.id == user_db.id

    # Exception when inserting existing phone
    with pytest.raises(pymongo.errors.DuplicateKeyError):
        await mongodb_user_db.create(user)

    # Unknown user
    unknown_user = await mongodb_user_db.get_by_phone("*****@*****.**")
    assert unknown_user is None

    # Delete user
    await mongodb_user_db.delete(user)
    deleted_user = await mongodb_user_db.get(user.id)
    assert deleted_user is None
Exemplo n.º 27
0
async def create_register_user(*, email=Form(...), password=Form(...)):
    user_in_db = await UserModel.filter(email=email)

    if user_in_db:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=ErrorCode.REGISTER_USER_ALREADY_EXISTS,
        )

    hashed_password = get_password_hash(password)
    created_user = await UserModel.create(
        id=str(uuid.uuid4()),
        email=email,
        hashed_password=hashed_password,
        is_active=True,
        is_superuser=False,
    )
    return created_user
Exemplo n.º 28
0
async def test_queries_oauth(
    sqlalchemy_user_db_oauth: SQLAlchemyUserDatabase[UserDBOAuth],
    oauth_account1,
    oauth_account2,
):
    user = UserDBOAuth(
        phone="*****@*****.**",
        hashed_password=get_password_hash("guinevere"),
        oauth_accounts=[oauth_account1, oauth_account2],
    )

    # Create
    user_db = await sqlalchemy_user_db_oauth.create(user)
    assert user_db.id is not None
    assert hasattr(user_db, "oauth_accounts")
    assert len(user_db.oauth_accounts) == 2

    # Update
    user_db.oauth_accounts[0].access_token = "NEW_TOKEN"
    await sqlalchemy_user_db_oauth.update(user_db)

    # Get by id
    id_user = await sqlalchemy_user_db_oauth.get(user.id)
    assert id_user is not None
    assert id_user.id == user_db.id
    assert id_user.oauth_accounts[0].access_token == "NEW_TOKEN"

    # Get by phone
    phone_user = await sqlalchemy_user_db_oauth.get_by_phone(str(user.phone))
    assert phone_user is not None
    assert phone_user.id == user_db.id
    assert len(phone_user.oauth_accounts) == 2

    # Get by OAuth account
    oauth_user = await sqlalchemy_user_db_oauth.get_by_oauth_account(
        oauth_account1.oauth_name, oauth_account1.account_id)
    assert oauth_user is not None
    assert oauth_user.id == user.id

    # Unknown OAuth account
    unknown_oauth_user = await sqlalchemy_user_db_oauth.get_by_oauth_account(
        "foo", "bar")
    assert unknown_oauth_user is None
Exemplo n.º 29
0
    async def register(request: Request,
                       user: user_create_model):  # type: ignore
        user = cast(models.BaseUserCreate, user)  # Prevent mypy complain
        existing_user = await user_db.get_by_email(user.email)

        if existing_user is not None:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=ErrorCode.REGISTER_USER_ALREADY_EXISTS,
            )

        hashed_password = get_password_hash(user.password)
        db_user = user_db_model(**user.create_update_dict(),
                                hashed_password=hashed_password)
        created_user = await user_db.create(db_user)

        await router.run_handlers(Event.ON_AFTER_REGISTER, created_user,
                                  request)

        return created_user
Exemplo n.º 30
0
async def reset_password(_: Response, formdata: ResetPasswordVM):
    token = formdata.token
    password = formdata.password

    try:
        data = jwt.decode(token,
                          s.SECRET_KEY_EMAIL,
                          audience=RESET_PASSWORD_TOKEN_AUDIENCE,
                          algorithms=[JWT_ALGORITHM])
        user_id = data.get("user_id")
        if user_id is None:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=ErrorCode.RESET_PASSWORD_BAD_TOKEN,
            )

        try:
            user_uuid = UUID4(user_id)
        except ValueError:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=ErrorCode.RESET_PASSWORD_BAD_TOKEN,
            )

        user = await userdb.get(user_uuid)
        if user is None or not user.is_active:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=ErrorCode.RESET_PASSWORD_BAD_TOKEN,
            )

        user.hashed_password = get_password_hash(password)
        # Use UserDB in order to remove the extra attributes generated by UserDBComplete
        user = UserDB(**user.dict())
        await userdb.update(user)
        return True
    except jwt.PyJWTError:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=ErrorCode.RESET_PASSWORD_BAD_TOKEN,
        )