From 940b2091b1f1f451b106e03df6cb957bf73d0011 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Wed, 4 May 2022 11:25:39 +0200 Subject: [PATCH] Don't set Pydantic schemas on FastAPIUsers class: pass it directly on router creation --- fastapi_users/fastapi_users.py | 49 +++++++++++++++++----------------- tests/test_fastapi_users.py | 16 +++++------ tests/test_openapi.py | 10 +++---- 3 files changed, 35 insertions(+), 40 deletions(-) diff --git a/fastapi_users/fastapi_users.py b/fastapi_users/fastapi_users.py index 500d2a06..a0d45243 100644 --- a/fastapi_users/fastapi_users.py +++ b/fastapi_users/fastapi_users.py @@ -22,54 +22,49 @@ except ModuleNotFoundError: # pragma: no cover BaseOAuth2 = Type # type: ignore -class FastAPIUsers(Generic[models.UP, models.ID, schemas.U, schemas.UC, schemas.UU]): +class FastAPIUsers(Generic[models.UP, models.ID]): """ Main object that ties together the component for users authentication. :param get_user_manager: Dependency callable getter to inject the user manager class instance. :param auth_backends: List of authentication backends. - :param user_schema: Pydantic schema of a public user. - :param user_create_schema: Pydantic schema for creating a user. - :param user_update_schema: Pydantic schema for updating a user. :attribute current_user: Dependency callable getter to inject authenticated user with a specific set of parameters. """ authenticator: Authenticator - _user_schema: Type[schemas.U] - _user_create_schema: Type[schemas.UC] - _user_update_schema: Type[schemas.UU] def __init__( self, get_user_manager: UserManagerDependency[models.UP, models.ID], auth_backends: Sequence[AuthenticationBackend], - user_schema: Type[schemas.U], - user_create_schema: Type[schemas.UC], - user_update_schema: Type[schemas.UU], ): self.authenticator = Authenticator(auth_backends, get_user_manager) - - self._user_schema = user_schema - self._user_create_schema = user_create_schema - self._user_update_schema = user_update_schema - self.get_user_manager = get_user_manager self.current_user = self.authenticator.current_user - def get_register_router(self) -> APIRouter: - """Return a router with a register route.""" + def get_register_router( + self, user_schema: Type[schemas.U], user_create_schema: Type[schemas.UC] + ) -> APIRouter: + """ + Return a router with a register route. + + :param user_schema: Pydantic schema of a public user. + :param user_create_schema: Pydantic schema for creating a user. + """ return get_register_router( - self.get_user_manager, - self._user_schema, - self._user_create_schema, + self.get_user_manager, user_schema, user_create_schema ) - def get_verify_router(self) -> APIRouter: - """Return a router with e-mail verification routes.""" - return get_verify_router(self.get_user_manager, self._user_schema) + def get_verify_router(self, user_schema: Type[schemas.U]) -> APIRouter: + """ + Return a router with e-mail verification routes. + + :param user_schema: Pydantic schema of a public user. + """ + return get_verify_router(self.get_user_manager, user_schema) def get_reset_password_router(self) -> APIRouter: """Return a reset password process router.""" @@ -118,18 +113,22 @@ class FastAPIUsers(Generic[models.UP, models.ID, schemas.U, schemas.UC, schemas. def get_users_router( self, + user_schema: Type[schemas.U], + user_update_schema: Type[schemas.UU], requires_verification: bool = False, ) -> APIRouter: """ Return a router with routes to manage users. + :param user_schema: Pydantic schema of a public user. + :param user_update_schema: Pydantic schema for updating a user. :param requires_verification: Whether the endpoints require the users to be verified or not. """ return get_users_router( self.get_user_manager, - self._user_schema, - self._user_update_schema, + user_schema, + user_update_schema, self.authenticator, requires_verification, ) diff --git a/tests/test_fastapi_users.py b/tests/test_fastapi_users.py index 9afed931..f4c60858 100644 --- a/tests/test_fastapi_users.py +++ b/tests/test_fastapi_users.py @@ -17,16 +17,12 @@ async def test_app_client( oauth_client, get_test_client, ) -> AsyncGenerator[httpx.AsyncClient, None]: - fastapi_users = FastAPIUsers[UserModel, IDType, User, UserCreate, UserUpdate]( - get_user_manager, - [mock_authentication], - User, - UserCreate, - UserUpdate, + fastapi_users = FastAPIUsers[UserModel, IDType]( + get_user_manager, [mock_authentication] ) app = FastAPI() - app.include_router(fastapi_users.get_register_router()) + app.include_router(fastapi_users.get_register_router(User, UserCreate)) app.include_router(fastapi_users.get_reset_password_router()) app.include_router(fastapi_users.get_auth_router(mock_authentication)) app.include_router( @@ -37,8 +33,10 @@ async def test_app_client( def custom_users_route(): return None - app.include_router(fastapi_users.get_users_router(), prefix="/users") - app.include_router(fastapi_users.get_verify_router()) + app.include_router( + fastapi_users.get_users_router(User, UserUpdate), prefix="/users" + ) + app.include_router(fastapi_users.get_verify_router(User)) @app.get("/current-user", response_model=User) def current_user(user: UserModel = Depends(fastapi_users.current_user())): diff --git a/tests/test_openapi.py b/tests/test_openapi.py index ea14a9a9..439da25d 100644 --- a/tests/test_openapi.py +++ b/tests/test_openapi.py @@ -8,9 +8,7 @@ from tests.conftest import IDType, User, UserCreate, UserModel, UserUpdate @pytest.fixture def fastapi_users(get_user_manager, mock_authentication) -> FastAPIUsers: - return FastAPIUsers[UserModel, IDType, User, UserCreate, UserUpdate]( - get_user_manager, [mock_authentication], User, UserCreate, UserUpdate - ) + return FastAPIUsers[UserModel, IDType](get_user_manager, [mock_authentication]) @pytest.fixture @@ -18,14 +16,14 @@ def test_app( fastapi_users: FastAPIUsers, secret, mock_authentication, oauth_client ) -> FastAPI: app = FastAPI() - app.include_router(fastapi_users.get_register_router()) + app.include_router(fastapi_users.get_register_router(User, UserCreate)) app.include_router(fastapi_users.get_reset_password_router()) app.include_router(fastapi_users.get_auth_router(mock_authentication)) app.include_router( fastapi_users.get_oauth_router(oauth_client, mock_authentication, secret) ) - app.include_router(fastapi_users.get_users_router()) - app.include_router(fastapi_users.get_verify_router()) + app.include_router(fastapi_users.get_users_router(User, UserUpdate)) + app.include_router(fastapi_users.get_verify_router(User)) return app