mirror of
https://github.com/fastapi-users/fastapi-users.git
synced 2025-11-02 12:21:53 +08:00
Native model and generic ID (#971)
* Use a generic Protocol model for User instead of Pydantic
* Remove UserDB Pydantic schema
* Harmonize schema variable naming to avoid confusions
* Revamp OAuth account model management
* Revamp AccessToken DB strategy to adopt generic model approach
* Make ID a generic instead of forcing UUIDs
* Improve generic typing
* Improve Strategy typing
* Tweak base DB typing
* Don't set Pydantic schemas on FastAPIUsers class: pass it directly on router creation
* Add IntegerIdMixin and export related classes
* Start to revamp doc for V10
* Revamp OAuth documentation
* Fix code highlights
* Write the 9.x.x ➡️ 10.x.x migration doc
* Fix pyproject.toml
This commit is contained in:
@ -5,7 +5,7 @@ import pytest
|
||||
from fastapi import Depends, FastAPI, status
|
||||
|
||||
from fastapi_users import FastAPIUsers
|
||||
from tests.conftest import User, UserCreate, UserDB, UserUpdate
|
||||
from tests.conftest import IDType, User, UserCreate, UserModel, UserUpdate
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -17,82 +17,92 @@ async def test_app_client(
|
||||
oauth_client,
|
||||
get_test_client,
|
||||
) -> AsyncGenerator[httpx.AsyncClient, None]:
|
||||
fastapi_users = FastAPIUsers[User, UserCreate, UserUpdate, UserDB](
|
||||
get_user_manager,
|
||||
[mock_authentication],
|
||||
User,
|
||||
UserCreate,
|
||||
UserUpdate,
|
||||
UserDB,
|
||||
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(
|
||||
fastapi_users.get_oauth_router(oauth_client, mock_authentication, secret)
|
||||
)
|
||||
app.include_router(fastapi_users.get_users_router(), prefix="/users")
|
||||
app.include_router(fastapi_users.get_verify_router())
|
||||
|
||||
@app.delete("/users/me")
|
||||
def custom_users_route():
|
||||
return None
|
||||
|
||||
@app.get("/current-user")
|
||||
def current_user(user=Depends(fastapi_users.current_user())):
|
||||
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())):
|
||||
return user
|
||||
|
||||
@app.get("/current-active-user")
|
||||
def current_active_user(user=Depends(fastapi_users.current_user(active=True))):
|
||||
return user
|
||||
|
||||
@app.get("/current-verified-user")
|
||||
def current_verified_user(user=Depends(fastapi_users.current_user(verified=True))):
|
||||
return user
|
||||
|
||||
@app.get("/current-superuser")
|
||||
def current_superuser(
|
||||
user=Depends(fastapi_users.current_user(active=True, superuser=True))
|
||||
@app.get("/current-active-user", response_model=User)
|
||||
def current_active_user(
|
||||
user: UserModel = Depends(fastapi_users.current_user(active=True)),
|
||||
):
|
||||
return user
|
||||
|
||||
@app.get("/current-verified-superuser")
|
||||
@app.get("/current-verified-user", response_model=User)
|
||||
def current_verified_user(
|
||||
user: UserModel = Depends(fastapi_users.current_user(verified=True)),
|
||||
):
|
||||
return user
|
||||
|
||||
@app.get("/current-superuser", response_model=User)
|
||||
def current_superuser(
|
||||
user: UserModel = Depends(
|
||||
fastapi_users.current_user(active=True, superuser=True)
|
||||
)
|
||||
):
|
||||
return user
|
||||
|
||||
@app.get("/current-verified-superuser", response_model=User)
|
||||
def current_verified_superuser(
|
||||
user=Depends(
|
||||
user: UserModel = Depends(
|
||||
fastapi_users.current_user(active=True, verified=True, superuser=True)
|
||||
),
|
||||
):
|
||||
return user
|
||||
|
||||
@app.get("/optional-current-user")
|
||||
def optional_current_user(user=Depends(fastapi_users.current_user(optional=True))):
|
||||
@app.get("/optional-current-user", response_model=User)
|
||||
def optional_current_user(
|
||||
user: UserModel = Depends(fastapi_users.current_user(optional=True)),
|
||||
):
|
||||
return user
|
||||
|
||||
@app.get("/optional-current-active-user")
|
||||
@app.get("/optional-current-active-user", response_model=User)
|
||||
def optional_current_active_user(
|
||||
user=Depends(fastapi_users.current_user(optional=True, active=True)),
|
||||
user: UserModel = Depends(
|
||||
fastapi_users.current_user(optional=True, active=True)
|
||||
),
|
||||
):
|
||||
return user
|
||||
|
||||
@app.get("/optional-current-verified-user")
|
||||
@app.get("/optional-current-verified-user", response_model=User)
|
||||
def optional_current_verified_user(
|
||||
user=Depends(fastapi_users.current_user(optional=True, verified=True)),
|
||||
user: UserModel = Depends(
|
||||
fastapi_users.current_user(optional=True, verified=True)
|
||||
),
|
||||
):
|
||||
return user
|
||||
|
||||
@app.get("/optional-current-superuser")
|
||||
@app.get("/optional-current-superuser", response_model=User)
|
||||
def optional_current_superuser(
|
||||
user=Depends(
|
||||
user: UserModel = Depends(
|
||||
fastapi_users.current_user(optional=True, active=True, superuser=True)
|
||||
),
|
||||
):
|
||||
return user
|
||||
|
||||
@app.get("/optional-current-verified-superuser")
|
||||
@app.get("/optional-current-verified-superuser", response_model=User)
|
||||
def optional_current_verified_superuser(
|
||||
user=Depends(
|
||||
user: UserModel = Depends(
|
||||
fastapi_users.current_user(
|
||||
optional=True, active=True, verified=True, superuser=True
|
||||
)
|
||||
@ -150,7 +160,9 @@ class TestGetCurrentUser:
|
||||
)
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
|
||||
async def test_valid_token(self, test_app_client: httpx.AsyncClient, user: UserDB):
|
||||
async def test_valid_token(
|
||||
self, test_app_client: httpx.AsyncClient, user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/current-user", headers={"Authorization": f"Bearer {user.id}"}
|
||||
)
|
||||
@ -171,7 +183,7 @@ class TestGetCurrentActiveUser:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
|
||||
async def test_valid_token_inactive_user(
|
||||
self, test_app_client: httpx.AsyncClient, inactive_user: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, inactive_user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/current-active-user",
|
||||
@ -179,7 +191,9 @@ class TestGetCurrentActiveUser:
|
||||
)
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
|
||||
async def test_valid_token(self, test_app_client: httpx.AsyncClient, user: UserDB):
|
||||
async def test_valid_token(
|
||||
self, test_app_client: httpx.AsyncClient, user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/current-active-user", headers={"Authorization": f"Bearer {user.id}"}
|
||||
)
|
||||
@ -200,7 +214,7 @@ class TestGetCurrentVerifiedUser:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
|
||||
async def test_valid_token_unverified_user(
|
||||
self, test_app_client: httpx.AsyncClient, user: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/current-verified-user",
|
||||
@ -209,7 +223,7 @@ class TestGetCurrentVerifiedUser:
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
async def test_valid_token_verified_user(
|
||||
self, test_app_client: httpx.AsyncClient, verified_user: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, verified_user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/current-verified-user",
|
||||
@ -232,7 +246,7 @@ class TestGetCurrentSuperuser:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
|
||||
async def test_valid_token_regular_user(
|
||||
self, test_app_client: httpx.AsyncClient, user: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/current-superuser", headers={"Authorization": f"Bearer {user.id}"}
|
||||
@ -240,7 +254,7 @@ class TestGetCurrentSuperuser:
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
async def test_valid_token_superuser(
|
||||
self, test_app_client: httpx.AsyncClient, superuser: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, superuser: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/current-superuser", headers={"Authorization": f"Bearer {superuser.id}"}
|
||||
@ -262,7 +276,7 @@ class TestGetCurrentVerifiedSuperuser:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
|
||||
async def test_valid_token_regular_user(
|
||||
self, test_app_client: httpx.AsyncClient, user: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/current-verified-superuser",
|
||||
@ -271,7 +285,7 @@ class TestGetCurrentVerifiedSuperuser:
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
async def test_valid_token_verified_user(
|
||||
self, test_app_client: httpx.AsyncClient, verified_user: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, verified_user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/current-verified-superuser",
|
||||
@ -280,7 +294,7 @@ class TestGetCurrentVerifiedSuperuser:
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
async def test_valid_token_superuser(
|
||||
self, test_app_client: httpx.AsyncClient, superuser: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, superuser: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/current-verified-superuser",
|
||||
@ -289,7 +303,7 @@ class TestGetCurrentVerifiedSuperuser:
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
async def test_valid_token_verified_superuser(
|
||||
self, test_app_client: httpx.AsyncClient, verified_superuser: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, verified_superuser: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/current-verified-superuser",
|
||||
@ -313,7 +327,9 @@ class TestOptionalGetCurrentUser:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert response.json() is None
|
||||
|
||||
async def test_valid_token(self, test_app_client: httpx.AsyncClient, user: UserDB):
|
||||
async def test_valid_token(
|
||||
self, test_app_client: httpx.AsyncClient, user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/optional-current-user", headers={"Authorization": f"Bearer {user.id}"}
|
||||
)
|
||||
@ -337,7 +353,7 @@ class TestOptionalGetCurrentVerifiedUser:
|
||||
assert response.json() is None
|
||||
|
||||
async def test_valid_token_unverified_user(
|
||||
self, test_app_client: httpx.AsyncClient, user: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/optional-current-verified-user",
|
||||
@ -347,7 +363,7 @@ class TestOptionalGetCurrentVerifiedUser:
|
||||
assert response.json() is None
|
||||
|
||||
async def test_valid_token_verified_user(
|
||||
self, test_app_client: httpx.AsyncClient, verified_user: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, verified_user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/optional-current-verified-user",
|
||||
@ -373,7 +389,7 @@ class TestOptionalGetCurrentActiveUser:
|
||||
assert response.json() is None
|
||||
|
||||
async def test_valid_token_inactive_user(
|
||||
self, test_app_client: httpx.AsyncClient, inactive_user: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, inactive_user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/optional-current-active-user",
|
||||
@ -382,7 +398,9 @@ class TestOptionalGetCurrentActiveUser:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert response.json() is None
|
||||
|
||||
async def test_valid_token(self, test_app_client: httpx.AsyncClient, user: UserDB):
|
||||
async def test_valid_token(
|
||||
self, test_app_client: httpx.AsyncClient, user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/optional-current-active-user",
|
||||
headers={"Authorization": f"Bearer {user.id}"},
|
||||
@ -407,7 +425,7 @@ class TestOptionalGetCurrentSuperuser:
|
||||
assert response.json() is None
|
||||
|
||||
async def test_valid_token_regular_user(
|
||||
self, test_app_client: httpx.AsyncClient, user: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/optional-current-superuser",
|
||||
@ -417,7 +435,7 @@ class TestOptionalGetCurrentSuperuser:
|
||||
assert response.json() is None
|
||||
|
||||
async def test_valid_token_superuser(
|
||||
self, test_app_client: httpx.AsyncClient, superuser: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, superuser: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/optional-current-superuser",
|
||||
@ -444,7 +462,7 @@ class TestOptionalGetCurrentVerifiedSuperuser:
|
||||
assert response.json() is None
|
||||
|
||||
async def test_valid_token_regular_user(
|
||||
self, test_app_client: httpx.AsyncClient, user: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/optional-current-verified-superuser",
|
||||
@ -454,7 +472,7 @@ class TestOptionalGetCurrentVerifiedSuperuser:
|
||||
assert response.json() is None
|
||||
|
||||
async def test_valid_token_verified_user(
|
||||
self, test_app_client: httpx.AsyncClient, verified_user: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, verified_user: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/optional-current-verified-superuser",
|
||||
@ -464,7 +482,7 @@ class TestOptionalGetCurrentVerifiedSuperuser:
|
||||
assert response.json() is None
|
||||
|
||||
async def test_valid_token_superuser(
|
||||
self, test_app_client: httpx.AsyncClient, superuser: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, superuser: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/optional-current-verified-superuser",
|
||||
@ -474,7 +492,7 @@ class TestOptionalGetCurrentVerifiedSuperuser:
|
||||
assert response.json() is None
|
||||
|
||||
async def test_valid_token_verified_superuser(
|
||||
self, test_app_client: httpx.AsyncClient, verified_superuser: UserDB
|
||||
self, test_app_client: httpx.AsyncClient, verified_superuser: UserModel
|
||||
):
|
||||
response = await test_app_client.get(
|
||||
"/optional-current-verified-superuser",
|
||||
|
||||
Reference in New Issue
Block a user